aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/collection_proxy.rb
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2012-08-01 22:28:26 +0100
committerJon Leighton <j@jonathanleighton.com>2012-08-01 22:33:24 +0100
commit26d3e325cb85884504564b8af07dd083fc47d2a8 (patch)
treeb84186e5a1b2c971dcd457524d6e745894d8608a /activerecord/lib/active_record/associations/collection_proxy.rb
parent66aaca4e5d69b6acbbfc97f298b775fa13b7335a (diff)
downloadrails-26d3e325cb85884504564b8af07dd083fc47d2a8.tar.gz
rails-26d3e325cb85884504564b8af07dd083fc47d2a8.tar.bz2
rails-26d3e325cb85884504564b8af07dd083fc47d2a8.zip
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.
Diffstat (limited to 'activerecord/lib/active_record/associations/collection_proxy.rb')
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb198
1 files changed, 79 insertions, 119 deletions
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
# # #<Pet id: 2, name: "Spook">,
# # #<Pet id: 3, name: "Choo-Choo">
# # ]
+ 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
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
+ 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
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
+ 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 <tt>:dependent</tt>
# 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 <tt>:dependent</tt> option. Returns an array with the
@@ -586,13 +572,11 @@ module ActiveRecord
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
+ 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
# # => [#<Pet name: "Fancy-Fancy">]
+ 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
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
+ 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 <tt>SELECT COUNT(*)</tt> 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
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
+ 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 <tt>collection.size > 1</tt>.
#
@@ -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