目的のメソッドのシグネチャを既に知っているので、 を使用する代わりにそれらを定義する方がよい場合がありますmethod_missing
。そのようにすることができます(クラス定義内):
[:bill_date, :registration_date, :some_other_date].each do |attr|
define_method("#{attr}_human") do
(send(attr) || Date.today).strftime('%b %d, %Y')
end
define_method("#{attr}_human=") do |date_string|
self.send "#{attr}=", Date.strptime(date_string, '%b %d, %Y')
end
end
すべての日付属性をリストすることが問題にならない場合は、内部の魔法の代わりに通常のメソッドを扱っているため、このアプローチの方が優れていますmethod_missing
。
で終わる名前を持つすべての属性にそれを適用したい場合は、_date
そのようにそれらを取得できます(クラス定義内):
column_names.grep(/_date$/)
そして、ここにmethod_missing
解決策があります(前のものもテストされていませんが、テストされていません):
def method_missing(method_name, *args, &block)
# delegate to superclass if you're not handling that method_name
return super unless /^(.*)_date(=?)/ =~ method_name
# after match we have attribute name in $1 captured group and '' or '=' in $2
if $2.blank?
(send($1) || Date.today).strftime('%b %d, %Y')
else
self.send "#{$1}=", Date.strptime(args[0], '%b %d, %Y')
end
end
さらに、メソッドをオーバーライドし、内部で処理するメソッド名respond_to?
を返すと便利です(1.9 では代わりにオーバーライドする必要があります)。true
method_missing
respond_to_missing?