diff options
author | Jon Leighton <j@jonathanleighton.com> | 2012-05-03 00:38:30 +0100 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2012-05-04 12:50:07 +0100 |
commit | 75a22814ef331ebeb35ee827699fc4177984921f (patch) | |
tree | 199230c62ed0ccb81078199d8fa0684792db06bb /activerecord | |
parent | 0c76a52c472546083a199f685f96170031b36fdd (diff) | |
download | rails-75a22814ef331ebeb35ee827699fc4177984921f.tar.gz rails-75a22814ef331ebeb35ee827699fc4177984921f.tar.bz2 rails-75a22814ef331ebeb35ee827699fc4177984921f.zip |
extract code from AR::Base
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/associations/collection_proxy.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/dynamic_matchers.rb | 60 | ||||
-rw-r--r-- | activerecord/test/cases/named_scope_test.rb | 4 |
3 files changed, 31 insertions, 35 deletions
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 8bbab75de6..261a829281 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -79,7 +79,7 @@ module ActiveRecord end def method_missing(method, *args, &block) - match = DynamicMatchers::Method.match(method) + match = DynamicMatchers::Method.match(self, method) if match && match.is_a?(DynamicMatchers::Instantiator) scoped.send(method, *args) do |r| proxy_association.send :set_owner_attributes, r diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb index 01efaee8fc..f3f143940f 100644 --- a/activerecord/lib/active_record/dynamic_matchers.rb +++ b/activerecord/lib/active_record/dynamic_matchers.rb @@ -1,10 +1,8 @@ module ActiveRecord module DynamicMatchers def respond_to?(name, include_private = false) - match = Method.match(name) - valid_match = match && all_attributes_exists?(match.attribute_names) - - valid_match || super + match = Method.match(self, name) + match && match.valid? || super end private @@ -19,11 +17,10 @@ module ActiveRecord # Each dynamic finder using <tt>scoped_by_*</tt> is also defined in the class after it # is first invoked, so that future attempts to use it do not run through method_missing. def method_missing(name, *arguments, &block) - if match = Method.match(name) - attribute_names = match.attribute_names - super unless all_attributes_exists?(attribute_names) + match = Method.match(self, name) - match.define(self) + if match && match.valid? + match.define send(name, *arguments, &block) else super @@ -31,9 +28,9 @@ module ActiveRecord end class Method - def self.match(name) + def self.match(model, name) klass = klasses.find { |k| name =~ k.pattern } - klass.new(name) if klass + klass.new(model, name) if klass end def self.klasses @@ -55,15 +52,32 @@ module ActiveRecord '' end - attr_reader :name, :attribute_names + attr_reader :model, :name, :attribute_names - def initialize(name) + def initialize(model, name) + @model = model @name = name.to_s @attribute_names = @name.match(self.class.pattern)[1].split('_and_') end - def define(klass) - klass.class_eval <<-CODE, __FILE__, __LINE__ + 1 + def expand_attribute_names_for_aggregates + attribute_names.map do |attribute_name| + if aggregation = model.reflect_on_aggregation(attribute_name.to_sym) + model.send(:aggregate_mapping, aggregation).map do |field_attr, _| + field_attr.to_sym + end + else + attribute_name.to_sym + end + end.flatten + end + + def valid? + (expand_attribute_names_for_aggregates - model.column_methods_hash.keys).empty? + end + + def define + model.class_eval <<-CODE, __FILE__, __LINE__ + 1 def self.#{name}(#{signature}) #{body} end @@ -227,24 +241,6 @@ module ActiveRecord end end - # Similar in purpose to +expand_hash_conditions_for_aggregates+. - def expand_attribute_names_for_aggregates(attribute_names) - attribute_names.map do |attribute_name| - if aggregation = reflect_on_aggregation(attribute_name.to_sym) - aggregate_mapping(aggregation).map do |field_attr, _| - field_attr.to_sym - end - else - attribute_name.to_sym - end - end.flatten - end - - def all_attributes_exists?(attribute_names) - (expand_attribute_names_for_aggregates(attribute_names) - - column_methods_hash.keys).empty? - end - def aggregate_mapping(reflection) mapping = reflection.options[:mapping] || [reflection.name, reflection.name] mapping.first.is_a?(Array) ? mapping : [mapping] diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 479b375360..393e578219 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -442,11 +442,11 @@ end class DynamicScopeMatchTest < ActiveRecord::TestCase def test_scoped_by_no_match - assert_nil ActiveRecord::DynamicMatchers::ScopedBy.match("not_scoped_at_all") + assert_nil ActiveRecord::DynamicMatchers::ScopedBy.match(nil, "not_scoped_at_all") end def test_scoped_by - match = ActiveRecord::DynamicMatchers::ScopedBy.match("scoped_by_age_and_sex_and_location") + match = ActiveRecord::DynamicMatchers::ScopedBy.match(nil, "scoped_by_age_and_sex_and_location") assert_not_nil match assert_equal %w(age sex location), match.attribute_names end |