From 26d3e325cb85884504564b8af07dd083fc47d2a8 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Wed, 1 Aug 2012 22:28:26 +0100 Subject: Use explicit delegations This makes it easier to see what the documentation refers to. It also means that we are not doing unnecessary work for delegations that have no args / splats / block / etc. --- .../active_record/associations/collection_proxy.rb | 198 ++++++++------------- 1 file changed, 79 insertions(+), 119 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index ab6a4ed86c..65a5044a3d 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -34,15 +34,25 @@ module ActiveRecord # is computed directly through SQL and does not trigger by itself the # instantiation of the actual post records. class CollectionProxy < Relation - delegate :target, :load_target, :loaded?, :to => :@association + def initialize(association) #:nodoc: + @association = association + super association.klass, association.klass.arel_table + merge! association.scoped + end + + def target + @association.target + end + + def load_target + @association.load_target + end + + def loaded? + @association.loaded? + end ## - # :method: select - # - # :call-seq: - # select(select = nil) - # select(&block) - # # Works in two ways. # # *First:* Specify a subset of fields to be selected from the result set. @@ -96,13 +106,11 @@ module ActiveRecord # # #, # # # # # ] + def select(select = nil, &block) + @association.select(select, &block) + end ## - # :method: find - # - # :call-seq: - # find(*args, &block) - # # Finds an object in the collection responding to the +id+. Uses the same # rules as +ActiveRecord::Base.find+. Returns +ActiveRecord::RecordNotFound++ # error if the object can not be found. @@ -129,13 +137,11 @@ module ActiveRecord # # #, # # # # # ] + def find(*args, &block) + @association.find(*args, &block) + end ## - # :method: first - # - # :call-seq: - # first(limit = nil) - # # Returns the first record, or the first +n+ records, from the collection. # If the collection is empty, the first form returns +nil+, and the second # form returns an empty array. @@ -162,13 +168,11 @@ module ActiveRecord # another_person_without.pets # => [] # another_person_without.pets.first # => nil # another_person_without.pets.first(3) # => [] + def first(*args) + @association.first(*args) + end ## - # :method: last - # - # :call-seq: - # last(limit = nil) - # # Returns the last record, or the last +n+ records, from the collection. # If the collection is empty, the first form returns +nil+, and the second # form returns an empty array. @@ -195,13 +199,11 @@ module ActiveRecord # another_person_without.pets # => [] # another_person_without.pets.last # => nil # another_person_without.pets.last(3) # => [] + def last(*args) + @association.last(*args) + end ## - # :method: build - # - # :call-seq: - # build(attributes = {}, options = {}, &block) - # # Returns a new object of the collection type that has been instantiated # with +attributes+ and linked to this object, but have not yet been saved. # You can pass an array of attributes hashes, this will return an array @@ -226,13 +228,11 @@ module ActiveRecord # # person.pets.size # => 5 # size of the collection # person.pets.count # => 0 # count from database + def build(attributes = {}, options = {}, &block) + @association.build(attributes, options, &block) + end ## - # :method: create - # - # :call-seq: - # create(attributes = {}, options = {}, &block) - # # Returns a new object of the collection type that has been instantiated with # attributes, linked to this object and that has already been saved (if it # passes the validations). @@ -259,13 +259,11 @@ module ActiveRecord # # #, # # # # # ] + def create(attributes = {}, options = {}, &block) + @association.create(attributes, options, &block) + end ## - # :method: create! - # - # :call-seq: - # create!(attributes = {}, options = {}, &block) - # # Like +create+, except that if the record is invalid, raises an exception. # # class Person @@ -279,13 +277,11 @@ module ActiveRecord # # person.pets.create!(name: nil) # # => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank + def create!(attributes = {}, options = {}, &block) + @association.create!(attributes, options, &block) + end ## - # :method: concat - # - # :call-seq: - # concat(*records) - # # Add one or more records to the collection by setting their foreign keys # to the association's primary key. Since << flattens its argument list and # inserts each record, +push+ and +concat+ behave identically. Returns +self+ @@ -310,13 +306,11 @@ module ActiveRecord # # person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')]) # person.pets.size # => 5 + def concat(*records) + @association.concat(*records) + end ## - # :method: replace - # - # :call-seq: - # replace(other_array) - # # Replace this collection with +other_array+. This will perform a diff # and delete/add only records that have changed. # @@ -339,13 +333,11 @@ module ActiveRecord # # person.pets.replace(["doo", "ggie", "gaga"]) # # => ActiveRecord::AssociationTypeMismatch: Pet expected, got String + def replace(other_array) + @association.replace(other_array) + end ## - # :method: delete_all - # - # :call-seq: - # delete_all() - # # Deletes all the records from the collection. For +has_many+ associations, # the deletion is done according to the strategy specified by the :dependent # option. Returns an array with the deleted records. @@ -434,13 +426,11 @@ module ActiveRecord # # Pet.find(1, 2, 3) # # => ActiveRecord::RecordNotFound + def delete_all + @association.delete_all + end ## - # :method: destroy_all - # - # :call-seq: - # destroy_all() - # # Deletes the records of the collection directly from the database. # This will _always_ remove the records ignoring the +:dependent+ # option. @@ -463,15 +453,11 @@ module ActiveRecord # person.pets # => [] # # Pet.find(1) # => Couldn't find Pet with id=1 + def destroy_all + @association.destroy_all + end ## - # :method: delete - # - # :call-seq: - # delete(*records) - # delete(*fixnum_ids) - # delete(*string_ids) - # # Deletes the +records+ supplied and removes them from the collection. For # +has_many+ associations, the deletion is done according to the strategy # specified by the :dependent option. Returns an array with the @@ -586,13 +572,11 @@ module ActiveRecord # # #, # # # # # ] + def delete(*records) + @association.delete(*records) + end ## - # :method: destroy - # - # :call-seq: - # destroy(*records) - # # Destroys the +records+ supplied and removes them from the collection. # This method will _always_ remove record from the database ignoring # the +:dependent+ option. Returns an array with the removed records. @@ -661,13 +645,11 @@ module ActiveRecord # person.pets # => [] # # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6) + def destroy(*records) + @association.destroy(*records) + end ## - # :method: uniq - # - # :call-seq: - # uniq() - # # Specifies whether the records should be unique or not. # # class Person < ActiveRecord::Base @@ -682,13 +664,11 @@ module ActiveRecord # # person.pets.select(:name).uniq # # => [#] + def uniq + @association.uniq + end ## - # :method: count - # - # :call-seq: - # count() - # # Count all records using SQL. # # class Person < ActiveRecord::Base @@ -702,13 +682,11 @@ module ActiveRecord # # #, # # # # # ] + def count(column_name = nil, options = {}) + @association.count(column_name, options) + end ## - # :method: size - # - # :call-seq: - # size() - # # Returns the size of the collection. If the collection hasn't been loaded, # it executes a SELECT COUNT(*) query. # @@ -729,13 +707,11 @@ module ActiveRecord # person.pets.size # => 3 # # Because the collection is already loaded, this will behave like # # collection.size and no SQL count query is executed. + def size + @association.size + end ## - # :method: length - # - # :call-seq: - # length() - # # Returns the size of the collection calling +size+ on the target. # If the collection has been already loaded, +length+ and +size+ are # equivalent. @@ -755,10 +731,11 @@ module ActiveRecord # # #, # # # # # ] + def length + @association.length + end ## - # :method: empty? - # # Returns +true+ if the collection is empty. # # class Person < ActiveRecord::Base @@ -772,14 +749,11 @@ module ActiveRecord # # person.pets.count # => 0 # person.pets.empty? # => true + def empty? + @association.empty? + end ## - # :method: any? - # - # :call-seq: - # any? - # any?{|item| block} - # # Returns +true+ if the collection is not empty. # # class Person < ActiveRecord::Base @@ -809,14 +783,11 @@ module ActiveRecord # pet.group == 'dogs' # end # # => true + def any?(&block) + @association.any?(&block) + end ## - # :method: many? - # - # :call-seq: - # many? - # many?{|item| block} - # # Returns true if the collection has more than one record. # Equivalent to collection.size > 1. # @@ -851,13 +822,11 @@ module ActiveRecord # pet.group == 'cats' # end # # => true + def many?(&block) + @association.many?(&block) + end ## - # :method: include? - # - # :call-seq: - # include?(record) - # # Returns +true+ if the given object is present in the collection. # # class Person < ActiveRecord::Base @@ -868,17 +837,8 @@ module ActiveRecord # # person.pets.include?(Pet.find(20)) # => true # person.pets.include?(Pet.find(21)) # => false - delegate :select, :find, :first, :last, - :build, :create, :create!, - :concat, :replace, :delete_all, :destroy_all, :delete, :destroy, :uniq, - :sum, :count, :size, :length, :empty?, - :any?, :many?, :include?, - :to => :@association - - def initialize(association) #:nodoc: - @association = association - super association.klass, association.klass.arel_table - merge! association.scoped + def include?(record) + @association.include?(record) end alias_method :new, :build -- cgit v1.2.3