The document discusses different approaches to implementing wizards in Rails applications. It describes various wizard implementation strategies, including having separate controllers and models per step, accumulating step data in the session or hidden parameters, using a state machine pattern in the model, and leveraging wizard gems. It then proposes an "ultra light & maintainable" approach of using a single controller and model with "step submodels" to represent each step and ensure validations are only applied for the relevant step. The document aims to implement wizards in a RESTful and object-oriented way while meeting goals of productivity, maintainability and performance.
13. 1001 Wizard
Implementations
1. One Controller/ActiveRecord Per Wizard Step
•
Create a REST resource per wizard step
•
•
•
Multiple ActiveRecords with distinct
validations
Multiple Controllers
Multiple sets of Views and Helpers
•
Bind every wizard step form to corresponding
ActiveRecord
•
Have each wizard step controller redirect to
the next one on create or update
14. 1001 Wizard
Implementations
1. One Controller/ActiveRecord Per Wizard Step
Step 1
ActiveRecord
Step 1
Controller
Step 2
ActiveRecord
Create &
Redirect to New
Step 2
Controller
Create &
Redirect to New
Step 3
ActiveRecord
Step 3
Controller
Step 4
ActiveRecord
Create &
Redirect to New
Step 4
Controller
16. 1001 Wizard
Implementations
1. One Controller/ActiveRecord Per Wizard Step
Cons
Redundant code across controllers
Repetitive redirect logic
Redundant authentication logic
Similar model loading logic
Similar REST actions
Tying database tables to presentation details
17. 1001 Wizard
Implementations
1a. One Controller/Presenter Per Wizard Step
•
Create one ActiveRecord
•
Create a controller and ActiveModel presenter per
wizard step
•
Have each ActiveModel presenter manage its own
step validation logic
•
Bind every wizard step form to corresponding
ActiveModel presenter
•
Have each wizard step controller redirect to the
next one on create or update
18. 1001 Wizard
Implementations
1a. One Controller/Presenter Per Wizard Step
Step 1
Controller
Step 1
Presenter
Step 2
Presenter
Create &
Redirect to New
Step 2
Controller
Create &
Redirect to New
Step 3
Presenter
Step 3
Controller
ActiveRecord
Step 4
Presenter
Create &
Redirect to New
Step 4
Controller
19. 1001 Wizard
Implementations
1a. One Controller/Presenter Per Wizard Step
Pros
Easy to understand and follow
RESTful
Works with one ActiveRecord
20. 1001 Wizard
Implementations
1a. One Controller/Presenter Per Wizard Step
Cons
Redundant code across controllers
Repetitive redirect logic
Redundant authentication logic
Similar model loading logic
Similar REST actions
Too much presenter validation/persistence
management code
21. 1001 Wizard
Implementations
1b. One Action/Presenter Per Wizard Step
•
Create one ActiveRecord
•
Create one controller with a different new and create action
variation per wizard step
•
e.g. new_step1, create_step1, new_step2, create_step2, etc…
•
Create a different ActiveModel presenter per wizard step
•
Have each ActiveModel presenter manage its own step
validation logic
•
Bind every wizard step form to corresponding ActiveModel
presenter
•
Have each wizard step action redirect to the next one on create
22. 1001 Wizard
Implementations
1b. One Action/Presenter Per Wizard Step
Step 1
Presenter
Validation/Persistance
Adapter
ActiveRecord
Create Step &
Redirect to New Ste
Controller
Step 2
Presenter
Validation/Persistance
Adapter
Step 3
Presenter
Validation/PersistanceAdapt
er
Step 1 New
Step 1 Create
Step 2 New
Step 2 Create
Step 3 New
Step 3 Create
Step 4 New
Step 4 Create
Step 4
Presenter
Validation/Persistance Adapter
23. 1001 Wizard
Implementations
1b. One Action/Presenter Per Wizard Step
Pros
Easy to understand and follow
Works with one ActiveRecord
Lighter controller code
Reused controller hooks (e.g. authentication)
24. 1001 Wizard
Implementations
1b. One Action/Presenter Per Wizard Step
Cons
Not RESTful
Redundant code across actions
Repetitive redirect logic
Repetitive update logic
Too much presenter management code
25. 1001 Wizard
Implementations
2. Session Accumulation
Step 1
Create one ActiveRecord
Have multiple Controllers or Actions accumulate
wizard step data in the session
Have ActiveModel presenters handle
validation/forms
On the final step, create ActiveRecord running all
Create
validations
Step 3
Accumulate
in Session
Step 2
Accumulate
in Session
Accumulate
in Session
Step 4
ActiveRecor
d
27. 1001 Wizard
Implementations
2. Session Accumulation
Cons
Reliance on session has implications on scalability
Controller code more complex due to managing
session data storage
Validations defined twice, once per ActiveModel
presenters used for form validation and once in the
actual ActiveRecord
28. 1001 Wizard
Implementations
3. Hidden Value Accumulation
Same as session value accumulation except the
controller manages data coming from a request
parameter
Same pros and cons as Session Value
Accumulation except that it has no scalability
implications
NOTE: hidden value must be encrypted for
security
29. 1001 Wizard
Implementations
4. State Machine
Create one ActiveRecord
Make ActiveRecord a state machine managing steps:
adding a step column
add current_step, next_step, and prev_step methods
Different view per step
Have single ActiveRecord manage each step
validations by relying on conditional validations. For
example:
validate :phone,
presence: true,
if: lambda {current_step==“shipping”}
31. 1001 Wizard
Implementations
4. State Machine
Cons
Puts presentation concerns in Model (breaks MVC)
The state machine wizard must be a layer on top of
the Model. It has nothing to do with the business
model.
Stores an extra column in the database for purely
presentation-related reasons
Can be avoided with session storage of state, opening
a different can of worms (controller complexity)
More complexity in declaring validations due to
conditions and potentially overloading the Model
32. 1001 Wizard
Implementations
5. Gems
Wizardry: state machine in model
Wicked: clean state machine in controller (better)
but no validation support beyond conditional
validation
Rails-Wizard-Generator: XML XML XML
Stepper: Nice support for steps in model and
controller
34. Ultra Light & Maintainable
Wizard
Philosophy:
A wizard is simply a builder of a model
Every step is simply a partial data-view of the
model
REST resource is still the model itself and thus
must have a single controller
Models must manage validations without
conditions by relying on step-polymorphism
View forms are presented based on steppolymorphism
35. Ultra Light & Maintainable
Wizard
Details:
Create one main ActiveRecord model
Create “step submodels” subclassing the main model:
Each presents a partial view of the main model
Each has validations only for its step, thus no
conditionals
Each has before and after initialization for that step
Create a single controller:
It begins wizard by creating main ActiveRecord
Every step represents an Edit action of a “step
submodel”
Create a different view per step, each binding to “step
submodel” to ensure the right validations are triggered