Blog #6
Let's imagine a situation - You need create multiple methods with similar purposes (same name and same logic) but doing so will have repetitions, so it will not be optimal, making the code file become more versbose.
def create_order_cod
order = Order.not_draft.where(payment_method: :cod).last
OrderMailer.create_order_email(order.id)
end
def create_order_transfer
order = Order.not_draft.where(payment_method: :transfer).last
OrderMailer.create_order_email(order.id)
end
def create_order_paypal
order = Order.not_draft.where(payment_method: :paypal).last
OrderMailer.create_order_email(order.id)
endI had this problem when trying to create email preview methods like above.
Before we start to deal with this, let's state our wish first, which is to create a loop that generates methods by the names we give them.
Ruby on Rails supports a method that can help us do just that, it's called define_method.
Just to be clear, we can do this:
define_method(:my_method) do |foo, bar| # or even |*args|
# do something
endThis means same as:
def my_method(foo, bar)
# do something
endIf you want to define method parameters that have default values, you need to get a bit more creative and do something like this:
define_method(:my_method) do |foo, bar|
bar ||= {}
# do something
endSo with my case, I edited as follows:
Order.payment_methods.each_key do |payment_method|
define_method("create_order_#{payment_method}") do
order = Order.not_draft.where(payment_method: payment_method).last
OrderMailer.create_order_email(order.id)
end
endAlthough define_method helps us to solve the long-winded problem, it also comes with the disadvantage that when maintaining the code, it is difficult to find the methods that are generated by this method.
Use it carefully or it will become your own obsession :D