Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>A little late to the party here, but I was researching this exact issue for myself and found that the gem I'm currently using to manage my state machines (<a href="https://github.com/pluginaweek/state_machine/">state_machine by pluginaweek</a>) has some methods that deal with this issue quite nicely.</p> <p>When used with ActiveRecord (and I'm assuming other persistence layers as well), it provides a <code>#state_event=</code> method that accepts a string representation of the event you would like to fire. See documentation <a href="https://github.com/pluginaweek/state_machine/blob/master/lib/state_machine/integrations/active_record.rb#L50">here</a>.</p> <pre><code># For example, vehicle = Vehicle.create # =&gt; #&lt;Vehicle id: 1, name: nil, state: "parked"&gt; vehicle.state_event # =&gt; nil vehicle.state_event = 'invalid' vehicle.valid? # =&gt; false vehicle.errors.full_messages # =&gt; ["State event is invalid"] vehicle.state_event = 'ignite' vehicle.valid? # =&gt; true vehicle.save # =&gt; true vehicle.state # =&gt; "idling" vehicle.state_event # =&gt; nil # Note that this can also be done on a mass-assignment basis: vehicle = Vehicle.create(:state_event =&gt; 'ignite') # =&gt; #&lt;Vehicle id: 1, name: nil, state: "idling"&gt; vehicle.state # =&gt; "idling" </code></pre> <p>This allows you to simply add a <code>state_event</code> field in your resource's edit forms and get state transitions as easily as updating any other attribute.</p> <p>Now we're obviously still using PUT to trigger events using this method, which isn't RESTful. The gem does, however, provide <a href="https://github.com/pluginaweek/state_machine/tree/master/examples/rails-rest">an interesting example</a> that at least "feels" quite RESTful, despite it using the same non-RESTful method under the covers. </p> <p>As you can see <a href="https://github.com/pluginaweek/state_machine/blob/master/examples/rails-rest/view__form.html.erb#L22">here</a> and <a href="https://github.com/pluginaweek/state_machine/blob/master/examples/rails-rest/view__form.html.erb#L27">here</a>, the gem's introspection capabilities allow you to present in your forms either the event you would like to fire <strong>or</strong> the name of that event's resulting state. </p> <pre><code>&lt;div class="field"&gt; &lt;%= f.label :state %&gt;&lt;br /&gt; &lt;%= f.collection_select :state_event, @user.state_transitions, :event, :human_to_name, :include_blank =&gt; @user.human_state_name %&gt; &lt;/div&gt; &lt;div class="field"&gt; &lt;%= f.label :access_state %&gt;&lt;br /&gt; &lt;%= f.collection_select :access_state_event, @user.access_state_transitions, :event, :human_event, :include_blank =&gt; "don't change" %&gt; &lt;/div&gt; </code></pre> <p>Using the latter technique, you get simple form-based updating of the model's state to any valid next state without having to write any extra code. It's not technically RESTful, but it allows you to easily present it that way in the UI. </p> <p>The cleanliness of this technique combined with the inherent conflicts in trying to cast an event-based state machine into a simple RESTful resource was enough to satisfy me, so hopefully it provides some insight to you as well. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload