aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2012-05-03 00:38:30 +0100
committerJon Leighton <j@jonathanleighton.com>2012-05-04 12:50:07 +0100
commit75a22814ef331ebeb35ee827699fc4177984921f (patch)
tree199230c62ed0ccb81078199d8fa0684792db06bb /activerecord
parent0c76a52c472546083a199f685f96170031b36fdd (diff)
downloadrails-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.rb2
-rw-r--r--activerecord/lib/active_record/dynamic_matchers.rb60
-rw-r--r--activerecord/test/cases/named_scope_test.rb4
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