正如您已经知道所需方法的签名,最好定义它们而不是使用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?
方法并返回true
方法名称也很好,您可以在内部处理method_missing
(在 1.9 中您应该重写respond_to_missing?
)。