exploring the magic behind dynamic finders: diving into activerecord::base.method_missing

12
Exploring the Magic Behind Dynamic Finders Diving into ActiveRecord::Base.method_missing

Post on 13-Sep-2014

3.541 views

Category:

Technology


0 download

DESCRIPTION

An exploration of how dynamic finders work in ActiveRecord.

TRANSCRIPT

Page 1: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

Exploring the Magic Behind

Dynamic Finders Diving into

ActiveRecord::Base.method_missing

Page 2: 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

Page 3: 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

Person.find_by_first_name 'mike'

Person.find_by_first_name_and_last_name 'mike', 'bowler'

Dynamic finder

Page 4: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

methods vs messages

Customer Object

first_name()

Message Method

Person

Page 5: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

messages without methods

Customer Object

search()

method_missing()

Message

Method

Person

Page 6: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

method_missing in rails

ActiveRecord::Base implements method_missing and dynamically adds support for the find_ methods

Page 7: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

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

Page 8: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

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

Page 9: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

Can we make this faster?

Page 10: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

Metaprogramming

Ruby’s metaprogramming allows us to dynamically create a new method

Page 11: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

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

Page 12: Exploring the magic behind dynamic finders: diving into ActiveRecord::Base.method_missing

Shameless Plug

I can help you with your Ruby and/or Rails projects. Ask me how.

Mike [email protected] (company)www.SphericalImprovement.com (blog)