Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
create a functioning wizard for any model in three steps
Ruby
tree: 5f1bc6aed2

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
app
config
db
lib
public
script
spec
test
.gitignore
CHANGELOG.rdoc
LICENSE
README.rdoc
Rakefile
init.rb
wizardly.gemspec

README.rdoc

wizardly

wizardly produces a functional wizard from an ActiveRecord model in three steps.

Resources

Development

Source

  • git://github.com/jeffp/wizardly.git

Install

Description

wizardly builds on Alex Kira's validation_group plugin code to DRY up the Rails MVC implementation of a wizard. In three easy steps, wizardly produces the scaffolding and controller of a functioning wizard.

Features include:

  • Model-based definition

  • Wizard controller macro

  • Wizard scaffolding generator

  • Default wizard buttons

  • Custom button creation

  • Page and button callbacks

Setup

Install the wizardly gem and require the gem at the bottom of your config/environment.rb file:

require 'wizardly'

For any rails app, run the following to install rake tasks (optional)

./script/generate wizardly_app

Example

Create a working controller wizard for any model in 3 steps. Here's how:

Step 1: Define validation groups for your model.

class User < ActiveRecord::Base    
  validation_group :step1, :fields=>[:first_name, :last_name]
  validation_group :step2, :fields=>[:age, :gender]
  ...
end

Step 2: Tell your controller to act 'wizardly'.

class SignupController < ActionController::Base
  act_wizardly_for :user
end

Step 3: Generate a 'wizardly' scaffold for your controller.

./script/generate wizardly_scaffold :signup

You are ready to go.

General usage and configuration of wizardly follows.

Usage

Default Behavior and Scaffolding Configuration

The wizardly_scaffold generator produces an html view for each validation_group declared in the model. The wizard progresses to each page in the same order of the validation_group(s) in the model. Buttons for navigating the wizard are included on each page.

You can view a wizardly controller's configuration by using the wizardly:config rake task. First you'll need to install it if you already have not

./script/generate wizardly_app

Then you can call the rake task for any controller configured with the 'act_wizardly_for' macro

rake wizardly:config name=signup

Substitute the name of any wizardly controller for 'signup'.

Completing and Canceling

Once a user has entered a wizard, there are two ways they can leave, either by completing or canceling the wizard.

The above example is pretty simple. In fact, no redirects have been defined for completing or canceling the wizard in the above example so the wizardly controller uses the HTTP_REFERER for both cases. What if there is no referer? The controller raises a RedirectNotDefined error. Let's remedy this problem with some options in the macro.

class SignupController < ActionController::Base
  act_wizardly_for :user, :completed=>'/main/finished', 
    :canceled=>'/main/canceled'
end

Now whether the user completes or cancels the wizard, the controller knows how to redirect. Alternately, if you want to redirect to the same page for both cases

class SignupController < ActionController::Base
  act_wizardly_for :user, :redirect=>'/main'
end

Other options

Here's a list of options you can use in the macro

:completed => '/main/finished'
:canceled => {:controller=>'main', :action=>'canceled'}
:skip => {true|false}
:mask_fields => [:password, :password_confirmation] (by default)

The :skip option tells the scaffold helpers to include or exclude a skip button on every page. The :mask_fields options tells the scaffold generator which fields are html 'password' fields.

Buttons

The wizardly controller defines five default button functions: next, back, skip, cancel, and finish. All but :skip are used in the scaffolding by default. You can add :skip functionality to all pages by adding an option to the macro

class SignupController < ActionController::Base
  act_wizardly_for :user, :redirect=>'/main', :skip=>true
end

You can create, customize and change buttons for any controller and any page. See the Advanced Configuration section.

Callbacks

The wizard macro 'act_wizardly_for' creates controller actions for each page. The process for each page is conventional, but hooks (or callbacks) are available for the developer to change the processing. Here's an example. Say our model declares a :step4 validation_group with :username, :password, and :password_confirmation fields. We'd like to handle this step specifically.

class SignupController < ActionController::Base
  act_wizardly_for :user, :redirect=>'/main'

  def on_step4_page_errors
    #clear the password field if errors
    @user[:password] = ''
    @user[:password_confirmation] = ''
  end
end

The above callback is only called if :step4 does not validate according to its validation_group.

Every page has a set of callbacks. Here's the list for our :step1 page.

def on_get_step1_page; end    # called just before rendering the GET action
def on_step1_page_errors; end # called just before rendering with errors
def on_step1_page_next; end   
def on_step1_page_back; end
def on_step1_page_cancel; end
def on_step1_page_finish; end
def on_step1_page_skip; end

Each callback is defined for the controller object, thus giving it access to all controller variables and methods just as any other action method. Each callback has access to the model through an instance variable using the model's name. So for instance if our model is :user, the instance variable is '@user'. Each wizard page action also defines a @title, @description and @step instance variable. These are primarily used for scaffolding. The @step holds the name of the current validation group, ie. :step1, step2, … in our examples.

Notice the last five callbacks are related to the default wizard buttons. Each callback gives the developer a chance to intervene before the impending render or redirect caused by a button click in the view.

Important: Method names for button callbacks will change if you change the name of the button. For general use, this is not an issue. See the Advanced Configuration section.

Rendering Callback

For anyone needing to handle rendering in a special way, wizardly provides a render call back for this.

class SignupController < ActionController::Base
  act_wizardly_for :user, :redirect=>'/main'

  def render_wizard_page
    respond_to do |format|
      format.html
      format.xml { render_xml(@step) }
    end
  end

  def render_xml(step)
    ...
  end
end

Advanced Configuration

To be provided

Testing

Testing uses RSpec and Webrat. Make sure you have those gems installed. Then to test the development code run the following:

rake spec:all

Dependencies

  • validation_group is currently integrated (plugin not required)

  • ActiveRecord

  • ActionController

Something went wrong with that request. Please try again.