0

I am using state_machine with rails to handle state on some active record models and testing them with rspec and factory girl. I also have a serialized array property called state_path that keeps track of the state history.

class Project < ActiveRecord::Base
  serialize :state_path, Array

  def initialize(*)
    super
    state_path << state_name
  end

  state_machine :state, :initial => :draft do
    after_transition do |project, transition|
      project.state_path << transition.to_name
    end

    event :do_work do
      transition :draft => :complete, :if => :tps_has_cover_page?
    end

    state :draft do
      # ...
    end

    state :complete do
      # ...
    end
  end

  private
    def tps_has_cover_page?
      # ...
    end
end

Now, to test that the after_transition hook is properly populating the state_path property, I stub out the tps_has_cover_page? transition condition method, because I don't care about that functionality in this test, and also it is integrated with other models (tps report model perhaps?)

it "should store the state path" do
  allow_any_instance_of(Project).to receive(:tps_has_cover_page?).and_return(true)

  project = create(:project)
  project.do_work

  expect(project.state_path).to eq([:draft, :complete])
end

However, the transition condition method name could change, or more conditions could be added, which I'm not really concerned with in this test (obviously, since I'm stubbing it).

Question: is there a way to dynamically collect all of the transition condition methods on a state machine? To then be able to build a macro that stubs out all of the condition methods?

ianstarz
  • 417
  • 4
  • 12

1 Answers1

1

Try:

transition_conditions = state_machine.events.map(&:branches).flatten.flat_map(&:if_condition)
ianstarz
  • 417
  • 4
  • 12
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
  • I have to flatten the branches before I can do the final flat map because the branches themselves are wrapped in arrays. `Project.state_machine.events.map(&:branches).flatten.flat_map(&:if_condition)` otherwise works great! Thanks for the answer, can you confirm the flatten? I'll accept answer if so. – ianstarz Mar 02 '14 at 02:58
  • running state_machine 1.2.0 btw – ianstarz Mar 02 '14 at 02:59
  • also for others referencing this there are also `:unless_conditions` inside the branches if you need those too – ianstarz Mar 02 '14 at 03:00