I have gotten very tired of writing the same code over and over. And apparently I was so tired I forgot to publish this last year.
def foo_bar
my_member ? my_member.foo_bar : nil
end
The rails delegate method allows you to delegate a method to another class. Neat! There are two tweaks that I made to suite my salty tastes.
1. Nil freaks out. Sure you can write something like
:to => (my_member or return nil) as pointed out on the rails ticket. But that is sort of groddy. boo!
2. I want to rename the destination method sometimes. Avoid collisions, make new friends. Win-Win.
Here is delegate_x. Delegate extra! You can list out the delegated methods or, to rename them, put them in a hash of destination_method_name => target_method_name
class WebTwoPointOMGCorp
attr_accessor :giraffe
delegate_x :hovercraft, :to => :giraffe
delegate_x :to => :giraffe, :giraffe_spots => :num_spots
end
The first is equivalent to:
def hover_craft
giraffe ? giraffe.hover_craft : nil
end
and the second
def giraffe_spots
giraffe.num_spots if giraffe
end
With ActiveRecord :has_one and :belongs_to associations, check out Stefan Kaes’s piggyback plugin to piggy back attributes (define methods) to queried records.
Sweet. A little (terribly formatted) code below. Jam it in the lib or something. Make it a plugin. Just remember, the hovercraft owned by the giraffe is really the hovercraft owned by WebTwoPointOMGCorp.
(Actually I just wrote this whole post to show Joel’s awesome new spongecell giraffe that breathes fire! We love giraffes and so should you.)
class Module
# like delegate only better
def delegate_x(*methods)
options = methods.pop
unless options.is_a?(Hash) && to = options.delete(:to)
raise ArgumentError, "Delegation needs a target. Supply an
options hash with a :to key"
end
methods.concat(options.keys)
unless methods.any?
raise ArgumentError, "No delegated methods specified. Specify :method => :target_method or list methods"
end
methods.each do |method|
target_method = options[method]||method
module_eval(<<-EOS, "(__DELEGATIONX__)", 1)
def #{ method }(*args, &block)
#{to}.__send__(#{target_method.inspect},*args, &block) if #{to}
end
EOS
end
end
end