Using a Method Missing in Rails

I have a model with several date attributes. I would like to be able to set and get values ​​as strings. I overloaded one of the methods (bill_date) as follows:

  def bill_date_human
    date = self.bill_date || Date.today
    date.strftime('%b %d, %Y')
  end
  def bill_date_human=(date_string)
    self.bill_date = Date.strptime(date_string, '%b %d, %Y')
  end

This works fine for my needs, but I want to do the same for several other date attributes ... how can I use the missing method so that any date attribute can be set / received like this?

+5
source share
2 answers

As you already know the signatures of the desired methods, it would be better to define them instead of using them method_missing. You can do it like this (inside the class definition):

[: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?).

+10

ActiveModel AttributeMethods ( ), ( ) .

class MyModel < ActiveRecord::Base

  attribute_method_suffix '_human'

  def attribute_human(attr_name)
    date = self.send(attr_name) || Date.today
    date.strftime('%b %d, %Y')
  end
end

, my_instance.bill_date_human attribute_human attr_name, 'bill_date'. ActiveModel , method_missing, respond_to. , .

+5

All Articles