diff options
author | Avi Tzurel <avi@kensodev.com> | 2012-05-19 00:42:34 +0300 |
---|---|---|
committer | Avi Tzurel <avi@kensodev.com> | 2012-05-19 00:42:34 +0300 |
commit | 782792002fdf9566b2cb2f27ea8c0c472f9a9ac5 (patch) | |
tree | 873c2594e295da41b1ee5a817da3900b5008f60a /activerecord/lib | |
parent | ede5e9b3db8e4238009b582f5ff53029d04d0418 (diff) | |
parent | 1b5c775e7a6d5457da6d2fe02e9e72c6788a7373 (diff) | |
download | rails-782792002fdf9566b2cb2f27ea8c0c472f9a9ac5.tar.gz rails-782792002fdf9566b2cb2f27ea8c0c472f9a9ac5.tar.bz2 rails-782792002fdf9566b2cb2f27ea8c0c472f9a9ac5.zip |
Merge branch 'master' of github.com:lifo/docrails
Diffstat (limited to 'activerecord/lib')
4 files changed, 155 insertions, 126 deletions
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 9abe648708..aa354d9009 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -24,7 +24,7 @@ module ActiveRecord # # If you need to work on all current children, new and existing records, # +load_target+ and the +loaded+ flag are your friends. - class CollectionAssociation < Association + class CollectionAssociation < Association #:nodoc: # Implements the reader method, e.g. foo.items for Foo.has_many :items def reader(force_reload = false) @@ -127,16 +127,6 @@ module ActiveRecord # Add +records+ to this association. Returns +self+ so method calls may # be chained. Since << flattens its argument list and inserts each record, # +push+ and +concat+ behave identically. - # - # class Person < ActiveRecord::Base - # pets :has_many - # end - # - # person.pets << Person.new(name: 'Nemo') - # person.pets.concat(Person.new(name: 'Droopy')) - # person.pets.push(Person.new(name: 'Ren')) - # - # person.pets # => [#<Pet name: "Nemo">, #<Pet name: "Droopy">, #<Pet name: "Ren">] def concat(*records) load_target if owner.new_record? @@ -181,17 +171,6 @@ module ActiveRecord # Destroy all the records from this association. # - # class Person < ActiveRecord::Base - # has_many :pets - # end - # - # person.pets.size # => 3 - # - # person.pets.destroy_all - # - # person.pets.size # => 0 - # person.pets # => [] - # # See destroy for more info. def destroy_all destroy(load_target).tap do @@ -302,51 +281,12 @@ module ActiveRecord # <tt>collection.size.zero?</tt>. If the collection has not been already # loaded and you are going to fetch the records anyway it is better to # check <tt>collection.length.zero?</tt>. - # - # class Person < ActiveRecord::Base - # has_many :pets - # end - # - # person.pets.count # => 1 - # person.pets.empty? # => false - # - # person.pets.delete_all - # person.pets.count # => 0 - # person.pets.empty? # => true def empty? size.zero? end # Returns true if the collections is not empty. # Equivalent to +!collection.empty?+. - # - # class Person < ActiveRecord::Base - # has_many :pets - # end - # - # person.pets.count # => 0 - # person.pets.any? # => false - # - # person.pets << Pet.new(name: 'Snoop') - # person.pets.count # => 0 - # person.pets.any? # => true - # - # Also, you can pass a block to define a criteria. The behaviour - # is the same, it returns true if the collection based on the - # criteria is not empty. - # - # person.pets - # # => [#<Pet name: "Snoop", group: "dogs">] - # - # person.pets.any? do |pet| - # pet.group == 'cats' - # end - # # => false - # - # person.pets.any? do |pet| - # pet.group == 'dogs' - # end - # # => true def any? if block_given? load_target.any? { |*block_args| yield(*block_args) } @@ -357,38 +297,6 @@ module ActiveRecord # Returns true if the collection has more than 1 record. # Equivalent to +collection.size > 1+. - # - # class Person < ActiveRecord::Base - # has_many :pets - # end - # - # person.pets.count #=> 1 - # person.pets.many? #=> false - # - # person.pets << Pet.new(name: 'Snoopy') - # person.pets.count #=> 2 - # person.pets.many? #=> true - # - # Also, you can pass a block to define a criteria. The - # behaviour is the same, it returns true if the collection - # based on the criteria has more than 1 record. - # - # person.pets - # # => [ - # # #<Pet name: "GorbyPuff", group: "cats">, - # # #<Pet name: "Wy", group: "cats">, - # # #<Pet name: "Snoop", group: "dogs"> - # # ] - # - # person.pets.many? do |pet| - # pet.group == 'dogs' - # end - # # => false - # - # person.pets.many? do |pet| - # pet.group == 'cats' - # end - # # => true def many? if block_given? load_target.many? { |*block_args| yield(*block_args) } @@ -406,26 +314,6 @@ module ActiveRecord # Replace this collection with +other_array+. This will perform a diff # and delete/add only records that have changed. - # - # class Person < ActiveRecord::Base - # has_many :pets - # end - # - # person.pets - # # => [#<Pet id: 1, name: "Wy", group: "cats", person_id: 1>] - # - # other_pets = [Pet.new(name: 'GorbyPuff', group: 'celebrities'] - # - # person.pets.replace(other_pets) - # - # person.pets - # # => [#<Pet id: 2, name: "GorbyPuff", group: "celebrities", person_id: 1>] - # - # If the supplied array has an incorrect association type, it raises - # an ActiveRecord::AssociationTypeMismatch error: - # - # person.pets.replace(["doo", "ggie", "gaga"]) - # # => ActiveRecord::AssociationTypeMismatch: Pet expected, got String def replace(other_array) other_array.each { |val| raise_on_type_mismatch(val) } original_target = load_target.dup diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index cf4cc98f38..40f59f2c77 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -33,9 +33,150 @@ module ActiveRecord # # is computed directly through SQL and does not trigger by itself the # instantiation of the actual post records. - class CollectionProxy < Relation # :nodoc: + class CollectionProxy < Relation delegate :target, :load_target, :loaded?, :to => :@association + ## + # :method: concat + # Add +records+ to this association. Returns +self+ so method calls may + # be chained. Since << flattens its argument list and inserts each record, + # +push+ and +concat+ behave identically. + # + # class Person < ActiveRecord::Base + # pets :has_many + # end + # + # person.pets << Person.new(name: 'Nemo') + # person.pets.concat(Person.new(name: 'Droopy')) + # person.pets.push(Person.new(name: 'Ren')) + # + # person.pets # => [#<Pet name: "Nemo">, #<Pet name: "Droopy">, #<Pet name: "Ren">] + + ## + # :method: replace + # Replace this collection with +other_array+. This will perform a diff + # and delete/add only records that have changed. + # + # class Person < ActiveRecord::Base + # has_many :pets + # end + # + # person.pets + # # => [#<Pet id: 1, name: "Wy", group: "cats", person_id: 1>] + # + # other_pets = [Pet.new(name: 'GorbyPuff', group: 'celebrities'] + # + # person.pets.replace(other_pets) + # + # person.pets + # # => [#<Pet id: 2, name: "GorbyPuff", group: "celebrities", person_id: 1>] + # + # If the supplied array has an incorrect association type, it raises + # an ActiveRecord::AssociationTypeMismatch error: + # + # person.pets.replace(["doo", "ggie", "gaga"]) + # # => ActiveRecord::AssociationTypeMismatch: Pet expected, got String + + ## + # :method: destroy_all + # Destroy all the records from this association. + # + # class Person < ActiveRecord::Base + # has_many :pets + # end + # + # person.pets.size # => 3 + # + # person.pets.destroy_all + # + # person.pets.size # => 0 + # person.pets # => [] + + ## + # :method: empty? + # Returns true if the collection is empty. + # Equivalent to +size.zero?+. + # + # class Person < ActiveRecord::Base + # has_many :pets + # end + # + # person.pets.count # => 1 + # person.pets.empty? # => false + # + # person.pets.delete_all + # person.pets.count # => 0 + # person.pets.empty? # => true + + ## + # :method: any? + # Returns true if the collections is not empty. + # Equivalent to +!collection.empty?+. + # + # class Person < ActiveRecord::Base + # has_many :pets + # end + # + # person.pets.count # => 0 + # person.pets.any? # => false + # + # person.pets << Pet.new(name: 'Snoop') + # person.pets.count # => 0 + # person.pets.any? # => true + # + # Also, you can pass a block to define a criteria. The behaviour + # is the same, it returns true if the collection based on the + # criteria is not empty. + # + # person.pets + # # => [#<Pet name: "Snoop", group: "dogs">] + # + # person.pets.any? do |pet| + # pet.group == 'cats' + # end + # # => false + # + # person.pets.any? do |pet| + # pet.group == 'dogs' + # end + # # => true + + ## + # :method: many? + # Returns true if the collection has more than 1 record. + # Equivalent to +collection.size > 1+. + # + # class Person < ActiveRecord::Base + # has_many :pets + # end + # + # person.pets.count #=> 1 + # person.pets.many? #=> false + # + # person.pets << Pet.new(name: 'Snoopy') + # person.pets.count #=> 2 + # person.pets.many? #=> true + # + # Also, you can pass a block to define a criteria. The + # behaviour is the same, it returns true if the collection + # based on the criteria has more than 1 record. + # + # person.pets + # # => [ + # # #<Pet name: "GorbyPuff", group: "cats">, + # # #<Pet name: "Wy", group: "cats">, + # # #<Pet name: "Snoop", group: "dogs"> + # # ] + # + # person.pets.many? do |pet| + # pet.group == 'dogs' + # end + # # => false + # + # person.pets.many? do |pet| + # pet.group == 'cats' + # end + # # => true delegate :select, :find, :first, :last, :build, :create, :create!, :concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq, diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index b2ed606e5f..f2833fbf3c 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -127,7 +127,7 @@ module ActiveRecord object.is_a?(self) end - # Returns an instance of <tt>Arel::Table</tt> loaded with the curent table name. + # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name. # # class Post < ActiveRecord::Base # scope :published_and_commented, published.and(self.arel_table[:comments_count].gt(0)) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 779e052e3c..05ced3299b 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -370,17 +370,12 @@ module ActiveRecord end end - # Deletes the records matching +conditions+ without instantiating the records first, and hence not - # calling the +destroy+ method nor invoking callbacks. This is a single SQL DELETE statement that - # goes straight to the database, much more efficient than +destroy_all+. Be careful with relations - # though, in particular <tt>:dependent</tt> rules defined on associations are not honored. Returns - # the number of rows affected. - # - # ==== Parameters - # - # * +conditions+ - Conditions are specified the same way as with +find+ method. - # - # ==== Example + # Deletes the records matching +conditions+ without instantiating the records + # first, and hence not calling the +destroy+ method nor invoking callbacks. This + # is a single SQL DELETE statement that goes straight to the database, much more + # efficient than +destroy_all+. Be careful with relations though, in particular + # <tt>:dependent</tt> rules defined on associations are not honored. Returns the + # number of rows affected. # # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')") # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else']) @@ -389,6 +384,11 @@ module ActiveRecord # Both calls delete the affected posts all at once with a single DELETE statement. # If you need to destroy dependent associations or call your <tt>before_*</tt> or # +after_destroy+ callbacks, use the +destroy_all+ method instead. + # + # If a limit scope is supplied, +delete_all+ raises an ActiveRecord error: + # + # Post.limit(100).delete_all + # # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit scope def delete_all(conditions = nil) raise ActiveRecordError.new("delete_all doesn't support limit scope") if self.limit_value |