Enables dynamic finders like User.find_by_user_name(user_name) and
<tt>User.scoped_by_user_name(user_name). Refer
to Dynamic attribute-based finders section at the top of this file for more
detailed information.
It’s even possible to use all the additional parameters to find.
For example, the full interface for find_all_by_amount is actually
find_all_by_amount(amount, options).
Each dynamic finder using scoped_by_* is also defined in the class
after it is first invoked, so that future attempts to use it do not run
through method_missing.
# File activerecord/lib/active_record/dynamic_matchers.rb, line 24
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
method_trace = "#{__FILE__}:#{__LINE__}:in `#{method_id}'"
backtrace = [method_trace] + caller
raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{attribute_names.size})", backtrace
end
if match.respond_to?(:scope?) && match.scope?
self.class_eval def self.#{method_id}(*args) # def self.scoped_by_user_name_and_password(*args) attributes = Hash[[:#{attribute_names.join(',:')}].zip(args)] # attributes = Hash[[:user_name, :password].zip(args)] # scoped(:conditions => attributes) # scoped(:conditions => attributes) end # end, __FILE__, __LINE__ + 1
send(method_id, *arguments)
elsif match.finder?
options = if arguments.length > attribute_names.size
arguments.extract_options!
else
{}
end
relation = options.any? ? scoped(options) : scoped
relation.send :find_by_attributes, match, attribute_names, *arguments, &block
elsif match.instantiator?
scoped.send :find_or_instantiator_by_attributes, match, attribute_names, *arguments, &block
end
else
super
end
end