parametric 0.0.3 → 0.0.4
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 +7 -7
- data/README.md +34 -4
- data/lib/parametric/hash.rb +1 -1
- data/lib/parametric/params.rb +1 -0
- data/lib/parametric/policies.rb +14 -0
- data/lib/parametric/typed_params.rb +23 -0
- data/lib/parametric/version.rb +1 -1
- data/lib/parametric.rb +1 -0
- data/parametric.gemspec +1 -1
- data/spec/parametric_spec.rb +113 -73
- metadata +63 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
5
|
-
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2e111716f0cd0f60d10a0354e70ac7ecfea42634
|
4
|
+
data.tar.gz: 2012ce66941c5a24f4bf8b3f2dc7e7ceab86311a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f146875b9b83e0b8e85cc89ff04dc817e731653bbda09d0a54c85db1957ef68b6b0007e52a9cda1a704069d9438a4d0b205acc6ce12ef62429f1ab316c4ad800
|
7
|
+
data.tar.gz: d52634e2b6526a3c81ecef0126a6558351beb030b49f28ae6c07861d2d389d777cbbbfc710f6d32ebf55f9fe6f55b8d9fe8b7fb18b697363f20b7b49c828f767
|
data/README.md
CHANGED
@@ -57,7 +57,7 @@ class OrdersSearch
|
|
57
57
|
|
58
58
|
def results
|
59
59
|
query = Order.sort(params[:sort])
|
60
|
-
query = query.where(["code LIKE ? OR user_name ?", params[:q]]) if params[:q]
|
60
|
+
query = query.where(["code LIKE ? OR user_name LIKE ?", params[:q]]) if params[:q]
|
61
61
|
query = query.where(status: params[:status]) if params[:status].any?
|
62
62
|
query = query.paginate(page: params[:page], per_page: params[:per_page])
|
63
63
|
end
|
@@ -151,6 +151,36 @@ order_search.schema[:status].multiple # => true
|
|
151
151
|
order_search.schema[:status].default # => 'closed'
|
152
152
|
```
|
153
153
|
|
154
|
+
## Coercing values
|
155
|
+
|
156
|
+
Param definitions take an optional `:coerce` option with a symbol or proc to coerce resulting values.
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
class UsersSearch
|
160
|
+
include Parametric::Params
|
161
|
+
param :age, 'User age', coerce: :to_i
|
162
|
+
param :name, 'User name', coerce: lambda{|name| "Mr. #{name}"}
|
163
|
+
end
|
164
|
+
|
165
|
+
search = UsersSearch.new(age: '36', name: 'Ismael')
|
166
|
+
|
167
|
+
search.available_params[:age] # => 36
|
168
|
+
search.available_params[:name] # => 'Mr. Ismael'
|
169
|
+
```
|
170
|
+
|
171
|
+
### Parametric::TypedParams
|
172
|
+
|
173
|
+
The `Parametric::TypedParams` module includes extra DSL methods to coerce values to standard Ruby types.
|
174
|
+
|
175
|
+
class UsersSearch
|
176
|
+
include Parametric::TypedParams
|
177
|
+
integer :age, 'User age'
|
178
|
+
array :accounts
|
179
|
+
string :country_code
|
180
|
+
# you can still use :coerce
|
181
|
+
param :name, 'User name', coerce: lambda{|name| "Mr. #{name}"}
|
182
|
+
end
|
183
|
+
|
154
184
|
## Parametric::Hash
|
155
185
|
|
156
186
|
The alternative `Parametric::Hash` class makes your objects quack like a hash, instead of exposing the `#params` object directly.
|
@@ -158,9 +188,9 @@ The alternative `Parametric::Hash` class makes your objects quack like a hash, i
|
|
158
188
|
```ruby
|
159
189
|
class OrdersParams < Parametric::Hash
|
160
190
|
param :q, 'Full text search query'
|
161
|
-
|
162
|
-
|
163
|
-
|
191
|
+
integer :page, 'Page number', default: 1
|
192
|
+
integer :per_page, 'Items per page', default: 30
|
193
|
+
array :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped']
|
164
194
|
end
|
165
195
|
```
|
166
196
|
|
data/lib/parametric/hash.rb
CHANGED
data/lib/parametric/params.rb
CHANGED
@@ -43,6 +43,7 @@ module Parametric
|
|
43
43
|
def _reduce(raw_params)
|
44
44
|
self.class._allowed_params.each_with_object(ParamsHash.new) do |(key,options),memo|
|
45
45
|
policy = Policies::Policy.new((raw_params.has_key?(key) ? raw_params[key] : []), options)
|
46
|
+
policy = policy.wrap(Policies::CoercePolicy) if options[:coerce]
|
46
47
|
policy = policy.wrap(Policies::NestedPolicy) if options[:nested]
|
47
48
|
policy = policy.wrap(Policies::MultiplePolicy) if options[:multiple]
|
48
49
|
policy = policy.wrap(Policies::OptionsPolicy) if options[:options]
|
data/lib/parametric/policies.rb
CHANGED
@@ -44,6 +44,20 @@ module Parametric
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
+
class CoercePolicy < Policy
|
48
|
+
def value
|
49
|
+
decorated.value.map do |v|
|
50
|
+
if options[:coerce].is_a?(Symbol) && v.respond_to?(options[:coerce])
|
51
|
+
v.send(options[:coerce])
|
52
|
+
elsif options[:coerce].respond_to?(:call)
|
53
|
+
options[:coerce].call v
|
54
|
+
else
|
55
|
+
v
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
47
61
|
class SinglePolicy < Policy
|
48
62
|
def value
|
49
63
|
decorated.value.first
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'parametric/params'
|
2
|
+
module Parametric
|
3
|
+
module TypedParams
|
4
|
+
def self.included(base)
|
5
|
+
base.send(:include, Params)
|
6
|
+
base.extend DSL
|
7
|
+
end
|
8
|
+
|
9
|
+
module DSL
|
10
|
+
def integer(field_name, label = '', opts = {}, &block)
|
11
|
+
param(field_name, label, opts.merge(coerce: :to_i), &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
def string(field_name, label = '', opts = {}, &block)
|
15
|
+
param(field_name, label, opts.merge(coerce: :to_s), &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def array(field_name, label = '', opts = {}, &block)
|
19
|
+
param(field_name, label, opts.merge(multiple: true), &block)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/parametric/version.rb
CHANGED
data/lib/parametric.rb
CHANGED
data/parametric.gemspec
CHANGED
data/spec/parametric_spec.rb
CHANGED
@@ -5,103 +5,133 @@ describe Parametric do
|
|
5
5
|
Parametric::VERSION.should_not be_nil
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
shared_examples 'a configurable params object' do
|
9
|
+
it 'ignores undeclared fields' do
|
10
|
+
subject.params.has_key?(:foo).should be_false
|
11
|
+
end
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
include Parametric::Params
|
13
|
-
param :name, 'User name'
|
14
|
-
param :page, 'page number', default: 1
|
15
|
-
param :per_page, 'items per page', default: 50
|
16
|
-
param :status, 'status', options: ['one', 'two', 'three'], multiple: true
|
17
|
-
param :piped_status, 'status with pipes', multiple: true, separator: '|'
|
18
|
-
param :country, 'country', options: ['UK', 'CL', 'JPN']
|
19
|
-
param :email, 'email', match: /\w+@\w+\.\w+/
|
20
|
-
param :emails, 'emails', match: /\w+@\w+\.\w+/, multiple: true, default: 'default@email.com'
|
21
|
-
param :available, 'available', default: true
|
22
|
-
end
|
13
|
+
it 'sets passed values' do
|
14
|
+
subject.params[:per_page].should == 20
|
23
15
|
end
|
24
16
|
|
25
|
-
|
26
|
-
|
17
|
+
it 'uses defaults if no value passed' do
|
18
|
+
subject.params[:page].should == 1
|
19
|
+
end
|
27
20
|
|
28
|
-
|
29
|
-
|
30
|
-
|
21
|
+
it 'does not set value if outside of declared options' do
|
22
|
+
subject.params[:status].should == []
|
23
|
+
end
|
31
24
|
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
it 'does not set value if it does not :match' do
|
26
|
+
klass.new(email: 'my@email').params[:email].should be_nil
|
27
|
+
end
|
35
28
|
|
36
|
-
|
37
|
-
|
38
|
-
|
29
|
+
it 'does set value if it does :match' do
|
30
|
+
klass.new(email: 'my@email.com').params[:email].should == 'my@email.com'
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
it 'only sets value for :multiple values that :match' do
|
34
|
+
klass.new(emails: 'my@email,your,her@email.com').params[:emails].should == ['her@email.com']
|
35
|
+
end
|
43
36
|
|
44
|
-
|
45
|
-
|
46
|
-
|
37
|
+
it 'returns :default wrapped in array if :multiple' do
|
38
|
+
klass.new().params[:emails].should == ['default@email.com']
|
39
|
+
end
|
47
40
|
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
it 'turns :multiple comma-separated values into arrays' do
|
42
|
+
klass.new(status: 'one,three').params[:status].should == ['one', 'three']
|
43
|
+
end
|
51
44
|
|
52
|
-
|
53
|
-
|
54
|
-
|
45
|
+
it 'does set value if it does :match' do
|
46
|
+
klass.new(email: 'my@email.com').params[:email].should == 'my@email.com'
|
47
|
+
end
|
55
48
|
|
56
|
-
|
57
|
-
|
58
|
-
|
49
|
+
it ':multiple values can be arrays' do
|
50
|
+
klass.new(status: ['one','three']).params[:status].should == ['one', 'three']
|
51
|
+
end
|
59
52
|
|
60
|
-
|
61
|
-
|
62
|
-
|
53
|
+
it 'defaults work for false values' do
|
54
|
+
klass.new(email: 'my@email').params[:email].should be_nil
|
55
|
+
end
|
63
56
|
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
it 'does set value if it does :match' do
|
58
|
+
klass.new(available: false).params[:available].should be_false
|
59
|
+
end
|
67
60
|
|
68
|
-
|
69
|
-
|
70
|
-
|
61
|
+
it 'turns :multiple separated values with custom separator into arrays' do
|
62
|
+
klass.new(piped_status: 'one|three').params[:piped_status].should == ['one', 'three']
|
63
|
+
end
|
71
64
|
|
72
|
-
|
73
|
-
|
74
|
-
|
65
|
+
it 'does not turn non-multiple comma-separated values into arrays' do
|
66
|
+
klass.new(name: 'foo,bar').params[:name].should == 'foo,bar'
|
67
|
+
end
|
75
68
|
|
76
|
-
|
77
|
-
|
78
|
-
|
69
|
+
it 'filters out undeclared options' do
|
70
|
+
klass.new(status: 'one,three,fourteen').params[:status].should == ['one', 'three']
|
71
|
+
end
|
79
72
|
|
80
|
-
|
81
|
-
|
82
|
-
|
73
|
+
it 'defaults empty multiple options to empty array' do
|
74
|
+
klass.new().params[:status].should == []
|
75
|
+
end
|
83
76
|
|
84
|
-
|
85
|
-
|
86
|
-
|
77
|
+
it 'wraps single multiple options in array' do
|
78
|
+
klass.new(status: 'one').params[:status].should == ['one']
|
79
|
+
end
|
87
80
|
|
88
|
-
|
89
|
-
|
90
|
-
|
81
|
+
it 'does not accept comma-separated values outside of options unless :multiple == true' do
|
82
|
+
klass.new(country: 'UK,CL').params[:country].should be_nil
|
83
|
+
end
|
91
84
|
|
92
|
-
|
93
|
-
|
94
|
-
|
85
|
+
it 'does accept single option' do
|
86
|
+
klass.new(country: 'UK').params[:country].should == 'UK'
|
87
|
+
end
|
95
88
|
|
96
|
-
|
97
|
-
|
89
|
+
it 'does not accept single option if not in declared options' do
|
90
|
+
klass.new(country: 'USA').params[:country].should be_nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
describe 'TypedParams' do
|
95
|
+
let(:klass) do
|
96
|
+
Class.new do
|
97
|
+
include Parametric::TypedParams
|
98
|
+
string :name, 'User name'
|
99
|
+
integer :page, 'page number', default: 1
|
100
|
+
integer :per_page, 'items per page', default: 50
|
101
|
+
array :status, 'status', options: ['one', 'two', 'three']
|
102
|
+
array :piped_status, 'status with pipes', separator: '|'
|
103
|
+
string :country, 'country', options: ['UK', 'CL', 'JPN']
|
104
|
+
string :email, 'email', match: /\w+@\w+\.\w+/
|
105
|
+
array :emails, 'emails', match: /\w+@\w+\.\w+/, default: 'default@email.com'
|
98
106
|
end
|
107
|
+
end
|
108
|
+
|
109
|
+
let(:subject) { klass.new(foo: 'bar', per_page: '20', status: 'four') }
|
110
|
+
it_should_behave_like 'a configurable params object'
|
111
|
+
end
|
112
|
+
|
113
|
+
describe Parametric::Params do
|
99
114
|
|
100
|
-
|
101
|
-
|
115
|
+
let(:klass) do
|
116
|
+
Class.new do
|
117
|
+
include Parametric::Params
|
118
|
+
param :name, 'User name'
|
119
|
+
param :page, 'page number', default: 1, coerce: :to_i
|
120
|
+
param :per_page, 'items per page', default: 50, coerce: lambda{|value| value.to_i}
|
121
|
+
param :status, 'status', options: ['one', 'two', 'three'], multiple: true
|
122
|
+
param :piped_status, 'status with pipes', multiple: true, separator: '|'
|
123
|
+
param :country, 'country', options: ['UK', 'CL', 'JPN']
|
124
|
+
param :email, 'email', match: /\w+@\w+\.\w+/
|
125
|
+
param :emails, 'emails', match: /\w+@\w+\.\w+/, multiple: true, default: 'default@email.com'
|
126
|
+
param :available, 'available', default: true
|
102
127
|
end
|
103
128
|
end
|
104
129
|
|
130
|
+
describe '#params' do
|
131
|
+
let(:subject) { klass.new(foo: 'bar', per_page: 20, status: 'four') }
|
132
|
+
it_should_behave_like 'a configurable params object'
|
133
|
+
end
|
134
|
+
|
105
135
|
describe '#available_params' do
|
106
136
|
let(:subject) { klass.new(foo: 'bar', name: 'lala', per_page: 20, status: 'four', emails: 'one@email.com,two@email.com') }
|
107
137
|
|
@@ -113,6 +143,16 @@ describe Parametric do
|
|
113
143
|
subject.available_params[:page].should == 1
|
114
144
|
end
|
115
145
|
|
146
|
+
describe ':coerce option' do
|
147
|
+
it 'accepts method_name as a symbol' do
|
148
|
+
klass.new(page: '10').available_params[:page].should == 10
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'accepts a proc' do
|
152
|
+
klass.new(per_page: '10').available_params[:per_page].should == 10
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
116
156
|
describe '#flat' do
|
117
157
|
it 'joins values back' do
|
118
158
|
subject.available_params.flat[:emails].should == 'one@email.com,two@email.com'
|
@@ -163,8 +203,8 @@ describe Parametric do
|
|
163
203
|
describe Parametric::Hash do
|
164
204
|
let(:klass) do
|
165
205
|
Class.new(Parametric::Hash) do
|
166
|
-
|
167
|
-
|
206
|
+
string :name, 'User name'
|
207
|
+
integer :page, 'page number', default: 1
|
168
208
|
param :per_page, 'items per page', default: 50
|
169
209
|
end
|
170
210
|
end
|
metadata
CHANGED
@@ -1,55 +1,65 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: parametric
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
|
-
authors:
|
6
|
+
authors:
|
7
7
|
- Ismael Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
- !ruby/object:Gem::Dependency
|
11
|
+
date: 2014-06-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
|
-
|
17
|
-
|
18
|
-
requirements:
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
19
17
|
- - ~>
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version:
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
22
20
|
type: :development
|
23
|
-
version_requirements: *id001
|
24
|
-
- !ruby/object:Gem::Dependency
|
25
|
-
name: rake
|
26
21
|
prerelease: false
|
27
|
-
|
28
|
-
requirements:
|
29
|
-
-
|
30
|
-
-
|
31
|
-
|
32
|
-
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
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'
|
33
34
|
type: :development
|
34
|
-
version_requirements: *id002
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: rspec
|
37
35
|
prerelease: false
|
38
|
-
|
39
|
-
requirements:
|
40
|
-
-
|
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: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.1
|
41
48
|
type: :development
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.1
|
55
|
+
description: Useful for modelling search or form objects, white-listed query parameters
|
56
|
+
and safe parameter defaults.
|
57
|
+
email:
|
45
58
|
- ismaelct@gmail.com
|
46
59
|
executables: []
|
47
|
-
|
48
60
|
extensions: []
|
49
|
-
|
50
61
|
extra_rdoc_files: []
|
51
|
-
|
52
|
-
files:
|
62
|
+
files:
|
53
63
|
- .gitignore
|
54
64
|
- .rspec
|
55
65
|
- .travis.yml
|
@@ -61,37 +71,39 @@ files:
|
|
61
71
|
- lib/parametric/hash.rb
|
62
72
|
- lib/parametric/params.rb
|
63
73
|
- lib/parametric/policies.rb
|
74
|
+
- lib/parametric/typed_params.rb
|
64
75
|
- lib/parametric/utils.rb
|
65
76
|
- lib/parametric/version.rb
|
66
77
|
- parametric.gemspec
|
67
78
|
- spec/nested_params_spec.rb
|
68
79
|
- spec/parametric_spec.rb
|
69
80
|
- spec/spec_helper.rb
|
70
|
-
homepage:
|
71
|
-
licenses:
|
81
|
+
homepage: ''
|
82
|
+
licenses:
|
72
83
|
- MIT
|
73
84
|
metadata: {}
|
74
|
-
|
75
85
|
post_install_message:
|
76
86
|
rdoc_options: []
|
77
|
-
|
78
|
-
require_paths:
|
87
|
+
require_paths:
|
79
88
|
- lib
|
80
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
-
requirements:
|
82
|
-
-
|
83
|
-
|
84
|
-
|
85
|
-
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
86
99
|
requirements: []
|
87
|
-
|
88
100
|
rubyforge_project:
|
89
|
-
rubygems_version: 2.0.
|
101
|
+
rubygems_version: 2.0.3
|
90
102
|
signing_key:
|
91
103
|
specification_version: 4
|
92
|
-
summary: DSL for declaring allowed parameters with options, regexp patern and default
|
93
|
-
|
104
|
+
summary: DSL for declaring allowed parameters with options, regexp patern and default
|
105
|
+
values.
|
106
|
+
test_files:
|
94
107
|
- spec/nested_params_spec.rb
|
95
108
|
- spec/parametric_spec.rb
|
96
109
|
- spec/spec_helper.rb
|
97
|
-
has_rdoc:
|