Merge pull request #4732 from pwim/refactor-dynamic-match
Refactor dynamic match
This commit is contained in:
commit
49e69237c4
@ -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
|
||||
|
||||
new(finder, instantiator, bang, names.split('_and_'))
|
||||
klass.new(method) if klass
|
||||
end
|
||||
|
||||
def initialize(finder, instantiator, bang, attribute_names)
|
||||
@finder = finder
|
||||
@instantiator = instantiator
|
||||
@bang = bang
|
||||
@attribute_names = attribute_names
|
||||
def self.matches?(method)
|
||||
method =~ self::METHOD_PATTERN
|
||||
end
|
||||
|
||||
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 @@ def finder?
|
||||
@finder && !@instantiator
|
||||
end
|
||||
|
||||
def instantiator?
|
||||
@finder == :first && @instantiator
|
||||
end
|
||||
|
||||
def creator?
|
||||
@finder == :first && @instantiator == :create
|
||||
end
|
||||
|
||||
def instantiator?
|
||||
@instantiator
|
||||
end
|
||||
|
||||
def bang?
|
||||
@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?
|
||||
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
|
||||
|
@ -25,7 +25,7 @@ def method_missing(method_id, *arguments, &block)
|
||||
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
|
||||
|
@ -19,5 +19,9 @@ def initialize(scope, attribute_names)
|
||||
|
||||
attr_reader :scope, :attribute_names
|
||||
alias :scope? :scope
|
||||
|
||||
def valid_arguments?(arguments)
|
||||
arguments.size >= @attribute_names.size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user