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 aName
- Additional fields like the
Release Date
andDuration
should be only validated in thepending
,declined
andpublished
state -
declined
andpublished
movies should track aModerator 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:
- Using only Ruby/Rails and no state machine gems
- Using a gem like rails_state_machine Show archive.org snapshot
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.