1

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?

2 Answers 2

5

...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
Sign up to request clarification or add additional context in comments.

Comments

1

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>

2 Comments

I've actually got > 20 states, broken into catagories, so the metaprogramming approach works. Thanks for the answer.
Ah, yes. I missed "numerous". Another advantage of metaprogramming generally is that it often allows you to structure your code so that you can add, delete, modify or rename elements within modules without affecting the code elsewhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.