verification 1.0.1

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.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in verification.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 David Heinemeier Hansson
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.
data/README ADDED
@@ -0,0 +1,34 @@
1
+ This module provides a class-level method for specifying that certain
2
+ actions are guarded against being called without certain prerequisites
3
+ being met. This is essentially a special kind of before_filter.
4
+
5
+ An action may be guarded against being invoked without certain request
6
+ parameters being set, or without certain session values existing.
7
+
8
+ When a verification is violated, values may be inserted into the flash, and
9
+ a specified redirection is triggered. If no specific action is configured,
10
+ verification failures will by default result in a 400 Bad Request response.
11
+
12
+ Usage:
13
+
14
+ class GlobalController < ActionController::Base
15
+ # Prevent the #update_settings action from being invoked unless
16
+ # the 'admin_privileges' request parameter exists. The
17
+ # settings action will be redirected to in current controller
18
+ # if verification fails.
19
+ verify :params => "admin_privileges", :only => :update_post,
20
+ :redirect_to => { :action => "settings" }
21
+
22
+ # Disallow a post from being updated if there was no information
23
+ # submitted with the post, and if there is no active post in the
24
+ # session, and if there is no "note" key in the flash. The route
25
+ # named category_url will be redirected to if verification fails.
26
+
27
+ verify :params => "post", :session => "post", "flash" => "note",
28
+ :only => :update_post,
29
+ :add_flash => { "alert" => "Failed to create your message" },
30
+ :redirect_to => :category_url
31
+
32
+ Note that these prerequisites are not business rules. They do not examine
33
+ the content of the session or the parameters. That level of validation should
34
+ be encapsulated by your domain model or helper methods in the controller.
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the verification plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ end
14
+
15
+ desc 'Generate documentation for the verification plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Verification'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ # Include hook code here
2
+
3
+ require 'action_controller/verification'
@@ -0,0 +1,132 @@
1
+ module ActionController #:nodoc:
2
+ module Verification #:nodoc:
3
+ extend ActiveSupport::Concern
4
+
5
+ include AbstractController::Callbacks, Flash, Rendering
6
+
7
+ # This module provides a class-level method for specifying that certain
8
+ # actions are guarded against being called without certain prerequisites
9
+ # being met. This is essentially a special kind of before_filter.
10
+ #
11
+ # An action may be guarded against being invoked without certain request
12
+ # parameters being set, or without certain session values existing.
13
+ #
14
+ # When a verification is violated, values may be inserted into the flash, and
15
+ # a specified redirection is triggered. If no specific action is configured,
16
+ # verification failures will by default result in a 400 Bad Request response.
17
+ #
18
+ # Usage:
19
+ #
20
+ # class GlobalController < ActionController::Base
21
+ # # Prevent the #update_settings action from being invoked unless
22
+ # # the 'admin_privileges' request parameter exists. The
23
+ # # settings action will be redirected to in current controller
24
+ # # if verification fails.
25
+ # verify :params => "admin_privileges", :only => :update_post,
26
+ # :redirect_to => { :action => "settings" }
27
+ #
28
+ # # Disallow a post from being updated if there was no information
29
+ # # submitted with the post, and if there is no active post in the
30
+ # # session, and if there is no "note" key in the flash. The route
31
+ # # named category_url will be redirected to if verification fails.
32
+ #
33
+ # verify :params => "post", :session => "post", "flash" => "note",
34
+ # :only => :update_post,
35
+ # :add_flash => { "alert" => "Failed to create your message" },
36
+ # :redirect_to => :category_url
37
+ #
38
+ # Note that these prerequisites are not business rules. They do not examine
39
+ # the content of the session or the parameters. That level of validation should
40
+ # be encapsulated by your domain model or helper methods in the controller.
41
+ module ClassMethods
42
+ # Verify the given actions so that if certain prerequisites are not met,
43
+ # the user is redirected to a different action. The +options+ parameter
44
+ # is a hash consisting of the following key/value pairs:
45
+ #
46
+ # <tt>:params</tt>::
47
+ # a single key or an array of keys that must be in the <tt>params</tt>
48
+ # hash in order for the action(s) to be safely called.
49
+ # <tt>:session</tt>::
50
+ # a single key or an array of keys that must be in the <tt>session</tt>
51
+ # in order for the action(s) to be safely called.
52
+ # <tt>:flash</tt>::
53
+ # a single key or an array of keys that must be in the flash in order
54
+ # for the action(s) to be safely called.
55
+ # <tt>:method</tt>::
56
+ # a single key or an array of keys--any one of which must match the
57
+ # current request method in order for the action(s) to be safely called.
58
+ # (The key should be a symbol: <tt>:get</tt> or <tt>:post</tt>, for
59
+ # example.)
60
+ # <tt>:xhr</tt>::
61
+ # true/false option to ensure that the request is coming from an Ajax
62
+ # call or not.
63
+ # <tt>:add_flash</tt>::
64
+ # a hash of name/value pairs that should be merged into the session's
65
+ # flash if the prerequisites cannot be satisfied.
66
+ # <tt>:add_headers</tt>::
67
+ # a hash of name/value pairs that should be merged into the response's
68
+ # headers hash if the prerequisites cannot be satisfied.
69
+ # <tt>:redirect_to</tt>::
70
+ # the redirection parameters to be used when redirecting if the
71
+ # prerequisites cannot be satisfied. You can redirect either to named
72
+ # route or to the action in some controller.
73
+ # <tt>:render</tt>::
74
+ # the render parameters to be used when the prerequisites cannot be satisfied.
75
+ # <tt>:only</tt>::
76
+ # only apply this verification to the actions specified in the associated
77
+ # array (may also be a single value).
78
+ # <tt>:except</tt>::
79
+ # do not apply this verification to the actions specified in the associated
80
+ # array (may also be a single value).
81
+ def verify(options={})
82
+ before_filter :only => options[:only], :except => options[:except] do
83
+ verify_action options
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def verify_action(options) #:nodoc:
91
+ if prereqs_invalid?(options)
92
+ flash.update(options[:add_flash]) if options[:add_flash]
93
+ response.headers.merge!(options[:add_headers]) if options[:add_headers]
94
+ apply_remaining_actions(options) unless performed?
95
+ end
96
+ end
97
+
98
+ def prereqs_invalid?(options) # :nodoc:
99
+ verify_presence_of_keys_in_hash_flash_or_params(options) ||
100
+ verify_method(options) ||
101
+ verify_request_xhr_status(options)
102
+ end
103
+
104
+ def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
105
+ [*options[:params] ].find { |v| v && params[v.to_sym].nil? } ||
106
+ [*options[:session]].find { |v| session[v].nil? } ||
107
+ [*options[:flash] ].find { |v| flash[v].nil? }
108
+ end
109
+
110
+ def verify_method(options) # :nodoc:
111
+ [*options[:method]].all? { |v| request.request_method_symbol != v.to_sym } if options[:method]
112
+ end
113
+
114
+ def verify_request_xhr_status(options) # :nodoc:
115
+ request.xhr? != options[:xhr] unless options[:xhr].nil?
116
+ end
117
+
118
+ def apply_redirect_to(redirect_to_option) # :nodoc:
119
+ (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.__send__(redirect_to_option) : redirect_to_option
120
+ end
121
+
122
+ def apply_remaining_actions(options) # :nodoc:
123
+ case
124
+ when options[:render] ; render(options[:render])
125
+ when options[:redirect_to] ; redirect_to(apply_redirect_to(options[:redirect_to]))
126
+ else head(:bad_request)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ ActionController::Base.send :include, ActionController::Verification
@@ -0,0 +1 @@
1
+ require 'action_controller/verification'
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
4
+ require 'action_controller'
5
+ require File.dirname(__FILE__) + '/../lib/action_controller/verification'
6
+
7
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
8
+ SharedTestRoutes.draw do
9
+ match '/:controller(/:action(/:id))'
10
+ end
11
+
12
+ ActionController::Base.send :include, SharedTestRoutes.url_helpers
13
+
14
+ module ActionController
15
+ class TestCase
16
+ setup { @routes = SharedTestRoutes }
17
+ end
18
+ end
@@ -0,0 +1,288 @@
1
+ require 'test_helper'
2
+
3
+ class VerificationTestController < ActionController::Base
4
+ use Rack::MethodOverride
5
+
6
+ verify :only => :guarded_one, :params => "one",
7
+ :add_flash => { :error => 'unguarded' },
8
+ :redirect_to => { :action => "unguarded" }
9
+
10
+ verify :only => :guarded_two, :params => %w( one two ),
11
+ :redirect_to => { :action => "unguarded" }
12
+
13
+ verify :only => :guarded_with_flash, :params => "one",
14
+ :add_flash => { :notice => "prereqs failed" },
15
+ :redirect_to => { :action => "unguarded" }
16
+
17
+ verify :only => :guarded_in_session, :session => "one",
18
+ :redirect_to => { :action => "unguarded" }
19
+
20
+ verify :only => [:multi_one, :multi_two], :session => %w( one two ),
21
+ :redirect_to => { :action => "unguarded" }
22
+
23
+ verify :only => :guarded_by_method, :method => :post,
24
+ :redirect_to => { :action => "unguarded" }
25
+
26
+ verify :only => :guarded_by_xhr, :xhr => true,
27
+ :redirect_to => { :action => "unguarded" }
28
+
29
+ verify :only => :guarded_by_not_xhr, :xhr => false,
30
+ :redirect_to => { :action => "unguarded" }
31
+
32
+ before_filter :unconditional_redirect, :only => :two_redirects
33
+ verify :only => :two_redirects, :method => :post,
34
+ :redirect_to => { :action => "unguarded" }
35
+
36
+ verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" }
37
+
38
+ verify :only => :must_be_put, :method => :put, :render => { :status => 405, :text => "Must be put" }, :add_headers => { "Allow" => "PUT" }
39
+
40
+ verify :only => :guarded_one_for_named_route_test, :params => "one",
41
+ :redirect_to => :foo_url
42
+
43
+ verify :only => :no_default_action, :params => "santa"
44
+
45
+ verify :only => :guarded_with_back, :method => :post,
46
+ :redirect_to => :back
47
+
48
+ def guarded_one
49
+ render :text => "#{params[:one]}"
50
+ end
51
+
52
+ def guarded_one_for_named_route_test
53
+ render :text => "#{params[:one]}"
54
+ end
55
+
56
+ def guarded_with_flash
57
+ render :text => "#{params[:one]}"
58
+ end
59
+
60
+ def guarded_two
61
+ render :text => "#{params[:one]}:#{params[:two]}"
62
+ end
63
+
64
+ def guarded_in_session
65
+ render :text => "#{session["one"]}"
66
+ end
67
+
68
+ def multi_one
69
+ render :text => "#{session["one"]}:#{session["two"]}"
70
+ end
71
+
72
+ def multi_two
73
+ render :text => "#{session["two"]}:#{session["one"]}"
74
+ end
75
+
76
+ def guarded_by_method
77
+ render :text => "#{request.method}"
78
+ end
79
+
80
+ def guarded_by_xhr
81
+ render :text => "#{request.xhr?}"
82
+ end
83
+
84
+ def guarded_by_not_xhr
85
+ render :text => "#{request.xhr?}"
86
+ end
87
+
88
+ def unguarded
89
+ render :text => "#{params[:one]}"
90
+ end
91
+
92
+ def two_redirects
93
+ render :nothing => true
94
+ end
95
+
96
+ def must_be_post
97
+ render :text => "Was a post!"
98
+ end
99
+
100
+ def must_be_put
101
+ render :text => "Was a put!"
102
+ end
103
+
104
+ def guarded_with_back
105
+ render :text => "#{params[:one]}"
106
+ end
107
+
108
+ def no_default_action
109
+ # Will never run
110
+ end
111
+
112
+ protected
113
+
114
+ def unconditional_redirect
115
+ redirect_to :action => "unguarded"
116
+ end
117
+ end
118
+
119
+ class VerificationTest < ActionController::TestCase
120
+ tests ::VerificationTestController
121
+
122
+ def test_using_symbol_back_with_no_referrer
123
+ assert_raise(ActionController::RedirectBackError) { get :guarded_with_back }
124
+ end
125
+
126
+ def test_using_symbol_back_redirects_to_referrer
127
+ @request.env["HTTP_REFERER"] = "/foo"
128
+ get :guarded_with_back
129
+ assert_redirected_to '/foo'
130
+ end
131
+
132
+ def test_no_deprecation_warning_for_named_route
133
+ assert_not_deprecated do
134
+ with_routing do |set|
135
+ set.draw do
136
+ match 'foo', :to => 'test#foo', :as => :foo
137
+ match 'verification_test/:action', :to => ::VerificationTestController
138
+ end
139
+ get :guarded_one_for_named_route_test, :two => "not one"
140
+ assert_redirected_to '/foo'
141
+ end
142
+ end
143
+ end
144
+
145
+ def test_guarded_one_with_prereqs
146
+ get :guarded_one, :one => "here"
147
+ assert_equal "here", @response.body
148
+ end
149
+
150
+ def test_guarded_one_without_prereqs
151
+ get :guarded_one
152
+ assert_redirected_to :action => "unguarded"
153
+ assert_equal 'unguarded', flash[:error]
154
+ end
155
+
156
+ def test_guarded_with_flash_with_prereqs
157
+ get :guarded_with_flash, :one => "here"
158
+ assert_equal "here", @response.body
159
+ assert flash.empty?
160
+ end
161
+
162
+ def test_guarded_with_flash_without_prereqs
163
+ get :guarded_with_flash
164
+ assert_redirected_to :action => "unguarded"
165
+ assert_equal "prereqs failed", flash[:notice]
166
+ end
167
+
168
+ def test_guarded_two_with_prereqs
169
+ get :guarded_two, :one => "here", :two => "there"
170
+ assert_equal "here:there", @response.body
171
+ end
172
+
173
+ def test_guarded_two_without_prereqs_one
174
+ get :guarded_two, :two => "there"
175
+ assert_redirected_to :action => "unguarded"
176
+ end
177
+
178
+ def test_guarded_two_without_prereqs_two
179
+ get :guarded_two, :one => "here"
180
+ assert_redirected_to :action => "unguarded"
181
+ end
182
+
183
+ def test_guarded_two_without_prereqs_both
184
+ get :guarded_two
185
+ assert_redirected_to :action => "unguarded"
186
+ end
187
+
188
+ def test_unguarded_with_params
189
+ get :unguarded, :one => "here"
190
+ assert_equal "here", @response.body
191
+ end
192
+
193
+ def test_unguarded_without_params
194
+ get :unguarded
195
+ assert @response.body.blank?
196
+ end
197
+
198
+ def test_guarded_in_session_with_prereqs
199
+ get :guarded_in_session, {}, "one" => "here"
200
+ assert_equal "here", @response.body
201
+ end
202
+
203
+ def test_guarded_in_session_without_prereqs
204
+ get :guarded_in_session
205
+ assert_redirected_to :action => "unguarded"
206
+ end
207
+
208
+ def test_multi_one_with_prereqs
209
+ get :multi_one, {}, "one" => "here", "two" => "there"
210
+ assert_equal "here:there", @response.body
211
+ end
212
+
213
+ def test_multi_one_without_prereqs
214
+ get :multi_one
215
+ assert_redirected_to :action => "unguarded"
216
+ end
217
+
218
+ def test_multi_two_with_prereqs
219
+ get :multi_two, {}, "one" => "here", "two" => "there"
220
+ assert_equal "there:here", @response.body
221
+ end
222
+
223
+ def test_multi_two_without_prereqs
224
+ get :multi_two
225
+ assert_redirected_to :action => "unguarded"
226
+ end
227
+
228
+ def test_guarded_by_method_with_prereqs
229
+ post :guarded_by_method
230
+ assert_equal "POST", @response.body
231
+ end
232
+
233
+ def test_guarded_by_method_without_prereqs
234
+ get :guarded_by_method
235
+ assert_redirected_to :action => "unguarded"
236
+ end
237
+
238
+ def test_guarded_by_xhr_with_prereqs
239
+ xhr :post, :guarded_by_xhr
240
+ assert_equal "true", @response.body
241
+ end
242
+
243
+ def test_guarded_by_xhr_without_prereqs
244
+ get :guarded_by_xhr
245
+ assert_redirected_to :action => "unguarded"
246
+ end
247
+
248
+ def test_guarded_by_not_xhr_with_prereqs
249
+ get :guarded_by_not_xhr
250
+ assert_equal "false", @response.body
251
+ end
252
+
253
+ def test_guarded_by_not_xhr_without_prereqs
254
+ xhr :post, :guarded_by_not_xhr
255
+ assert_redirected_to :action => "unguarded"
256
+ end
257
+
258
+ def test_guarded_post_and_calls_render_succeeds
259
+ post :must_be_post
260
+ assert_equal "Was a post!", @response.body
261
+ end
262
+
263
+ def test_guarded_put_and_calls_render_succeeds
264
+ put :must_be_put
265
+ assert_equal "Was a put!", @response.body
266
+ end
267
+
268
+ def test_guarded_post_with_put_params_and_calls_render_succeeds
269
+ post :must_be_put, '_method' => 'put'
270
+ assert_equal "Was a put!", @response.body
271
+ end
272
+
273
+ def test_default_failure_should_be_a_bad_request
274
+ post :no_default_action
275
+ assert_response :bad_request
276
+ end
277
+
278
+ def test_guarded_post_and_calls_render_fails_and_sets_allow_header
279
+ get :must_be_post
280
+ assert_response 405
281
+ assert_equal "Must be post", @response.body
282
+ assert_equal "POST", @response.headers["Allow"]
283
+ end
284
+
285
+ def test_second_redirect
286
+ assert_nothing_raised { get :two_redirects }
287
+ end
288
+ end
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "verification"
5
+ s.version = "1.0.1"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["David Heinemeier Hansson"]
8
+ s.email = ["david@loudthinking.com"]
9
+ s.homepage = "https://rubygems.org/gems/verification"
10
+ s.summary = %q{Verify preconditions for Rails actions}
11
+ s.description = %q{Verify preconditions for Rails actions}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency('activesupport', '~>3.0.0')
19
+ s.add_dependency('actionpack', '~>3.0.0')
20
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: verification
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
11
+ platform: ruby
12
+ authors:
13
+ - David Heinemeier Hansson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-16 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: actionpack
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 3
48
+ - 0
49
+ - 0
50
+ version: 3.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Verify preconditions for Rails actions
54
+ email:
55
+ - david@loudthinking.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - MIT-LICENSE
66
+ - README
67
+ - Rakefile
68
+ - init.rb
69
+ - lib/action_controller/verification.rb
70
+ - lib/verification.rb
71
+ - test/test_helper.rb
72
+ - test/verification_test.rb
73
+ - verification.gemspec
74
+ has_rdoc: true
75
+ homepage: https://rubygems.org/gems/verification
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.3.7
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Verify preconditions for Rails actions
108
+ test_files:
109
+ - test/test_helper.rb
110
+ - test/verification_test.rb