Поскольку вы уже знаете сигнатуру желаемых методов, может быть лучше определить их вместо использования 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?
).