Wicked Documentation

repository·main·Indexed 25 days ago

https://github.com/zombocom/wicked

A Ruby gem that enables Rails developers to transform standard controllers into step-by-step wizards using a RESTful state machine approach. It provides tools for managing multi-step processes, such as user onboarding, including navigation helpers (next_wizard_path, previous_wizard_path), flow control methods (skip_step, jump_to), and support for internationalized URLs via Wicked::Wizard::Translated.

Tokens
4.5K
Snippets
13
Records
33
Agent score
83%

What's inside Wicked

  1. Render Wizard steps and views

    main

    In your controller actions (like show or update), call render_wizard at the end. By default, Wicked looks for a view file named after the current step within the controller's view directory.

    For example, if the step is :confirm_password in AfterSignupController, Wicked will render app/views/after_signup/confirm_password.html.erb.

    class AfterSignupController < ApplicationController
      include Wicked::Wizard
      steps :confirm_password, :confirm_profile, :find_friends
    
      def show
        @user = current_user
        case step
        when :find_friends
          @friends = @user.find_friends
        end
        render_wizard
      end
    end
  2. Configure a Wizard Controller

    main

    To turn a Rails controller into a wizard, include Wicked::Wizard in the class and define the sequence of steps using the steps method. Alternatively, you can inherit from Wicked::WizardController.

    Important: Wicked uses the :id parameter to control the flow of steps. If your controller requires an :id parameter, you must use nested routes and prefix the ID (e.g., :product_id) to avoid conflicts.

    class AfterSignupController < ApplicationController
      include Wicked::Wizard
    
      steps :confirm_password, :confirm_profile, :find_friends
    end
  3. Set Dynamic Step Names

    main

    You can define the order of steps dynamically based on request parameters. To do this, manually assign self.steps in a before_action and ensure it is called before before_action :setup_wizard.

    include Wicked::Wizard
    before_action :set_steps
    before_action :setup_wizard
    
    private
    def set_steps
      if params[:flow] == "twitter"
        self.steps = [:ask_twitter, :ask_email]
      elsif params[:flow] == "facebook"
        self.steps = [:ask_facebook, :ask_email]
      end
    end
  4. Internationalize Wizard URLs using I18n

    main

    To use translated URLs (e.g., /after_signup/uno instead of /after_signup/first), replace include Wicked::Wizard with include Wicked::Wizard::Translated in your controller.

    1. Define translations in your locale files (e.g., config/locales/es.yml) under a wicked key:
    es:
      wicked:
        first: "uno"
        second: "dos"
    1. Important: Because step, next_step, and previous_step will now return the translated strings, you must use the wizard_value method to access the original (canonical) step symbols in your controller logic.

    Example of correct step checking:

    steps :confirm_password, :confirm_profile, :find_friends
    
    def show
      case wizard_value(step)
      when :find_friends
        @friends = current_user.find_friends
      end
      render_wizard
    end
    include Wicked::Wizard::Translated
  5. Create Custom URLs via I18n

    main

    You can use Wicked::Wizard::Translated to create custom, readable URLs even in a single language. Add the desired URL slugs to your locale file under the wicked key:

    en:
      wicked:
        first: "verify_email"
        second: "if_you_are_popular_add_friends"

    Note: Always use wizard_value() when comparing steps to ensure you are using the canonical symbols rather than the custom URL strings.

  6. Enable translated step names in Wizard controllers

    main

    To use translated step names in your wizard, include Wicked::Wizard::Translated in your controller. This module replaces the standard setup_wizard with setup_wizard_translated, which automatically sets the wizard's steps based on your I18n translations.

    Translations must be nested under the wicked namespace in your locale files (e.g., es.yml).

    Example translation structure (es.yml):

    es:
      wicked:
        first: "uno"
        second: "dos"
    module Wicked
      module Wizard
        module Translated
          # Include this in your controller to enable translation support
        end
      end
    end
  7. Integrate Wicked::Wizard into a Rails Controller

    main

    To use Wicked in a controller, include Wicked::Wizard within the module. This provides the necessary path helpers, step management, and automatic variable initialization via before_action.

    Note: If you are defining steps using a before_action in your controller, you must use prepend_before_action to ensure the steps are defined before Wicked attempts to initialize the wizard state.

  8. Test Wizard Actions with RSpec

    main

    When testing wizard controllers with RSpec, you can target specific blocks by passing the step ID as the id parameter in your request helpers.

    # Test find_friends block of show action
    get :show, params: { id: :find_friends }
    
    # Test find_friends block of update action
    patch :update, params: {'id' => 'find_friends', "user" => { "id" => @user.id.to_s }}
  9. Pass parameters to finish_wizard_path

    main

    To pass data to the final redirect, define finish_wizard_path with a params argument and pass the data through render_wizard.

    steps :first_step, :second_step
    
    def show
      # Pass params as the third argument to render_wizard
      render_wizard(nil, {}, { hello: 'world' })
    end
    
    def update
      render_wizard(@user, {}, { hello: 'world' })
    end
    
    def finish_wizard_path(params)
      # params will be { hello: 'world' }
    end
  10. Control wizard flow with skip_step and jump_to

    main

    You can programmatically alter the wizard flow in your controller actions:

    • skip_step: Skips the current step and moves to the next logical one.
    • jump_to(:step_name): Jumps directly to a specific step.

    Note: Both methods trigger a redirect. Do not call return immediately after calling them; the actual redirection happens when render_wizard is called. You can pass parameters to the target step using skip_step(param: 'value') or jump_to(:step, param: 'value').

    def show
      if @user.has_facebook_access_token?
        @friends = @user.find_friends
      else
        skip_step
      end
      render_wizard
    end
  11. Override the finish_wizard_path

    main

    By default, Wicked redirects to a specific path when the wizard is complete. You can customize this destination by overriding the finish_wizard_path method in your wizard controller.

    def finish_wizard_path
      user_path(current_user)
    end