simple_params 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Gemfile.lock +1 -1
- data/lib/simple_params/api_pie_doc/nested_array.rb +31 -0
- data/lib/simple_params/api_pie_doc.rb +15 -0
- data/lib/simple_params/errors.rb +35 -45
- data/lib/simple_params/params.rb +55 -12
- data/lib/simple_params/validations.rb +5 -0
- data/lib/simple_params/version.rb +1 -1
- data/lib/simple_params.rb +1 -0
- data/spec/acceptance_spec.rb +15 -2
- data/spec/api_pie_doc/nested_array_spec.rb +46 -0
- data/spec/api_pie_doc_spec.rb +14 -0
- data/spec/errors_spec.rb +98 -16
- data/spec/fixtures/dummy_params.rb +5 -0
- data/spec/params_spec.rb +55 -4
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MWQxN2I0ZTRlYjM1NmFmMDc0ZGRhNDA5YWQ3ZDhjMWUzZWMzM2QzMw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MjA4ZmQ5NDcxMjM1OTRjNzAwZTMzM2Y3MjExMGJlZDIwNDVmY2YwZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTI0YjczMDJjMTI0OGQ4NmY4ZDZkZWYwMGNhYTA5NzIyZjZjODRiMGE4ZTZi
|
10
|
+
NzZkZDJlY2YyMDE4YzQ3OWQ1YWE3Mjg1MDg2MjlhZTAyZTJhMTc3NTRiN2M5
|
11
|
+
ZGM5MTFlMTE3NjFjZDhjMDFkMjJhMjZjYTEwNTQ0NzViN2JiNWY=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YTY4MmRhMWRlYTQ1NmM1N2YzNmMwZjIzNTE3ZTNiZjQ3NDY0ZjhlMTI5MmI5
|
14
|
+
NTBiMmNjYTAxZWJiNzhkZTIxNThkMDFhMDc5NGE0OTdmYjI3ZTQ0ZmQ4ZDc0
|
15
|
+
Nzc4MjllNDYyZGZjNTJjM2FiNmFkNTUxMmEwNmM3ODFkODNlZmU=
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
module SimpleParams
|
2
|
+
class ApiPieDoc::NestedArray < ApiPieDoc::AttributeBase
|
3
|
+
|
4
|
+
attr_accessor :attributes
|
5
|
+
|
6
|
+
def initialize(simple_params_array)
|
7
|
+
super
|
8
|
+
self.attributes = attribute.values[0].map { |attribute| ApiPieDoc::Attribute.new(attribute) }
|
9
|
+
self.options ||= attribute.delete(:options) || attribute[1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def name
|
13
|
+
attribute.keys.first.to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
return nil if do_not_document?
|
18
|
+
nested_description
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def nested_description
|
24
|
+
start = "param :#{name}, Array, #{description}, #{requirement_description} do"
|
25
|
+
attribute_descriptors = []
|
26
|
+
attributes.each { |attribute| attribute_descriptors << attribute.to_s }
|
27
|
+
finish = "end"
|
28
|
+
[start, attribute_descriptors, finish].flatten.join("\n")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -3,16 +3,21 @@ module SimpleParams
|
|
3
3
|
|
4
4
|
attr_accessor :base_attributes,
|
5
5
|
:nested_hashes,
|
6
|
+
:nested_arrays,
|
6
7
|
:nested_attributes,
|
8
|
+
:nested_array_attributes,
|
7
9
|
:docs
|
8
10
|
|
9
11
|
def initialize(simple_params)
|
10
12
|
self.base_attributes = simple_params.defined_attributes
|
11
13
|
self.nested_hashes = simple_params.nested_hashes
|
14
|
+
self.nested_arrays = simple_params.nested_arrays
|
12
15
|
self.nested_attributes = []
|
16
|
+
self.nested_array_attributes = []
|
13
17
|
self.docs = []
|
14
18
|
|
15
19
|
build_nested_attributes
|
20
|
+
build_nested_array_attributes
|
16
21
|
end
|
17
22
|
|
18
23
|
def build
|
@@ -24,6 +29,10 @@ module SimpleParams
|
|
24
29
|
docs << NestedAttribute.new(nested_attribute).to_s
|
25
30
|
end
|
26
31
|
|
32
|
+
nested_array_attributes.each do |nested_attribute|
|
33
|
+
docs << NestedArray.new(nested_attribute).to_s
|
34
|
+
end
|
35
|
+
|
27
36
|
docs.join("\n")
|
28
37
|
end
|
29
38
|
|
@@ -34,5 +43,11 @@ module SimpleParams
|
|
34
43
|
nested_attributes << { name => parameter_set.defined_attributes, options: parameter_set.options }
|
35
44
|
end
|
36
45
|
end
|
46
|
+
|
47
|
+
def build_nested_array_attributes
|
48
|
+
nested_arrays.each do |name, parameter_set|
|
49
|
+
nested_array_attributes << { name => parameter_set.defined_attributes, options: parameter_set.options }
|
50
|
+
end
|
51
|
+
end
|
37
52
|
end
|
38
53
|
end
|
data/lib/simple_params/errors.rb
CHANGED
@@ -2,14 +2,23 @@ require "active_model"
|
|
2
2
|
|
3
3
|
module SimpleParams
|
4
4
|
class Errors < ActiveModel::Errors
|
5
|
+
attr_reader :base
|
5
6
|
|
6
|
-
def initialize(base,
|
7
|
+
def initialize(base, nested_hash_errors = {}, nested_array_errors = {})
|
7
8
|
super(base)
|
8
|
-
@
|
9
|
+
@base = base
|
10
|
+
@nested_hash_errors = symbolize_nested(nested_hash_errors)
|
11
|
+
@nested_array_errors = symbolize_nested(nested_array_errors)
|
9
12
|
end
|
10
13
|
|
11
14
|
def [](attribute)
|
12
|
-
|
15
|
+
if is_a_nested_hash_error_attribute?(attribute)
|
16
|
+
set(attribute.to_sym, @nested_hash_errors[attribute.to_sym])
|
17
|
+
elsif is_a_nested_array_error_attribute?(attribute)
|
18
|
+
set(attribute.to_sym, @nested_array_errors[attribute.to_sym])
|
19
|
+
else
|
20
|
+
get(attribute.to_sym) || set(attribute.to_sym, [])
|
21
|
+
end
|
13
22
|
end
|
14
23
|
|
15
24
|
def []=(attribute, error)
|
@@ -28,26 +37,18 @@ module SimpleParams
|
|
28
37
|
|
29
38
|
def clear
|
30
39
|
super
|
31
|
-
@
|
32
|
-
if fetch_nested_attribute(attribute).present?
|
33
|
-
fetch_nested_attribute(attribute).errors.clear
|
34
|
-
end
|
35
|
-
end
|
40
|
+
@nested_hash_errors.map { |attribute, errors| errors.clear }
|
36
41
|
end
|
37
42
|
|
38
43
|
def empty?
|
39
44
|
super &&
|
40
|
-
@
|
41
|
-
if fetch_nested_attribute(attribute).present?
|
42
|
-
fetch_nested_attribute(attribute).errors.empty?
|
43
|
-
end
|
44
|
-
end
|
45
|
+
@nested_hash_errors.all? { |attribute, errors| errors.empty? }
|
45
46
|
end
|
46
47
|
alias_method :blank?, :empty?
|
47
48
|
|
48
49
|
def include?(attribute)
|
49
|
-
if
|
50
|
-
|
50
|
+
if is_a_nested_hash_error_attribute?(attribute)
|
51
|
+
!@nested_hash_errors[attribute.to_sym].empty?
|
51
52
|
else
|
52
53
|
messages[attribute].present?
|
53
54
|
end
|
@@ -57,21 +58,16 @@ module SimpleParams
|
|
57
58
|
|
58
59
|
def values
|
59
60
|
messages.values +
|
60
|
-
@
|
61
|
-
|
62
|
-
fetch_nested_attribute(attribute).errors.values
|
63
|
-
end
|
61
|
+
@nested_hash_errors.map do |attribute, errors|
|
62
|
+
errors.values
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
66
|
def full_messages
|
68
67
|
parent_messages = map { |attribute, message| full_message(attribute, message) }
|
69
|
-
nested_messages = @
|
70
|
-
|
71
|
-
|
72
|
-
messages.map do |message|
|
73
|
-
"#{attribute} " + message
|
74
|
-
end
|
68
|
+
nested_messages = @nested_hash_errors.map do |attribute, errors|
|
69
|
+
unless errors.full_messages.nil?
|
70
|
+
errors.full_messages.map { |message| "#{attribute} " + message }
|
75
71
|
end
|
76
72
|
end
|
77
73
|
(parent_messages + nested_messages).flatten
|
@@ -88,10 +84,10 @@ module SimpleParams
|
|
88
84
|
self.messages.dup
|
89
85
|
end
|
90
86
|
|
91
|
-
@
|
92
|
-
|
87
|
+
@nested_hash_errors.map do |attribute, errors|
|
88
|
+
error_messages = nested_error_messages(attribute, full_messages)
|
93
89
|
unless errors.empty?
|
94
|
-
messages.merge!(attribute.to_sym =>
|
90
|
+
messages.merge!(attribute.to_sym => error_messages)
|
95
91
|
end
|
96
92
|
end
|
97
93
|
messages
|
@@ -104,14 +100,14 @@ module SimpleParams
|
|
104
100
|
|
105
101
|
private
|
106
102
|
def nested_error_messages(attribute, full_messages = false)
|
107
|
-
if
|
108
|
-
|
109
|
-
|
103
|
+
if is_a_nested_hash_error_attribute?(attribute)
|
104
|
+
errors = @nested_hash_errors[attribute.to_sym]
|
105
|
+
if full_messages
|
110
106
|
errors.messages.each_with_object({}) do |(attr, array), messages|
|
111
107
|
messages[attr] = array.map { |message| errors.full_message(attr, message) }
|
112
108
|
end
|
113
109
|
else
|
114
|
-
|
110
|
+
errors.messages.dup
|
115
111
|
end
|
116
112
|
else
|
117
113
|
{}
|
@@ -119,29 +115,23 @@ module SimpleParams
|
|
119
115
|
end
|
120
116
|
|
121
117
|
def add_error_to_attribute(attribute, error)
|
122
|
-
if
|
123
|
-
|
118
|
+
if is_a_nested_hash_error_attribute?(attribute)
|
119
|
+
@nested_hash_errors[attribute.to_sym][:base] = error
|
124
120
|
else
|
125
121
|
self[attribute] << error
|
126
122
|
end
|
127
123
|
end
|
128
124
|
|
129
|
-
def
|
130
|
-
|
131
|
-
set(attribute.to_sym, fetch_nested_attribute(attribute).errors)
|
132
|
-
else
|
133
|
-
set(attribute.to_sym, [])
|
134
|
-
end
|
125
|
+
def is_a_nested_hash_error_attribute?(attribute)
|
126
|
+
@nested_hash_errors.keys.include?(attribute.to_sym)
|
135
127
|
end
|
136
128
|
|
137
|
-
def
|
138
|
-
|
139
|
-
@base.send(attribute)
|
140
|
-
end
|
129
|
+
def is_a_nested_array_error_attribute?(attribute)
|
130
|
+
@nested_array_errors.keys.include?(attribute.to_sym)
|
141
131
|
end
|
142
132
|
|
143
133
|
def symbolize_nested(nested)
|
144
|
-
nested.
|
134
|
+
nested.inject({}) { |memo,(k,v) | memo[k.to_sym] = v; memo }
|
145
135
|
end
|
146
136
|
end
|
147
137
|
end
|
data/lib/simple_params/params.rb
CHANGED
@@ -5,6 +5,7 @@ module SimpleParams
|
|
5
5
|
class Params
|
6
6
|
include Virtus.model
|
7
7
|
include ActiveModel::Validations
|
8
|
+
extend ActiveModel::Naming
|
8
9
|
include SimpleParams::Validations
|
9
10
|
|
10
11
|
TYPES = [
|
@@ -31,6 +32,10 @@ module SimpleParams
|
|
31
32
|
|
32
33
|
attr_accessor :strict_enforcement, :options
|
33
34
|
|
35
|
+
def model_name
|
36
|
+
ActiveModel::Name.new(self)
|
37
|
+
end
|
38
|
+
|
34
39
|
def api_pie_documentation
|
35
40
|
SimpleParams::ApiPieDoc.new(self).build
|
36
41
|
end
|
@@ -61,11 +66,22 @@ module SimpleParams
|
|
61
66
|
@nested_hashes ||= {}
|
62
67
|
end
|
63
68
|
|
69
|
+
def nested_array(name, opts={}, &block)
|
70
|
+
attr_accessor name
|
71
|
+
nested_array_class = define_nested_class(name, opts, &block)
|
72
|
+
@nested_arrays ||= {}
|
73
|
+
@nested_arrays[name.to_sym] = nested_array_class
|
74
|
+
end
|
75
|
+
|
76
|
+
def nested_arrays
|
77
|
+
@nested_arrays ||= {}
|
78
|
+
end
|
79
|
+
|
64
80
|
def defined_attributes
|
65
81
|
@define_attributes ||= {}
|
66
82
|
end
|
67
|
-
private
|
68
83
|
|
84
|
+
private
|
69
85
|
def define_attribute(name, opts = {})
|
70
86
|
opts[:type] ||= :string
|
71
87
|
defined_attributes[name.to_sym] = opts
|
@@ -103,12 +119,10 @@ module SimpleParams
|
|
103
119
|
def define_nested_class(name, options, &block)
|
104
120
|
klass_name = name.to_s.split('_').collect(&:capitalize).join
|
105
121
|
Class.new(Params).tap do |klass|
|
106
|
-
|
107
|
-
|
108
|
-
# end
|
122
|
+
self.const_set(klass_name, klass)
|
123
|
+
extend ActiveModel::Naming
|
109
124
|
klass.class_eval(&block)
|
110
125
|
klass.class_eval("self.options = #{options}")
|
111
|
-
self.const_set(klass_name, klass)
|
112
126
|
end
|
113
127
|
end
|
114
128
|
end
|
@@ -124,13 +138,16 @@ module SimpleParams
|
|
124
138
|
@original_params = hash_to_symbolized_hash(params)
|
125
139
|
define_attributes(@original_params)
|
126
140
|
|
127
|
-
#
|
141
|
+
# Nested Hashes
|
128
142
|
@nested_params = nested_hashes.keys
|
129
|
-
|
143
|
+
|
144
|
+
# Nested Arrays
|
145
|
+
@nested_arrays = nested_arrays.keys
|
130
146
|
|
131
147
|
# Nested Classes
|
132
148
|
set_accessors(params)
|
133
149
|
initialize_nested_classes
|
150
|
+
initialize_nested_array_classes
|
134
151
|
end
|
135
152
|
|
136
153
|
def define_attributes(params)
|
@@ -140,7 +157,7 @@ module SimpleParams
|
|
140
157
|
end
|
141
158
|
|
142
159
|
def attributes
|
143
|
-
(defined_attributes.keys + nested_hashes.keys).flatten
|
160
|
+
(defined_attributes.keys + nested_hashes.keys + nested_arrays.keys).flatten
|
144
161
|
end
|
145
162
|
|
146
163
|
def original_params
|
@@ -151,9 +168,6 @@ module SimpleParams
|
|
151
168
|
|
152
169
|
def to_hash
|
153
170
|
hash = {}
|
154
|
-
# self.class.defined_attributes.each_pair do |key, opts|
|
155
|
-
# hash[key.to_sym] = send(key)
|
156
|
-
# end
|
157
171
|
attributes.each do |attribute|
|
158
172
|
if send(attribute).is_a?(SimpleParams::Params)
|
159
173
|
hash[attribute] = send(attribute).to_hash
|
@@ -165,6 +179,20 @@ module SimpleParams
|
|
165
179
|
hash
|
166
180
|
end
|
167
181
|
|
182
|
+
def errors
|
183
|
+
nested_errors_hash = {}
|
184
|
+
@nested_params.each do |param|
|
185
|
+
nested_errors_hash[param.to_sym] = send(param).errors
|
186
|
+
end
|
187
|
+
|
188
|
+
nested_arrays_hash = {}
|
189
|
+
@nested_arrays.each do |array|
|
190
|
+
nested_arrays_hash[array.to_sym] = send(array).map(&:errors)
|
191
|
+
end
|
192
|
+
|
193
|
+
@errors ||= SimpleParams::Errors.new(self, nested_errors_hash, nested_arrays_hash)
|
194
|
+
end
|
195
|
+
|
168
196
|
# Overriding this method to allow for non-strict enforcement!
|
169
197
|
def method_missing(method_name, *arguments, &block)
|
170
198
|
if strict_enforcement?
|
@@ -197,7 +225,7 @@ module SimpleParams
|
|
197
225
|
def set_accessors(params={})
|
198
226
|
params.each do |attribute_name, value|
|
199
227
|
# Don't set accessors for nested classes
|
200
|
-
unless value.is_a?(Hash)
|
228
|
+
unless value.is_a?(Hash)
|
201
229
|
send("#{attribute_name}=", value)
|
202
230
|
end
|
203
231
|
end
|
@@ -226,6 +254,10 @@ module SimpleParams
|
|
226
254
|
self.class.nested_hashes
|
227
255
|
end
|
228
256
|
|
257
|
+
def nested_arrays
|
258
|
+
self.class.nested_arrays
|
259
|
+
end
|
260
|
+
|
229
261
|
def initialize_nested_classes
|
230
262
|
nested_hashes.each do |key, klass|
|
231
263
|
initialization_params = @original_params[key.to_sym] || {}
|
@@ -233,6 +265,17 @@ module SimpleParams
|
|
233
265
|
end
|
234
266
|
end
|
235
267
|
|
268
|
+
def initialize_nested_array_classes
|
269
|
+
nested_arrays.each do |key, klass|
|
270
|
+
initialization_params = @original_params[key.to_sym] || []
|
271
|
+
initialization_array = []
|
272
|
+
initialization_params.each do |initialization_param|
|
273
|
+
initialization_array << klass.new(initialization_param, self)
|
274
|
+
end
|
275
|
+
send("#{key}=", initialization_array)
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
236
279
|
def define_anonymous_class(name, hash)
|
237
280
|
klass_name = name.to_s.split('_').collect(&:capitalize).join
|
238
281
|
anonymous_klass = Class.new(Params).tap do |klass|
|
@@ -14,6 +14,11 @@ module SimpleParams
|
|
14
14
|
nested_class = send("#{key}")
|
15
15
|
nested_class.valid?
|
16
16
|
end
|
17
|
+
|
18
|
+
nested_arrays.each do |key, array|
|
19
|
+
nested_array = send("#{key}")
|
20
|
+
nested_array.each { |a| a.valid? }
|
21
|
+
end
|
17
22
|
errors.empty?
|
18
23
|
ensure
|
19
24
|
self.validation_context = current_context
|
data/lib/simple_params.rb
CHANGED
@@ -9,6 +9,7 @@ require 'simple_params/type_mappings'
|
|
9
9
|
require 'simple_params/api_pie_doc'
|
10
10
|
require 'simple_params/api_pie_doc/attribute_base'
|
11
11
|
require 'simple_params/api_pie_doc/attribute'
|
12
|
+
require 'simple_params/api_pie_doc/nested_array'
|
12
13
|
require 'simple_params/api_pie_doc/nested_attribute'
|
13
14
|
require 'simple_params/validation_matchers/validation_matcher'
|
14
15
|
require 'simple_params/validation_matchers/coercion_matcher'
|
data/spec/acceptance_spec.rb
CHANGED
@@ -6,6 +6,7 @@ class AcceptanceParams < SimpleParams::Params
|
|
6
6
|
param :name
|
7
7
|
param :age, type: :integer, optional: true, validations: { inclusion: { in: 18..100 } }
|
8
8
|
param :color, default: "red", validations: { inclusion: { in: ["red", "green"] }}
|
9
|
+
param :sibling_names, type: :array, optional: true
|
9
10
|
validate :name_has_letters
|
10
11
|
|
11
12
|
nested_hash :address do
|
@@ -16,6 +17,11 @@ class AcceptanceParams < SimpleParams::Params
|
|
16
17
|
param :company, optional: true
|
17
18
|
end
|
18
19
|
|
20
|
+
nested_array :dogs do
|
21
|
+
param :name
|
22
|
+
param :age, type: :integer, validations: { inclusion: { in: 1..20 } }
|
23
|
+
end
|
24
|
+
|
19
25
|
def name_has_letters
|
20
26
|
if name.present? && !(name =~ /^[a-zA-Z]*$/)
|
21
27
|
errors.add(:name, "must only contain letters")
|
@@ -59,13 +65,15 @@ describe SimpleParams::Params do
|
|
59
65
|
name: "Tom",
|
60
66
|
age: nil,
|
61
67
|
color: "red",
|
68
|
+
sibling_names: nil,
|
62
69
|
address: {
|
63
70
|
street: "1 Main St.",
|
64
71
|
city: nil,
|
65
72
|
zip_code: nil,
|
66
73
|
state: "North Carolina",
|
67
74
|
company: nil
|
68
|
-
}
|
75
|
+
},
|
76
|
+
dogs: []
|
69
77
|
})
|
70
78
|
end
|
71
79
|
end
|
@@ -135,7 +143,7 @@ describe SimpleParams::Params do
|
|
135
143
|
describe "attributes", attributes: true do
|
136
144
|
it "returns array of attribute symbols" do
|
137
145
|
params = AcceptanceParams.new
|
138
|
-
params.attributes.should eq([:reference, :name, :age, :color, :address])
|
146
|
+
params.attributes.should eq([:reference, :name, :age, :color, :sibling_names, :address, :dogs])
|
139
147
|
end
|
140
148
|
|
141
149
|
it "returns array of attribute symbols for nested class" do
|
@@ -305,6 +313,7 @@ describe SimpleParams::Params do
|
|
305
313
|
param :name, String, desc: '', required: true
|
306
314
|
param :age, Integer, desc: '', required: false
|
307
315
|
param :color, String, desc: '', required: false
|
316
|
+
param :sibling_names, Array, desc: '', required: false
|
308
317
|
param :address, Hash, desc: '', required: true do
|
309
318
|
param :street, String, desc: '', required: true
|
310
319
|
param :city, String, desc: '', required: true
|
@@ -312,6 +321,10 @@ describe SimpleParams::Params do
|
|
312
321
|
param :state, String, desc: '', required: false
|
313
322
|
param :company, String, desc: '', required: false
|
314
323
|
end
|
324
|
+
param :dogs, Array, desc: '', required: true do
|
325
|
+
param :name, String, desc: '', required: true
|
326
|
+
param :age, Integer, desc: '', required: true
|
327
|
+
end
|
315
328
|
API_PIE_DOCS
|
316
329
|
|
317
330
|
expect(documentation).to be_a String
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleParams::ApiPieDoc::NestedArray do
|
4
|
+
|
5
|
+
let(:simple_param_attribute) {
|
6
|
+
{:address=>
|
7
|
+
{:street=>{:type=>:string},
|
8
|
+
:city=>{:validations=>{:length=>{:in=>4..40}, :presence=>true}, :type=>:string},
|
9
|
+
:zip_code=>{:optional=>true, :type=>:string},
|
10
|
+
:state=>{:default=>"North Carolina", :type=>:string}
|
11
|
+
},
|
12
|
+
:options=>{desc: 'i like pie'}
|
13
|
+
}
|
14
|
+
}
|
15
|
+
let(:nested_attribute) { described_class.new(simple_param_attribute) }
|
16
|
+
|
17
|
+
it_behaves_like 'a base attribute'
|
18
|
+
|
19
|
+
describe '#initialize' do
|
20
|
+
specify 'should give instance an attribute' do
|
21
|
+
expect(nested_attribute.attribute).to eq simple_param_attribute
|
22
|
+
end
|
23
|
+
|
24
|
+
specify 'should give instance options' do
|
25
|
+
expect(nested_attribute.options).to eq({ desc: 'i like pie' })
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#name' do
|
30
|
+
specify 'should set respond with the right name' do
|
31
|
+
expect(nested_attribute.name).to eq 'address'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#options' do
|
36
|
+
specify 'should return nested attribute options' do
|
37
|
+
expect(nested_attribute.options).to eq({desc: 'i like pie'})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#to_s' do
|
42
|
+
specify 'should return properly formatted string' do
|
43
|
+
expect(nested_attribute.to_s).to eq("param :address, Array, desc: 'i like pie', required: true do\nparam :street, String, desc: '', required: true\nparam :city, String, desc: '', required: true\nparam :zip_code, String, desc: '', required: false\nparam :state, String, desc: '', required: false\nend")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/api_pie_doc_spec.rb
CHANGED
@@ -16,17 +16,31 @@ describe SimpleParams::ApiPieDoc do
|
|
16
16
|
expect(api_pie_doc.nested_hashes.keys).to eq [:address, :phone]
|
17
17
|
end
|
18
18
|
|
19
|
+
specify "should give object nested_arrays" do
|
20
|
+
expect(api_pie_doc.nested_arrays.keys).to eq [:dogs]
|
21
|
+
end
|
22
|
+
|
19
23
|
specify "should call #build_nested_attributes" do
|
20
24
|
expect_any_instance_of(SimpleParams::ApiPieDoc).to receive(:build_nested_attributes)
|
21
25
|
api_pie_doc
|
22
26
|
end
|
23
27
|
|
28
|
+
specify "should call #build_nested_array_attributes" do
|
29
|
+
expect_any_instance_of(SimpleParams::ApiPieDoc).to receive(:build_nested_array_attributes)
|
30
|
+
api_pie_doc
|
31
|
+
end
|
32
|
+
|
24
33
|
specify "should give object nested_attributes" do
|
25
34
|
expect(api_pie_doc.nested_attributes.flat_map(&:keys)).to include(:address, :phone)
|
26
35
|
expect(api_pie_doc.nested_attributes[0].values.flat_map(&:keys)).to eq [:street, :city, :zip_code, :state]
|
27
36
|
expect(api_pie_doc.nested_attributes[1].values.flat_map(&:keys)).to eq [:cell_phone, :phone_number, :area_code]
|
28
37
|
end
|
29
38
|
|
39
|
+
specify "should give object nested_array_attributes" do
|
40
|
+
expect(api_pie_doc.nested_array_attributes.flat_map(&:keys)).to include(:dogs)
|
41
|
+
expect(api_pie_doc.nested_array_attributes[0].values.flat_map(&:keys)).to eq [:name, :age]
|
42
|
+
end
|
43
|
+
|
30
44
|
specify "should give object docs" do
|
31
45
|
expect(api_pie_doc.docs).to eq []
|
32
46
|
end
|
data/spec/errors_spec.rb
CHANGED
@@ -4,7 +4,10 @@ describe SimpleParams::Errors do
|
|
4
4
|
class Person
|
5
5
|
extend ActiveModel::Naming
|
6
6
|
def initialize
|
7
|
-
@errors = SimpleParams::Errors.new(self,
|
7
|
+
@errors = SimpleParams::Errors.new(self,
|
8
|
+
{ dog: dog.errors },
|
9
|
+
{ cats: cats_errors },
|
10
|
+
)
|
8
11
|
end
|
9
12
|
|
10
13
|
attr_accessor :name, :age
|
@@ -14,6 +17,14 @@ describe SimpleParams::Errors do
|
|
14
17
|
@dog ||= Dog.new
|
15
18
|
end
|
16
19
|
|
20
|
+
def cats
|
21
|
+
@cats ||= [Cat.new]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cats_errors
|
25
|
+
cats.map { |cat| cat.errors }
|
26
|
+
end
|
27
|
+
|
17
28
|
def read_attribute_for_validation(attr)
|
18
29
|
send(attr)
|
19
30
|
end
|
@@ -49,7 +60,30 @@ describe SimpleParams::Errors do
|
|
49
60
|
end
|
50
61
|
end
|
51
62
|
|
52
|
-
|
63
|
+
class Cat
|
64
|
+
extend ActiveModel::Naming
|
65
|
+
def initialize
|
66
|
+
@errors = SimpleParams::Errors.new(self)
|
67
|
+
end
|
68
|
+
|
69
|
+
attr_accessor :name
|
70
|
+
attr_accessor :age
|
71
|
+
attr_reader :errors
|
72
|
+
|
73
|
+
def read_attribute_for_validation(attr)
|
74
|
+
send(attr)
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.human_attribute_name(attr, options = {})
|
78
|
+
attr
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.lookup_ancestors
|
82
|
+
[self]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "setting and getting errors", setters_getters: true do
|
53
87
|
it "get returns the errors for the provided key" do
|
54
88
|
errors = SimpleParams::Errors.new(self)
|
55
89
|
errors[:foo] = "omg"
|
@@ -105,7 +139,7 @@ describe SimpleParams::Errors do
|
|
105
139
|
end
|
106
140
|
end
|
107
141
|
|
108
|
-
describe "setting and getting nested error model" do
|
142
|
+
describe "setting and getting nested error model", nested_model: true do
|
109
143
|
it "can access error model" do
|
110
144
|
person = Person.new
|
111
145
|
dog = person.dog
|
@@ -152,7 +186,55 @@ describe SimpleParams::Errors do
|
|
152
186
|
end
|
153
187
|
end
|
154
188
|
|
155
|
-
describe "
|
189
|
+
describe "setting and getting nested array error model", nested_array: true do
|
190
|
+
it "can access error model" do
|
191
|
+
person = Person.new
|
192
|
+
cats = person.cats
|
193
|
+
cat_errors = cats.first.errors
|
194
|
+
person.errors[:cats][0].should eq(cat_errors)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "can add to nested errors through []", failing: true do
|
198
|
+
person = Person.new
|
199
|
+
person.errors[:cats].first[:base] = 'should not be nil'
|
200
|
+
person.errors[:cats].first[:base].should eq(['should not be nil'])
|
201
|
+
person.cats.first.errors[:base].should eq(['should not be nil'])
|
202
|
+
end
|
203
|
+
|
204
|
+
it "can add to nested errors through add" do
|
205
|
+
person = Person.new
|
206
|
+
person.errors[:cats].first.add(:age, 'should not be nil')
|
207
|
+
person.cats.first.errors[:age].should eq(['should not be nil'])
|
208
|
+
end
|
209
|
+
|
210
|
+
it "can add multiple errors to nested errors through []" do
|
211
|
+
person = Person.new
|
212
|
+
person.errors[:cats].first[:name] = 'should not be nil'
|
213
|
+
person.errors[:cats].first[:name] = 'must be cute'
|
214
|
+
person.cats.first.errors[:name].should eq(['should not be nil', 'must be cute'])
|
215
|
+
end
|
216
|
+
|
217
|
+
it "can add multiple errors to nested errors through add" do
|
218
|
+
person = Person.new
|
219
|
+
person.errors[:cats].first.add(:name, 'should not be nil')
|
220
|
+
person.errors[:cats].first.add(:name, 'must be cute')
|
221
|
+
person.cats.first.errors[:name].should eq(['should not be nil', 'must be cute'])
|
222
|
+
end
|
223
|
+
|
224
|
+
it "can add individual errors to nested attributes through []" do
|
225
|
+
person = Person.new
|
226
|
+
person.errors[:cats][0][:age] = 'should not be nil'
|
227
|
+
person.cats.first.errors[:age].should eq(['should not be nil'])
|
228
|
+
end
|
229
|
+
|
230
|
+
it "can add individual errors to nested attributes through add" do
|
231
|
+
person = Person.new
|
232
|
+
person.errors[:cats].first.add(:age, 'should not be nil')
|
233
|
+
person.cats.first.errors[:age].should eq(['should not be nil'])
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
describe "#clear", clear: true do
|
156
238
|
it "clears errors" do
|
157
239
|
person = Person.new
|
158
240
|
person.errors[:name] = 'should not be nil'
|
@@ -173,7 +255,7 @@ describe SimpleParams::Errors do
|
|
173
255
|
end
|
174
256
|
end
|
175
257
|
|
176
|
-
describe "#empty?, #blank?, and #include?" do
|
258
|
+
describe "#empty?, #blank?, and #include?", empty: true do
|
177
259
|
it "is empty without any errors" do
|
178
260
|
person = Person.new
|
179
261
|
person.errors.should be_empty
|
@@ -201,7 +283,7 @@ describe SimpleParams::Errors do
|
|
201
283
|
end
|
202
284
|
end
|
203
285
|
|
204
|
-
describe "#added?" do
|
286
|
+
describe "#added?", added: true do
|
205
287
|
it "added? detects if a specific error was added to the object" do
|
206
288
|
person = Person.new
|
207
289
|
person.errors.add(:name, "can not be blank")
|
@@ -246,7 +328,7 @@ describe SimpleParams::Errors do
|
|
246
328
|
end
|
247
329
|
end
|
248
330
|
|
249
|
-
describe "#size" do
|
331
|
+
describe "#size", size: true do
|
250
332
|
it "size calculates the number of error messages" do
|
251
333
|
person = Person.new
|
252
334
|
person.errors.add(:name, "can not be blank")
|
@@ -260,7 +342,7 @@ describe SimpleParams::Errors do
|
|
260
342
|
end
|
261
343
|
end
|
262
344
|
|
263
|
-
describe "#to_a" do
|
345
|
+
describe "#to_a", to_a: true do
|
264
346
|
it "to_a returns the list of errors with complete messages containing the attribute names" do
|
265
347
|
person = Person.new
|
266
348
|
person.errors.add(:name, "can not be blank")
|
@@ -276,7 +358,7 @@ describe SimpleParams::Errors do
|
|
276
358
|
end
|
277
359
|
end
|
278
360
|
|
279
|
-
describe "#to_s" do
|
361
|
+
describe "#to_s", to_s: true do
|
280
362
|
it "to_a returns the list of errors with complete messages containing the attribute names" do
|
281
363
|
person = Person.new
|
282
364
|
person.errors.add(:name, "can not be blank")
|
@@ -292,8 +374,8 @@ describe SimpleParams::Errors do
|
|
292
374
|
end
|
293
375
|
end
|
294
376
|
|
295
|
-
describe "#to_hash" do
|
296
|
-
it "to_hash returns the error messages hash" do
|
377
|
+
describe "#to_hash", to_hash: true do
|
378
|
+
it "to_hash returns the error messages hash", hash_failing: true do
|
297
379
|
person = Person.new
|
298
380
|
person.errors.add(:name, "can not be blank")
|
299
381
|
person.errors.to_hash.should eq({ name: ["can not be blank"] })
|
@@ -328,7 +410,7 @@ describe SimpleParams::Errors do
|
|
328
410
|
end
|
329
411
|
end
|
330
412
|
|
331
|
-
describe "#as_json" do
|
413
|
+
describe "#as_json", as_json: true do
|
332
414
|
it "as_json creates a json formatted representation of the errors hash" do
|
333
415
|
person = Person.new
|
334
416
|
person.errors[:name] = 'can not be nil'
|
@@ -368,7 +450,7 @@ describe SimpleParams::Errors do
|
|
368
450
|
end
|
369
451
|
end
|
370
452
|
|
371
|
-
describe "#full_messages" do
|
453
|
+
describe "#full_messages", full_messages: true do
|
372
454
|
it "full_messages creates a list of error messages with the attribute name included" do
|
373
455
|
person = Person.new
|
374
456
|
person.errors.add(:name, "can not be blank")
|
@@ -408,7 +490,7 @@ describe SimpleParams::Errors do
|
|
408
490
|
end
|
409
491
|
end
|
410
492
|
|
411
|
-
describe "#generate_message" do
|
493
|
+
describe "#generate_message", generate_message: true do
|
412
494
|
it "generate_message works without i18n_scope" do
|
413
495
|
person = Person.new
|
414
496
|
Person.should_not respond_to(:i18n_scope)
|
@@ -418,7 +500,7 @@ describe SimpleParams::Errors do
|
|
418
500
|
end
|
419
501
|
end
|
420
502
|
|
421
|
-
describe "#adds_on_empty" do
|
503
|
+
describe "#adds_on_empty", add_on_empty: true do
|
422
504
|
it "add_on_empty generates message" do
|
423
505
|
person = Person.new
|
424
506
|
person.errors.should_receive(:generate_message).with(:name, :empty, {})
|
@@ -446,7 +528,7 @@ describe SimpleParams::Errors do
|
|
446
528
|
end
|
447
529
|
end
|
448
530
|
|
449
|
-
describe "#adds_on_blank" do
|
531
|
+
describe "#adds_on_blank", add_on_blank: true do
|
450
532
|
it "add_on_blank generates message" do
|
451
533
|
person = Person.new
|
452
534
|
person.errors.should_receive(:generate_message).with(:name, :blank, {})
|
data/spec/params_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
require 'fixtures/dummy_params'
|
3
3
|
|
4
4
|
describe SimpleParams::Params do
|
5
|
-
describe "strict parameter enforcement" do
|
5
|
+
describe "strict parameter enforcement", param_enforcement: true do
|
6
6
|
context "with default handling (strict enforcement)" do
|
7
7
|
it "raises error on expected param" do
|
8
8
|
expect { DummyParams.new(other_param: 1) }.to raise_error(SimpleParamsError)
|
@@ -67,12 +67,26 @@ describe SimpleParams::Params do
|
|
67
67
|
params.address.zip_code.should eq("20165")
|
68
68
|
end
|
69
69
|
end
|
70
|
+
|
71
|
+
describe "nested arrays", nested: true do
|
72
|
+
it "can access nested arrays as arrays" do
|
73
|
+
params.dogs.should respond_to(:first)
|
74
|
+
params.dogs.first.should be_nil
|
75
|
+
end
|
76
|
+
|
77
|
+
it "can access nested arrays as arrays with data", failing: true do
|
78
|
+
params = DummyParams.new(dogs: [{ name: "Spot", age: 20 }])
|
79
|
+
params.dogs.should respond_to(:first)
|
80
|
+
params.dogs.first.should_not be_nil
|
81
|
+
params.dogs.first.name.should eq("Spot")
|
82
|
+
end
|
83
|
+
end
|
70
84
|
end
|
71
85
|
|
72
86
|
describe "attributes", attributes: true do
|
73
87
|
it "returns array of attribute symbols" do
|
74
88
|
params = DummyParams.new
|
75
|
-
params.attributes.should eq([:name, :age, :first_initial, :amount, :color, :height, :address, :phone])
|
89
|
+
params.attributes.should eq([:name, :age, :first_initial, :amount, :color, :height, :address, :phone, :dogs])
|
76
90
|
end
|
77
91
|
end
|
78
92
|
|
@@ -123,7 +137,40 @@ describe SimpleParams::Params do
|
|
123
137
|
end
|
124
138
|
end
|
125
139
|
|
126
|
-
describe "
|
140
|
+
describe "validations", validations: true do
|
141
|
+
let(:params) do
|
142
|
+
DummyParams.new(
|
143
|
+
name: nil,
|
144
|
+
age: 30,
|
145
|
+
address: {
|
146
|
+
city: "Greenville"
|
147
|
+
},
|
148
|
+
dogs: [
|
149
|
+
{ name: "Spot", age: 12 },
|
150
|
+
{ age: 14 }
|
151
|
+
]
|
152
|
+
)
|
153
|
+
end
|
154
|
+
|
155
|
+
it "validates required params" do
|
156
|
+
params.should_not be_valid
|
157
|
+
params.errors[:name].should eq(["can't be blank"])
|
158
|
+
end
|
159
|
+
|
160
|
+
it "validates nested params" do
|
161
|
+
params.should_not be_valid
|
162
|
+
params.address.errors[:street].should eq(["can't be blank"])
|
163
|
+
params.errors[:address][:street].should eq(["can't be blank"])
|
164
|
+
end
|
165
|
+
|
166
|
+
it "validates nested arrays" do
|
167
|
+
params.should_not be_valid
|
168
|
+
params.errors[:dogs][0][:name].should eq([])
|
169
|
+
params.errors[:dogs][1][:name].should eq(["can't be blank"])
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "optional params with inclusion", optional_params: true do
|
127
174
|
let(:params) do
|
128
175
|
DummyParams.new(
|
129
176
|
name: "Bill",
|
@@ -311,7 +358,7 @@ describe SimpleParams::Params do
|
|
311
358
|
end
|
312
359
|
|
313
360
|
describe "api_pie_documentation", api_pie_documentation: true do
|
314
|
-
it "generates
|
361
|
+
it "generates valid api_pie documentation" do
|
315
362
|
documentation = DummyParams.api_pie_documentation
|
316
363
|
api_docs = <<-API_PIE_DOCS
|
317
364
|
param :name, String, desc: '', required: true
|
@@ -331,6 +378,10 @@ describe SimpleParams::Params do
|
|
331
378
|
param :phone_number, String, desc: '', required: true
|
332
379
|
param :area_code, String, desc: '', required: false
|
333
380
|
end
|
381
|
+
param :dogs, Array, desc: '', required: true do
|
382
|
+
param :name, String, desc: '', required: true
|
383
|
+
param :age, Integer, desc: '', required: true
|
384
|
+
end
|
334
385
|
API_PIE_DOCS
|
335
386
|
|
336
387
|
expect(documentation).to be_a String
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_params
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- brycesenz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -131,6 +131,7 @@ files:
|
|
131
131
|
- lib/simple_params/api_pie_doc.rb
|
132
132
|
- lib/simple_params/api_pie_doc/attribute.rb
|
133
133
|
- lib/simple_params/api_pie_doc/attribute_base.rb
|
134
|
+
- lib/simple_params/api_pie_doc/nested_array.rb
|
134
135
|
- lib/simple_params/api_pie_doc/nested_attribute.rb
|
135
136
|
- lib/simple_params/attribute.rb
|
136
137
|
- lib/simple_params/errors.rb
|
@@ -149,6 +150,7 @@ files:
|
|
149
150
|
- simple_params.gemspec
|
150
151
|
- spec/acceptance_spec.rb
|
151
152
|
- spec/api_pie_doc/attribute_spec.rb
|
153
|
+
- spec/api_pie_doc/nested_array_spec.rb
|
152
154
|
- spec/api_pie_doc/nested_attribute_spec.rb
|
153
155
|
- spec/api_pie_doc_spec.rb
|
154
156
|
- spec/attribute_spec.rb
|
@@ -191,6 +193,7 @@ summary: A DSL for specifying params, including type coercion and validation
|
|
191
193
|
test_files:
|
192
194
|
- spec/acceptance_spec.rb
|
193
195
|
- spec/api_pie_doc/attribute_spec.rb
|
196
|
+
- spec/api_pie_doc/nested_array_spec.rb
|
194
197
|
- spec/api_pie_doc/nested_attribute_spec.rb
|
195
198
|
- spec/api_pie_doc_spec.rb
|
196
199
|
- spec/attribute_spec.rb
|