parametric 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: ea2ea42f0944e44e3fa09a487428f6b8cd6ef61f
4
- data.tar.gz: 5e058214303cc07ac28f93924529efe8b88875fc
5
- SHA512:
6
- metadata.gz: e418038925d9b0e9c302cfd616b8148dd855377aaf1fa3d69ec7cb9f821add9c6e649bb096bb539fb581b4c2fcb6ca2b51ea23fc953530930daa71cdb754d184
7
- data.tar.gz: 6efb123579da71f5195f3a36f5a02a0747193c55a60217c2061afc3186367cfe28bf5798c09ba11da82335b05a9e2cd83b2434964457685e9c3e905df621d45a
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
- param :page, 'Page number', default: 1
162
- param :per_page, 'Items per page', default: 30
163
- param :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true
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
 
@@ -1,7 +1,7 @@
1
1
  require 'forwardable'
2
2
  module Parametric
3
3
  class Hash
4
- include Params
4
+ include TypedParams
5
5
  include Enumerable
6
6
  extend ::Forwardable
7
7
  def_delegators(:params,
@@ -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]
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Parametric
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/parametric.rb CHANGED
@@ -6,4 +6,5 @@ require "parametric/utils"
6
6
  require "parametric/version"
7
7
  require "parametric/policies"
8
8
  require "parametric/params"
9
+ require "parametric/typed_params"
9
10
  require "parametric/hash"
data/parametric.gemspec CHANGED
@@ -20,5 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.5"
22
22
  spec.add_development_dependency "rake"
23
- spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency "rspec", '2.14.1'
24
24
  end
@@ -5,103 +5,133 @@ describe Parametric do
5
5
  Parametric::VERSION.should_not be_nil
6
6
  end
7
7
 
8
- describe Parametric::Params do
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
- let(:klass) do
11
- Class.new do
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
- describe '#params' do
26
- let(:subject) { klass.new(foo: 'bar', per_page: 20, status: 'four') }
17
+ it 'uses defaults if no value passed' do
18
+ subject.params[:page].should == 1
19
+ end
27
20
 
28
- it 'ignores undeclared fields' do
29
- subject.params.has_key?(:foo).should be_false
30
- end
21
+ it 'does not set value if outside of declared options' do
22
+ subject.params[:status].should == []
23
+ end
31
24
 
32
- it 'sets passed values' do
33
- subject.params[:per_page].should == 20
34
- end
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
- it 'uses defaults if no value passed' do
37
- subject.params[:page].should == 1
38
- end
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
- it 'does not set value if outside of declared options' do
41
- subject.params[:status].should == []
42
- end
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
- it 'does not set value if it does not :match' do
45
- klass.new(email: 'my@email').params[:email].should be_nil
46
- end
37
+ it 'returns :default wrapped in array if :multiple' do
38
+ klass.new().params[:emails].should == ['default@email.com']
39
+ end
47
40
 
48
- it 'defaults work for false values' do
49
- klass.new(email: 'my@email').params[:email].should be_nil
50
- end
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
- it 'does set value if it does :match' do
53
- klass.new(available: false).params[:available].should be_false
54
- end
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
- it 'only sets value for :multiple values that :match' do
57
- klass.new(emails: 'my@email,your,her@email.com').params[:emails].should == ['her@email.com']
58
- end
49
+ it ':multiple values can be arrays' do
50
+ klass.new(status: ['one','three']).params[:status].should == ['one', 'three']
51
+ end
59
52
 
60
- it 'returns :default wrapped in array if :multiple' do
61
- klass.new().params[:emails].should == ['default@email.com']
62
- end
53
+ it 'defaults work for false values' do
54
+ klass.new(email: 'my@email').params[:email].should be_nil
55
+ end
63
56
 
64
- it 'turns :multiple comma-separated values into arrays' do
65
- klass.new(status: 'one,three').params[:status].should == ['one', 'three']
66
- end
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
- it ':multiple values can be arrays' do
69
- klass.new(status: ['one','three']).params[:status].should == ['one', 'three']
70
- end
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
- it 'turns :multiple separated values with custom separator into arrays' do
73
- klass.new(piped_status: 'one|three').params[:piped_status].should == ['one', 'three']
74
- end
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
- it 'does not turn non-multiple comma-separated values into arrays' do
77
- klass.new(name: 'foo,bar').params[:name].should == 'foo,bar'
78
- end
69
+ it 'filters out undeclared options' do
70
+ klass.new(status: 'one,three,fourteen').params[:status].should == ['one', 'three']
71
+ end
79
72
 
80
- it 'filters out undeclared options' do
81
- klass.new(status: 'one,three,fourteen').params[:status].should == ['one', 'three']
82
- end
73
+ it 'defaults empty multiple options to empty array' do
74
+ klass.new().params[:status].should == []
75
+ end
83
76
 
84
- it 'defaults empty multiple options to empty array' do
85
- klass.new().params[:status].should == []
86
- end
77
+ it 'wraps single multiple options in array' do
78
+ klass.new(status: 'one').params[:status].should == ['one']
79
+ end
87
80
 
88
- it 'wraps single multiple options in array' do
89
- klass.new(status: 'one').params[:status].should == ['one']
90
- end
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
- it 'does not accept comma-separated values outside of options unless :multiple == true' do
93
- klass.new(country: 'UK,CL').params[:country].should be_nil
94
- end
85
+ it 'does accept single option' do
86
+ klass.new(country: 'UK').params[:country].should == 'UK'
87
+ end
95
88
 
96
- it 'does accept single option' do
97
- klass.new(country: 'UK').params[:country].should == 'UK'
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
- it 'does not accept single option if not in declared options' do
101
- klass.new(country: 'USA').params[:country].should be_nil
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
- param :name, 'User name'
167
- param :page, 'page number', default: 1
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
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
- date: 2014-04-03 00:00:00 Z
13
- dependencies:
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
- prerelease: false
17
- requirement: &id001 !ruby/object:Gem::Requirement
18
- requirements:
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
19
17
  - - ~>
20
- - !ruby/object:Gem::Version
21
- version: "1.5"
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
- requirement: &id002 !ruby/object:Gem::Requirement
28
- requirements:
29
- - &id003
30
- - ">="
31
- - !ruby/object:Gem::Version
32
- version: "0"
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
- requirement: &id004 !ruby/object:Gem::Requirement
39
- requirements:
40
- - *id003
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
- version_requirements: *id004
43
- description: Useful for modelling search or form objects, white-listed query parameters and safe parameter defaults.
44
- email:
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
- - *id003
83
- required_rubygems_version: !ruby/object:Gem::Requirement
84
- requirements:
85
- - *id003
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.5
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 values.
93
- test_files:
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: