simple_params 0.0.1pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.rspec +2 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +60 -0
- data/README.md +161 -0
- data/lib/simple_params/errors.rb +133 -0
- data/lib/simple_params/params.rb +129 -0
- data/lib/simple_params/validations.rb +28 -0
- data/lib/simple_params/version.rb +3 -0
- data/lib/simple_params.rb +4 -0
- data/simple_params.gemspec +26 -0
- data/spec/acceptance_spec.rb +129 -0
- data/spec/errors_spec.rb +453 -0
- data/spec/params_spec.rb +215 -0
- data/spec/spec_helper.rb +12 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NzljZWZmNDczMjI4ZDk5ZDg2NmYxNzRlNzQ5ZjhjNDU4YjJhMmVjNw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
ZWQ0MGE5MjE4NmQ4MDUxYzMxNmUwMjM4ZWU4NDk0YWQyYTJkNWZmNw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ODJkOTE3YzRjNTUzOGQ3ZGE0MDFlYzg5Mzc3YzNjMmI4NDJlZTA4OGZlYzkw
|
10
|
+
MDkzZDlmMmNkZjY1YmZlNjc0OGJhZTk2MGJiNTEwMjc0NDcyZWFmNzJiMmZi
|
11
|
+
MjVlNzFjZTU0NWY0NGY5ODg5M2RmYmQ0MTQ0ZjNhMTgzMTQ3ZjU=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDhlYzBmNDhlOGYzYjIyNzY2NDQ2ZmViNmFmOTA2YzQ1NmViNGJlOTEwOTg1
|
14
|
+
OTc4ODg2NDlmYzRkZGRlY2M4NTdjYTBhZjE0NWMzMWRmNTgwZWRmNjI5ZGY5
|
15
|
+
ZjFkY2I1MzliODY4Y2Q2N2I5ODVmYWM5ZDBmNDc4MzRiOWY2OTQ=
|
data/.rspec
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
simple_params_gem
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-1.9.3-p545
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
simple_params (0.0.1pre)
|
5
|
+
activemodel (>= 3.0, < 5.0)
|
6
|
+
virtus (>= 1.0.0)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
activemodel (4.2.0)
|
12
|
+
activesupport (= 4.2.0)
|
13
|
+
builder (~> 3.1)
|
14
|
+
activesupport (4.2.0)
|
15
|
+
i18n (~> 0.7)
|
16
|
+
json (~> 1.7, >= 1.7.7)
|
17
|
+
minitest (~> 5.1)
|
18
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
19
|
+
tzinfo (~> 1.1)
|
20
|
+
axiom-types (0.1.1)
|
21
|
+
descendants_tracker (~> 0.0.4)
|
22
|
+
ice_nine (~> 0.11.0)
|
23
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
24
|
+
builder (3.2.2)
|
25
|
+
coercible (1.0.0)
|
26
|
+
descendants_tracker (~> 0.0.1)
|
27
|
+
descendants_tracker (0.0.4)
|
28
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
29
|
+
diff-lcs (1.2.5)
|
30
|
+
equalizer (0.0.9)
|
31
|
+
i18n (0.7.0)
|
32
|
+
ice_nine (0.11.1)
|
33
|
+
json (1.8.2)
|
34
|
+
minitest (5.5.1)
|
35
|
+
rake (10.4.2)
|
36
|
+
rspec (2.99.0)
|
37
|
+
rspec-core (~> 2.99.0)
|
38
|
+
rspec-expectations (~> 2.99.0)
|
39
|
+
rspec-mocks (~> 2.99.0)
|
40
|
+
rspec-core (2.99.2)
|
41
|
+
rspec-expectations (2.99.2)
|
42
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
43
|
+
rspec-mocks (2.99.3)
|
44
|
+
thread_safe (0.3.4)
|
45
|
+
tzinfo (1.2.2)
|
46
|
+
thread_safe (~> 0.1)
|
47
|
+
virtus (1.0.4)
|
48
|
+
axiom-types (~> 0.1)
|
49
|
+
coercible (~> 1.0)
|
50
|
+
descendants_tracker (~> 0.0, >= 0.0.3)
|
51
|
+
equalizer (~> 0.0, >= 0.0.9)
|
52
|
+
|
53
|
+
PLATFORMS
|
54
|
+
ruby
|
55
|
+
|
56
|
+
DEPENDENCIES
|
57
|
+
bundler (~> 1.5)
|
58
|
+
rake (~> 10.1)
|
59
|
+
rspec (~> 2.6)
|
60
|
+
simple_params!
|
data/README.md
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# Simple Params
|
2
|
+
|
3
|
+
A simple class to handle parameter validation, for use in APIs or Service Objects. Simply pass in your JSON hash, and get a simple, validateable, accessible ActiveModel-like object.
|
4
|
+
|
5
|
+
This class provides the following benefits for handling params:
|
6
|
+
* Access via array-like (params[:person][:name]), or struct-like (params.person.name) syntax
|
7
|
+
* Ability to validate with any ActiveModel validation
|
8
|
+
* ActiveModel-like errors, including nested error objects for nested params
|
9
|
+
* Parameter type-coercion (e.g. transform "1" into the Integer 1)
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'simple_params', '~> 0.0.1pre'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install simple_params
|
24
|
+
|
25
|
+
## Defining your Params class
|
26
|
+
|
27
|
+
All you need to do is create a class to specify accepted parameters and validations
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class MyParams < SimpleParams::Params
|
31
|
+
param :name
|
32
|
+
param :age, type: Integer
|
33
|
+
param :date_of_birth, type: Date, optional: true
|
34
|
+
param :hair_color, default: "brown", validations: { inclusion: { in: ["brown", "red", "blonde", "white"] }}
|
35
|
+
|
36
|
+
nested_hash :address do
|
37
|
+
param :street
|
38
|
+
param :city
|
39
|
+
param :zip_code, validations: { length: { in: 5..9 } }
|
40
|
+
param :state, optional: true
|
41
|
+
param :country, default: "USA"
|
42
|
+
end
|
43
|
+
|
44
|
+
# You can include whatever custom methods you need as well
|
45
|
+
def full_address
|
46
|
+
[address.street, address.city, address.state, address.zip_code].join(" ")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
```
|
50
|
+
We can now treat these params in very ActiveModel-like ways. For example:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
params = MyParams.new(
|
54
|
+
{
|
55
|
+
name: "Bob Barker",
|
56
|
+
age: "91",
|
57
|
+
date_of_birth: "December 12th, 1923",
|
58
|
+
hair_color: "white",
|
59
|
+
address: {
|
60
|
+
street: "7800 Beverly Blvd",
|
61
|
+
city: "Los Angeles",
|
62
|
+
state: "California",
|
63
|
+
zip_code: "90036"
|
64
|
+
}
|
65
|
+
}
|
66
|
+
)
|
67
|
+
|
68
|
+
params.valid? #=> true
|
69
|
+
params.name #=> "Bob Barker"
|
70
|
+
params.full_address #=> "7800 Beverly Blvd Los Angeles California 90036"
|
71
|
+
```
|
72
|
+
|
73
|
+
## Validation & Errors
|
74
|
+
|
75
|
+
Errors are also treated in a very ActiveModel-like way, making it simple to validate even complexly nested inputs.
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
params = MyParams.new(
|
79
|
+
{
|
80
|
+
name: "",
|
81
|
+
age: "91",
|
82
|
+
address: {
|
83
|
+
city: "Los Angeles",
|
84
|
+
state: "California",
|
85
|
+
zip_code: "90036"
|
86
|
+
}
|
87
|
+
}
|
88
|
+
)
|
89
|
+
|
90
|
+
params.valid? #=> false
|
91
|
+
params.errors[:name] #=> ["can't be blank"]
|
92
|
+
params.errors[:address][:street] #=> ["can't be blank"]
|
93
|
+
params.address.errors[:street] #=> ["can't be blank"]
|
94
|
+
|
95
|
+
params.errors.as_json #=> {:name=>["can't be blank"], :address=>{:street=>["can't be blank"]}}
|
96
|
+
params.address.errors.as_json #=> {:street=>["can't be blank"]}
|
97
|
+
```
|
98
|
+
|
99
|
+
## Defaults
|
100
|
+
|
101
|
+
It is easy to set simple or complex defaults, with either a static value or a Proc
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
class DefaultParams < SimpleParams::Params
|
105
|
+
param :name, default: "Doc Brown"
|
106
|
+
param :first_initial, default: lambda { |params, attribute| params.name[0] }
|
107
|
+
|
108
|
+
nested_hash :car do
|
109
|
+
param :make, default: "DeLorean"
|
110
|
+
param :license_plate, default: lambda { |params, attribute| params.make[0..2].upcase + "-1234" }
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
params = DefaultParams.new
|
115
|
+
|
116
|
+
params.name #=> "Doc Brown"
|
117
|
+
params.first_initial #=> "D"
|
118
|
+
params.car.make #=> "DeLorean"
|
119
|
+
params.car.license_plate #=> "DEL-1234"
|
120
|
+
```
|
121
|
+
|
122
|
+
# Coercion
|
123
|
+
|
124
|
+
SimpleParams provides support for converting incoming params from one type to another. This is extremely helpful for integers, dates, floats, and booleans, which will often come in as strings but should not be treated as such.
|
125
|
+
|
126
|
+
By default, params are assumed to be strings, so there is no need to specify String as a type.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
class CoercionParams < SimpleParams::Params
|
130
|
+
param :name
|
131
|
+
param :age, type: Integer
|
132
|
+
param :date_of_birth, type: Date
|
133
|
+
param :pocket_change, type: BigDecimal
|
134
|
+
end
|
135
|
+
|
136
|
+
params = CoercionParams.new(name: "Bob", age: "21", date_of_birth: "June 1st, 1980", pocket_change: "2.35")
|
137
|
+
|
138
|
+
params.name #=> "Bob"
|
139
|
+
params.age #=> 21
|
140
|
+
params.date_of_birth #=> #<Date: 1980-06-01>
|
141
|
+
params.pocket_change #=> #<BigDecimal:89ed240,'0.235E1',18(18)>
|
142
|
+
```
|
143
|
+
|
144
|
+
SimpleParams also provide helper methods for implicitly specifying the type, if you prefer that syntax. Here is the same class as above, but redefined with these helper methods.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
class CoercionParams < SimpleParams::Params
|
148
|
+
param :name
|
149
|
+
integer_param :age
|
150
|
+
date_param :date_of_birth
|
151
|
+
decimal_param :pocket_change
|
152
|
+
end
|
153
|
+
```
|
154
|
+
|
155
|
+
## Contributing
|
156
|
+
|
157
|
+
1. Fork it
|
158
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
159
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
160
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
161
|
+
5. Create new Pull Request
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
3
|
+
module SimpleParams
|
4
|
+
class Errors < ActiveModel::Errors
|
5
|
+
|
6
|
+
def initialize(base, nested_attributes = [])
|
7
|
+
super(base)
|
8
|
+
@nested_attributes = symbolize_nested(nested_attributes)
|
9
|
+
end
|
10
|
+
|
11
|
+
def [](attribute)
|
12
|
+
get(attribute.to_sym) || reset_attribute(attribute.to_sym)
|
13
|
+
end
|
14
|
+
|
15
|
+
def []=(attribute, error)
|
16
|
+
add_error_to_attribute(attribute, error)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(attribute, message = :invalid, options = {})
|
20
|
+
message = normalize_message(attribute, message, options)
|
21
|
+
if exception = options[:strict]
|
22
|
+
exception = ActiveModel::StrictValidationFailed if exception == true
|
23
|
+
raise exception, full_message(attribute, message)
|
24
|
+
end
|
25
|
+
|
26
|
+
add_error_to_attribute(attribute, message)
|
27
|
+
end
|
28
|
+
|
29
|
+
def clear
|
30
|
+
super
|
31
|
+
@nested_attributes.each do |attribute|
|
32
|
+
if fetch_nested_attribute(attribute).present?
|
33
|
+
fetch_nested_attribute(attribute).errors.clear
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def empty?
|
39
|
+
super &&
|
40
|
+
@nested_attributes.all? do |attribute|
|
41
|
+
if fetch_nested_attribute(attribute).present?
|
42
|
+
fetch_nested_attribute(attribute).errors.empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
alias_method :blank?, :empty?
|
47
|
+
|
48
|
+
def include?(attribute)
|
49
|
+
if fetch_nested_attribute(attribute)
|
50
|
+
!fetch_nested_attribute(attribute).errors.empty?
|
51
|
+
else
|
52
|
+
messages[attribute].present?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
alias_method :has_key?, :include?
|
56
|
+
alias_method :key?, :include?
|
57
|
+
|
58
|
+
def values
|
59
|
+
messages.values +
|
60
|
+
@nested_attributes.map do |attribute|
|
61
|
+
if fetch_nested_attribute(attribute).present?
|
62
|
+
fetch_nested_attribute(attribute).errors.values
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def full_messages
|
68
|
+
parent_messages = map { |attribute, message| full_message(attribute, message) }
|
69
|
+
nested_messages = @nested_attributes.map do |attribute|
|
70
|
+
if fetch_nested_attribute(attribute)
|
71
|
+
messages = fetch_nested_attribute(attribute).errors.full_messages
|
72
|
+
messages.map do |message|
|
73
|
+
"#{attribute} " + message
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
(parent_messages + nested_messages).flatten
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_hash(full_messages = false)
|
81
|
+
messages = super(full_messages)
|
82
|
+
nested_messages = @nested_attributes.map do |attribute|
|
83
|
+
errors = nested_error_messages(attribute, full_messages)
|
84
|
+
unless errors.empty?
|
85
|
+
messages.merge!(attribute.to_sym => errors)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
messages
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
def nested_error_messages(attribute, full_messages = false)
|
93
|
+
if fetch_nested_attribute(attribute)
|
94
|
+
if full_messages
|
95
|
+
errors = fetch_nested_attribute(attribute).errors
|
96
|
+
errors.messages.each_with_object({}) do |(attribute, array), messages|
|
97
|
+
messages[attribute] = array.map { |message| errors.full_message(attribute, message) }
|
98
|
+
end
|
99
|
+
else
|
100
|
+
fetch_nested_attribute(attribute).errors.messages.dup
|
101
|
+
end
|
102
|
+
else
|
103
|
+
{}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_error_to_attribute(attribute, error)
|
108
|
+
if fetch_nested_attribute(attribute)
|
109
|
+
fetch_nested_attribute(attribute).errors[:base] = error
|
110
|
+
else
|
111
|
+
self[attribute] << error
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def reset_attribute(attribute)
|
116
|
+
if fetch_nested_attribute(attribute)
|
117
|
+
set(attribute.to_sym, fetch_nested_attribute(attribute).errors)
|
118
|
+
else
|
119
|
+
set(attribute.to_sym, [])
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def fetch_nested_attribute(attribute)
|
124
|
+
if @nested_attributes.include?(attribute)
|
125
|
+
@base.send(attribute)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def symbolize_nested(nested)
|
130
|
+
nested.map { |x| x.to_sym }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require "active_model"
|
2
|
+
require "virtus"
|
3
|
+
|
4
|
+
module SimpleParams
|
5
|
+
class Params
|
6
|
+
include Virtus.model
|
7
|
+
include ActiveModel::Validations
|
8
|
+
include SimpleParams::Validations
|
9
|
+
|
10
|
+
class << self
|
11
|
+
TYPE_MAPPINGS = {
|
12
|
+
integer: Integer,
|
13
|
+
string: String,
|
14
|
+
decimal: BigDecimal,
|
15
|
+
datetime: DateTime,
|
16
|
+
date: Time,
|
17
|
+
time: DateTime,
|
18
|
+
float: Float,
|
19
|
+
# See note on Virtus
|
20
|
+
boolean: Axiom::Types::Boolean,
|
21
|
+
array: Array,
|
22
|
+
hash: Hash
|
23
|
+
}
|
24
|
+
|
25
|
+
TYPE_MAPPINGS.each_pair do |sym, klass|
|
26
|
+
define_method("#{sym}_param") do |name, opts={}|
|
27
|
+
param(name, opts.merge(type: klass))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def param(name, opts={})
|
32
|
+
define_attribute(name, opts)
|
33
|
+
add_validations(name, opts)
|
34
|
+
end
|
35
|
+
|
36
|
+
def nested_hash(name, opts={}, &block)
|
37
|
+
attr_accessor name
|
38
|
+
nested_class = define_nested_class(&block)
|
39
|
+
@nested_hashes ||= {}
|
40
|
+
@nested_hashes[name.to_sym] = nested_class
|
41
|
+
end
|
42
|
+
alias_method :nested_param, :nested_hash
|
43
|
+
alias_method :nested, :nested_hash
|
44
|
+
|
45
|
+
def nested_hashes
|
46
|
+
@nested_hashes || {}
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def define_attribute(name, opts = {})
|
51
|
+
type = opts[:type] || String
|
52
|
+
default = opts[:default]
|
53
|
+
if default.present?
|
54
|
+
attribute name, type, default: default
|
55
|
+
else
|
56
|
+
attribute name, type
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_validations(name, opts = {})
|
61
|
+
validations = opts[:validations] || {}
|
62
|
+
validations.merge!(presence: true) unless opts[:optional]
|
63
|
+
validates name, validations unless validations.empty?
|
64
|
+
end
|
65
|
+
|
66
|
+
def define_nested_class(&block)
|
67
|
+
Class.new(Params).tap do |klass|
|
68
|
+
name_function = Proc.new {
|
69
|
+
def self.model_name
|
70
|
+
ActiveModel::Name.new(self, nil, "temp")
|
71
|
+
end
|
72
|
+
}
|
73
|
+
klass.class_eval(&name_function)
|
74
|
+
klass.class_eval(&block)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def initialize(params={}, parent = nil)
|
80
|
+
@parent = parent
|
81
|
+
@original_params = hash_to_symbolized_hash(params)
|
82
|
+
@nested_params = nested_hashes.keys
|
83
|
+
@errors = SimpleParams::Errors.new(self, @nested_params)
|
84
|
+
initialize_nested_classes
|
85
|
+
set_accessors(params)
|
86
|
+
# This method comes from Virtus
|
87
|
+
# virtus/lib/virtus/instance_methods.rb
|
88
|
+
set_default_attributes
|
89
|
+
end
|
90
|
+
|
91
|
+
protected
|
92
|
+
def set_accessors(params={})
|
93
|
+
params.each do |attribute_name, value|
|
94
|
+
# Don't set accessors for nested classes
|
95
|
+
unless value.is_a?(Hash)
|
96
|
+
send("#{attribute_name}=", value)
|
97
|
+
reset_blank_attributes
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def reset_blank_attributes
|
103
|
+
# Reset to the default value for blank attributes
|
104
|
+
attributes.each do |attribute_name, value|
|
105
|
+
if send(attribute_name).blank?
|
106
|
+
# This method comes from Virtus
|
107
|
+
# virtus/lib/virtus/instance_methods.rb
|
108
|
+
reset_attribute(attribute_name)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
def hash_to_symbolized_hash(hash)
|
115
|
+
hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
|
116
|
+
end
|
117
|
+
|
118
|
+
def nested_hashes
|
119
|
+
self.class.nested_hashes
|
120
|
+
end
|
121
|
+
|
122
|
+
def initialize_nested_classes
|
123
|
+
nested_hashes.each do |key, klass|
|
124
|
+
initialization_params = @original_params[key.to_sym] || {}
|
125
|
+
send("#{key}=", klass.new(initialization_params, self))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "active_model"
|
2
|
+
|
3
|
+
module SimpleParams
|
4
|
+
module Validations
|
5
|
+
extend ActiveModel::Validations
|
6
|
+
|
7
|
+
# Overriding #valid? to provide recursive validating of
|
8
|
+
# nested params
|
9
|
+
def valid?(context = nil)
|
10
|
+
current_context, self.validation_context = validation_context, context
|
11
|
+
errors.clear
|
12
|
+
run_validations!
|
13
|
+
nested_hashes.each do |key, value|
|
14
|
+
nested_class = send("#{key}")
|
15
|
+
nested_class.valid?
|
16
|
+
end
|
17
|
+
errors.empty?
|
18
|
+
ensure
|
19
|
+
self.validation_context = current_context
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate!
|
23
|
+
unless valid?
|
24
|
+
raise StandardError, errors.to_s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'simple_params/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "simple_params"
|
8
|
+
spec.version = SimpleParams::VERSION
|
9
|
+
spec.authors = ["brycesenz"]
|
10
|
+
spec.email = ["bryce.senz@gmail.com"]
|
11
|
+
spec.description = %q{Simple way to specify API params}
|
12
|
+
spec.summary = %q{A DSL for specifying params, including type coercion and validation}
|
13
|
+
spec.homepage = "https://github.com/brycesenz/simple_params"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activemodel", ">= 3.0", "< 5.0"
|
22
|
+
spec.add_dependency "virtus", ">= 1.0.0"
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.1"
|
25
|
+
spec.add_development_dependency "rspec", "~> 2.6"
|
26
|
+
end
|