parametric 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|