I learned something new about Module.include the other day. Consider the following:
module Turkey
def tastes_like?
"turkey"
end
end
module Duck
def tastes_like?
"duck"
end
end
module Chicken
def tastes_like?
"chicken"
end
end
class Turducken
include Turkey
include Duck
include Chicken
end
t = Turducken.new
p "This thing tastes like #{t.tastes_like?}"
#=> This thing tastes like chicken
It outputs chicken as I would expect since it was the last one included, but it also does one more thing that I didn’t expect. It sets up a method inheritance chain for duplicate methods so you have access to the method you have overridden. So if we call super in our example:
module Turkey
def tastes_like?
"turkey"
end
end
module Duck
def tastes_like?
super + "duck"
end
end
module Chicken
def tastes_like?
super + "chicken"
end
end
class Turducken
include Turkey
include Duck
include Chicken
end
t = Turducken.new
p "This thing tastes like #{t.tastes_like?}"
#=> This thing tastes like turkeyduckchicken
You get a proper turducken. Of course there are some order dependencies in my contrived example, but you get the point.
One real world example that I used this for was rails tag helpers. I wanted to wrap each text input in a div (take your snarky semantic markup comments somewhere else). So I just defined a text_field method in my helper and then wrapped the output of the super call.
module SomeHelper
def text_field(object_name, method, options = {})
content_tag(:div, super(object_name, method, options), :class => "input")
end
end