wizardry 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -6,12 +6,84 @@ Simple step-by-step wizard for Rails.
6
6
 
7
7
  Add this line to your application's Gemfile:
8
8
 
9
- gem 'wizardry'
9
+ ```ruby
10
+ gem 'wizardry'
11
+ ```
10
12
 
11
- And then execute:
12
-
13
- $ bundle
13
+ And run the `bundle` command to install it.
14
14
 
15
15
  ## Usage
16
16
 
17
- TODO: Write usage instructions here
17
+ Bring wizardry to your model:
18
+
19
+ ```ruby
20
+ class Product < ActiveRecord::Base
21
+ wizardry :initial, :middle, :final
22
+ end
23
+ ```
24
+
25
+ And you will get a bunch of methods.
26
+ To get name of the current step:
27
+
28
+ ```ruby
29
+ @product.current_step # => 'initial'
30
+ ```
31
+
32
+ To change the current step name:
33
+
34
+ ```ruby
35
+ @product.current_step = :middle
36
+ ```
37
+
38
+ Will be set only if new step name is included in wizardry steps (**initial**, **middle**, **final** in our example).
39
+
40
+ For the second step name:
41
+
42
+ ```ruby
43
+ @product.second_step # => 'middle'
44
+ ```
45
+
46
+ Also `first_step`, `third_step`, etc. methods are available.
47
+
48
+ You can check position of the current step:
49
+
50
+ ```ruby
51
+ @product.second_step? # => true
52
+ # or
53
+ @product.current_step.middle? # => true
54
+ ```
55
+
56
+ Also `first_step?`, `third_step?`, etc. methods are accessible.
57
+
58
+ To get name of the next and previous steps:
59
+
60
+ ```ruby
61
+ @product.next_step
62
+ # and
63
+ @product.previous_step
64
+ ```
65
+
66
+ If not exists next/previous step then `nil` will be returned.
67
+
68
+ Class methods are accessible:
69
+
70
+ ```ruby
71
+ Product.steps # => ['initial', 'middle', 'final']
72
+ # and
73
+ Product.steps_regexp # => /initial|middle|final/
74
+ ```
75
+
76
+ ### Routing helpers
77
+
78
+ Wizardry includes some routing helpers:
79
+
80
+ ```ruby
81
+ resources :products do
82
+ has_wizardry
83
+ end
84
+ # same as
85
+ wizardry_resources :products
86
+ ```
87
+
88
+ will replace default *:id/edit* path with *:id/edit/:step* (and `:step => /initial|middle|final/` in our example).
89
+ `has_wizardry` is also acceptable for singular resources. And `wizardry_resource` herper is here for that.
data/lib/wizardry.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'wizardry/version'
2
2
  require 'wizardry/base'
3
+ require 'wizardry/routes'
3
4
 
4
5
  module Wizardry
5
- ORDINALS = [:first, :second, :third, :fourth, :fifth, :sixth, :seventh]
6
+ ORDINALS = %w[first second third fourth fifth sixth seventh]
6
7
  end
data/lib/wizardry/base.rb CHANGED
@@ -4,9 +4,10 @@ module Wizardry
4
4
 
5
5
  module ClassMethods
6
6
  def wizardry(*steps)
7
- cattr_accessor :steps, instance_writer: false
7
+ class_attribute :steps, :steps_regexp, instance_writer: false
8
8
 
9
- self.steps = steps
9
+ self.steps = steps.map{ |s| s.to_s.inquiry }
10
+ self.steps_regexp = Regexp.new(steps.join('|'))
10
11
 
11
12
  include WizardryMethods
12
13
 
@@ -30,7 +31,8 @@ module Wizardry
30
31
  end
31
32
 
32
33
  def current_step=(step)
33
- @current_step = step if steps.include?(step)
34
+ step = step.to_s
35
+ @current_step = step.inquiry if steps.include?(step)
34
36
  end
35
37
 
36
38
  def next_step
@@ -0,0 +1,34 @@
1
+ class ActionDispatch::Routing::Mapper
2
+ def has_wizardry
3
+ unless resource_scope?
4
+ raise ArgumentError, "can't use has_wizardry outside resource(s) scope"
5
+ end
6
+
7
+ options = @scope[:scope_level_resource].options
8
+
9
+ if options.has_key?(:only)
10
+ only = Array.wrap(options.delete(:only))
11
+ only.map!(&:to_sym).delete(:edit)
12
+ options.merge!(only: only) if only.present?
13
+ end
14
+
15
+ except = Array.wrap(options.delete(:except))
16
+ except.map!(&:to_sym) << :edit
17
+ options.merge!(except: except.uniq)
18
+
19
+ res = @scope[:scope_level_resource].instance_variable_get(:@name)
20
+
21
+ get 'edit/:step' => :edit, step: res.to_s.classify.constantize.steps_regexp, as: :edit, on: :member
22
+ end
23
+
24
+ [:resources, :resource].each do |method|
25
+ class_eval <<-EOT, __FILE__, __LINE__ + 1
26
+ def wizardry_#{method}(*res) # def wizardry_resources(*res)
27
+ #{method} *res do # resources *res do
28
+ has_wizardry # has_wizardry
29
+ yield if block_given? # yield if block_given?
30
+ end # end
31
+ end # end
32
+ EOT
33
+ end
34
+ end
@@ -1,3 +1,3 @@
1
1
  module Wizardry
2
- VERSION = "0.0.1"
2
+ VERSION = '0.0.2'
3
3
  end
@@ -0,0 +1,2 @@
1
+ class ProductsController < ApplicationController
2
+ end
@@ -1,58 +1,6 @@
1
1
  Dummy::Application.routes.draw do
2
- # The priority is based upon order of creation:
3
- # first created -> highest priority.
4
-
5
- # Sample of regular route:
6
- # match 'products/:id' => 'catalog#view'
7
- # Keep in mind you can assign values other than :controller and :action
8
-
9
- # Sample of named route:
10
- # match 'products/:id/purchase' => 'catalog#purchase', :as => :purchase
11
- # This route can be invoked with purchase_url(:id => product.id)
12
-
13
- # Sample resource route (maps HTTP verbs to controller actions automatically):
14
- # resources :products
15
-
16
- # Sample resource route with options:
17
- # resources :products do
18
- # member do
19
- # get 'short'
20
- # post 'toggle'
21
- # end
22
- #
23
- # collection do
24
- # get 'sold'
25
- # end
26
- # end
27
-
28
- # Sample resource route with sub-resources:
29
- # resources :products do
30
- # resources :comments, :sales
31
- # resource :seller
32
- # end
33
-
34
- # Sample resource route with more complex sub-resources
35
- # resources :products do
36
- # resources :comments
37
- # resources :sales do
38
- # get 'recent', :on => :collection
39
- # end
40
- # end
41
-
42
- # Sample resource route within a namespace:
43
- # namespace :admin do
44
- # # Directs /admin/products/* to Admin::ProductsController
45
- # # (app/controllers/admin/products_controller.rb)
46
- # resources :products
47
- # end
48
-
49
- # You can have the root of your site routed with "root"
50
- # just remember to delete public/index.html.
51
- # root :to => 'welcome#index'
52
-
53
- # See how all your routes lay out with "rake routes"
54
-
55
- # This is a legacy wild controller route that's not recommended for RESTful applications.
56
- # Note: This route will make all actions in every controller accessible via GET requests.
57
- # match ':controller(/:action(/:id))(.:format)'
2
+ resources :products, except: :destroy, path_names: { new: :make } do
3
+ get :commit, on: :collection
4
+ has_wizardry
5
+ end
58
6
  end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,20 @@
1
1
  ENV['RAILS_ENV'] = 'test'
2
2
 
3
- require File.expand_path('../dummy/config/environment.rb', __FILE__)
3
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
4
4
  require 'minitest/autorun'
5
+ require 'action_controller/test_case'
6
+
7
+ class MiniTest::Spec
8
+ include ActiveSupport::Testing::SetupAndTeardown
9
+ end
10
+
11
+ class RoutingSpec < Minitest::Spec
12
+ include ActionDispatch::Integration::Runner
13
+ include Rails.application.routes.url_helpers
14
+
15
+ before do
16
+ @routes = Rails.application.routes
17
+ end
18
+
19
+ register_spec_type(/Routing/, self)
20
+ end
@@ -7,28 +7,47 @@ describe Wizardry::Base do
7
7
  end
8
8
 
9
9
  it 'must have steps array' do
10
- assert_equal Product.steps, [:initial, :middle, :final]
10
+ assert_equal Product.steps, %w[initial middle final]
11
+ end
12
+
13
+ it 'must have steps regexp' do
14
+ assert_equal Product.steps_regexp, /initial|middle|final/
15
+ end
16
+
17
+ it 'must be instance of StringInquirer class in steps array' do
18
+ assert_equal Product.steps.map{ |s| s.instance_of?(ActiveSupport::StringInquirer) }, [true, true, true]
11
19
  end
12
20
  end
13
21
 
14
22
  describe 'instance methods' do
15
- before :each do
23
+ before do
16
24
  @product = Product.new
17
25
  end
18
26
 
19
27
  it 'must return current step as first step' do
20
- assert_equal @product.current_step, :initial
28
+ assert_equal @product.current_step, 'initial'
21
29
  end
22
30
 
23
- it 'must set current step name' do
31
+ it 'must update current step name with instance of StringInquirer' do
32
+ @product.current_step = 'middle'
33
+ assert_equal @product.current_step, 'middle'
34
+ assert_instance_of ActiveSupport::StringInquirer, @product.current_step
35
+ end
36
+
37
+ it 'must update current step name when symbol is passed' do
24
38
  @product.current_step = :middle
25
- assert_equal @product.current_step, :middle
39
+ assert_equal @product.current_step, 'middle'
40
+ end
41
+
42
+ it 'must not update current step name' do
43
+ @product.current_step = :fictional
44
+ refute_equal @product.current_step, 'fictional'
26
45
  end
27
46
 
28
47
  it 'must have ordinal methods' do
29
- assert_equal @product.first_step, :initial
30
- assert_equal @product.second_step, :middle
31
- assert_equal @product.last_step, :final
48
+ assert_equal @product.first_step, 'initial'
49
+ assert_equal @product.second_step, 'middle'
50
+ assert_equal @product.last_step, 'final'
32
51
 
33
52
  assert @product.first_step?
34
53
  refute @product.second_step?
@@ -42,7 +61,7 @@ describe Wizardry::Base do
42
61
  end
43
62
 
44
63
  it 'must return next step name' do
45
- assert_equal @product.next_step, :middle
64
+ assert_equal @product.next_step, 'middle'
46
65
  end
47
66
 
48
67
  it 'must return `nil` on last step' do
@@ -56,7 +75,7 @@ describe Wizardry::Base do
56
75
 
57
76
  it 'must return previous step name' do
58
77
  @product.current_step = :middle
59
- assert_equal @product.previous_step, :initial
78
+ assert_equal @product.previous_step, 'initial'
60
79
  end
61
80
  end
62
81
  end
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Wizardry Routing' do
4
+ it 'must accept wizardry `edit` routes' do
5
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1', step: 'initial'}, '/products/1/edit/initial')
6
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1', step: 'middle'}, '/products/1/edit/middle')
7
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1', step: 'final'}, '/products/1/edit/final')
8
+ assert '/products/1/initial', edit_product_path(id: 1, step: 'initial')
9
+ end
10
+
11
+ it 'must accept only valid steps' do
12
+ assert_raises ActionController::RoutingError do
13
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1', step: 'fictional'}, '/products/1/edit/fictional')
14
+ end
15
+ end
16
+
17
+ it 'must not accept default `edit` route' do
18
+ assert_raises ActionController::RoutingError do
19
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1'}, '/products/1/edit')
20
+ end
21
+ end
22
+
23
+ it 'must not accept `destroy` route' do
24
+ assert_raises ActionController::RoutingError do
25
+ assert_recognizes({ controller: 'products', action: 'destroy', id: '1'}, { path: '/products/1', method: :delete })
26
+ end
27
+ end
28
+
29
+ it 'must accept routes defined in block' do
30
+ assert_recognizes({ controller: 'products', action: 'commit' }, '/products/commit')
31
+ assert '/products/commit', commit_products_path
32
+ end
33
+
34
+ it 'must have overriden `new` path name' do
35
+ assert_recognizes({ controller: 'products', action: 'new' }, '/products/make')
36
+ assert '/products/make', new_product_path
37
+ end
38
+
39
+ it 'must have `wizardry_resources` helper' do
40
+ with_routing do |set|
41
+ set.draw{ wizardry_resources :products }
42
+
43
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1', step: 'initial'}, '/products/1/edit/initial')
44
+ end
45
+ end
46
+
47
+ it 'must have `wizardry_resource` helper' do
48
+ with_routing do |set|
49
+ set.draw{ wizardry_resource :products }
50
+
51
+ assert_recognizes({ controller: 'products', action: 'edit', step: 'initial'}, '/products/edit/initial')
52
+ end
53
+ end
54
+
55
+ it 'must not let to use `has_wizardry` outside resource(s) scope' do
56
+ with_routing do |set|
57
+ assert_raises ArgumentError do
58
+ set.draw{ has_wizardry }
59
+ end
60
+ end
61
+ end
62
+
63
+ it 'must not accept default `edit` route with `only` option' do
64
+ with_routing do |set|
65
+ set.draw{ wizardry_resources :products, only: [:edit, :update] }
66
+
67
+ assert_raises ActionController::RoutingError do
68
+ assert_recognizes({ controller: 'products', action: 'edit', id: '1'}, '/products/1/edit')
69
+ end
70
+ end
71
+ end
72
+ end
data/wizardry.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |gem|
8
8
 
9
9
  gem.files = `git ls-files`.split($\)
10
10
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
11
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
11
+ gem.test_files = gem.files.grep(%r{^spec/})
12
12
  gem.name = 'wizardry'
13
13
  gem.require_paths = ['lib']
14
14
  gem.version = Wizardry::VERSION
@@ -16,4 +16,5 @@ Gem::Specification.new do |gem|
16
16
  gem.add_dependency 'rails', '~> 3.2'
17
17
 
18
18
  gem.add_development_dependency 'sqlite3'
19
+ gem.add_development_dependency 'minitest'
19
20
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wizardry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-01 00:00:00.000000000 Z
12
+ date: 2012-08-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  description: Simple step-by-step wizard for Rails
47
63
  email:
48
64
  - lexmag@gmail.com
@@ -57,11 +73,13 @@ files:
57
73
  - Rakefile
58
74
  - lib/wizardry.rb
59
75
  - lib/wizardry/base.rb
76
+ - lib/wizardry/routes.rb
60
77
  - lib/wizardry/version.rb
61
78
  - spec/dummy/Rakefile
62
79
  - spec/dummy/app/assets/javascripts/application.js
63
80
  - spec/dummy/app/assets/stylesheets/application.css
64
81
  - spec/dummy/app/controllers/application_controller.rb
82
+ - spec/dummy/app/controllers/products_controller.rb
65
83
  - spec/dummy/app/helpers/application_helper.rb
66
84
  - spec/dummy/app/mailers/.gitkeep
67
85
  - spec/dummy/app/models/.gitkeep
@@ -94,6 +112,7 @@ files:
94
112
  - spec/dummy/script/rails
95
113
  - spec/spec_helper.rb
96
114
  - spec/wizardry/base_spec.rb
115
+ - spec/wizardry/routes_spec.rb
97
116
  - wizardry.gemspec
98
117
  homepage: ''
99
118
  licenses: []
@@ -109,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
128
  version: '0'
110
129
  segments:
111
130
  - 0
112
- hash: 3814436817286261879
131
+ hash: -4094284250890369797
113
132
  required_rubygems_version: !ruby/object:Gem::Requirement
114
133
  none: false
115
134
  requirements:
@@ -118,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
118
137
  version: '0'
119
138
  segments:
120
139
  - 0
121
- hash: 3814436817286261879
140
+ hash: -4094284250890369797
122
141
  requirements: []
123
142
  rubyforge_project:
124
143
  rubygems_version: 1.8.24
@@ -130,6 +149,7 @@ test_files:
130
149
  - spec/dummy/app/assets/javascripts/application.js
131
150
  - spec/dummy/app/assets/stylesheets/application.css
132
151
  - spec/dummy/app/controllers/application_controller.rb
152
+ - spec/dummy/app/controllers/products_controller.rb
133
153
  - spec/dummy/app/helpers/application_helper.rb
134
154
  - spec/dummy/app/mailers/.gitkeep
135
155
  - spec/dummy/app/models/.gitkeep
@@ -162,3 +182,4 @@ test_files:
162
182
  - spec/dummy/script/rails
163
183
  - spec/spec_helper.rb
164
184
  - spec/wizardry/base_spec.rb
185
+ - spec/wizardry/routes_spec.rb