class ActiveRecord::DynamicMatchers::Method

def attributes_hash

same parameter name.
Given that the parameters starts with `_`, the finder needs to use the
def attributes_hash
  "{" + attribute_names.map { |name| ":#{name} => _#{name}" }.join(",") + "}"
end

def body

def body
  "#{finder}(#{attributes_hash})"
end

def define

def define
  model.class_eval <<-CODE, __FILE__, __LINE__ + 1
    def self.#{name}(#{signature})
      #{body}
    end
  CODE
end

def finder

def finder
  raise NotImplementedError
end

def initialize(model, method_name)

def initialize(model, method_name)
  @model           = model
  @name            = method_name.to_s
  @attribute_names = @name.match(self.class.pattern)[1].split("_and_")
  @attribute_names.map! { |name| @model.attribute_aliases[name] || name }
end

def match(model, name)

def match(model, name)
  klass = matchers.find { |k| k.pattern.match?(name) }
  klass.new(model, name) if klass
end

def pattern

def pattern
  @pattern ||= /\A#{prefix}_([_a-zA-Z]\w*)#{suffix}\Z/
end

def prefix

def prefix
  raise NotImplementedError
end

def signature

to prevent errors, we start each param name with `_`.
The parameters in the signature may have reserved Ruby words, in order
def signature
  attribute_names.map { |name| "_#{name}" }.join(", ")
end

def suffix

def suffix
  ""
end

def valid?

def valid?
  attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) }
end