Permalink
Browse files

extract code from AR::Base

  • Loading branch information...
1 parent 0c76a52 commit 75a22814ef331ebeb35ee827699fc4177984921f @jonleighton jonleighton committed May 2, 2012
@@ -79,7 +79,7 @@ def respond_to?(name, include_private = false)
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
@@ -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,21 +17,20 @@ def respond_to?(name, include_private = false)
# 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
end
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 @@ def self.suffix
''
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 @@ def instantiator
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]
@@ -442,11 +442,11 @@ def test_eager_default_scope_relations_are_deprecated
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

0 comments on commit 75a2281

Please sign in to comment.