diff options
author | Jon Leighton <j@jonathanleighton.com> | 2012-01-30 23:37:09 -0800 |
---|---|---|
committer | Jon Leighton <j@jonathanleighton.com> | 2012-01-30 23:37:09 -0800 |
commit | 49e69237c40a819d3f2404931d1b08c7defc974e (patch) | |
tree | 340ba6d8bbd86c6e8f2ca5ec86d4cc5fa32ae340 /activerecord | |
parent | c99eb232c2d85b18cca78f699895aff007e7aa85 (diff) | |
parent | b08bf9979232f40309a826947f8ff85d8ccbaa8a (diff) | |
download | rails-49e69237c40a819d3f2404931d1b08c7defc974e.tar.gz rails-49e69237c40a819d3f2404931d1b08c7defc974e.tar.bz2 rails-49e69237c40a819d3f2404931d1b08c7defc974e.zip |
Merge pull request #4732 from pwim/refactor-dynamic-match
Refactor dynamic match
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/dynamic_finder_match.rb | 82 | ||||
-rw-r--r-- | activerecord/lib/active_record/dynamic_matchers.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/dynamic_scope_match.rb | 4 |
3 files changed, 60 insertions, 28 deletions
diff --git a/activerecord/lib/active_record/dynamic_finder_match.rb b/activerecord/lib/active_record/dynamic_finder_match.rb index b309df9b1b..e266fbb2e9 100644 --- a/activerecord/lib/active_record/dynamic_finder_match.rb +++ b/activerecord/lib/active_record/dynamic_finder_match.rb @@ -6,33 +6,23 @@ module ActiveRecord # class DynamicFinderMatch def self.match(method) - finder = :first - bang = false - instantiator = nil - - case method.to_s - when /^find_(all_|last_)?by_([_a-zA-Z]\w*)$/ - finder = :last if $1 == 'last_' - finder = :all if $1 == 'all_' - names = $2 - when /^find_by_([_a-zA-Z]\w*)\!$/ - bang = true - names = $1 - when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/ - instantiator = $1 == 'initialize' ? :new : :create - names = $2 - else - return nil + method = method.to_s + klass = [FindBy, FindByBang, FindOrInitializeCreateBy].find do |klass| + klass.matches?(method) end + klass.new(method) if klass + end - new(finder, instantiator, bang, names.split('_and_')) + def self.matches?(method) + method =~ self::METHOD_PATTERN end - def initialize(finder, instantiator, bang, attribute_names) - @finder = finder - @instantiator = instantiator - @bang = bang - @attribute_names = attribute_names + def initialize(method) + @finder = :first + @instantiator = nil + match_data = method.match(self.class::METHOD_PATTERN) + @attribute_names = match_data[-1].split("_and_") + initialize_from_match_data(match_data) end attr_reader :finder, :attribute_names, :instantiator @@ -41,16 +31,54 @@ module ActiveRecord @finder && !@instantiator end + def creator? + @finder == :first && @instantiator == :create + end + def instantiator? - @finder == :first && @instantiator + @instantiator end - def creator? - @finder == :first && @instantiator == :create + def bang? + false + end + + def valid_arguments?(arguments) + arguments.size >= @attribute_names.size end + private + + def initialize_from_match_data(match_data) + end + end + + class FindBy < DynamicFinderMatch + METHOD_PATTERN = /^find_(all_|last_)?by_([_a-zA-Z]\w*)$/ + + def initialize_from_match_data(match_data) + @finder = :last if match_data[1] == 'last_' + @finder = :all if match_data[1] == 'all_' + end + end + + class FindByBang < DynamicFinderMatch + METHOD_PATTERN = /^find_by_([_a-zA-Z]\w*)\!$/ + def bang? - @bang + true + end + end + + class FindOrInitializeCreateBy < DynamicFinderMatch + METHOD_PATTERN = /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/ + + def initialize_from_match_data(match_data) + @instantiator = match_data[1] == 'initialize' ? :new : :create + end + + def valid_arguments?(arguments) + arguments.size == 1 && arguments.first.is_a?(Hash) || super end end end diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb index b6b8e24436..60ce3dd4f1 100644 --- a/activerecord/lib/active_record/dynamic_matchers.rb +++ b/activerecord/lib/active_record/dynamic_matchers.rb @@ -25,7 +25,7 @@ module ActiveRecord if match = (DynamicFinderMatch.match(method_id) || DynamicScopeMatch.match(method_id)) attribute_names = match.attribute_names super unless all_attributes_exists?(attribute_names) - if !(match.is_a?(DynamicFinderMatch) && match.instantiator? && arguments.first.is_a?(Hash)) && arguments.size < attribute_names.size + unless match.valid_arguments?(arguments) method_trace = "#{__FILE__}:#{__LINE__}:in `#{method_id}'" backtrace = [method_trace] + caller raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{attribute_names.size})", backtrace diff --git a/activerecord/lib/active_record/dynamic_scope_match.rb b/activerecord/lib/active_record/dynamic_scope_match.rb index c832e927d6..a502155aac 100644 --- a/activerecord/lib/active_record/dynamic_scope_match.rb +++ b/activerecord/lib/active_record/dynamic_scope_match.rb @@ -19,5 +19,9 @@ module ActiveRecord attr_reader :scope, :attribute_names alias :scope? :scope + + def valid_arguments?(arguments) + arguments.size >= @attribute_names.size + end end end |