stronger_parameters 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7f1ac00b775682d4c9c6afb626ba93e34c5592d5
4
+ data.tar.gz: a91d5b4d4d1ca33e232b71761cfce8698f70e989
5
+ SHA512:
6
+ metadata.gz: ddb1bc2266c76e9796903d0f5610878ab6435ae0a99191bebb94e462ecd710deb5b3c4ab3e5b6d5ee4c1101d124015102c9900eb21eceddd71e49a8f18c8b76a
7
+ data.tar.gz: f64f92a712ab52389c838315cc71dc6d9b3f292adfd9a8638213a6d84187762f5c2dd372e838c98a08dd38c7bd3564d45a19b9a98d5961138485bd341b481b48
data/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # stronger_parameters
2
+
3
+ This is an extension of `strong_parameters` with added type checking.
4
+
5
+ ## Simple types
6
+ You can specify simple types like this:
7
+
8
+ ```ruby
9
+ params.permit(
10
+ :id => Parameters.id,
11
+ :name => Parameters.string
12
+ )
13
+ ```
14
+
15
+ ## Arrays
16
+ You can specify arrays like this:
17
+
18
+ ```ruby
19
+ params.permit(
20
+ :id => Parameters.array(Parameters.id)
21
+ )
22
+ ```
23
+
24
+ This will allow an array of id parameters that all are IDs.
25
+
26
+ ## Nested Parameters
27
+
28
+ ```ruby
29
+ params.permit(
30
+ :name => Parameters.string,
31
+ :emails => Parameters.array(Parameters.string),
32
+ :friends => Parameters.array(
33
+ Parameters.map(
34
+ :name => Parameters.string,
35
+ :family => Parameters.map(
36
+ :name => Parameters.string
37
+ )
38
+ :hobbies => Parameters.array(Parameters.string)
39
+ )
40
+ )
41
+ )
42
+ ```
43
+
44
+ This will allow parameters like this:
45
+
46
+ ```json
47
+ {
48
+ "name": "Mick",
49
+ "emails": ["mick@zendesk.com", "mick@staugaard.com"],
50
+ "friends": [
51
+ {"name": "Morten", "family": {"name": "Primdahl"}, "hobbies": ["work", "art"]},
52
+ {"name": "Eric", "family": {"name": "Chapweske"}, "hobbies": ["boating", "whiskey"]}
53
+ ]
54
+ }
55
+ ```
56
+
57
+ ### ActiveModel Nested Attributes
58
+
59
+ ```ruby
60
+ params.require(:author).permit(
61
+ :name => Parameters.string,
62
+ :books_attributes => Parameters.array(
63
+ Parameters.map(
64
+ :title => Parameters.string,
65
+ :id => Parameters.id,
66
+ :_destroy => Parameters.boolean
67
+ )
68
+ )
69
+ )
70
+ ```
71
+
72
+ This will allow parameters like this:
73
+
74
+ ```json
75
+ {
76
+ "author": {
77
+ "name": "Eric Chapweske",
78
+ "books_attributes": [
79
+ {"title": "Boatin' and Drinkin'", "id": 234, "_destroy": true},
80
+ {"title": "Advanced Boatin' and Drinkin'", "id": 567}
81
+ ]
82
+ }
83
+ }
84
+ ```
85
+
86
+ ## Combining Requirements
87
+
88
+ If you want to permit a parameter to be one of multiple types, you can use the `|` operator:
89
+
90
+ ```ruby
91
+ params.require(:ticket).permit(
92
+ :status => Parameters.id | Parameters.enum('open', 'closed')
93
+ )
94
+ ```
95
+
96
+ This will allow these parameter sets:
97
+
98
+ ```json
99
+ {
100
+ "ticket": {
101
+ "status": 123
102
+ }
103
+ }
104
+ ```
105
+ ```json
106
+ {
107
+ "ticket": {
108
+ "status": "open"
109
+ }
110
+ }
111
+ ```
112
+
113
+ You can use the `&` operator to apply further restrictions on the type:
114
+
115
+ ```ruby
116
+ params.require(:user).permit(
117
+ :age => Parameters.integer & Parameters.gte(0)
118
+ )
119
+ ```
120
+
121
+ This requires the parameter to be an integer greater than or equal to 0.
122
+
123
+ ### Combining Requirements in Arrays
124
+
125
+ You can also use the `|` and `&` operators in arrays:
126
+
127
+ ```ruby
128
+ params.require(:group).permit(
129
+ :users => Parameters.array(Parameters.id | Parameters.string)
130
+ )
131
+ ```
132
+
133
+ This will permit these parameters:
134
+ ```json
135
+ {
136
+ "group": {
137
+ "users": [123, "mick@zendesk.com", 345, 676, "morten@zendesk.com"]
138
+ }
139
+ }
140
+ ```
141
+
142
+ ## Types
143
+
144
+ | Syntax | (Simplified) Definition |
145
+ |--------------------------------|-------------------------------------------------------------------------|
146
+ | Parameters.string | value.is_a?(String) |
147
+ | Parameters.integer | value.is_a?(Fixnum) |
148
+ | Parameters.enum('asc', 'desc') | ['asc', 'desc'].include?(value) |
149
+ | Parameters.lt(10) | value < 10 |
150
+ | Parameters.lte(10) | value <= 10 |
151
+ | Parameters.gt(0) | value > 0 |
152
+ | Parameters.gte(0) | value >= 0 |
153
+ | Parameters.integer32 | Parameters.integer & Parameters.lte(2 ** 31) & Parameters.gte(-2 ** 31) |
154
+ | Parameters.integer64 | Parameters.integer & Parameters.lte(2 ** 63) & Parameters.gte(-2 ** 63) |
155
+ | Parameters.id | Parameters.integer & Parameters.lte(2 ** 31) & Parameters.gte(0) |
156
+ | Parameters.bigid | Parameters.integer & Parameters.lte(2 ** 63) & Parameters.gte(0) |
157
+ | Parameters.boolean | Parameters.enum(true, false, 'true', 'false', 1, 0) |
@@ -0,0 +1,6 @@
1
+ require 'stronger_parameters/version'
2
+ require 'action_pack'
3
+ require 'strong_parameters' if ActionPack::VERSION::MAJOR == 3
4
+ require 'stronger_parameters/railtie'
5
+ require 'stronger_parameters/parameters'
6
+ require 'stronger_parameters/constraints'
@@ -0,0 +1,84 @@
1
+ require 'stronger_parameters/errors'
2
+
3
+ module StrongerParameters
4
+ class Constraint
5
+ def value(v)
6
+ v
7
+ end
8
+
9
+ def |(other)
10
+ OrConstraint.new(self, other)
11
+ end
12
+
13
+ def &(other)
14
+ AndConstraint.new(self, other)
15
+ end
16
+
17
+ def ==(other)
18
+ self.class == other.class
19
+ end
20
+ end
21
+
22
+ class OrConstraint < Constraint
23
+ attr_reader :constraints
24
+
25
+ def initialize(*constraints)
26
+ @constraints = constraints
27
+ end
28
+
29
+ def value(v)
30
+ exception = nil
31
+
32
+ constraints.each do |c|
33
+ begin
34
+ return c.value(v)
35
+ rescue InvalidParameter => e
36
+ exception ||= e
37
+ end
38
+ end
39
+
40
+ raise exception
41
+ end
42
+
43
+ def |(other)
44
+ constraints << other
45
+ self
46
+ end
47
+
48
+ def ==(other)
49
+ super && constraints == other.constraints
50
+ end
51
+ end
52
+
53
+ class AndConstraint < Constraint
54
+ attr_reader :constraints
55
+
56
+ def initialize(*constraints)
57
+ @constraints = constraints
58
+ end
59
+
60
+ def value(v)
61
+ constraints.each do |c|
62
+ v = c.value(v)
63
+ end
64
+ v
65
+ end
66
+
67
+ def &(other)
68
+ constraints << other
69
+ self
70
+ end
71
+
72
+ def ==(other)
73
+ super && constraints == other.constraints
74
+ end
75
+ end
76
+ end
77
+
78
+ require 'stronger_parameters/constraints/string_constraint'
79
+ require 'stronger_parameters/constraints/fixnum_constraint'
80
+ require 'stronger_parameters/constraints/boolean_constraint'
81
+ require 'stronger_parameters/constraints/array_constraint'
82
+ require 'stronger_parameters/constraints/hash_constraint'
83
+ require 'stronger_parameters/constraints/enumeration_constraint'
84
+ require 'stronger_parameters/constraints/comparison_constraints'
@@ -0,0 +1,25 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class ArrayConstraint < Constraint
5
+ attr_reader :item_constraint
6
+
7
+ def initialize(item_constraint)
8
+ @item_constraint = item_constraint
9
+ end
10
+
11
+ def value(v)
12
+ if v.is_a?(Array)
13
+ return v.map do |item|
14
+ item_constraint.value(item)
15
+ end
16
+ end
17
+
18
+ raise InvalidParameter.new(v, "must be an array")
19
+ end
20
+
21
+ def ==(other)
22
+ super && item_constraint == other.item_constraint
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,20 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class BooleanConstraint < Constraint
5
+ TRUE_VALUES = [true, 'true', '1', 1].freeze
6
+ FALSE_VALUES = [false, 'false', '0', 0].freeze
7
+
8
+ def value(v)
9
+ if TRUE_VALUES.include?(v)
10
+ return true
11
+ end
12
+
13
+ if FALSE_VALUES.include?(v)
14
+ return false
15
+ end
16
+
17
+ raise InvalidParameter.new(v, "must be either true or false")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,47 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class ComparisonConstraints < Constraint
5
+ attr_reader :limit
6
+
7
+ def initialize(limit)
8
+ @limit = limit
9
+ end
10
+
11
+ def ==(other)
12
+ super && limit == other.limit
13
+ end
14
+ end
15
+
16
+ class LessThanConstraint < ComparisonConstraints
17
+ def value(v)
18
+ return v if v < limit
19
+
20
+ raise InvalidParameter.new(v, "must be less than #{limit}")
21
+ end
22
+ end
23
+
24
+ class LessThanOrEqualConstraint < ComparisonConstraints
25
+ def value(v)
26
+ return v if v <= limit
27
+
28
+ raise InvalidParameter.new(v, "must be less than or equal to #{limit}")
29
+ end
30
+ end
31
+
32
+ class GreaterThanConstraint < ComparisonConstraints
33
+ def value(v)
34
+ return v if v > limit
35
+
36
+ raise InvalidParameter.new(v, "must be greater than #{limit}")
37
+ end
38
+ end
39
+
40
+ class GreaterThanOrEqualConstraint < ComparisonConstraints
41
+ def value(v)
42
+ return v if v >= limit
43
+
44
+ raise InvalidParameter.new(v, "must be greater than or equal to #{limit}")
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,21 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class EnumerationConstraint < Constraint
5
+ attr_reader :allowed
6
+
7
+ def initialize(*allowed)
8
+ @allowed = allowed
9
+ end
10
+
11
+ def value(v)
12
+ return v if allowed.include?(v)
13
+
14
+ raise InvalidParameter.new(v, "must be one of these: #{allowed.to_sentence}")
15
+ end
16
+
17
+ def ==(other)
18
+ super && allowed == other.allowed
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class FixnumConstraint < Constraint
5
+ def value(v)
6
+ if v.is_a?(Fixnum)
7
+ return v
8
+ elsif v.is_a?(String) && v =~ /^\d+$/
9
+ return v.to_i
10
+ end
11
+
12
+ raise InvalidParameter.new(v, 'must be an integer')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,28 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class HashConstraint < Constraint
5
+ attr_reader :constraints
6
+
7
+ def initialize(constraints)
8
+ @constraints = constraints.with_indifferent_access
9
+ end
10
+
11
+ def value(v)
12
+ if v.is_a?(Hash)
13
+ return ActionController::Parameters.new(v).permit(constraints)
14
+ end
15
+
16
+ raise InvalidParameter.new(v, "must be a hash")
17
+ end
18
+
19
+ def merge(other)
20
+ other_constraints = other.is_a?(HashConstraint) ? other.constraints : other
21
+ self.class.new(constraints.merge(other_constraints))
22
+ end
23
+
24
+ def ==(other)
25
+ super && constraints == other.constraints
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ require 'stronger_parameters/constraints'
2
+
3
+ module StrongerParameters
4
+ class StringConstraint < Constraint
5
+ attr_reader :maximum_length
6
+
7
+ def initialize(options = {})
8
+ @maximum_length = options[:maximum_length] || options[:max_length]
9
+ end
10
+
11
+ def value(v)
12
+ if v.is_a?(String)
13
+ if maximum_length && v.bytesize > maximum_length
14
+ raise InvalidParameter.new(v, "can not be longer than #{maximum_length} bytes")
15
+ end
16
+
17
+ return v
18
+ end
19
+
20
+ raise InvalidParameter.new(v, 'must be a string')
21
+ end
22
+
23
+ def ==(other)
24
+ super && maximum_length == other.maximum_length
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module StrongerParameters
2
+ class InvalidParameter < StandardError
3
+ attr_accessor :key, :value, :message
4
+
5
+ def initialize(value, message)
6
+ @value = value
7
+ @message = message
8
+ super(message)
9
+ end
10
+
11
+ def to_s
12
+ if key.present?
13
+ "found invalid value for #{key}. Value #{super}"
14
+ else
15
+ "found invalid value. Value #{super}"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,136 @@
1
+ require 'action_pack'
2
+
3
+ if ActionPack::VERSION::MAJOR == 3
4
+ require 'action_controller/parameters'
5
+ else
6
+ require 'action_controller/metal/strong_parameters'
7
+ end
8
+
9
+ require 'stronger_parameters/constraints'
10
+ require 'stronger_parameters/errors'
11
+
12
+ module StrongerParameters
13
+ module Parameters
14
+ extend ActiveSupport::Concern
15
+
16
+ included do
17
+ alias_method_chain :hash_filter, :stronger_parameters
18
+ cattr_accessor :action_on_invalid_parameters, :instance_accessor => false
19
+ end
20
+
21
+ module ClassMethods
22
+ def anything
23
+ Constraint.new
24
+ end
25
+
26
+ def string(options = {})
27
+ StringConstraint.new(options)
28
+ end
29
+
30
+ def integer
31
+ @integer ||= FixnumConstraint.new
32
+ end
33
+
34
+ def lt(limit)
35
+ LessThanConstraint.new(limit)
36
+ end
37
+
38
+ def lte(limit)
39
+ LessThanOrEqualConstraint.new(limit)
40
+ end
41
+
42
+ def gt(limit)
43
+ GreaterThanConstraint.new(limit)
44
+ end
45
+
46
+ def gte(limit)
47
+ GreaterThanOrEqualConstraint.new(limit)
48
+ end
49
+
50
+ def integer32
51
+ integer & lte(2 ** 31) & gte(-2 ** 31)
52
+ end
53
+
54
+ def integer64
55
+ integer & lte(2 ** 63) & gte(-2 ** 63)
56
+ end
57
+
58
+ def id
59
+ integer & lte(2 ** 31) & gte(0)
60
+ end
61
+
62
+ def bigid
63
+ integer & lte(2 ** 63) & gte(0)
64
+ end
65
+
66
+ def enumeration(*allowed)
67
+ EnumerationConstraint.new(*allowed)
68
+ end
69
+ alias_method :enum, :enumeration
70
+
71
+ def boolean
72
+ BooleanConstraint.new
73
+ end
74
+
75
+ def array(item_constraint)
76
+ ArrayConstraint.new(item_constraint)
77
+ end
78
+
79
+ def map(constraints)
80
+ HashConstraint.new(constraints)
81
+ end
82
+ end
83
+
84
+ def hash_filter_with_stronger_parameters(params, filter)
85
+ stronger_filter = ActiveSupport::HashWithIndifferentAccess.new
86
+ other_filter = ActiveSupport::HashWithIndifferentAccess.new
87
+
88
+ filter.each do |k,v|
89
+ if v.is_a?(Constraint)
90
+ stronger_filter[k] = v
91
+ else
92
+ other_filter[k] = v
93
+ end
94
+ end
95
+
96
+ hash_filter_without_stronger_parameters(params, other_filter)
97
+
98
+ slice(*stronger_filter.keys).each do |key, value|
99
+ if value.nil?
100
+ params[key] = nil
101
+ next
102
+ end
103
+
104
+ constraint = stronger_filter[key]
105
+ begin
106
+ params[key] = constraint.value(value)
107
+ rescue InvalidParameter => e
108
+ e.key = key
109
+
110
+ name = "invalid_parameter.action_controller"
111
+ ActiveSupport::Notifications.publish(name, :key => key, :value => value, :message => e.message)
112
+
113
+ params[key] = value
114
+
115
+ raise unless self.class.action_on_invalid_parameters == :log
116
+ end
117
+ end
118
+ end
119
+
120
+ end
121
+
122
+ module ControllerSupport
123
+ extend ActiveSupport::Concern
124
+
125
+ Parameters = ActionController::Parameters
126
+
127
+ included do
128
+ rescue_from(StrongerParameters::InvalidParameter) do |e|
129
+ render :text => "Invalid parameter: #{e.key} #{e.message}", :status => :bad_request
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ ActionController::Parameters.send :include, StrongerParameters::Parameters
136
+ ActionController::Base.send :include, StrongerParameters::ControllerSupport
@@ -0,0 +1,11 @@
1
+ require 'rails/railtie'
2
+
3
+ module StrongParameters
4
+ class Railtie < ::Rails::Railtie
5
+ initializer "stronger_parameters.config", :before => "action_controller.set_configs" do |app|
6
+ ActionController::Parameters.action_on_invalid_parameters = app.config.action_controller.delete(:action_on_invalid_parameters) do
7
+ (Rails.env.test? || Rails.env.development?) ? :log : false
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module StrongerParameters
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'array parameter constraints' do
4
+ subject { ActionController::Parameters.array(ActionController::Parameters.string) }
5
+
6
+ permits ['a', 'b']
7
+
8
+ rejects 'abc'
9
+ rejects 123
10
+ rejects [123, 456]
11
+ rejects ['abc', 123]
12
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'boolean parameter constraints' do
4
+ subject { ActionController::Parameters.boolean }
5
+
6
+ permits true, :as => true
7
+ permits 'true', :as => true
8
+ permits 1, :as => true
9
+ permits '1', :as => true
10
+
11
+ permits false, :as => false
12
+ permits 'false', :as => false
13
+ permits 0, :as => false
14
+ permits '0', :as => false
15
+
16
+ rejects 'foo'
17
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'comparison parameter constraints' do
4
+ describe 'less-than types' do
5
+ subject { ActionController::Parameters.lt(2) }
6
+
7
+ permits 1
8
+ rejects 2
9
+ rejects 3
10
+ end
11
+
12
+ describe 'less-than-or-equal types' do
13
+ subject { ActionController::Parameters.lte(2) }
14
+
15
+ permits 1
16
+ permits 2
17
+ rejects 3
18
+ end
19
+
20
+ describe 'greater-than types' do
21
+ subject { ActionController::Parameters.gt(2) }
22
+
23
+ rejects 1
24
+ rejects 2
25
+ permits 3
26
+ end
27
+
28
+ describe 'greater-than-or-equal types' do
29
+ subject { ActionController::Parameters.gte(2) }
30
+
31
+ rejects 1
32
+ permits 2
33
+ permits 3
34
+ end
35
+ end
@@ -0,0 +1,26 @@
1
+ require_relative 'test_helper'
2
+
3
+ class BooksController < ActionController::Base
4
+ def create
5
+ params.require(:book).permit(:id => Parameters.integer)
6
+
7
+ head :ok
8
+ end
9
+ end
10
+
11
+ describe BooksController do
12
+ it 'rejects invalid params' do
13
+ post :create, { :magazine => { :name => 'Mjallo!' } }
14
+ assert_response :bad_request
15
+ response.body.must_equal 'Required parameter missing: book'
16
+
17
+ post :create, { :book => { :id => 'Mjallo!' } }
18
+ assert_response :bad_request
19
+ response.body.must_equal 'Invalid parameter: id must be an integer'
20
+ end
21
+
22
+ it 'permits valid params' do
23
+ post :create, { :book => { :id => '123' } }
24
+ assert_response :ok
25
+ end
26
+ end
@@ -0,0 +1,12 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'enum parameter constraints' do
4
+ subject { ActionController::Parameters.enumeration('abc', 123) }
5
+
6
+ permits 'abc'
7
+ permits 123
8
+
9
+ rejects 'abcd'
10
+ rejects '123'
11
+ rejects 1234
12
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'integer parameter constraints' do
4
+ subject { ActionController::Parameters.integer }
5
+
6
+ permits 123
7
+ permits '123', :as => 123
8
+
9
+ rejects 'abc'
10
+ rejects Date.today
11
+ rejects Time.now
12
+
13
+ end
@@ -0,0 +1,28 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'array parameter constraints' do
4
+ subject do
5
+ ActionController::Parameters.map(
6
+ :id => ActionController::Parameters.integer,
7
+ :name => ActionController::Parameters.string
8
+ )
9
+ end
10
+
11
+ def self.permits(value, options = {})
12
+ options[:as] ||= value
13
+ options[:as] = options[:as].with_indifferent_access
14
+
15
+ super(value, options)
16
+ end
17
+
18
+ permits(:id => 1, :name => 'Mick')
19
+ permits({:id => '1', :name => 'Mick'}, :as => {:id => 1, :name => 'Mick'})
20
+ permits(:id => 1)
21
+ permits({:id => '1'}, :as => {:id => 1})
22
+ permits(:name => 'Mick')
23
+
24
+ rejects(:id => 1, :name => 123)
25
+ rejects(:id => 'Mick', :name => 'Mick')
26
+ rejects(123)
27
+ rejects('abc')
28
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'operator parameter constraints' do
4
+ describe 'OR types' do
5
+ subject { ActionController::Parameters.integer | ActionController::Parameters.string }
6
+
7
+ permits 'abc'
8
+ permits '123', :as => 123
9
+
10
+ rejects Date.today
11
+ rejects Time.now
12
+ end
13
+
14
+ describe 'AND types' do
15
+ subject { ActionController::Parameters.string & ActionController::Parameters.integer }
16
+
17
+ permits '123', :as => 123
18
+
19
+ rejects 123
20
+ rejects 'abc'
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe 'string parameter constraints' do
4
+ subject { ActionController::Parameters.string }
5
+
6
+ permits 'abc'
7
+
8
+ rejects 123
9
+ rejects Date.today
10
+ rejects Time.now
11
+
12
+ it 'rejects strings that are too long' do
13
+ assert_rejects(:value) { params(:value => '123').permit(:value => ActionController::Parameters.string(:max_length => 2)) }
14
+ end
15
+ end
@@ -0,0 +1,72 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+
3
+ require 'test/unit'
4
+ require 'rails'
5
+ require 'action_controller'
6
+ require 'rails/test_help'
7
+
8
+ class FakeApplication < Rails::Application; end
9
+
10
+ Rails.application = FakeApplication
11
+ Rails.configuration.action_controller = ActiveSupport::OrderedOptions.new
12
+ Rails.configuration.secret_key_base = 'secret_key_base'
13
+
14
+ require 'action_pack'
15
+ require 'strong_parameters' if ActionPack::VERSION::MAJOR == 3
16
+
17
+ module ActionController
18
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
19
+ SharedTestRoutes.draw do
20
+ get ':controller(/:action)'
21
+ post ':controller(/:action)'
22
+ put ':controller(/:action)'
23
+ delete ':controller(/:action)'
24
+ end
25
+
26
+ class Base
27
+ include ActionController::Testing
28
+ include SharedTestRoutes.url_helpers
29
+
30
+ rescue_from(ActionController::ParameterMissing) do |e|
31
+ render :text => "Required parameter missing: #{e.param}", :status => :bad_request
32
+ end
33
+ end
34
+
35
+ class ActionController::TestCase
36
+ setup do
37
+ @routes = SharedTestRoutes
38
+ end
39
+ end
40
+ end
41
+
42
+ require 'stronger_parameters'
43
+ require 'minitest/rails'
44
+ require 'minitest/autorun'
45
+
46
+ class MiniTest::Spec
47
+ def params(hash)
48
+ ActionController::Parameters.new(hash)
49
+ end
50
+
51
+ def assert_rejects(key, &block)
52
+ err = block.must_raise StrongerParameters::InvalidParameter
53
+ err.key.must_equal key.to_s
54
+ end
55
+
56
+ def self.permits(value, options = {})
57
+ type_casted = options.fetch(:as, value)
58
+
59
+ it "permits #{value.inspect} as #{type_casted.inspect}" do
60
+ permitted = params(:value => value).permit(:value => subject)
61
+ permitted[:value].must_equal type_casted
62
+ end
63
+ end
64
+
65
+ def self.rejects(value, options = {})
66
+ key = options.fetch(:key, :value)
67
+
68
+ it "rejects #{value.inspect}" do
69
+ assert_rejects(key) { params(:value => value).permit(:value => subject) }
70
+ end
71
+ end
72
+ end
metadata ADDED
@@ -0,0 +1,190 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stronger_parameters
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mick Staugaard
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest-rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: appraisal
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: actionpack
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>'
116
+ - !ruby/object:Gem::Version
117
+ version: '2'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>'
123
+ - !ruby/object:Gem::Version
124
+ version: '2'
125
+ description:
126
+ email:
127
+ - mick@zendesk.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - lib/stronger_parameters/constraints/array_constraint.rb
133
+ - lib/stronger_parameters/constraints/boolean_constraint.rb
134
+ - lib/stronger_parameters/constraints/comparison_constraints.rb
135
+ - lib/stronger_parameters/constraints/enumeration_constraint.rb
136
+ - lib/stronger_parameters/constraints/fixnum_constraint.rb
137
+ - lib/stronger_parameters/constraints/hash_constraint.rb
138
+ - lib/stronger_parameters/constraints/string_constraint.rb
139
+ - lib/stronger_parameters/constraints.rb
140
+ - lib/stronger_parameters/errors.rb
141
+ - lib/stronger_parameters/parameters.rb
142
+ - lib/stronger_parameters/railtie.rb
143
+ - lib/stronger_parameters/version.rb
144
+ - lib/stronger_parameters.rb
145
+ - test/array_contraints_test.rb
146
+ - test/boolean_constraints_test.rb
147
+ - test/comparison_constraints_test.rb
148
+ - test/controller_test.rb
149
+ - test/enum_constraints_test.rb
150
+ - test/fixnum_constraints_test.rb
151
+ - test/hash_constraint_test.rb
152
+ - test/operator_constraints_test.rb
153
+ - test/string_constraints_test.rb
154
+ - test/test_helper.rb
155
+ - README.md
156
+ homepage: https://github.com/zendesk/stronger_parameters
157
+ licenses:
158
+ - Apache License Version 2.0
159
+ metadata: {}
160
+ post_install_message:
161
+ rdoc_options: []
162
+ require_paths:
163
+ - lib
164
+ required_ruby_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ required_rubygems_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ requirements: []
175
+ rubyforge_project:
176
+ rubygems_version: 2.0.14
177
+ signing_key:
178
+ specification_version: 4
179
+ summary: Type checking and type casting of parameters for Action Pack
180
+ test_files:
181
+ - test/array_contraints_test.rb
182
+ - test/boolean_constraints_test.rb
183
+ - test/comparison_constraints_test.rb
184
+ - test/controller_test.rb
185
+ - test/enum_constraints_test.rb
186
+ - test/fixnum_constraints_test.rb
187
+ - test/hash_constraint_test.rb
188
+ - test/operator_constraints_test.rb
189
+ - test/string_constraints_test.rb
190
+ - test/test_helper.rb