parametric 0.0.4 → 0.0.5
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 +4 -4
- data/README.md +19 -0
- data/lib/parametric/params.rb +16 -5
- data/lib/parametric/policies.rb +2 -2
- data/lib/parametric/version.rb +1 -1
- data/lib/support/class_attribute.rb +68 -0
- data/spec/parametric_spec.rb +25 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d80f56c0ada8312a25dfcc6ed080b0295f17cfa
|
4
|
+
data.tar.gz: 7940d26ce661dfdd7ead181f77ead1979d62413b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ae1bfae9b04299ee38aff8f5be88a15dd505a6a69fd162c2be0ee261d789a2d55795603f7536d9de30df08b5548423cfbeb2db8f05cc0ce64dbc584392d46c3
|
7
|
+
data.tar.gz: effe305919dab6e2c4d47636b2711e1ec4600532b3f1429fecfa85234f32a50894cbde7d58334a04de3724759f4948918225ca3c139e9864e3ed0c81fb3275bb
|
data/README.md
CHANGED
@@ -124,6 +124,23 @@ search = OrdersSearch.new
|
|
124
124
|
search.params[:status] # => ['closed']
|
125
125
|
```
|
126
126
|
|
127
|
+
### :nullable fields
|
128
|
+
|
129
|
+
In same cases you won't want Parametric to provide nil or empty keys for attributes missing from the input. For example when missing keys has special meaning in your application.
|
130
|
+
|
131
|
+
In those cases you can add the `:nullable` option to said param definitions:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
class OrdersSearch
|
135
|
+
include Parametric::Params
|
136
|
+
param :query, 'Search query. optional', nullable: true
|
137
|
+
param :tags, 'Tags', multiple: true
|
138
|
+
end
|
139
|
+
|
140
|
+
search = OrdersSearch.new({})
|
141
|
+
search.params # {tags: []}
|
142
|
+
```
|
143
|
+
|
127
144
|
## `available_params`
|
128
145
|
|
129
146
|
`#available_params` returns the subset of keys that were populated (including defaults). Useful for building query strings.
|
@@ -172,6 +189,7 @@ search.available_params[:name] # => 'Mr. Ismael'
|
|
172
189
|
|
173
190
|
The `Parametric::TypedParams` module includes extra DSL methods to coerce values to standard Ruby types.
|
174
191
|
|
192
|
+
```ruby
|
175
193
|
class UsersSearch
|
176
194
|
include Parametric::TypedParams
|
177
195
|
integer :age, 'User age'
|
@@ -180,6 +198,7 @@ class UsersSearch
|
|
180
198
|
# you can still use :coerce
|
181
199
|
param :name, 'User name', coerce: lambda{|name| "Mr. #{name}"}
|
182
200
|
end
|
201
|
+
```
|
183
202
|
|
184
203
|
## Parametric::Hash
|
185
204
|
|
data/lib/parametric/params.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'ostruct'
|
2
|
+
require 'support/class_attribute'
|
2
3
|
module Parametric
|
3
4
|
|
4
5
|
class ParamsHash < Hash
|
@@ -13,6 +14,8 @@ module Parametric
|
|
13
14
|
|
14
15
|
def self.included(base)
|
15
16
|
base.send(:attr_reader, :params)
|
17
|
+
base.class_attribute :_allowed_params
|
18
|
+
base._allowed_params = {}
|
16
19
|
base.extend DSL
|
17
20
|
end
|
18
21
|
|
@@ -42,7 +45,9 @@ module Parametric
|
|
42
45
|
|
43
46
|
def _reduce(raw_params)
|
44
47
|
self.class._allowed_params.each_with_object(ParamsHash.new) do |(key,options),memo|
|
45
|
-
|
48
|
+
has_key = raw_params.respond_to?(:has_key?) && raw_params.has_key?(key)
|
49
|
+
value = has_key ? raw_params[key] : []
|
50
|
+
policy = Policies::Policy.new(value, options)
|
46
51
|
policy = policy.wrap(Policies::CoercePolicy) if options[:coerce]
|
47
52
|
policy = policy.wrap(Policies::NestedPolicy) if options[:nested]
|
48
53
|
policy = policy.wrap(Policies::MultiplePolicy) if options[:multiple]
|
@@ -50,13 +55,19 @@ module Parametric
|
|
50
55
|
policy = policy.wrap(Policies::MatchPolicy) if options[:match]
|
51
56
|
policy = policy.wrap(Policies::DefaultPolicy) if options.has_key?(:default)
|
52
57
|
policy = policy.wrap(Policies::SinglePolicy) unless options[:multiple]
|
53
|
-
memo[key] = policy.value
|
58
|
+
memo[key] = policy.value unless options[:nullable] && !has_key
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
57
62
|
module DSL
|
58
|
-
|
59
|
-
|
63
|
+
|
64
|
+
# When subclasses params definitions
|
65
|
+
# we want to copy parent class definitions
|
66
|
+
# so changes in the child class
|
67
|
+
# don't mutate the parent definitions
|
68
|
+
#
|
69
|
+
def inherited(subclass)
|
70
|
+
subclass._allowed_params = self._allowed_params.dup
|
60
71
|
end
|
61
72
|
|
62
73
|
def param(field_name, label = '', opts = {}, &block)
|
@@ -72,4 +83,4 @@ module Parametric
|
|
72
83
|
|
73
84
|
end
|
74
85
|
|
75
|
-
end
|
86
|
+
end
|
data/lib/parametric/policies.rb
CHANGED
@@ -38,7 +38,7 @@ module Parametric
|
|
38
38
|
|
39
39
|
class NestedPolicy < Policy
|
40
40
|
def value
|
41
|
-
decorated.value.map do |v|
|
41
|
+
decorated.value.find_all{|v| v.respond_to?(:has_key?)}.map do |v|
|
42
42
|
options[:nested].new(v)
|
43
43
|
end
|
44
44
|
end
|
@@ -81,4 +81,4 @@ module Parametric
|
|
81
81
|
end
|
82
82
|
|
83
83
|
end
|
84
|
-
end
|
84
|
+
end
|
data/lib/parametric/version.rb
CHANGED
@@ -0,0 +1,68 @@
|
|
1
|
+
begin
|
2
|
+
require 'active_support/core_ext/class/attribute'
|
3
|
+
rescue LoadError
|
4
|
+
module Kernel
|
5
|
+
# Returns the object's singleton class.
|
6
|
+
def singleton_class
|
7
|
+
class << self
|
8
|
+
self
|
9
|
+
end
|
10
|
+
end unless respond_to?(:singleton_class) # exists in 1.9.2
|
11
|
+
|
12
|
+
# class_eval on an object acts like singleton_class.class_eval.
|
13
|
+
def class_eval(*args, &block)
|
14
|
+
singleton_class.class_eval(*args, &block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Module
|
19
|
+
def remove_possible_method(method)
|
20
|
+
if method_defined?(method) || private_method_defined?(method)
|
21
|
+
remove_method(method)
|
22
|
+
end
|
23
|
+
rescue NameError
|
24
|
+
# If the requested method is defined on a superclass or included module,
|
25
|
+
# method_defined? returns true but remove_method throws a NameError.
|
26
|
+
# Ignore this.
|
27
|
+
end
|
28
|
+
|
29
|
+
def redefine_method(method, &block)
|
30
|
+
remove_possible_method(method)
|
31
|
+
define_method(method, &block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Class
|
36
|
+
def class_attribute(*attrs)
|
37
|
+
attrs.each do |name|
|
38
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
39
|
+
def self.#{name}() nil end
|
40
|
+
def self.#{name}?() !!#{name} end
|
41
|
+
|
42
|
+
def self.#{name}=(val)
|
43
|
+
singleton_class.class_eval do
|
44
|
+
remove_possible_method(:#{name})
|
45
|
+
define_method(:#{name}) { val }
|
46
|
+
end
|
47
|
+
|
48
|
+
if singleton_class?
|
49
|
+
class_eval do
|
50
|
+
remove_possible_method(:#{name})
|
51
|
+
def #{name}
|
52
|
+
defined?(@#{name}) ? @#{name} : singleton_class.#{name}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
val
|
57
|
+
end
|
58
|
+
RUBY
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def singleton_class?
|
65
|
+
ancestors.first != self
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/spec/parametric_spec.rb
CHANGED
@@ -89,6 +89,10 @@ describe Parametric do
|
|
89
89
|
it 'does not accept single option if not in declared options' do
|
90
90
|
klass.new(country: 'USA').params[:country].should be_nil
|
91
91
|
end
|
92
|
+
|
93
|
+
it 'does not include parameters marked as :nullable' do
|
94
|
+
klass.new.params.has_key?(:nullable).should be_false
|
95
|
+
end
|
92
96
|
end
|
93
97
|
|
94
98
|
describe 'TypedParams' do
|
@@ -103,11 +107,25 @@ describe Parametric do
|
|
103
107
|
string :country, 'country', options: ['UK', 'CL', 'JPN']
|
104
108
|
string :email, 'email', match: /\w+@\w+\.\w+/
|
105
109
|
array :emails, 'emails', match: /\w+@\w+\.\w+/, default: 'default@email.com'
|
110
|
+
param :nullable, 'nullable param', nullable: true
|
106
111
|
end
|
107
112
|
end
|
108
113
|
|
109
114
|
let(:subject) { klass.new(foo: 'bar', per_page: '20', status: 'four') }
|
110
115
|
it_should_behave_like 'a configurable params object'
|
116
|
+
|
117
|
+
it 'does not break when value is nil' do
|
118
|
+
klass = Class.new do
|
119
|
+
include Parametric::TypedParams
|
120
|
+
array :friends, 'friends', nullable: true do
|
121
|
+
string :name, 'Name'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
klass.new(friends: nil).params[:friends].should == []
|
125
|
+
klass.new(friends: []).params[:friends].should == []
|
126
|
+
klass.new(friends: [{name: 'foo'}]).params[:friends].first[:name].should == 'foo'
|
127
|
+
klass.new.params.has_key?(:friends).should be_false
|
128
|
+
end
|
111
129
|
end
|
112
130
|
|
113
131
|
describe Parametric::Params do
|
@@ -124,6 +142,7 @@ describe Parametric do
|
|
124
142
|
param :email, 'email', match: /\w+@\w+\.\w+/
|
125
143
|
param :emails, 'emails', match: /\w+@\w+\.\w+/, multiple: true, default: 'default@email.com'
|
126
144
|
param :available, 'available', default: true
|
145
|
+
param :nullable, 'nullable param', nullable: true
|
127
146
|
end
|
128
147
|
end
|
129
148
|
|
@@ -132,6 +151,12 @@ describe Parametric do
|
|
132
151
|
it_should_behave_like 'a configurable params object'
|
133
152
|
end
|
134
153
|
|
154
|
+
describe 'subclassing' do
|
155
|
+
let(:subclass){ Class.new(klass) }
|
156
|
+
let(:subject){ subclass.new(foo: 'bar', per_page: 20, status: 'four') }
|
157
|
+
it_should_behave_like 'a configurable params object'
|
158
|
+
end
|
159
|
+
|
135
160
|
describe '#available_params' do
|
136
161
|
let(:subject) { klass.new(foo: 'bar', name: 'lala', per_page: 20, status: 'four', emails: 'one@email.com,two@email.com') }
|
137
162
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parametric
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ismael Celis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-07-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/parametric/typed_params.rb
|
75
75
|
- lib/parametric/utils.rb
|
76
76
|
- lib/parametric/version.rb
|
77
|
+
- lib/support/class_attribute.rb
|
77
78
|
- parametric.gemspec
|
78
79
|
- spec/nested_params_spec.rb
|
79
80
|
- spec/parametric_spec.rb
|