Exploring the Magic Behind
Dynamic Finders Diving into
ActiveRecord::Base.method_missing
What are they?
address
last_name
first_name
id
people class Person < ActiveRecord::Base
end
What are they?
address
last_name
first_name
id
people class Person < ActiveRecord::Base
end
Person.find_by_first_name 'mike'
Person.find_by_first_name_and_last_name 'mike', 'bowler'
Dynamic finder
methods vs messages
Customer Object
first_name()
Message Method
Person
messages without methods
Customer Object
search()
method_missing()
Message
Method
Person
method_missing in rails
ActiveRecord::Base implements method_missing and dynamically adds support for the find_ methods
Inside ActiveRecord::Base
def method_missing(method_id, *arguments) if match =~ /^find_(all_by|by)_([_a-zA-Z]\w*)$/ # ... elsif match =~ /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/ # ... else super endend
find :all, :conditions => { :first_name => first_name, :last_name => last_name }
Person.find_all_by_first_name_and_last_name( ‘mike’, ‘bowler’)
def self.method_missing(method_id, *arguments) if method_id.to_s =~ /^find_all_by_([_a-zA-Z]\w*)$/ attribute_names = $1.split '_and_' conditions = {} attribute_names.each_with_index do |name, index| conditions[name.to_sym] = arguments[index] end find :all, :conditions => conditions else super endend
Can we make this faster?
Metaprogramming
Ruby’s metaprogramming allows us to dynamically create a new method
def self.method_missing(method_id, *arguments) if method_id.to_s =~ /^find_all_by_([_a-zA-Z]\w*)$/ attribute_names = $1.split('_and_') conditions = attribute_names.collect {|name| ":#{name} => #{name}"}. join(', ')
class_eval <<-END def self.#{method_id} #{attribute_names.join ','} find(:all, :conditions => {#{conditions}}) puts "in method" end END __send__(method_id, *arguments) else super endend
def self.find_all_by_first_name_and_last_name first_name,last_name find(:all, :conditions => {:first_name => first_name, :last_name => last_name})end
Shameless Plug
I can help you with your Ruby and/or Rails projects. Ask me how.
Mike [email protected] (company)www.SphericalImprovement.com (blog)