diff options
author | Jon Leighton <j@jonathanleighton.com> | 2011-01-02 20:33:18 +0000 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2011-01-03 16:24:31 -0800 |
commit | 3103296a61709e808aa89c3d37cf22bcdbc5a675 (patch) | |
tree | 2f8b031165014329b4c77a785c17f06c056bf850 /activerecord/lib/active_record/associations/association_collection.rb | |
parent | d6289aadce1b8fa93e799500e52f92ce8d159d6f (diff) | |
download | rails-3103296a61709e808aa89c3d37cf22bcdbc5a675.tar.gz rails-3103296a61709e808aa89c3d37cf22bcdbc5a675.tar.bz2 rails-3103296a61709e808aa89c3d37cf22bcdbc5a675.zip |
Let AssociationCollection#find use #scoped to do its finding. Note that I am removing test_polymorphic_has_many_going_through_join_model_with_disabled_include, since this specifies different behaviour for an association than for a regular scope. It seems reasonable to expect scopes and association proxies to behave in roughly the same way rather than having subtle differences.
Diffstat (limited to 'activerecord/lib/active_record/associations/association_collection.rb')
-rw-r--r-- | activerecord/lib/active_record/associations/association_collection.rb | 81 |
1 files changed, 42 insertions, 39 deletions
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index be5d264a8f..8b0017e7bf 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -32,37 +32,10 @@ module ActiveRecord end def find(*args) - options = args.extract_options! - - # If using a custom finder_sql, scan the entire collection. if @reflection.options[:finder_sql] - expects_array = args.first.kind_of?(Array) - ids = args.flatten.compact.uniq.map { |arg| arg.to_i } - - if ids.size == 1 - id = ids.first - record = load_target.detect { |r| id == r.id } - expects_array ? [ record ] : record - else - load_target.select { |r| ids.include?(r.id) } - end + find_by_scan(*args) else - merge_options_from_reflection!(options) - construct_find_options!(options) - - with_scope(:find => @scope[:find].slice(:conditions, :order)) do - relation = @reflection.klass.send(:construct_finder_arel, options, @reflection.klass.send(:current_scoped_methods)) - - case args.first - when :first, :last - relation.send(args.first) - when :all - records = relation.all - @reflection.options[:uniq] ? uniq(records) : records - else - relation.find(*args) - end - end + find_by_sql(*args) end end @@ -360,7 +333,25 @@ module ActiveRecord end protected - def construct_find_options!(options) + + def construct_find_scope + { + :conditions => construct_conditions, + :select => construct_select, + :readonly => @reflection.options[:readonly], + :order => @reflection.options[:order], + :limit => @reflection.options[:limit], + :include => @reflection.options[:include], + :joins => @reflection.options[:joins], + :group => @reflection.options[:group], + :having => @reflection.options[:having], + :offset => @reflection.options[:offset] + } + end + + def construct_select + @reflection.options[:select] || + @reflection.options[:uniq] && "DISTINCT #{@reflection.quoted_table_name}.*" end def load_target @@ -394,7 +385,7 @@ module ActiveRecord target end - def method_missing(method, *args) + def method_missing(method, *args, &block) match = DynamicFinderMatch.match(method) if match && match.creator? attributes = match.attribute_names @@ -406,15 +397,9 @@ module ActiveRecord elsif @reflection.klass.scopes[method] @_scopes_cache ||= {} @_scopes_cache[method] ||= {} - @_scopes_cache[method][args] ||= with_scope(@scope) { @reflection.klass.send(method, *args) } + @_scopes_cache[method][args] ||= scoped.readonly(nil).send(method, *args) else - with_scope(@scope) do - if block_given? - @reflection.klass.send(method, *args) { |*block_args| yield(*block_args) } - else - @reflection.klass.send(method, *args) - end - end + scoped.readonly(nil).send(method, *args, &block) end end @@ -547,6 +532,24 @@ module ActiveRecord @target.include?(record) end end + + # If using a custom finder_sql, #find scans the entire collection. + def find_by_scan(*args) + expects_array = args.first.kind_of?(Array) + ids = args.flatten.compact.uniq.map { |arg| arg.to_i } + + if ids.size == 1 + id = ids.first + record = load_target.detect { |r| id == r.id } + expects_array ? [ record ] : record + else + load_target.select { |r| ids.include?(r.id) } + end + end + + def find_by_sql(*args) + scoped.find(*args) + end end end end |