├── VERSION
├── test
├── rails_app
│ ├── lib
│ │ ├── tasks
│ │ │ └── .gitkeep
│ │ └── assets
│ │ │ └── .gitkeep
│ ├── public
│ │ ├── favicon.ico
│ │ ├── robots.txt
│ │ ├── 422.html
│ │ ├── 404.html
│ │ ├── 500.html
│ │ └── index.html
│ ├── app
│ │ ├── mailers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ ├── .gitkeep
│ │ │ ├── users.rb
│ │ │ ├── order.rb
│ │ │ ├── big_company.rb
│ │ │ └── company.rb
│ │ ├── views
│ │ │ ├── companies
│ │ │ │ ├── show.html.erb
│ │ │ │ ├── index.html.erb
│ │ │ │ ├── _step1_step.html.erb
│ │ │ │ ├── _step2_step.html.erb
│ │ │ │ ├── _step3_step.html.erb
│ │ │ │ └── new.html.erb
│ │ │ └── layouts
│ │ │ │ └── application.html.erb
│ │ ├── helpers
│ │ │ └── application_helper.rb
│ │ └── controllers
│ │ │ ├── application_controller.rb
│ │ │ ├── companies_controller.rb
│ │ │ └── orders_controller.rb
│ ├── config.ru
│ ├── config
│ │ ├── environment.rb
│ │ ├── boot.rb
│ │ ├── routes.rb
│ │ ├── initializers
│ │ │ ├── mime_types.rb
│ │ │ ├── inflections.rb
│ │ │ ├── backtrace_silencers.rb
│ │ │ ├── session_store.rb
│ │ │ ├── secret_token.rb
│ │ │ └── wrap_parameters.rb
│ │ ├── database.yml
│ │ ├── locales
│ │ │ └── en.yml
│ │ ├── environments
│ │ │ ├── development.rb
│ │ │ ├── test.rb
│ │ │ └── production.rb
│ │ └── application.rb
│ ├── Rakefile
│ ├── script
│ │ └── rails
│ └── db
│ │ ├── schema.rb
│ │ └── migrate
│ │ └── 20110928102949_create_tables.rb
├── models
│ ├── assigns_test.rb
│ ├── models_test.rb
│ ├── validation_test.rb
│ └── instance_test.rb
├── controllers
│ ├── controller_additions_test.rb
│ ├── controller_create_test.rb
│ ├── redirect_test.rb
│ ├── controller_invalid_params_test.rb
│ ├── controller_test.rb
│ ├── controller_update_test.rb
│ └── controller_resource_test.rb
├── helper.rb
├── integration
│ └── steps_test.rb
└── helpers
│ └── helper_test.rb
├── lib
├── stepper.rb
└── stepper
│ ├── exceptions.rb
│ ├── engine.rb
│ ├── railtie.rb
│ ├── helper
│ └── action_view_additions.rb
│ ├── controllers
│ ├── controller_resource.rb
│ └── controller_additions.rb
│ └── models
│ └── active_record_additions.rb
├── .document
├── .travis.yml
├── config
└── locales
│ └── stepper.yml
├── .gitignore
├── Gemfile
├── app
└── views
│ └── stepper
│ └── _fields.html.erb
├── LICENSE.txt
├── Rakefile
├── Gemfile.lock
├── README.md
└── stepper.gemspec
/VERSION:
--------------------------------------------------------------------------------
1 | 0.2.0
--------------------------------------------------------------------------------
/test/rails_app/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/rails_app/public/favicon.ico:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/rails_app/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/rails_app/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/rails_app/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/stepper.rb:
--------------------------------------------------------------------------------
1 | require 'stepper/railtie'
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/show.html.erb:
--------------------------------------------------------------------------------
1 | show page
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/index.html.erb:
--------------------------------------------------------------------------------
1 | index page
--------------------------------------------------------------------------------
/.document:
--------------------------------------------------------------------------------
1 | lib/**/*.rb
2 | bin/*
3 | -
4 | features/**/*.feature
5 | LICENSE.txt
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 1.9.2
4 | - 1.9.3
5 | - ruby-head
6 |
--------------------------------------------------------------------------------
/test/rails_app/app/helpers/application_helper.rb:
--------------------------------------------------------------------------------
1 | module ApplicationHelper
2 | end
3 |
--------------------------------------------------------------------------------
/lib/stepper/exceptions.rb:
--------------------------------------------------------------------------------
1 | module Stepper
2 | class StepperException < RuntimeError
3 | end
4 | end
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/_step1_step.html.erb:
--------------------------------------------------------------------------------
1 | <%= f.label :name %>
2 | <%= f.text_field :name %>
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/_step2_step.html.erb:
--------------------------------------------------------------------------------
1 | <%= f.label :code %>
2 | <%= f.text_field :code %>
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/_step3_step.html.erb:
--------------------------------------------------------------------------------
1 | <%= f.label :city %>
2 | <%= f.text_field :city %>
--------------------------------------------------------------------------------
/lib/stepper/engine.rb:
--------------------------------------------------------------------------------
1 | module Stepper #:nodoc:
2 | class Engine < ::Rails::Engine #:nodoc:
3 | end
4 | end
5 |
--------------------------------------------------------------------------------
/test/rails_app/app/models/users.rb:
--------------------------------------------------------------------------------
1 | class User < ActiveRecord::Base
2 | has_steps :steps => ["step1", "step2"]
3 | end
--------------------------------------------------------------------------------
/test/rails_app/app/models/order.rb:
--------------------------------------------------------------------------------
1 | class Order < ActiveRecord::Base
2 | has_steps :steps => ["step1", "step2", "step3"]
3 | end
--------------------------------------------------------------------------------
/test/rails_app/app/controllers/application_controller.rb:
--------------------------------------------------------------------------------
1 | class ApplicationController < ActionController::Base
2 | protect_from_forgery
3 | end
4 |
--------------------------------------------------------------------------------
/config/locales/stepper.yml:
--------------------------------------------------------------------------------
1 | en:
2 | stepper:
3 | next_step: 'Next'
4 | previous_step: 'Previous'
5 | save: 'Save'
6 | finish: 'Finish'
--------------------------------------------------------------------------------
/test/rails_app/app/models/big_company.rb:
--------------------------------------------------------------------------------
1 | class BigCompany < Company
2 | has_steps :current_step_column => :my_step, :steps => ["step4", "step5", "step6"]
3 |
4 | end
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | coverage
2 | rdoc
3 | doc
4 | .yardoc
5 | .bundle
6 | pkg
7 | .DS_Store
8 | *.tmproj
9 | tmtags
10 | .idea
11 | .rvmrc
12 | test/rails_app/tmp
13 | test/rails_app/log
--------------------------------------------------------------------------------
/test/rails_app/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require ::File.expand_path('../config/environment', __FILE__)
4 | run RailsApp::Application
5 |
--------------------------------------------------------------------------------
/test/rails_app/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the rails application
2 | require File.expand_path('../application', __FILE__)
3 |
4 | # Initialize the rails application
5 | RailsApp::Application.initialize!
6 |
--------------------------------------------------------------------------------
/test/rails_app/app/controllers/companies_controller.rb:
--------------------------------------------------------------------------------
1 | class CompaniesController < ApplicationController
2 | has_steps
3 |
4 | def show
5 |
6 | end
7 |
8 | def index
9 |
10 | end
11 | end
--------------------------------------------------------------------------------
/test/rails_app/config/boot.rb:
--------------------------------------------------------------------------------
1 | require 'rubygems'
2 |
3 | # Set up gems listed in the Gemfile.
4 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5 |
6 | require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
7 |
--------------------------------------------------------------------------------
/test/rails_app/config/routes.rb:
--------------------------------------------------------------------------------
1 | RailsApp::Application.routes.draw do
2 | resources :companies do
3 | get :next_step , :on => :member
4 | end
5 |
6 | resources :orders do
7 | get :next_step , :on => :member
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/test/rails_app/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 | # Mime::Type.register_alias "text/html", :iphone
6 |
--------------------------------------------------------------------------------
/test/rails_app/config/database.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: sqlite3
3 | database: db/development.sqlite3
4 | pool: 5
5 | timeout: 5000
6 |
7 | test:
8 | adapter: sqlite3
9 | database: ":memory:"
10 | timeout: 500
11 |
12 | production:
13 | adapter: sqlite3
14 | database: ":memory:"
15 |
--------------------------------------------------------------------------------
/test/rails_app/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | RailsApp::Application.load_tasks
8 |
--------------------------------------------------------------------------------
/test/rails_app/app/views/layouts/application.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | RailsApp
5 | <%= stylesheet_link_tag "application" %>
6 | <%= javascript_include_tag "application" %>
7 | <%= csrf_meta_tags %>
8 |
9 |
10 |
11 | <%= yield %>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/test/rails_app/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/test/rails_app/app/controllers/orders_controller.rb:
--------------------------------------------------------------------------------
1 | class OrdersController < ApplicationController
2 | has_steps :redirect_to => {
3 | :after_save => {:action => :index},
4 | :after_finish => proc { |controller, resource| controller.order_url(resource.id) }
5 | }
6 |
7 | def show
8 |
9 | end
10 |
11 | def index
12 |
13 | end
14 | end
--------------------------------------------------------------------------------
/test/rails_app/config/locales/en.yml:
--------------------------------------------------------------------------------
1 | # Sample localization file for English. Add more files in this directory for other locales.
2 | # See https://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3 |
4 | en:
5 | hello: "Hello world"
6 | stepper:
7 | next_step: 'Next step'
8 | previous_step: 'Previous step'
9 | save: 'Finish later'
10 | finish: 'Finish form'
--------------------------------------------------------------------------------
/test/rails_app/app/models/company.rb:
--------------------------------------------------------------------------------
1 | class Company < ActiveRecord::Base
2 | has_steps :current_step_column => :my_step, :steps => ["step1", "step2", "step3"]
3 |
4 | private
5 |
6 | def validate_step1
7 | self.validates_presence_of :name
8 | end
9 |
10 | def validate_step2
11 | self.validates_numericality_of :code
12 | end
13 |
14 | def validate_step3
15 | self.validates_presence_of :city
16 | end
17 |
18 | end
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format
4 | # (all these examples are active by default):
5 | # ActiveSupport::Inflector.inflections do |inflect|
6 | # inflect.plural /^(ox)$/i, '\1en'
7 | # inflect.singular /^(ox)en/i, '\1'
8 | # inflect.irregular 'person', 'people'
9 | # inflect.uncountable %w( fish sheep )
10 | # end
11 |
--------------------------------------------------------------------------------
/test/rails_app/app/views/companies/new.html.erb:
--------------------------------------------------------------------------------
1 | <% if @company.errors.any? %>
2 |
3 |
<%= pluralize(@company.errors.count, "error") %> prohibited this company from being saved:
4 |
5 |
6 | <% @company.errors.full_messages.each do |msg| %>
7 | - <%= msg %>
8 | <% end %>
9 |
10 |
11 | <% end %>
12 | <%= form_for @company do |f|%>
13 | <%= stepper f %>
14 | <% end %>
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7 | # Rails.backtrace_cleaner.remove_silencers!
8 |
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | RailsApp::Application.config.session_store :cookie_store, key: '_rails_app_session'
4 |
5 | # Use the database for sessions instead of the cookie-based default,
6 | # which shouldn't be used to store highly confidential information
7 | # (create the session table with "rails generate session_migration")
8 | # RailsApp::Application.config.session_store :active_record_store
9 |
--------------------------------------------------------------------------------
/test/models/assigns_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 | class AssignsModelTest < ActiveSupport::TestCase
3 |
4 | test "should assign default column" do
5 | assert_equal User.stepper_current_step_column, :current_step
6 | end
7 |
8 | test "should assign column from options" do
9 | assert_equal Company.stepper_current_step_column, :my_step
10 | end
11 |
12 | test "should assign default steps" do
13 | company = Company.new
14 | assert_equal company.stepper_steps, ["step1", "step2", "step3"]
15 | end
16 | end
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/secret_token.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Your secret key for verifying the integrity of signed cookies.
4 | # If you change this key, all old signed cookies will become invalid!
5 | # Make sure the secret is at least 30 characters and all random,
6 | # no regular words or you'll be exposed to dictionary attacks.
7 | RailsApp::Application.config.secret_token = '0870c81cd2bbca0f24ee0b2970e925f920c8142f80acb1b4d70ea308eb19d4b7c05632320860965dea4f78e9eee47305bbb6157efe6945af6b500c11c874d467'
8 |
--------------------------------------------------------------------------------
/test/rails_app/db/schema.rb:
--------------------------------------------------------------------------------
1 | ActiveRecord::Schema.define(:version => 20110928102949) do
2 |
3 | create_table "companies", :force => true do |t|
4 | t.string "name"
5 | t.string "my_step"
6 | t.integer "code"
7 | t.string "city"
8 | t.datetime "created_at"
9 | t.datetime "updated_at"
10 | end
11 |
12 | create_table "users", :force => true do |t|
13 | t.string "first_name"
14 | t.string "current_step"
15 | t.integer "last_name"
16 | t.datetime "created_at"
17 | t.datetime "updated_at"
18 | end
19 |
20 | end
--------------------------------------------------------------------------------
/test/rails_app/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 | #
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # Disable root element in JSON by default.
12 | ActiveSupport.on_load(:active_record) do
13 | self.include_root_in_json = false
14 | end
15 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 | gem "rails", ">= 3.1.0"
3 |
4 | group :development, :test do
5 | unless ENV["CI"]
6 | gem "ruby-debug19", :require => "ruby-debug", :platforms => [:ruby_19]
7 | gem "ruby-debug", :platforms => [:ruby_18]
8 | end
9 |
10 | gem "sqlite3"
11 | gem "shoulda", ">= 0"
12 | gem "bundler", ">= 1.0.0"
13 | gem "jeweler", ">= 1.6.4"
14 | gem "rcov", ">= 0", :platforms => :ruby_18
15 | gem "simplecov", ">= 0", :platforms => :ruby_19, :require => "false"
16 | gem "mocha"
17 | gem "capybara"
18 | gem "launchy"
19 | end
20 |
21 |
--------------------------------------------------------------------------------
/test/controllers/controller_additions_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class ControllerAdditionsTest < ActiveSupport::TestCase
4 | setup do
5 | @controller_class = Class.new
6 | @controller = @controller_class.new
7 | @controller_class.send(:include, Stepper::ControllerAdditions)
8 | end
9 |
10 | test "should has_steps setup before filter which passes call to ControllerResource" do
11 | Stepper::ControllerResource.stubs(:new).with(@controller, nil).stubs(:load_resource)
12 | @controller_class.stubs(:before_filter).with(:only => [:create, :update, :new, :next_step])
13 | @controller_class.has_steps
14 | end
15 |
16 | end
--------------------------------------------------------------------------------
/test/rails_app/db/migrate/20110928102949_create_tables.rb:
--------------------------------------------------------------------------------
1 | class CreateTables < ActiveRecord::Migration
2 | def self.up
3 | create_table "companies", :force => true do |t|
4 | t.string "name"
5 | t.string "my_step"
6 | t.integer "code"
7 | t.string "city"
8 | t.datetime "created_at"
9 | t.datetime "updated_at"
10 | end
11 |
12 | create_table "users", :force => true do |t|
13 | t.string "first_name"
14 | t.string "current_step"
15 | t.integer "last_name"
16 | t.datetime "created_at"
17 | t.datetime "updated_at"
18 | end
19 | end
20 |
21 | def self.down
22 | drop_table "companies"
23 | drop_table "users"
24 | end
25 | end
--------------------------------------------------------------------------------
/test/helper.rb:
--------------------------------------------------------------------------------
1 | ENV["RAILS_ENV"] = "test"
2 | require 'rubygems'
3 | require 'bundler'
4 | begin
5 | Bundler.setup(:default, :development)
6 | rescue Bundler::BundlerError => e
7 | $stderr.puts e.message
8 | $stderr.puts "Run `bundle install` to install missing gems"
9 | exit e.status_code
10 | end
11 |
12 | if ENV["COVERAGE"]
13 | require "simplecov"
14 | SimpleCov.start "rails" do
15 | add_filter "/test/"
16 | end
17 | end
18 |
19 | require 'test/unit'
20 | require 'ruby-debug' unless ENV["CI"]
21 | require 'shoulda'
22 | require 'stepper'
23 | require "rails_app/config/environment"
24 | require "rails/test_help"
25 | require 'capybara/rails'
26 |
27 | ActiveRecord::Migrator.migrate(File.expand_path("../rails_app/db/migrate/", __FILE__))
28 |
--------------------------------------------------------------------------------
/test/models/models_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 | class ActiveRecordTest < ActiveSupport::TestCase
3 |
4 | test "should have method" do
5 | assert_respond_to ActiveRecord::Base, :has_steps
6 | end
7 |
8 | test "should raise exception if options isn't hash" do
9 | assert_raise Stepper::StepperException do
10 | ActiveRecord::Base.has_steps "something"
11 | end
12 | end
13 |
14 | test "should raise exception if options is wrong" do
15 | assert_raise Stepper::StepperException do
16 | ActiveRecord::Base.has_steps :some => "some", :steps => ["step1", "step2"]
17 | end
18 | end
19 |
20 | test "should raise exception if options haven't :steps" do
21 | assert_raise Stepper::StepperException do
22 | ActiveRecord::Base.has_steps
23 | end
24 | end
25 |
26 | end
--------------------------------------------------------------------------------
/app/views/stepper/_fields.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= f.hidden_field current_step_column, :value => resource.next_step %>
3 | <%= render "#{resource.next_step}_step", :f => f %>
4 |
5 |
6 | - <%= f.submit :value => t('stepper.save').html_safe %>
7 | <% unless resource.first_step?(resource.next_step) %>
8 | - <%= f.submit :value => t('stepper.previous_step').html_safe %>
9 | <% end %>
10 | <% unless resource.last_step?(resource.next_step) %>
11 | - <%= f.submit :value =>t('stepper.next_step').html_safe %>
12 | <% else %>
13 | - <%= f.submit :value =>t('stepper.finish').html_safe %>
14 | <% end %>
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/rails_app/public/422.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The change you wanted was rejected (422)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The change you wanted was rejected.
23 |
Maybe you tried to change something you didn't have access to.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test/rails_app/public/404.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | The page you were looking for doesn't exist (404)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
The page you were looking for doesn't exist.
23 |
You may have mistyped the address or the page may have moved.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/test/rails_app/public/500.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | We're sorry, but something went wrong (500)
5 |
17 |
18 |
19 |
20 |
21 |
22 |
We're sorry, but something went wrong.
23 |
We've been notified about this issue and we'll take a look at it shortly.
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/stepper/railtie.rb:
--------------------------------------------------------------------------------
1 | require 'rails'
2 |
3 | require 'stepper/engine'
4 | require 'stepper/controllers/controller_additions'
5 | require 'stepper/controllers/controller_resource'
6 | require 'stepper/exceptions'
7 | require 'stepper/models/active_record_additions'
8 | require 'stepper/helper/action_view_additions'
9 |
10 | module Stepper
11 | class Railtie < ::Rails::Railtie #:nodoc:
12 | initializer 'stepper' do |app|
13 | ActiveSupport.on_load(:active_record) do
14 | ::ActiveRecord::Base.send :include, Stepper::ActiveRecordAdditions
15 | end
16 |
17 | ActiveSupport.on_load(:action_controller) do
18 | ::ActionController::Base.send :include, Stepper::ControllerAdditions
19 | end
20 |
21 | ActiveSupport.on_load(:action_view) do
22 | ::ActionView::Base.send :include, Stepper::ActionViewAdditions::InstanceMethods
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/test/models/validation_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 | class ValidationModelTest < ActiveSupport::TestCase
3 | setup do
4 | @company = Company.new
5 | end
6 |
7 | test "should validate step1" do
8 | @company.my_step = "step1"
9 | assert !@company.save
10 | assert_equal @company.errors.messages, { :name=>["can't be blank"] }
11 | end
12 |
13 | should "validate step 3 and previous steps" do
14 | @company.my_step = "step3"
15 | assert !@company.save
16 | assert_equal @company.errors.messages, { :name => ["can't be blank"],
17 | :code => ["is not a number"],
18 | :city => ["can't be blank"] }
19 | end
20 |
21 | should "not run method if it doesn't exists" do
22 | class << @company
23 | undef_method :validate_step2
24 | end
25 |
26 | @company.name = "name"
27 | @company.city = "Kiev"
28 | @company.my_step = "step3"
29 |
30 | assert_nothing_raised NoMethodError do
31 | @company.save!
32 | end
33 | end
34 |
35 |
36 | end
37 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 Anton Versal
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/test/controllers/controller_create_test.rb:
--------------------------------------------------------------------------------
1 | require "helper"
2 | class CompaniesCreateControllerTest < ActionController::TestCase
3 | tests CompaniesController
4 |
5 | setup do
6 | Company.expects(:new).with({'name' => 'Hina'}).returns(mock_company)
7 | mock_company.expects(:attributes=).with({'name' => 'Hina'}).returns(true)
8 | mock_company.expects(:save).returns(true)
9 | mock_company.stubs(:id).returns(1)
10 | end
11 |
12 | test "should redirect to next step if commit 'Next step'" do
13 | mock_company.stubs(:stepper_current_step).returns("step1")
14 | post(:create, {:company => {:name => "Hina"}, :commit => "Next step"})
15 | assert_response :redirect
16 | assert_redirected_to "http://test.host/companies/1/next_step"
17 | end
18 |
19 | test "should redirect to index if commit 'Finish later'" do
20 | post(:create, {:company => {:name => "Hina"}, :commit => "Finish later"})
21 | assert_response :redirect
22 | assert_redirected_to "http://test.host/companies"
23 | end
24 |
25 | protected
26 | def mock_company(stubs={})
27 | @mock_company ||= mock(stubs)
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/test/controllers/redirect_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class RedirectControllerTest < ActionController::TestCase
4 | tests OrdersController
5 |
6 | setup do
7 | Order.expects(:find).with('1').returns(mock_order)
8 | mock_order.expects(:attributes=).with({'code' => '23'}).returns(true)
9 | mock_order.expects(:save).returns(true)
10 | mock_order.stubs(:id).returns(1)
11 | end
12 |
13 | test "should redirect to :action => :index if commit 'Save'" do
14 | mock_order.stubs(:stepper_current_step).returns("step2")
15 | mock_order.stubs(:previous_step!)
16 | put(:update, {:order => {:code => "23"}, :commit => "Finish later", :id => 1})
17 | assert_response :redirect
18 | assert_redirected_to "http://test.host/orders"
19 | end
20 |
21 | test "should redirect to show if commit 'Finish' and option is Proc" do
22 | mock_order.stubs(:stepper_current_step).returns("step3")
23 | put(:update, {:order => {:code => "23"}, :commit => "Finish form", :id => 1})
24 | assert_response :redirect
25 | assert_redirected_to "http://test.host/orders/1"
26 | end
27 |
28 | protected
29 | def mock_order(stubs={})
30 | @mock_order ||= mock(stubs)
31 | end
32 | end
33 |
34 |
--------------------------------------------------------------------------------
/test/rails_app/config/environments/development.rb:
--------------------------------------------------------------------------------
1 | RailsApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # In the development environment your application's code is reloaded on
5 | # every request. This slows down response time but is perfect for development
6 | # since you don't have to restart the web server when you make code changes.
7 | config.cache_classes = false
8 |
9 | # Log error messages when you accidentally call methods on nil.
10 | config.whiny_nils = true
11 |
12 | # Show full error reports and disable caching
13 | config.consider_all_requests_local = true
14 | config.action_controller.perform_caching = false
15 |
16 | # Don't care if the mailer can't send
17 | config.action_mailer.raise_delivery_errors = false
18 |
19 | # Print deprecation notices to the Rails logger
20 | config.active_support.deprecation = :log
21 |
22 | # Only use best-standards-support built into browsers
23 | config.action_dispatch.best_standards_support = :builtin
24 |
25 | # Do not compress assets
26 | config.assets.compress = false
27 |
28 | # Expands the lines which load the assets
29 | config.assets.debug = true
30 | end
31 |
--------------------------------------------------------------------------------
/test/controllers/controller_invalid_params_test.rb:
--------------------------------------------------------------------------------
1 | require "helper"
2 | class CompaniesInvalidParamsControllerTest < ActionController::TestCase
3 | tests CompaniesController
4 |
5 | setup do
6 | @controller.expects(:render).at_least_once
7 | end
8 |
9 | test "should create action render to new action if object.save returns false" do
10 | Company.expects(:new).with({'name' => 'Hina'}).returns(mock_company)
11 | mock_company.expects(:attributes=).with({'name' => 'Hina'}).returns(true)
12 | mock_company.expects(:save).returns(false)
13 | mock_company.expects(:previous_step!)
14 | post(:create, {:company => {:name => "Hina"}, :commit => "Next step"})
15 | assert_response :success
16 | end
17 |
18 | test "should update action redirect to new action if object.save returns false" do
19 | Company.expects(:find).with('1').returns(mock_company)
20 | mock_company.expects(:attributes=).with({"name" => "Hina"}).returns(true)
21 | mock_company.expects(:save).returns(false)
22 | mock_company.expects(:previous_step!)
23 | post(:update, {:company => {:name => "Hina"}, :id => 1, :commit => "Next step"})
24 | assert_response :success
25 | end
26 |
27 | protected
28 | def mock_company(stubs={})
29 | @mock_company ||= mock(stubs)
30 | end
31 | end
--------------------------------------------------------------------------------
/test/integration/steps_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class StepsTest < ActionController::IntegrationTest
4 | include Capybara::DSL
5 |
6 | test "fill all steps" do
7 | visit new_company_path
8 | fill_in "Name", :with => "My company"
9 | click_button "Next step"
10 | fill_in "Code", :with => "04108"
11 | click_button "Next step"
12 | fill_in "City", :with => "Kiev"
13 | click_button "Finish form"
14 | assert_equal page.current_path, company_path(Company.last)
15 | end
16 |
17 |
18 | test "previous step" do
19 | visit new_company_path
20 | fill_in "Name", :with => "My company"
21 | click_button "Next step"
22 | assert page.has_selector?('label', :text => 'Code')
23 | click_button "Previous step"
24 | assert page.has_selector?('label', :text => 'Name')
25 | assert page.has_selector?('#company_name', :value => 'My company')
26 | assert page.has_no_selector?('#error_explanation')
27 | end
28 |
29 | test "finish later" do
30 | visit new_company_path
31 | fill_in "Name", :with => "My company"
32 | click_button "Next step"
33 | assert page.has_selector?('label', :text => 'Code')
34 | click_button "Finish later"
35 | assert_equal page.current_path, companies_path
36 | assert page.has_no_selector?('#error_explanation')
37 | end
38 |
39 | end
--------------------------------------------------------------------------------
/lib/stepper/helper/action_view_additions.rb:
--------------------------------------------------------------------------------
1 | module Stepper
2 | module ActionViewAdditions
3 | module InstanceMethods
4 | # Render partial from app/views/stepper/_fields
5 | # Adds buttons "Next", "Previous", "Save" and "Finish" to form and adds hidden field with current step name.
6 | #
7 | # Add to locales for changing step names:
8 | # en:
9 | # stepper:
10 | # next_step: 'Next step'
11 | # previous_step: 'Previous step'
12 | # save: 'Finish later'
13 | # finish: 'Finish'
14 | #
15 | # +next_step+ button validates, saves current step and renders next step of form;
16 | # +previous_step+ saves current step and renders previous step of form;
17 | # +save+ save current step and redirects to index page;
18 | # +finish+ is showed only for last step instead of +next_step+ button and it validates, saves last step and redirects to show.
19 | #
20 | # If you want to have other partial for buttons than add partial to: +app/views/stepper/_fields.html.erb+
21 | def stepper(form)
22 | resource = self.instance_variable_get :@_stepper_resource_instance
23 | current_step_column = resource.stepper_current_step_column
24 | self.render(:partial => "stepper/fields",
25 | :locals => { :f => form,
26 | :resource => resource,
27 | :current_step_column => current_step_column }).to_s
28 | end
29 | end
30 | end
31 | end
--------------------------------------------------------------------------------
/test/controllers/controller_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class CompaniesControllerTest < ActionController::TestCase
4 | tests CompaniesController
5 |
6 | test "should raise error if commit is unknown" do
7 | Company.expects(:new).with({'name' => 'Hina'}).returns(mock_company)
8 | mock_company.expects(:attributes=).with({'name' => 'Hina'}).returns(true)
9 | mock_company.expects(:save).returns(true)
10 | mock_company.stubs(:id).returns(1)
11 | assert_raise Stepper::StepperException do
12 | post(:create, {:company => {:name => "Hina"}, :commit => "some commit"})
13 | end
14 | end
15 |
16 | test "should assign resource if params[:id] exists" do
17 | @controller.stubs(:render)
18 |
19 | Company.expects(:find).with('1').returns(mock_company(:last_step? => false))
20 | get :next_step, :id => 1
21 | assert_response :success
22 | assert_equal assigns(:company), mock_company
23 | end
24 |
25 | test "should get existing assigns" do
26 | @controller.stubs(:render)
27 | @controller.instance_variable_set(:@company, mock_company(:last_step? => false))
28 | get :next_step, :id => 1
29 | assert_equal assigns(:company), mock_company
30 | end
31 |
32 | test "next_step action should redirect to show if company on at the last step" do
33 | @controller.instance_variable_set(:@company, mock_company(:last_step? => true, :id => "1"))
34 | get :next_step, :id => 1
35 | assert_response :redirect
36 | assert_redirected_to "http://test.host/companies/1"
37 | end
38 |
39 | protected
40 | def mock_company(stubs={})
41 | @mock_company ||= mock(stubs)
42 | end
43 | end
44 |
45 |
--------------------------------------------------------------------------------
/test/helpers/helper_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class StepperButtonsTest < ActionController::IntegrationTest
4 | test "first step should have 'finish later' and 'next step' buttons" do
5 | get new_company_path
6 | assert_select "li.next_step" do
7 | assert_select "input[value='Next step']"
8 | end
9 | assert_select "li.save" do
10 | assert_select "input[value='Finish later']"
11 | end
12 | assert_select "li.previous_step", false, "This page must contain no previous button"
13 | end
14 |
15 | test "second step should have 'finish later', 'previous step' and 'next step' buttons" do
16 | company = Company.create!(:name => "My company", :my_step => "step1")
17 | get next_step_company_path(:id => company.id)
18 |
19 | assert_select "li.next_step" do
20 | assert_select "input[value='Next step']"
21 | end
22 |
23 | assert_select "li.save" do
24 | assert_select "input[value='Finish later']"
25 | end
26 |
27 | assert_select "li.previous_step" do
28 | assert_select "input[value='Previous step']"
29 | end
30 | end
31 |
32 | test "last step should have 'finish later', 'previous step' and 'finish' buttons" do
33 | company = Company.create!(:name => "My company", :code => "04108", :my_step => "step2")
34 | get next_step_company_path(:id => company.id)
35 |
36 | assert_select "li.finish" do
37 | assert_select "input[value='Finish form']"
38 | end
39 |
40 | assert_select "li.save" do
41 | assert_select "input[value='Finish later']"
42 | end
43 |
44 | assert_select "li.previous_step" do
45 | assert_select "input[value='Previous step']"
46 | end
47 | end
48 |
49 | end
--------------------------------------------------------------------------------
/test/controllers/controller_update_test.rb:
--------------------------------------------------------------------------------
1 | require "helper"
2 |
3 | class CompaniesUpdateControllerTest < ActionController::TestCase
4 | tests CompaniesController
5 |
6 | setup do
7 | Company.expects(:find).with('1').returns(mock_company)
8 | mock_company.expects(:attributes=).with({'code' => '23'}).returns(true)
9 | mock_company.expects(:save).returns(true)
10 | mock_company.stubs(:id).returns(1)
11 | end
12 |
13 | test "should redirect to next step if commit 'Next step'" do
14 | mock_company.stubs(:stepper_current_step).returns("step2")
15 | put(:update, {:company => {:code => "23"}, :commit => "Next step", :id => 1})
16 | assert_response :redirect
17 | assert_redirected_to "http://test.host/companies/1/next_step"
18 | end
19 |
20 | test "should redirect to index if commit 'Finish later'" do
21 | mock_company.stubs(:previous_step!)
22 | put(:update, {:company => {:code => "23"}, :commit => "Finish later", :id => 1})
23 | assert_response :redirect
24 | assert_redirected_to "http://test.host/companies"
25 | end
26 |
27 | test "should redirect to previous step if commit 'Previous step'" do
28 | mock_company.expects(:previous_step!).returns(mock_company).at_least(2)
29 | mock_company.stubs(:current_step).returns("step2")
30 | put(:update, {:company => {:code => "23"}, :commit => "Previous step", :id => 1})
31 | assert_response :redirect
32 | assert_redirected_to "http://test.host/companies/1/next_step"
33 | end
34 |
35 | test "should redirect to show if commit 'Finish form'" do
36 | put(:update, {:company => {:code => "23"}, :commit => "Finish form", :id => 1})
37 | assert_response :redirect
38 | assert_redirected_to "http://test.host/companies/1"
39 | end
40 |
41 | protected
42 | def mock_company(stubs={})
43 | @mock_company ||= mock(stubs)
44 | end
45 | end
--------------------------------------------------------------------------------
/test/rails_app/config/application.rb:
--------------------------------------------------------------------------------
1 | require File.expand_path('../boot', __FILE__)
2 |
3 | # Pick the frameworks you want:
4 | require "active_record/railtie"
5 | require "action_controller/railtie"
6 | require "action_mailer/railtie"
7 | require "active_resource/railtie"
8 | require "rails/test_unit/railtie"
9 |
10 | require "stepper"
11 |
12 | module RailsApp
13 | class Application < Rails::Application
14 | # Settings in config/environments/* take precedence over those specified here.
15 | # Application configuration should go into files in config/initializers
16 | # -- all .rb files in that directory are automatically loaded.
17 |
18 | # Custom directories with classes and modules you want to be autoloadable.
19 | # config.autoload_paths += %W(#{config.root}/extras)
20 |
21 | # Only load the plugins named here, in the order given (default is alphabetical).
22 | # :all can be used as a placeholder for all plugins not explicitly named.
23 | # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
24 |
25 | # Activate observers that should always be running.
26 | # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
27 |
28 | # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
29 | # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
30 | # config.time_zone = 'Central Time (US & Canada)'
31 |
32 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
33 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
34 | # config.i18n.default_locale = :de
35 |
36 | # Configure the default encoding used in templates for Ruby 1.9.
37 | config.encoding = "utf-8"
38 |
39 | # Configure sensitive parameters which will be filtered from the log file.
40 | config.filter_parameters += [:password]
41 |
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/test/rails_app/config/environments/test.rb:
--------------------------------------------------------------------------------
1 | RailsApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # The test environment is used exclusively to run your application's
5 | # test suite. You never need to work with it otherwise. Remember that
6 | # your test database is "scratch space" for the test suite and is wiped
7 | # and recreated between test runs. Don't rely on the data there!
8 | config.cache_classes = true
9 |
10 | # Configure static asset server for tests with Cache-Control for performance
11 | config.serve_static_assets = true
12 | config.static_cache_control = "public, max-age=3600"
13 |
14 | # Log error messages when you accidentally call methods on nil
15 | config.whiny_nils = true
16 |
17 | # Show full error reports and disable caching
18 | config.consider_all_requests_local = true
19 | config.action_controller.perform_caching = false
20 |
21 | # Raise exceptions instead of rendering exception templates
22 | config.action_dispatch.show_exceptions = false
23 |
24 | # Disable request forgery protection in test environment
25 | config.action_controller.allow_forgery_protection = false
26 |
27 | # Tell Action Mailer not to deliver emails to the real world.
28 | # The :test delivery method accumulates sent emails in the
29 | # ActionMailer::Base.deliveries array.
30 | config.action_mailer.delivery_method = :test
31 |
32 | # Use SQL instead of Active Record's schema dumper when creating the test database.
33 | # This is necessary if your schema can't be completely dumped by the schema dumper,
34 | # like if you have constraints or database-specific column types
35 | # config.active_record.schema_format = :sql
36 |
37 | # Print deprecation notices to the stderr
38 | config.active_support.deprecation = :stderr
39 |
40 | # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets
41 | config.assets.allow_debugging = true
42 | end
43 |
--------------------------------------------------------------------------------
/test/models/instance_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 | class InstanceModelTest < ActiveSupport::TestCase
3 | setup do
4 | @company = Company.new
5 | end
6 |
7 | test "should have steeper_steps methods" do
8 | assert_equal @company.stepper_steps, ["step1", "step2", "step3"]
9 | end
10 |
11 | test "should have steps methods if steps method is free" do
12 | assert_equal @company.steps, ["step1", "step2", "step3"]
13 | end
14 |
15 | test "should check step is first" do
16 | assert @company.first_step?("step1")
17 | assert !@company.first_step?("step3")
18 | end
19 |
20 | test "should check step is last" do
21 | assert @company.last_step?("step3")
22 | assert !@company.last_step?("step1")
23 | end
24 |
25 | test "should check current step is first" do
26 | @company.my_step = "step1"
27 | assert @company.first_step?
28 | @company.my_step = "step3"
29 | assert !@company.first_step?
30 | end
31 |
32 | test "should check current step is last" do
33 | @company.my_step = "step3"
34 | assert @company.last_step?
35 | @company.my_step = "step1"
36 | assert !@company.last_step?
37 | end
38 |
39 | test "should return previous step" do
40 | assert_equal @company.previous_step, nil
41 | @company.my_step = "step1"
42 | assert_equal @company.previous_step, nil
43 | @company.my_step = "step2"
44 | assert_equal @company.previous_step, "step1"
45 | end
46 |
47 | test "should return next step" do
48 | assert_equal @company.next_step, "step1"
49 | @company.my_step = "step2"
50 | assert_equal @company.next_step, "step3"
51 | @company.my_step = "step3"
52 | assert_equal @company.next_step, nil
53 | end
54 |
55 | test "should next_step! change step" do
56 | @company.next_step!
57 | assert_equal @company.my_step, "step1"
58 | end
59 |
60 | test "should previous_step! change step" do
61 | @company.my_step = "step3"
62 | @company.previous_step!
63 | assert_equal @company.my_step, "step2"
64 | end
65 | end
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # encoding: utf-8
2 |
3 | require 'rubygems'
4 | require 'bundler'
5 | begin
6 | Bundler.setup(:default, :development)
7 | rescue Bundler::BundlerError => e
8 | $stderr.puts e.message
9 | $stderr.puts "Run `bundle install` to install missing gems"
10 | exit e.status_code
11 | end
12 | require 'rake'
13 |
14 | require 'jeweler'
15 | Jeweler::Tasks.new do |gem|
16 | # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17 | gem.name = "stepper"
18 | gem.homepage = "http://github.com/antonversal/stepper"
19 | gem.license = "MIT"
20 | gem.summary = %Q{Stepper is multistep form (wizard) solution for Rails 3.}
21 | gem.description = %Q{Stepper is multistep form (wizard) solution for Rails 3. Stepper allows you to split up your large form into series of pages that users can navigate through to complete the form and save it state.}
22 | gem.email = "ant.ver@gmail.com"
23 | gem.authors = ["Anton Versal"]
24 | # dependencies defined in Gemfile
25 | end
26 | Jeweler::RubygemsDotOrgTasks.new
27 |
28 | require 'rake/testtask'
29 | Rake::TestTask.new(:test) do |test|
30 | test.libs << 'lib' << 'test'
31 | test.pattern = 'test/**/*_test.rb'
32 | test.verbose = true
33 | end
34 |
35 | task :default => :test
36 |
37 | begin
38 | require 'rcov/rcovtask'
39 |
40 | Rcov::RcovTask.new do |test|
41 | test.libs << 'test'
42 | test.pattern = 'test/**/test_*.rb'
43 | test.verbose = true
44 | test.rcov_opts << '--exclude "gems/*"'
45 | end
46 | rescue LoadError => e
47 | end
48 |
49 | begin
50 | require "simplecov"
51 |
52 | desc "Execute tests with coverage report"
53 | task :rcov do
54 | ENV["COVERAGE"]="true"
55 | Rake::Task["test"].execute
56 | end
57 | rescue LoadError
58 | end
59 |
60 | require 'rdoc/task'
61 | Rake::RDocTask.new do |rdoc|
62 | version = File.exist?('VERSION') ? File.read('VERSION') : ""
63 |
64 | rdoc.rdoc_dir = 'rdoc'
65 | rdoc.title = "stepper #{version}"
66 | rdoc.rdoc_files.include('README*')
67 | rdoc.rdoc_files.include('lib/**/*.rb')
68 | end
69 |
--------------------------------------------------------------------------------
/test/controllers/controller_resource_test.rb:
--------------------------------------------------------------------------------
1 | require 'helper'
2 |
3 | class ControllerResourceTest < ActiveSupport::TestCase
4 | setup do
5 | @params = HashWithIndifferentAccess.new(:controller => "companies")
6 | @controller_class = Class.new
7 | @controller = @controller_class.new
8 | @controller.stubs(:params).returns(@params)
9 | end
10 |
11 | test "should load resource into instance variable if params[:id] is specified" do
12 | Company.stubs(:find).with(1).returns(mock_company(:id => 1))
13 | @params.merge!(:action => "next_step", :id => mock_company.id)
14 | resource = Stepper::ControllerResource.new(@controller)
15 | resource.load_resource
16 | assert_equal @controller.instance_variable_get(:@company), mock_company
17 | end
18 |
19 | test "should build resource and load into instance variable if params[:id] is not specified" do
20 | Company.stubs(:new).returns(mock_company)
21 | @params.merge!(:action => "some_action")
22 | resource = Stepper::ControllerResource.new(@controller)
23 | resource.load_resource
24 | assert_equal @controller.instance_variable_get(:@company), mock_company
25 | end
26 |
27 | test "should load resource into instance variable(:new)" do
28 | Company.stubs(:new).returns(mock_company)
29 | @params.merge!(:action => "create")
30 | resource = Stepper::ControllerResource.new(@controller)
31 | resource.load_resource
32 | assert_equal @controller.instance_variable_get(:@company), mock_company
33 | end
34 |
35 | test "should not load resource into instance variable if instance variable exists" do
36 | @controller.instance_variable_set(:@company, mock_company)
37 | @params.merge!(:action => "next_step", :id => 15)
38 | resource = Stepper::ControllerResource.new(@controller)
39 | resource.load_resource
40 | assert_equal @controller.instance_variable_get(:@company), mock_company
41 | end
42 |
43 | protected
44 | def mock_company(stubs={})
45 | @mock_company ||= mock(stubs)
46 | end
47 |
48 |
49 | end
--------------------------------------------------------------------------------
/test/rails_app/config/environments/production.rb:
--------------------------------------------------------------------------------
1 | RailsApp::Application.configure do
2 | # Settings specified here will take precedence over those in config/application.rb
3 |
4 | # Code is not reloaded between requests
5 | config.cache_classes = true
6 |
7 | # Full error reports are disabled and caching is turned on
8 | config.consider_all_requests_local = false
9 | config.action_controller.perform_caching = true
10 |
11 | # Disable Rails's static asset server (Apache or nginx will already do this)
12 | config.serve_static_assets = false
13 |
14 | # Compress JavaScripts and CSS
15 | config.assets.compress = true
16 |
17 | # Don't fallback to assets pipeline if a precompiled asset is missed
18 | config.assets.compile = false
19 |
20 | # Generate digests for assets URLs
21 | config.assets.digest = true
22 |
23 | # Defaults to Rails.root.join("public/assets")
24 | # config.assets.manifest = YOUR_PATH
25 |
26 | # Specifies the header that your server uses for sending files
27 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28 | # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
29 |
30 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
31 | # config.force_ssl = true
32 |
33 | # See everything in the log (default is :info)
34 | # config.log_level = :debug
35 |
36 | # Use a different logger for distributed setups
37 | # config.logger = SyslogLogger.new
38 |
39 | # Use a different cache store in production
40 | # config.cache_store = :mem_cache_store
41 |
42 | # Enable serving of images, stylesheets, and JavaScripts from an asset server
43 | # config.action_controller.asset_host = "http://assets.example.com"
44 |
45 | # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
46 | # config.assets.precompile += %w( search.js )
47 |
48 | # Disable delivery errors, bad email addresses will be ignored
49 | # config.action_mailer.raise_delivery_errors = false
50 |
51 | # Enable threaded mode
52 | # config.threadsafe!
53 |
54 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
55 | # the I18n.default_locale when a translation can not be found)
56 | config.i18n.fallbacks = true
57 |
58 | # Send deprecation notices to registered listeners
59 | config.active_support.deprecation = :notify
60 | end
61 |
--------------------------------------------------------------------------------
/lib/stepper/controllers/controller_resource.rb:
--------------------------------------------------------------------------------
1 | module Stepper
2 | class ControllerResource
3 | # Sets up before filter in +controller_class+ for +create+, +update+, +new+ and +next_step+ actions.
4 | # First argument can be name of resource.
5 | # For example we have +CompaniesController+ and want to load or build resource to +@my_company+ variable:
6 | # add_before_filter CompanyController, :my_company
7 | #
8 | # First argument it isn't required:
9 | # add_before_filter CompanyController
10 | # In this case resource will be loaded or built into +@company+ variable
11 | #
12 | def self.add_before_filter(controller_class, *args)
13 | resource_name = args.first if args.first.is_a?(Symbol) or args.first.is_a?(String)
14 | options = args.extract_options!
15 | controller_class.send(:before_filter, :only => [:create, :update, :new, :next_step]) do |controller|
16 | controller.instance_variable_set :@_stepper_redirect_to, options[:redirect_to] || {}
17 | controller_resource = controller.class.stepper_resource_class.new(controller, resource_name)
18 | controller.instance_variable_set :@_stepper_resource_instance, controller_resource.load_resource
19 | controller.instance_variable_set :@_stepper_name, controller_resource.name
20 | end
21 | end
22 |
23 | def initialize(controller, *args)
24 | @controller = controller
25 | @params = controller.params
26 | @name = args.first
27 | end
28 |
29 | def load_resource
30 | self.resource_instance ||= load_resource_instance
31 | self.resource_instance.attributes = @params[name] unless @params[name].blank?
32 | self.resource_instance
33 | end
34 |
35 | def load_resource_instance
36 | if ['create', 'new'].include? @params[:action]
37 | resource = resource_class.new(@params[name] || {})
38 | else
39 | resource = unless @params[:id].blank?
40 | resource_class.find(@params[:id])
41 | else
42 | resource_class.new
43 | end
44 | end
45 | resource
46 | end
47 |
48 | def resource_class
49 | name.camelize.constantize
50 | end
51 |
52 | def name_from_controller
53 | @params[:controller].sub("Controller", "").underscore.split('/').last.singularize
54 | end
55 |
56 | def name
57 | @name || name_from_controller
58 | end
59 |
60 | def resource_instance=(object)
61 | @controller.instance_variable_set "@#{name}", object
62 | end
63 |
64 | def resource_instance
65 | @controller.instance_variable_get "@#{name}"
66 | end
67 |
68 | end
69 | end
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | actionmailer (3.2.1)
5 | actionpack (= 3.2.1)
6 | mail (~> 2.4.0)
7 | actionpack (3.2.1)
8 | activemodel (= 3.2.1)
9 | activesupport (= 3.2.1)
10 | builder (~> 3.0.0)
11 | erubis (~> 2.7.0)
12 | journey (~> 1.0.1)
13 | rack (~> 1.4.0)
14 | rack-cache (~> 1.1)
15 | rack-test (~> 0.6.1)
16 | sprockets (~> 2.1.2)
17 | activemodel (3.2.1)
18 | activesupport (= 3.2.1)
19 | builder (~> 3.0.0)
20 | activerecord (3.2.1)
21 | activemodel (= 3.2.1)
22 | activesupport (= 3.2.1)
23 | arel (~> 3.0.0)
24 | tzinfo (~> 0.3.29)
25 | activeresource (3.2.1)
26 | activemodel (= 3.2.1)
27 | activesupport (= 3.2.1)
28 | activesupport (3.2.1)
29 | i18n (~> 0.6)
30 | multi_json (~> 1.0)
31 | addressable (2.2.7)
32 | archive-tar-minitar (0.5.2)
33 | arel (3.0.2)
34 | builder (3.0.0)
35 | capybara (1.1.2)
36 | mime-types (>= 1.16)
37 | nokogiri (>= 1.3.3)
38 | rack (>= 1.0.0)
39 | rack-test (>= 0.5.4)
40 | selenium-webdriver (~> 2.0)
41 | xpath (~> 0.1.4)
42 | childprocess (0.3.1)
43 | ffi (~> 1.0.6)
44 | columnize (0.3.6)
45 | erubis (2.7.0)
46 | ffi (1.0.11)
47 | git (1.2.5)
48 | hike (1.2.1)
49 | i18n (0.6.0)
50 | jeweler (1.8.3)
51 | bundler (~> 1.0)
52 | git (>= 1.2.5)
53 | rake
54 | rdoc
55 | journey (1.0.3)
56 | json (1.6.5)
57 | json_pure (1.6.5)
58 | launchy (2.0.5)
59 | addressable (~> 2.2.6)
60 | linecache (0.46)
61 | rbx-require-relative (> 0.0.4)
62 | linecache19 (0.5.13)
63 | ruby_core_source (>= 0.1.4)
64 | mail (2.4.1)
65 | i18n (>= 0.4.0)
66 | mime-types (~> 1.16)
67 | treetop (~> 1.4.8)
68 | metaclass (0.0.1)
69 | mime-types (1.17.2)
70 | mocha (0.10.4)
71 | metaclass (~> 0.0.1)
72 | multi_json (1.1.0)
73 | nokogiri (1.5.0)
74 | polyglot (0.3.3)
75 | rack (1.4.1)
76 | rack-cache (1.1)
77 | rack (>= 0.4)
78 | rack-ssl (1.3.2)
79 | rack
80 | rack-test (0.6.1)
81 | rack (>= 1.0)
82 | rails (3.2.1)
83 | actionmailer (= 3.2.1)
84 | actionpack (= 3.2.1)
85 | activerecord (= 3.2.1)
86 | activeresource (= 3.2.1)
87 | activesupport (= 3.2.1)
88 | bundler (~> 1.0)
89 | railties (= 3.2.1)
90 | railties (3.2.1)
91 | actionpack (= 3.2.1)
92 | activesupport (= 3.2.1)
93 | rack-ssl (~> 1.3.2)
94 | rake (>= 0.8.7)
95 | rdoc (~> 3.4)
96 | thor (~> 0.14.6)
97 | rake (0.9.2.2)
98 | rbx-require-relative (0.0.6)
99 | rcov (1.0.0)
100 | rdoc (3.12)
101 | json (~> 1.4)
102 | ruby-debug (0.10.4)
103 | columnize (>= 0.1)
104 | ruby-debug-base (~> 0.10.4.0)
105 | ruby-debug-base (0.10.4)
106 | linecache (>= 0.3)
107 | ruby-debug-base19 (0.11.26)
108 | columnize (>= 0.3.1)
109 | linecache19 (>= 0.5.11)
110 | ruby_core_source (>= 0.1.4)
111 | ruby-debug19 (0.11.6)
112 | columnize (>= 0.3.1)
113 | linecache19 (>= 0.5.11)
114 | ruby-debug-base19 (>= 0.11.19)
115 | ruby_core_source (0.1.5)
116 | archive-tar-minitar (>= 0.5.2)
117 | rubyzip (0.9.6.1)
118 | selenium-webdriver (2.13.0)
119 | childprocess (>= 0.2.1)
120 | ffi (~> 1.0.9)
121 | json_pure
122 | rubyzip
123 | shoulda (2.11.3)
124 | simplecov (0.6.0)
125 | multi_json (~> 1.0)
126 | simplecov-html (~> 0.5.3)
127 | simplecov-html (0.5.3)
128 | sprockets (2.1.2)
129 | hike (~> 1.2)
130 | rack (~> 1.0)
131 | tilt (~> 1.1, != 1.3.0)
132 | sqlite3 (1.3.5)
133 | thor (0.14.6)
134 | tilt (1.3.3)
135 | treetop (1.4.10)
136 | polyglot
137 | polyglot (>= 0.3.1)
138 | tzinfo (0.3.31)
139 | xpath (0.1.4)
140 | nokogiri (~> 1.3)
141 |
142 | PLATFORMS
143 | ruby
144 |
145 | DEPENDENCIES
146 | bundler (>= 1.0.0)
147 | capybara
148 | jeweler (>= 1.6.4)
149 | launchy
150 | mocha
151 | rails (>= 3.1.0)
152 | rcov
153 | ruby-debug
154 | ruby-debug19
155 | shoulda
156 | simplecov
157 | sqlite3
158 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Stepper
2 |
3 | [](http://travis-ci.org/antonversal/stepper)
4 |
5 | Stepper is multistep form (wizard) solution for Rails 3.1.
6 | Stepper allows you to split up your large form into series of pages that users can navigate through to complete the form and saving it's state.
7 |
8 | ## Installation
9 |
10 | You can use it with Rails >= 3.1:
11 |
12 | `gem install stepper`
13 |
14 | ## Getting Started
15 |
16 | ### Configuring model
17 |
18 | Create migration for model:
19 |
20 | ```ruby
21 | add_column :companies, :current_step, :string
22 | add_index :companies, :current_step
23 | ```
24 |
25 | Setup names of steps that you want to have:
26 |
27 | ```ruby
28 | class Company < ActiveRecord::Base
29 | has_steps :steps => %w{ description kind address }
30 | end
31 | ```
32 |
33 | Setup validation for each step if necessary, method should have name like `validate_#{step_name}`:
34 |
35 | ```ruby
36 | def validate_description
37 | self.validates_presence_of :name
38 | self.validates_presence_of :desc
39 | end
40 |
41 | def validate_address
42 | self.validates_presence_of :city
43 | self.validates_presence_of :country
44 | self.validates_presence_of :address
45 | end
46 |
47 | def validate_kind
48 | self.validates_presence_of :kind
49 | end
50 | ```
51 |
52 | Now your model supports a multistep form!
53 |
54 | ### Configuring controller
55 |
56 | Stepper uses `update`, `create`, `new` and `next_step` actions, so you should have the following routes:
57 |
58 | ```ruby
59 | resources :companies do
60 | get :next_step, :on => :member
61 | end
62 | ```
63 |
64 | For your controller you need just add the `has_steps method:
65 |
66 | ```ruby
67 | class CompaniesController < ApplicationController
68 | has_steps
69 | end
70 | ```
71 |
72 | And you should have a +show+ action because stepper redirects to it after finishing the last step by default. For more options see method documentation.
73 |
74 | ### Configuring view
75 |
76 | Add stepper helper method into the form in view that rendered by new action:
77 |
78 | ```erb
79 | <%= form_for(@company) do |f| %>
80 | <%= stepper f %>
81 | <% end %>
82 | ```
83 |
84 | The `stepper` helper renders partial according to the current step of form. Partials should be named like `#{step_name}_step`:
85 |
86 | `_name_step.html.erb`
87 |
88 | ```erb
89 | <%= f.label :name %>
90 | <%= f.text_field :name %>
91 | <%= f.label :desc %>
92 | <%= f.text_field :desc %>
93 | ```
94 |
95 | `_city_step.html.erb`
96 |
97 | ```erb
98 | <%= f.label :city %>
99 | <%= f.text_field :city %>
100 | <%= f.label :country %>
101 | <%= f.text_field :country %>
102 | <%= f.label :city %>
103 | <%= f.text_field :city %>
104 | ```
105 |
106 | `_kind_step.html.erb`
107 |
108 | ```erb
109 | <%= f.label :kind %>
110 | <%= f.text_field :kind %>
111 | ```
112 |
113 | `stepper` helper creates buttons "Next", "Previous", "Save" and "Finish" as well. You can change button names by adding the following to your locales:
114 |
115 | ```ruby
116 | en:
117 | stepper:
118 | next_step: 'Next step'
119 | previous_step: 'Previous step'
120 | save: 'Finish later'
121 | finish: 'Finish'
122 | ```
123 |
124 | `next_step` button validates, saves current step and renders next step of form;
125 | `previous_step` saves current step and renders previous step of form;
126 | `save` save current step and redirects to index page;
127 | `finish` is showed only for last step instead of `next_step` button and it validates, saves last step and redirects to show.
128 |
129 | If you want to have other partials for buttons than add your partial to: `app/views/stepper/_fields.html.erb`
130 |
131 | ## Contributing to stepper
132 |
133 | * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
134 | * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
135 | * Fork the project
136 | * Start a feature/bugfix branch
137 | * Commit and push until you are happy with your contribution
138 | * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
139 | * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
140 |
141 | ## Copyright
142 |
143 | Copyright (c) 2012 Anton Versal. See LICENSE.txt for
144 | further details.
145 |
146 |
--------------------------------------------------------------------------------
/lib/stepper/models/active_record_additions.rb:
--------------------------------------------------------------------------------
1 | module Stepper
2 |
3 | # This module is automatically included into all models.
4 | module ActiveRecordAdditions
5 |
6 | def self.included(base)
7 | base.extend ClassMethods
8 | end
9 |
10 | module ClassMethods
11 | # Sets up methods and define steps.
12 | # For example, you have model +Company+ and you want to fill it fields in few steps description, kind and address:
13 | # class Company < ActiveRecord::Base
14 | # has_steps :steps => %w{ description kind address }
15 | # end
16 | #
17 | # Model should have current step column, by default it name is +current_step+.
18 | # It should be added by migration:
19 | # add_column :companies, :current_step, :string
20 | # add_index :companies, :current_step
21 | #
22 | # The column name can be set up with option +current_step_column+.
23 | #
24 | # Options:
25 | # [:+steps+]
26 | # It is required option. Define steps for multistep form.
27 | #
28 | # [:+current_step_column+]
29 | # Define what field use for save current step of form. Default +current_step+
30 | #
31 |
32 | def has_steps(options = {})
33 | #check options
34 | raise Stepper::StepperException.new("Options for has_steps must be in a hash.") unless options.is_a? Hash
35 | options.each do |key, value|
36 | unless [:current_step_column, :steps].include? key
37 | raise Stepper::StepperException.new("Unknown option for has_steps: #{key.inspect} => #{value.inspect}.")
38 | end
39 | end
40 |
41 | raise Stepper::StepperException.new(":steps condition can't be blank") if options[:steps].blank?
42 |
43 | #set current step column
44 | class_attribute :stepper_current_step_column, :instance_writer => false
45 | self.stepper_current_step_column = options[:current_step_column] || :current_step
46 |
47 | class_attribute :stepper_options, :instance_writer => false
48 | self.stepper_options = options
49 |
50 | self.validate :current_step_validation
51 |
52 | include InstanceMethods
53 | end
54 | end
55 |
56 | module InstanceMethods
57 | def stepper_steps
58 | self.stepper_options[:steps]
59 | end
60 |
61 | unless self.respond_to? :steps
62 | define_method :steps do
63 | self.stepper_steps
64 | end
65 | end
66 |
67 | # returns index of current step in steps array
68 | def stepper_current_step_index
69 | stepper_steps.index(stepper_current_step)
70 | end
71 |
72 | # returns name of current step
73 | def stepper_current_step
74 | self.send(self.stepper_current_step_column)
75 | end
76 |
77 | # sets up name of current step
78 | def stepper_current_step=(step)
79 | self.send("#{self.stepper_current_step_column.to_s}=", step)
80 | end
81 |
82 | # Use to check current step or given step is last step
83 | # last_step?("address")
84 | def last_step?(step = stepper_current_step)
85 | step == self.stepper_steps.last
86 | end
87 |
88 | # Use to check current step or given step is first step
89 | # first_step?("address")
90 | def first_step?(step = stepper_current_step)
91 | (step == stepper_steps.first) or stepper_current_step.blank? && step.blank?
92 | end
93 |
94 | # returns previous step of current step
95 | def previous_step
96 | return nil if (first_step? or stepper_current_step.blank?)
97 | stepper_steps[stepper_steps.index(stepper_current_step) - 1]
98 | end
99 |
100 | # set previous step as current step
101 | def previous_step!
102 | self.stepper_current_step = self.previous_step
103 | self
104 | end
105 |
106 | # returns next step of current step
107 | def next_step
108 | return stepper_steps.first if self.stepper_current_step.blank?
109 | return nil if self.last_step?
110 | stepper_steps[stepper_steps.index(stepper_current_step) + 1]
111 | end
112 |
113 | # set next step as current step
114 | def next_step!
115 | self.stepper_current_step = self.next_step
116 | self
117 | end
118 |
119 | protected
120 |
121 | # Executes validation methods for current step and all previous steps if its exists.
122 | # You can set up what fields should be validated in methods for steps. For example:
123 | #
124 | # def validate_description
125 | # self.validates_presence_of :name
126 | # self.validates_presence_of :desc
127 | # end
128 | #
129 | # def validate_address
130 | # self.validates_presence_of :city
131 | # self.validates_presence_of :country
132 | # self.validates_presence_of :address
133 | # end
134 | #
135 | # def validate_kind
136 | # self.validates_presence_of :kind
137 | # end
138 |
139 | def current_step_validation
140 | return if stepper_current_step.blank?
141 | for i in 0..stepper_current_step_index do
142 | self.send("validate_#{stepper_steps[i]}") if self.respond_to?("validate_#{stepper_steps[i]}", true)
143 | end
144 | end
145 |
146 | end
147 | end
148 | end
149 |
--------------------------------------------------------------------------------
/lib/stepper/controllers/controller_additions.rb:
--------------------------------------------------------------------------------
1 | module Stepper
2 | module ControllerAdditions
3 |
4 | def self.included(base)
5 | base.extend ClassMethods
6 | end
7 |
8 | module ClassMethods
9 | # Sets up +create+, +update+, +new+ actions for controller and before filter for load resource.
10 | # If you use cancan or load resource in other way it will get loaded resource.
11 | #
12 | # First parameters can be name of resource, for example:
13 | #
14 | # class CompaniesController < ApplicationController
15 | # has_steps :my_company
16 | # end
17 | # It will load or build resource in +@my_company+ variable
18 | #
19 | # First argument it isn't required:
20 | # class CompaniesController < ApplicationController
21 | # has_steps
22 | # end
23 | # In this case resource will be loaded or built into +@company+ variable
24 | #
25 | # You can setup redirection for each +save+, +previous_step+, +next_step+ and +finish+ step to other action than default,
26 | # options should have +after+ prefix:
27 | #
28 | # class CompaniesController < ApplicationController
29 | # has_steps :redirect_to => { :after_save => {:action => :new} }
30 | # end
31 | #
32 | # You can set proc that will be executed for current controller:
33 | #
34 | # class CompaniesController < ApplicationController
35 | # has_steps :redirect_to => { :after_finish => proc{|controller, resource| controller.show_companies_url(resource)} }
36 | # end
37 |
38 | def has_steps(*args)
39 | include InstanceMethods
40 | stepper_resource_class.add_before_filter(self, *args)
41 | end
42 |
43 | def stepper_resource_class
44 | ControllerResource
45 | end
46 |
47 | end
48 |
49 | module InstanceMethods
50 |
51 | # controller +create+ action
52 | # it supports only html responce format for now
53 | def create
54 | respond_to do |format|
55 | if @_stepper_resource_instance.save
56 | format.html { redirect_steps }
57 | else
58 | @_stepper_resource_instance.previous_step!
59 | format.html { render :action => "new" }
60 | end
61 | end
62 | end
63 |
64 | # controller +update+ action
65 | # it supports only html responce format for now
66 | def update
67 | @_stepper_resource_instance.previous_step!.previous_step! if params[:commit] == t('stepper.previous_step').html_safe
68 |
69 | @_stepper_resource_instance.previous_step! if params[:commit] == t('stepper.save').html_safe
70 |
71 | respond_to do |format|
72 | if @_stepper_resource_instance.save
73 | format.html { redirect_steps }
74 | else
75 | @_stepper_resource_instance.previous_step!
76 | format.html { render :action => "new" }
77 | end
78 | end
79 | end
80 |
81 | # controller +new+ action
82 | # it supports only html responce format for now
83 | def new
84 |
85 | end
86 |
87 | # controller +new+ action
88 | # it supports only html responce format for now
89 | def next_step
90 | if @_stepper_resource_instance.last_step?
91 | redirect_to :action => :show, :id => @_stepper_resource_instance.id
92 | else
93 | render :action => :new
94 | end
95 | end
96 |
97 | protected
98 |
99 | # default redirection actions
100 | def default_redirection
101 | {
102 | :next_step => {:action => "next_step", :id => @_stepper_resource_instance.id},
103 | :previous_step => {:action => "next_step"},
104 | :save => {:action => "index"},
105 | :finish => {:action => "show", :id => @_stepper_resource_instance.id}
106 | }
107 | end
108 |
109 | # redirects to controller actions depends of commit value
110 | # save -> index
111 | # previous_step -> new
112 | # next_step -> new
113 | # finish -> show
114 |
115 | def redirect_steps
116 | options, response_status = redirect_steps_options
117 | redirect_to options, response_status
118 | end
119 |
120 | def redirect_steps_options
121 | case params[:commit]
122 | when t('stepper.save')
123 | [ extract_redirect_params(:save), {}]
124 | when t('stepper.previous_step')
125 | [ extract_redirect_params(:previous_step), {}]
126 | when t('stepper.next_step')
127 | [ extract_redirect_params(:next_step), {}]
128 | when t('stepper.finish')
129 | [ extract_redirect_params(:finish), {}]
130 | else
131 | raise Stepper::StepperException.new("Unknown commit: #{params[:commit]}")
132 | end
133 | end
134 |
135 | def extract_redirect_params(option)
136 | redirection = @_stepper_redirect_to["after_#{option.to_s}".to_sym]
137 | if redirection.is_a?(Proc)
138 | redirection.call(self, @_stepper_resource_instance)
139 | else
140 | redirection
141 | end || default_redirection[option]
142 | end
143 |
144 | # removes from params resource name, commit and id
145 | def sanitized_params
146 | params.except(@_stepper_name, :commit, :id)
147 | end
148 | end
149 |
150 | end
151 |
152 | end
--------------------------------------------------------------------------------
/stepper.gemspec:
--------------------------------------------------------------------------------
1 | # Generated by jeweler
2 | # DO NOT EDIT THIS FILE DIRECTLY
3 | # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4 | # -*- encoding: utf-8 -*-
5 |
6 | Gem::Specification.new do |s|
7 | s.name = "stepper"
8 | s.version = "0.2.0"
9 |
10 | s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11 | s.authors = ["Anton Versal"]
12 | s.date = "2012-02-24"
13 | s.description = "Stepper is multistep form (wizard) solution for Rails 3. Stepper allows you to split up your large form into series of pages that users can navigate through to complete the form and save it state."
14 | s.email = "ant.ver@gmail.com"
15 | s.extra_rdoc_files = [
16 | "LICENSE.txt",
17 | "README.md"
18 | ]
19 | s.files = [
20 | ".document",
21 | ".travis.yml",
22 | "Gemfile",
23 | "Gemfile.lock",
24 | "LICENSE.txt",
25 | "README.md",
26 | "Rakefile",
27 | "VERSION",
28 | "app/views/stepper/_fields.html.erb",
29 | "config/locales/stepper.yml",
30 | "lib/stepper.rb",
31 | "lib/stepper/controllers/controller_additions.rb",
32 | "lib/stepper/controllers/controller_resource.rb",
33 | "lib/stepper/engine.rb",
34 | "lib/stepper/exceptions.rb",
35 | "lib/stepper/helper/action_view_additions.rb",
36 | "lib/stepper/models/active_record_additions.rb",
37 | "lib/stepper/railtie.rb",
38 | "stepper.gemspec",
39 | "test/controllers/controller_additions_test.rb",
40 | "test/controllers/controller_create_test.rb",
41 | "test/controllers/controller_invalid_params_test.rb",
42 | "test/controllers/controller_resource_test.rb",
43 | "test/controllers/controller_test.rb",
44 | "test/controllers/controller_update_test.rb",
45 | "test/controllers/redirect_test.rb",
46 | "test/helper.rb",
47 | "test/helpers/helper_test.rb",
48 | "test/integration/steps_test.rb",
49 | "test/models/assigns_test.rb",
50 | "test/models/instance_test.rb",
51 | "test/models/models_test.rb",
52 | "test/models/validation_test.rb",
53 | "test/rails_app/Rakefile",
54 | "test/rails_app/app/controllers/application_controller.rb",
55 | "test/rails_app/app/controllers/companies_controller.rb",
56 | "test/rails_app/app/controllers/orders_controller.rb",
57 | "test/rails_app/app/helpers/application_helper.rb",
58 | "test/rails_app/app/mailers/.gitkeep",
59 | "test/rails_app/app/models/.gitkeep",
60 | "test/rails_app/app/models/big_company.rb",
61 | "test/rails_app/app/models/company.rb",
62 | "test/rails_app/app/models/order.rb",
63 | "test/rails_app/app/models/users.rb",
64 | "test/rails_app/app/views/companies/_step1_step.html.erb",
65 | "test/rails_app/app/views/companies/_step2_step.html.erb",
66 | "test/rails_app/app/views/companies/_step3_step.html.erb",
67 | "test/rails_app/app/views/companies/index.html.erb",
68 | "test/rails_app/app/views/companies/new.html.erb",
69 | "test/rails_app/app/views/companies/show.html.erb",
70 | "test/rails_app/app/views/layouts/application.html.erb",
71 | "test/rails_app/config.ru",
72 | "test/rails_app/config/application.rb",
73 | "test/rails_app/config/boot.rb",
74 | "test/rails_app/config/database.yml",
75 | "test/rails_app/config/environment.rb",
76 | "test/rails_app/config/environments/development.rb",
77 | "test/rails_app/config/environments/production.rb",
78 | "test/rails_app/config/environments/test.rb",
79 | "test/rails_app/config/initializers/backtrace_silencers.rb",
80 | "test/rails_app/config/initializers/inflections.rb",
81 | "test/rails_app/config/initializers/mime_types.rb",
82 | "test/rails_app/config/initializers/secret_token.rb",
83 | "test/rails_app/config/initializers/session_store.rb",
84 | "test/rails_app/config/initializers/wrap_parameters.rb",
85 | "test/rails_app/config/locales/en.yml",
86 | "test/rails_app/config/routes.rb",
87 | "test/rails_app/db/migrate/20110928102949_create_tables.rb",
88 | "test/rails_app/db/schema.rb",
89 | "test/rails_app/lib/assets/.gitkeep",
90 | "test/rails_app/lib/tasks/.gitkeep",
91 | "test/rails_app/public/404.html",
92 | "test/rails_app/public/422.html",
93 | "test/rails_app/public/500.html",
94 | "test/rails_app/public/favicon.ico",
95 | "test/rails_app/public/index.html",
96 | "test/rails_app/public/robots.txt",
97 | "test/rails_app/script/rails"
98 | ]
99 | s.homepage = "http://github.com/antonversal/stepper"
100 | s.licenses = ["MIT"]
101 | s.require_paths = ["lib"]
102 | s.rubygems_version = "1.8.16"
103 | s.summary = "Stepper is multistep form (wizard) solution for Rails 3."
104 |
105 | if s.respond_to? :specification_version then
106 | s.specification_version = 3
107 |
108 | if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
109 | s.add_runtime_dependency(%q, [">= 3.1.0"])
110 | s.add_development_dependency(%q, [">= 0"])
111 | s.add_development_dependency(%q, [">= 0"])
112 | s.add_development_dependency(%q, [">= 0"])
113 | s.add_development_dependency(%q, [">= 0"])
114 | s.add_development_dependency(%q, [">= 1.0.0"])
115 | s.add_development_dependency(%q, [">= 1.6.4"])
116 | s.add_development_dependency(%q, [">= 0"])
117 | s.add_development_dependency(%q, [">= 0"])
118 | s.add_development_dependency(%q, [">= 0"])
119 | s.add_development_dependency(%q, [">= 0"])
120 | s.add_development_dependency(%q, [">= 0"])
121 | else
122 | s.add_dependency(%q, [">= 3.1.0"])
123 | s.add_dependency(%q, [">= 0"])
124 | s.add_dependency(%q, [">= 0"])
125 | s.add_dependency(%q, [">= 0"])
126 | s.add_dependency(%q, [">= 0"])
127 | s.add_dependency(%q, [">= 1.0.0"])
128 | s.add_dependency(%q, [">= 1.6.4"])
129 | s.add_dependency(%q, [">= 0"])
130 | s.add_dependency(%q, [">= 0"])
131 | s.add_dependency(%q, [">= 0"])
132 | s.add_dependency(%q, [">= 0"])
133 | s.add_dependency(%q, [">= 0"])
134 | end
135 | else
136 | s.add_dependency(%q, [">= 3.1.0"])
137 | s.add_dependency(%q, [">= 0"])
138 | s.add_dependency(%q, [">= 0"])
139 | s.add_dependency(%q, [">= 0"])
140 | s.add_dependency(%q, [">= 0"])
141 | s.add_dependency(%q, [">= 1.0.0"])
142 | s.add_dependency(%q, [">= 1.6.4"])
143 | s.add_dependency(%q, [">= 0"])
144 | s.add_dependency(%q, [">= 0"])
145 | s.add_dependency(%q, [">= 0"])
146 | s.add_dependency(%q, [">= 0"])
147 | s.add_dependency(%q, [">= 0"])
148 | end
149 | end
150 |
151 |
--------------------------------------------------------------------------------
/test/rails_app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ruby on Rails: Welcome aboard
5 |
174 |
187 |
188 |
189 |
190 |
203 |
204 |
205 |
209 |
210 |
214 |
215 |
216 |
Getting started
217 |
Here’s how to get rolling:
218 |
219 |
220 | -
221 |
Use rails generate to create your models and controllers
222 | To see all available options, run it without parameters.
223 |
224 |
225 | -
226 |
Set up a default route and remove public/index.html
227 | Routes are set up in config/routes.rb.
228 |
229 |
230 | -
231 |
Create your database
232 | Run rake db:create to create your database. If you're not using SQLite (the default), edit config/database.yml with your username and password.
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
--------------------------------------------------------------------------------