aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorFrancesco Rodriguez <lrodriguezsanc@gmail.com>2012-09-21 23:25:52 -0500
committerFrancesco Rodriguez <lrodriguezsanc@gmail.com>2012-09-21 23:25:52 -0500
commit6dec7535fd26b8abea0211313ef2936d28ed1637 (patch)
treef7c681d18b5a040b11f338514d636f4dde0508d6 /activerecord
parent0eea22bdea4df3ec89ea65157a6a0e85cb048bca (diff)
downloadrails-6dec7535fd26b8abea0211313ef2936d28ed1637.tar.gz
rails-6dec7535fd26b8abea0211313ef2936d28ed1637.tar.bz2
rails-6dec7535fd26b8abea0211313ef2936d28ed1637.zip
update AR::Scoping documentation [ci skip]
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/scoping/default.rb55
-rw-r--r--activerecord/lib/active_record/scoping/named.rb113
2 files changed, 77 insertions, 91 deletions
diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb
index a2a85d4b96..6835d0e01b 100644
--- a/activerecord/lib/active_record/scoping/default.rb
+++ b/activerecord/lib/active_record/scoping/default.rb
@@ -5,17 +5,17 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- # Stores the default scope for the class
+ # Stores the default scope for the class.
class_attribute :default_scopes, instance_writer: false
self.default_scopes = []
end
module ClassMethods
- # Returns a scope for the model without the default_scope.
+ # Returns a scope for the model without the +default_scope+.
#
# class Post < ActiveRecord::Base
# def self.default_scope
- # where :published => true
+ # where published: true
# end
# end
#
@@ -23,16 +23,16 @@ module ActiveRecord
# Post.unscoped.all # Fires "SELECT * FROM posts"
#
# This method also accepts a block. All queries inside the block will
- # not use the default_scope:
+ # not use the +default_scope+:
#
# Post.unscoped {
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
# }
#
# It is recommended that you use the block form of unscoped because
- # chaining unscoped with <tt>scope</tt> does not work. Assuming that
- # <tt>published</tt> is a <tt>scope</tt>, the following two statements
- # are equal: the <tt>default_scope</tt> is applied on both.
+ # chaining unscoped with +scope+ does not work. Assuming that
+ # +published+ is a +scope+, the following two statements
+ # are equal: the +default_scope+ is applied on both.
#
# Post.unscoped.published
# Post.published
@@ -50,35 +50,37 @@ module ActiveRecord
# the model.
#
# class Article < ActiveRecord::Base
- # default_scope { where(:published => true) }
+ # default_scope { where(published: true) }
# end
#
# Article.all # => SELECT * FROM articles WHERE published = true
#
- # The <tt>default_scope</tt> is also applied while creating/building a record. It is not
- # applied while updating a record.
+ # The +default_scope+ is also applied while creating/building a record.
+ # It is not applied while updating a record.
#
# Article.new.published # => true
# Article.create.published # => true
#
- # (You can also pass any object which responds to <tt>call</tt> to the <tt>default_scope</tt>
- # macro, and it will be called when building the default scope.)
+ # (You can also pass any object which responds to +call+ to the
+ # +default_scope+ macro, and it will be called when building the
+ # default scope.)
#
- # If you use multiple <tt>default_scope</tt> declarations in your model then they will
- # be merged together:
+ # If you use multiple +default_scope+ declarations in your model then
+ # they will be merged together:
#
# class Article < ActiveRecord::Base
- # default_scope { where(:published => true) }
- # default_scope { where(:rating => 'G') }
+ # default_scope { where(published: true) }
+ # default_scope { where(rating: 'G') }
# end
#
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
#
- # This is also the case with inheritance and module includes where the parent or module
- # defines a <tt>default_scope</tt> and the child or including class defines a second one.
+ # This is also the case with inheritance and module includes where the
+ # parent or module defines a +default_scope+ and the child or including
+ # class defines a second one.
#
- # If you need to do more complex things with a default scope, you can alternatively
- # define it as a class method:
+ # If you need to do more complex things with a default scope, you can
+ # alternatively define it as a class method:
#
# class Article < ActiveRecord::Base
# def self.default_scope
@@ -100,7 +102,7 @@ module ActiveRecord
self.default_scopes = default_scopes + [scope]
end
- def build_default_scope #:nodoc:
+ def build_default_scope # :nodoc:
if !Base.is_a?(method(:default_scope).owner)
# The user has defined their own default scope method, so call that
evaluate_default_scope { default_scope }
@@ -117,17 +119,18 @@ module ActiveRecord
end
end
- def ignore_default_scope? #:nodoc:
+ def ignore_default_scope? # :nodoc:
Thread.current["#{self}_ignore_default_scope"]
end
- def ignore_default_scope=(ignore) #:nodoc:
+ def ignore_default_scope=(ignore) # :nodoc:
Thread.current["#{self}_ignore_default_scope"] = ignore
end
- # The ignore_default_scope flag is used to prevent an infinite recursion situation where
- # a default scope references a scope which has a default scope which references a scope...
- def evaluate_default_scope
+ # The ignore_default_scope flag is used to prevent an infinite recursion
+ # situation where a default scope references a scope which has a default
+ # scope which references a scope...
+ def evaluate_default_scope # :nodoc:
return if ignore_default_scope?
begin
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 75f31229b5..fb5f5b5be0 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -3,7 +3,7 @@ require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/kernel/singleton_class'
module ActiveRecord
- # = Active Record Named \Scopes
+ # = Active Record \Named \Scopes
module Scoping
module Named
extend ActiveSupport::Concern
@@ -16,11 +16,11 @@ module ActiveRecord
# posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
#
# fruits = Fruit.all
- # fruits = fruits.where(:color => 'red') if options[:red_only]
+ # fruits = fruits.where(color: 'red') if options[:red_only]
# fruits = fruits.limit(10) if limited?
#
- # You can define a \scope that applies to all finders using
- # ActiveRecord::Base.default_scope.
+ # You can define a scope that applies to all finders using
+ # <tt>ActiveRecord::Base.default_scope</tt>.
def all
if current_scope
current_scope.clone
@@ -31,7 +31,6 @@ module ActiveRecord
end
end
- ##
# Collects attributes from scopes that should be applied when creating
# an AR instance for the particular class this is called on.
def scope_attributes # :nodoc:
@@ -44,86 +43,70 @@ module ActiveRecord
end
end
- ##
# Are there default attributes associated with this scope?
def scope_attributes? # :nodoc:
current_scope || default_scopes.any?
end
- # Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
- # such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
+ # Adds a class method for retrieving and querying objects. A \scope
+ # represents a narrowing of a database query, such as
+ # <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
#
# class Shirt < ActiveRecord::Base
- # scope :red, where(:color => 'red')
- # scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true)
+ # scope :red, -> { where(color: 'red') }
+ # scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
# end
#
- # The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
- # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
+ # The above calls to +scope+ define class methods <tt>Shirt.red</tt> and
+ # <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
+ # represents the query <tt>Shirt.where(color: 'red')</tt>.
#
- # Note that this is simply 'syntactic sugar' for defining an actual class method:
+ # You should always pass a callable object to the scopes defined
+ # with +scope+. This ensures that the scope is re-evaluated each
+ # time it is called.
+ #
+ # Note that this is simply 'syntactic sugar' for defining an actual
+ # class method:
#
# class Shirt < ActiveRecord::Base
# def self.red
- # where(:color => 'red')
+ # where(color: 'red')
# end
# end
#
- # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it
- # resembles the association object constructed by a <tt>has_many</tt> declaration. For instance,
- # you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>, <tt>Shirt.red.where(:size => 'small')</tt>.
- # Also, just as with the association objects, named \scopes act like an Array, implementing Enumerable;
- # <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt>
- # all behave as if Shirt.red really was an Array.
- #
- # These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce
- # all shirts that are both red and dry clean only.
- # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
- # returns the number of garments for which these criteria obtain. Similarly with
- # <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
- #
- # All \scopes are available as class methods on the ActiveRecord::Base descendant upon which
- # the \scopes were defined. But they are also available to <tt>has_many</tt> associations. If,
+ # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
+ # <tt>Shirt.red</tt> is not an Array; it resembles the association object
+ # constructed by a +has_many+ declaration. For instance, you can invoke
+ # <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
+ # <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
+ # association objects, named \scopes act like an Array, implementing
+ # Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
+ # and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
+ # <tt>Shirt.red</tt> really was an Array.
+ #
+ # These named \scopes are composable. For instance,
+ # <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
+ # both red and dry clean only. Nested finds and calculations also work
+ # with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
+ # returns the number of garments for which these criteria obtain.
+ # Similarly with <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
+ #
+ # All scopes are available as class methods on the ActiveRecord::Base
+ # descendant upon which the \scopes were defined. But they are also
+ # available to +has_many+ associations. If,
#
# class Person < ActiveRecord::Base
# has_many :shirts
# end
#
- # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
- # only shirts.
- #
- # Named \scopes can also be procedural:
- #
- # class Shirt < ActiveRecord::Base
- # scope :colored, lambda { |color| where(:color => color) }
- # end
- #
- # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
- #
- # On Ruby 1.9 you can use the 'stabby lambda' syntax:
- #
- # scope :colored, ->(color) { where(:color => color) }
- #
- # Note that scopes defined with \scope will be evaluated when they are defined, rather than
- # when they are used. For example, the following would be incorrect:
- #
- # class Post < ActiveRecord::Base
- # scope :recent, where('published_at >= ?', Time.current - 1.week)
- # end
- #
- # The example above would be 'frozen' to the <tt>Time.current</tt> value when the <tt>Post</tt>
- # class was defined, and so the resultant SQL query would always be the same. The correct
- # way to do this would be via a lambda, which will re-evaluate the scope each time
- # it is called:
- #
- # class Post < ActiveRecord::Base
- # scope :recent, lambda { where('published_at >= ?', Time.current - 1.week) }
- # end
+ # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
+ # Elton's red, dry clean only shirts.
#
- # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
+ # \Named scopes can also have extensions, just as with +has_many+
+ # declarations:
#
# class Shirt < ActiveRecord::Base
- # scope :red, where(:color => 'red') do
+ # scope :red, -> { where(color: 'red') } do
# def dom_id
# 'red_shirts'
# end
@@ -133,18 +116,18 @@ module ActiveRecord
# Scopes can also be used while creating/building a record.
#
# class Article < ActiveRecord::Base
- # scope :published, where(:published => true)
+ # scope :published, -> { where(published: true) }
# end
#
# Article.published.new.published # => true
# Article.published.create.published # => true
#
- # Class methods on your model are automatically available
+ # \Class methods on your model are automatically available
# on scopes. Assuming the following setup:
#
# class Article < ActiveRecord::Base
- # scope :published, where(:published => true)
- # scope :featured, where(:featured => true)
+ # scope :published, -> { where(published: true) }
+ # scope :featured, -> { where(featured: true) }
#
# def self.latest_article
# order('published_at desc').first