39
Ultra Light & Maintainable Wizards in Rails Andy Maleh President and Chief Journeyman Soft Buzz

Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Embed Size (px)

Citation preview

Page 1: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Ultra Light & Maintainable Wizards in RailsAndy Maleh

President and Chief Journeyman

Soft Buzz

Page 2: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Overview

Why Use A Wizard?

Wizard Example

Wizard Implementation Goals

1001 Wizard Implementations

Ultra Light & Maintainable Wizard

Page 3: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Why Use A Wizard?

Avoid overwhelming user with a huge

form

Page 4: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Why Use A Wizard?

Simplify a workflow into multiple steps

Page 5: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Why Use A Wizard?

Help the user by providing guidance

Page 6: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Event Registration Wizard

Page 7: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Step 1 – Personal Info

Page 8: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Step 2 – Background Info

Page 9: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Step 3 – Review

Page 10: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Step 4 – Payment

Page 11: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Example

Steps Done – Order Confirmation

Page 12: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Implementation Goals

REST

MVC

OO

Non-Functional Requirements:

Productivity

Maintainability

Performance

Security

Page 13: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1. 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

Page 14: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1. One Controller/ActiveRecord Per Wizard Step

Step 1

Controller

Step 2

Controller

Step 3

Controller

Step 4

Controller

Create &

Redirect to New

Create &

Redirect to New

Create &

Redirect to New

Step 1

ActiveRecord

Step 2

ActiveRecord

Step 3

ActiveRecord

Step 4

ActiveRecord

Page 15: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1. One Controller/ActiveRecord Per Wizard Step

Pros

Easy to understand and follow

RESTful

Page 16: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1. 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

Page 17: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1a. 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

Page 18: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1a. One Controller/Presenter Per Wizard Step

Step 1

Controller

Step 2

Controller

Step 3

Controller

Step 4

Controller

Create &

Redirect to New

Create &

Redirect to New

Create &

Redirect to New

Step 1

Presenter

Step 2

Presenter

Step 3

Presenter

Step 4

Presenter

ActiveRecord

Page 19: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1a. One Controller/Presenter Per Wizard Step

Pros

Easy to understand and follow

RESTful

Works with one ActiveRecord

Page 20: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1a. 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

Page 21: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1b. 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 ActiveModelpresenter

• Have each wizard step action redirect to the next one on create

Page 22: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1b. One Action/Presenter Per Wizard Step

Controller

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 1

Presenter

Validation/Persistance

Adapter

Step 2

Presenter

Validation/Persistance

Adapter

Step 3

Presenter

Validation/PersistanceAdapt

er

Step 4

Presenter

Validation/Persistance Adapter

ActiveRecord

Create Step &

Redirect to New Step

Page 23: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1b. 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)

Page 24: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations1b. One Action/Presenter Per Wizard Step

Cons

Not RESTful

Redundant code across actions

Repetitive redirect logic

Repetitive update logic

Too much presenter management code

Page 25: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations2. Session Accumulation

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

validationsStep 1

Step 2

Step 3

Step 4

Accumulate

in Session

Accumulate

in Session

Accumulate

in Session

Create

ActiveRecor

d

Page 26: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations2. Session Accumulation

Pros

Works with one ActiveRecord

Page 27: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations2. 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

Page 28: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations3. 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

Page 29: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations4. 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”}

Page 30: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations4. State Machine

Pros

Works with one ActiveRecord

Simpler step management logic in one controller

Page 31: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations4. 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

Page 32: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

1001 Wizard

Implementations5. 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

Page 33: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Wizard Implementation

GoalsREST

MVC

OO

Non-Functional Requirements:

Productivity

Maintainability

Performance

Security

Page 34: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Ultra Light & Maintainable

WizardPhilosophy:

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 step-

polymorphism

Page 35: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Ultra Light & Maintainable

WizardDetails:

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

Page 36: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Ultra Light & Maintainable

Wizard

Controller

Create

Edit

Update

Step 1

ActiveRecord

Validations/Step Logic

Step 2

ActiveRecord

Validations/Step Logic

Step 3

ActiveRecord

Validations/Step Logic

ActiveRecord

Step 4

ActiveRecord

Validations/Step Logic

Update &

Redirect to Edit

Page 37: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Ultra Light & Maintainable

WizardCode Review in Editor

Page 38: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Review

Why Use A Wizard?

Wizard Example

Wizard Implementation Goals

1001 Wizard Implementations

Ultra Light & Maintainable Wizard

Page 39: Ultra Light and Maintainable Wizards in Rails at Montreal.rb

Contact

Andy Maleh

BLOG: http://andymaleh.blogspot.com

TWITTER: @AndyMaleh

WEBSITE:http://www.softbuzz.ca