320 State machines [3d]

Updated . Posted . Visible to the public.

Your MovieDB gained traction and is now a popular tool among cineasts. This comes with a downside: You noticed a degrading content quality, which only can be contained by introducing a new moderation process. While everyone can keep adding new movies, they should at first be drafts that require a mandatory review by an administrator before publication.

Requirements

Movies in MovieDB should have one of the following workflow states:

  • draft
  • pending
  • published
  • declined

A movie always begins as a draft and then transitions through the states as it's getting reviewed. This could be a typical state flow for a movie:

stateDiagram-v2
    [*] --> draft
    draft --> pending
    pending --> declined: Reason
    declined --> pending
    pending --> published

Changes to the authorization

Change the visibility rules (Consul powers) so:

  • All users can see published movies of other users.
  • All users can see the movies they created themselves, regardless of their state.
  • An admin can see movies from other users that are published, pending or declined.

Changes to the UI

We will now add some additional controls to transition a movie between states:

  • When a user views one of her draft or declined movies, she sees a button Submit for Review on the movie's show view. This changes the movie's state to pending.
  • When an admin opens a pending movie by any user, she sees two buttons Publish and Decline.
  • Before the admin may decline a movie, she is required to enter a declining reason. The declining reason should be entered in a form like the other forms in your app, with the same form round trip and controller handling. Consider whether you want to implement this inside an existing :movies resource or in a new one just for the declining form.
  • In addition, when an admin edits a movie by any user, she can choose any state from a select box, regardless of the movie's current state. Note that any transition constraints and callbacks will not be enforced when the #state is set directly. We only do this to allow admins to correct user errors.

Changes to the validity of movies

States of a given state machine are frequently used as conditions for our model validations. Your movies' validation logic should also be adjusted:

  • Movies in the draft state should already be valid if they only have a Name
  • Additional fields like the Release Date and Duration should be only validated in the pending, declined and published state
  • declined and published movies should track a Moderator ID (the ID of the admin that reviewed the movie), which must also be validated in these states

Implementation

Make two implementations of the requirements above:

Make sure that you have tests for all the changes you make. Note that your E2E-Tests should rather focus on the effects of the required moderation process than on details of your technical implementation.

Tip

factory_bot offers traits Show archive.org snapshot to define variants of a factory. Your default factory should create records in a state that is useful for the vast majority of tests.

Tip

We often use state machines to track the state of "wizard forms", i.e. long forms that are broken down to multiple smaller screens.

Henning Koch
Last edit
Michael Leimstädtner
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra Curriculum (2015-09-08 17:25)