# File lib/active_record/dynamic_matchers.rb, line 3 3: def respond_to?(method_id, include_private = false) 4: if match = DynamicFinderMatch.match(method_id) 5: return true if all_attributes_exists?(match.attribute_names) 6: elsif match = DynamicScopeMatch.match(method_id) 7: return true if all_attributes_exists?(match.attribute_names) 8: end 9: 10: super 11: end
# File lib/active_record/dynamic_matchers.rb, line 72 72: def aggregate_mapping(reflection) 73: mapping = reflection.options[:mapping] || [reflection.name, reflection.name] 74: mapping.first.is_a?(Array) ? mapping : [mapping] 75: end
# File lib/active_record/dynamic_matchers.rb, line 67 67: def all_attributes_exists?(attribute_names) 68: (expand_attribute_names_for_aggregates(attribute_names) - 69: column_methods_hash.keys).empty? 70: end
Similar in purpose to expand_hash_conditions_for_aggregates.
# File lib/active_record/dynamic_matchers.rb, line 55 55: def expand_attribute_names_for_aggregates(attribute_names) 56: attribute_names.map { |attribute_name| 57: unless (aggregation = reflect_on_aggregation(attribute_name.to_sym)).nil? 58: aggregate_mapping(aggregation).map do |field_attr, _| 59: field_attr.to_sym 60: end 61: else 62: attribute_name.to_sym 63: end 64: }.flatten 65: end
Enables dynamic finders like User.find_by_user_name(user_name) and 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 lib/active_record/dynamic_matchers.rb, line 24 24: def method_missing(method_id, *arguments, &block) 25: if match = (DynamicFinderMatch.match(method_id) || DynamicScopeMatch.match(method_id)) 26: attribute_names = match.attribute_names 27: super unless all_attributes_exists?(attribute_names) 28: if !(match.is_a?(DynamicFinderMatch) && match.instantiator? && arguments.first.is_a?(Hash)) && arguments.size < attribute_names.size 29: method_trace = "#{__FILE__}:#{__LINE__}:in `#{method_id}'" 30: backtrace = [method_trace] + caller 31: raise ArgumentError, "wrong number of arguments (#{arguments.size} for #{attribute_names.size})", backtrace 32: end 33: if match.respond_to?(:scope?) && match.scope? 34: 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 35: send(method_id, *arguments) 36: elsif match.finder? 37: options = arguments.extract_options! 38: relation = options.any? ? scoped(options) : scoped 39: relation.send :find_by_attributes, match, attribute_names, *arguments, &block 40: elsif match.instantiator? 41: scoped.send :find_or_instantiator_by_attributes, match, attribute_names, *arguments, &block 42: end 43: else 44: super 45: end 46: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.