Metaprogramming Techniques | 35
module ActiveMerchant
module Billing
module Integrations
module ActionViewHelper
def payment_service_for(order, account, options = {}, &proc)
...
end
end
end
end
end
Then, in the plugin’sinit.rb script, the module is included inActionView::Base:
require 'active_merchant/billing/integrations/action_view_helper'
ActionView::Base.send(:include,
ActiveMerchant::Billing::Integrations::ActionViewHelper)
It certainly would be simpler in code to directly openActionView::Baseand add the
method, but this has the advantage of modularity. All Active Merchant code is con-
tained within theActiveMerchant module.
There is one caveat to this approach. Because any included modules are searched for
methods after the class’s own methods are searched, you cannot directly overwrite a
class’s methods by including a module:
module M
def test_method
"Test from M"
end
end
class C
def test_method
"Test from C"
end
end
C.send(:include, M)
C.new.test_method # => "Test from C"
Instead, you should create a new name in the module and usealias_method_chain:
module M
def test_method_with_module
"Test from M"
end
end
class C
def test_method
"Test from C"
end
end