port5432
port5432

Reputation: 6403

Metaprogramming Ruby convenience methods

In my program I am using a state machine, and have numerous convenience methods. I am currently creating a long list of "?" methods in the model.

def purchase_ready?
    self.current_state == 'purchase_ready'
end

def completed?
    self.current_state == 'completed'
end

def region_prepared?
   self.current_state == 'region_prepared'
end

What's the metaprogramming way to do this?

Upvotes: 1

Views: 126

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110755

The lazy way is to use BasicObject#method_missing:

class State
  def initialize state
    @state = state
  end

  def method_missing name, *args
    case name
    when :purchase_ready, :completed, :region_prepared
      @state == name
    else
      super
    end
  end
end

state = State.new(:purchase_ready)
state.purchase_ready
  #=> true 
state.completed
  #=> false
state.region_prepared
  #=> false
state.purchase_not_ready
  #-> NoMethodError: undefined method `purchase_not_ready' for
  #   #<State:0x007f9dfb9674b8 @state=:purchase_ready>

Upvotes: 1

port5432
port5432

Reputation: 6403

...and here's an answer!

Thanks to this blog: http://rohitrox.github.io/2013/07/02/ruby-dynamic-methods/

[:purchase_ready, :completed, :region_prepared].each do |method|
   define_method "#{method}?" do
      self.current_state == "#{method}"
   end
end

Upvotes: 5

Related Questions