parametric 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6f8f3fe8f214b883a606c2418b1aaabc5b70e5b3
4
+ data.tar.gz: 736039abdbf281c7121ff770f41fe718ff9a3e64
5
+ SHA512:
6
+ metadata.gz: 1349a426eceace4895e23d2be890d82c5748b20d9628087f29d163c0aef1dc13d79796b240cb5ece5336dc325af853b6f81940d272749fcd2370b0419b45e742
7
+ data.tar.gz: f0b3cb7792f497cdf8283afc2acb3b8b67fbf8acd17be94d81034e123eb55a2b7960b5062c5156bfc1de701ca3ad53c3cef074f87af616d06ea61b8c5ff1a341
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in parametric.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ismael Celis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,211 @@
1
+ # Parametric
2
+
3
+ DSL for declaring allowed parameters with options, regexp patern and default values.
4
+
5
+ Useful for building self-documeting APIs, search or form objects.
6
+
7
+ ## Usage
8
+
9
+ Declare your parameters
10
+
11
+ ```ruby
12
+ class OrdersSearch
13
+ include Parametric::Params
14
+ param :q, 'Full text search query'
15
+ param :page, 'Page number', default: 1
16
+ param :per_page, 'Items per page', default: 30
17
+ param :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true
18
+ end
19
+ ```
20
+
21
+ Populate and use. Missing keys return defaults, if provided.
22
+
23
+ ```ruby
24
+ order_search = OrdersSearch.new(page: 2, q: 'foobar')
25
+ order_search.params[:page] # => 2
26
+ order_search.params[:per_page] # => 30
27
+ order_search.params[:q] # => 'foobar'
28
+ order_search.params[:status] # => nil
29
+ ```
30
+
31
+ Undeclared keys are ignored.
32
+
33
+ ```ruby
34
+ order_search = OrdersSearch.new(page: 2, foo: 'bar')
35
+ order_params.params.has_key?(:foo) # => false
36
+ ```
37
+
38
+ ```ruby
39
+ order_search = OrderParams.new(status: 'checkout,closed')
40
+ order_search.params[:status] #=> ['checkout', 'closed']
41
+ ```
42
+
43
+ ### Search object pattern
44
+
45
+ A class that declares allowed params and defaults, and builds a query.
46
+
47
+ ```ruby
48
+ class OrdersSearch
49
+ include Parametric::Params
50
+ param :q, 'Full text search query'
51
+ param :page, 'Page number', default: 1
52
+ param :per_page, 'Items per page', default: 30
53
+ param :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true
54
+ param :sort, 'Sort', options: ['updated_on-desc', 'updated_on-asc'], default: 'updated_on-desc'
55
+
56
+ def results
57
+ query = Order.sort(params[:sort])
58
+ query = query.where(["code LIKE ? OR user_name ?", params[:q]]) if params[:q]
59
+ query = query.where(status: params[:status]) if params[:status].any?
60
+ query = query.paginate(page: params[:page], per_page: params[:per_page])
61
+ end
62
+ end
63
+ ```
64
+
65
+ ### :match
66
+
67
+ Pass a regular expression to match parameter value. Non-matching values will be ignored or use default value, if available.
68
+
69
+ ```ruby
70
+ class OrdersSearch
71
+ include Parametric::Params
72
+ param :email, 'Valid email address', match: /\w+@\w+\.\w+/
73
+ end
74
+ ```
75
+
76
+ ### :options array
77
+
78
+ Declare allowed values in an array. Values not in the options will be ignored or use default value.
79
+
80
+ ```ruby
81
+ class OrdersSearch
82
+ include Parametric::Params
83
+ param :sort, 'Sort', options: ['updated_on-desc', 'updated_on-asc'], default: 'updated_on-desc'
84
+ end
85
+ ```
86
+
87
+ ### :multiple values
88
+
89
+ `:multiple` values are separated on "," and treated as arrays.
90
+
91
+ ```ruby
92
+ class OrdersSearch
93
+ include Parametric::Params
94
+ param :status, 'Order status', multiple: true
95
+ end
96
+
97
+ search = OrdersSearch.new(status: 'closed,shipped,abandoned')
98
+ search.params[:status] # => ['closed', 'shipped', 'abandoned']
99
+ ```
100
+
101
+ If `:options` array is declared, values outside of the options will be filtered out.
102
+
103
+ ```ruby
104
+ class OrdersSearch
105
+ include Parametric::Params
106
+ param :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true
107
+ end
108
+
109
+ search = OrdersSearch.new(status: 'closed,shipped,abandoned')
110
+ search.params[:status] # => ['closed', 'shipped']
111
+ ```
112
+
113
+ When using `:multiple`, results and defaults are always returned as an array, for consistency.
114
+
115
+ ```ruby
116
+ class OrdersSearch
117
+ include Parametric::Params
118
+ param :status, 'Order status', multiple: true, default: 'closed'
119
+ end
120
+
121
+ search = OrdersSearch.new
122
+ search.params[:status] # => ['closed']
123
+ ```
124
+
125
+ ## `available_params`
126
+
127
+ `#available_params` returns the subset of keys that were populated (including defaults). Useful to build query strings.
128
+
129
+ ```ruby
130
+ order_search = OrdersSearch.new(page: 2, foo: 'bar')
131
+ order_search.available_params # => {page: 2, per_page: 50}
132
+ ```
133
+
134
+ ## `schema`
135
+
136
+ `#schema` returns a data structure including meta-data on each parameter, such as "label" and "options". Useful for building forms or self-documented Hypermedia APIs (or maybe [json-schema](http://json-schema.org/example2.html) endpoints).
137
+
138
+ ```ruby
139
+ order_search.schema # =>
140
+
141
+ {
142
+ q: {label: 'Full text search query', value: ''},
143
+ page: {label: 'Page number', value: 1},
144
+ per_page: {label: 'Items per page', value: 30},
145
+ status: {label: 'Order status', value: '', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true},
146
+ sort: {label: 'Sort', value: 'updated_on-desc', options: ['updated_on-desc', 'updated_on-asc']}
147
+ }
148
+ ```
149
+
150
+ ## Parametric::Hash
151
+
152
+ The alternative `Parametric::Hash` module makes your objects quack like a hash, instead of exposing the `#params` object directly.
153
+
154
+ ```ruby
155
+ class OrdersParams
156
+ include Parametric::Hash
157
+ param :q, 'Full text search query'
158
+ param :page, 'Page number', default: 1
159
+ param :per_page, 'Items per page', default: 30
160
+ param :status, 'Order status', options: ['checkout', 'pending', 'closed', 'shipped'], multiple: true
161
+ end
162
+ ```
163
+
164
+ ```ruby
165
+ order_params = OrdersParams.new(page: 2, q: 'foobar')
166
+ order_params[:page] # => 2
167
+ order_params[:per_page] # => 30
168
+ order_params.each{|key, value| ... }
169
+ ```
170
+
171
+ ## Use cases
172
+
173
+ ### In Rails
174
+
175
+ ```ruby
176
+ def index
177
+ @search = OrdersSearch.new(params)
178
+ @results = @search.results
179
+ end
180
+ ```
181
+
182
+ I use this along with [Oat](https://github.com/ismasan/oat) in API projects:
183
+
184
+ ```ruby
185
+ def index
186
+ search = OrdersSearch.new(params)
187
+ render json: OrdersSerializer.new(search)
188
+ end
189
+ ```
190
+
191
+ ## Installation
192
+
193
+ Add this line to your application's Gemfile:
194
+
195
+ gem 'parametric'
196
+
197
+ And then execute:
198
+
199
+ $ bundle
200
+
201
+ Or install it yourself as:
202
+
203
+ $ gem install parametric
204
+
205
+ ## Contributing
206
+
207
+ 1. Fork it ( http://github.com/<my-github-username>/parametric/fork )
208
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
209
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
210
+ 4. Push to the branch (`git push origin my-new-feature`)
211
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,36 @@
1
+ module Parametric
2
+ module Hash
3
+
4
+ def self.included(base)
5
+ base.send(:include, Params)
6
+ base.send(:include, Enumerable)
7
+ base.extend Forwardable
8
+ base.send(:def_delegators, :params,
9
+ :[],
10
+ :[]=,
11
+ :each,
12
+ :each_value,
13
+ :each_key,
14
+ :each_pair,
15
+ :keys,
16
+ :values,
17
+ :values_at,
18
+ :fetch,
19
+ :size,
20
+ :to_hash,
21
+ :merge,
22
+ :merge!,
23
+ :replace,
24
+ :update,
25
+ :has_key?,
26
+ :key?,
27
+ :key,
28
+ :select,
29
+ :select!,
30
+ :delete,
31
+ :store
32
+ )
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,60 @@
1
+ module Parametric
2
+
3
+ module Params
4
+
5
+ def self.included(base)
6
+ base.send(:attr_reader, :params)
7
+ base.extend DSL
8
+ end
9
+
10
+ def initialize(raw_params = {})
11
+ @params = _reduce(raw_params)
12
+ end
13
+
14
+ def available_params
15
+ @available_params ||= params.each_with_object({}) do |(k,v),memo|
16
+ memo[k] = v if Utils.present?(v)
17
+ end
18
+ end
19
+
20
+ def schema
21
+ @schema ||= params.each_with_object({}) do |(k,v),memo|
22
+ memo[k] = {
23
+ value: Utils.value(v),
24
+ label: self.class._allowed_params[k][:label],
25
+ multiple: !!self.class._allowed_params[k][:multiple]
26
+ }
27
+ memo[k][:match] = self.class._allowed_params[k][:match].to_s if self.class._allowed_params[k].has_key?(:match)
28
+ memo[k][:options] = self.class._allowed_params[k][:options] if self.class._allowed_params[k].has_key?(:options)
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def _reduce(raw_params)
35
+ self.class._allowed_params.each_with_object({}) do |(key,options),memo|
36
+ policy = Policies::Policy.new(raw_params[key], options)
37
+ policy = policy.wrap(Policies::MultiplePolicy) if options[:multiple]
38
+ policy = policy.wrap(Policies::OptionsPolicy) if options[:options]
39
+ policy = policy.wrap(Policies::MatchPolicy) if options[:match]
40
+ policy = policy.wrap(Policies::DefaultPolicy) if options.has_key?(:default)
41
+ policy = policy.wrap(Policies::SinglePolicy) unless options[:multiple]
42
+
43
+ memo[key] = policy.value
44
+ end
45
+ end
46
+
47
+ module DSL
48
+ def _allowed_params
49
+ @allowed_params ||= {}
50
+ end
51
+
52
+ def param(field_name, label = '', opts = {})
53
+ opts[:label] = label
54
+ _allowed_params[field_name] = opts
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,62 @@
1
+ module Parametric
2
+ module Policies
3
+
4
+ class Policy
5
+ def initialize(value, options, decorated = nil)
6
+ @value, @options = value, options
7
+ @decorated = decorated
8
+ end
9
+
10
+ def wrap(decoratedClass)
11
+ decoratedClass.new(@value, @options, self)
12
+ end
13
+
14
+ def value
15
+ Array(@value)
16
+ end
17
+
18
+ protected
19
+ attr_reader :decorated, :options
20
+ end
21
+
22
+ class DefaultPolicy < Policy
23
+ def value
24
+ v = decorated.value
25
+ v.any? ? v : Array(options[:default])
26
+ end
27
+ end
28
+
29
+ class MultiplePolicy < Policy
30
+ OPTION_SEPARATOR = /\s*,\s*/.freeze
31
+
32
+ def value
33
+ v = decorated.value.first
34
+ v = v.split(options.fetch(:separator, OPTION_SEPARATOR)) if v.is_a?(String)
35
+ Array(v)
36
+ end
37
+ end
38
+
39
+ class SinglePolicy < Policy
40
+ def value
41
+ decorated.value.first
42
+ end
43
+ end
44
+
45
+ class OptionsPolicy < Policy
46
+ def value
47
+ decorated.value.each_with_object([]){|a,arr|
48
+ arr << a if options[:options].include?(a)
49
+ }
50
+ end
51
+ end
52
+
53
+ class MatchPolicy < Policy
54
+ def value
55
+ decorated.value.each_with_object([]){|a,arr|
56
+ arr << a if a.to_s =~ options[:match]
57
+ }
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,24 @@
1
+ module Parametric
2
+ module Utils
3
+ def self.value(val)
4
+ if val.nil?
5
+ ''
6
+ elsif val.is_a?(Array)
7
+ val.join(',')
8
+ else
9
+ val
10
+ end
11
+ end
12
+
13
+ def self.present?(value)
14
+ case value
15
+ when String
16
+ value.strip != ''
17
+ when Array, Hash
18
+ value.any?
19
+ else
20
+ !value.nil?
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Parametric
2
+ VERSION = "0.0.1"
3
+ end
data/lib/parametric.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Parametric
2
+
3
+ end
4
+
5
+ require "parametric/utils"
6
+ require "parametric/version"
7
+ require "parametric/policies"
8
+ require "parametric/params"
9
+ require "parametric/hash"
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'parametric/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "parametric"
8
+ spec.version = Parametric::VERSION
9
+ spec.authors = ["Ismael Celis"]
10
+ spec.email = ["ismaelct@gmail.com"]
11
+ spec.summary = %q{DSL for declaring allowed parameters with options, regexp patern and default values.}
12
+ spec.description = %q{Useful for modelling search or form objects, white-listed query parameters and safe parameter defaults.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe Parametric do
4
+ it 'should have a version number' do
5
+ Parametric::VERSION.should_not be_nil
6
+ end
7
+
8
+ describe Parametric do
9
+
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
+ end
22
+ end
23
+
24
+ describe '#params' do
25
+ let(:subject) { klass.new(foo: 'bar', per_page: 20, status: 'four') }
26
+
27
+ it 'ignores undeclared fields' do
28
+ subject.params.has_key?(:foo).should be_false
29
+ end
30
+
31
+ it 'sets passed values' do
32
+ subject.params[:per_page].should == 20
33
+ end
34
+
35
+ it 'uses defaults if no value passed' do
36
+ subject.params[:page].should == 1
37
+ end
38
+
39
+ it 'does not set value if outside of declared options' do
40
+ subject.params[:status].should == []
41
+ end
42
+
43
+ it 'does not set value if it does not :match' do
44
+ klass.new(email: 'my@email').params[:email].should be_nil
45
+ end
46
+
47
+ it 'does set value if it does :match' do
48
+ klass.new(email: 'my@email.com').params[:email].should == 'my@email.com'
49
+ end
50
+
51
+ it 'only sets value for :multiple values that :match' do
52
+ klass.new(emails: 'my@email,your,her@email.com').params[:emails].should == ['her@email.com']
53
+ end
54
+
55
+ it 'returns :default wrapped in array if :multiple' do
56
+ klass.new().params[:emails].should == ['default@email.com']
57
+ end
58
+
59
+ it 'turns :multiple comma-separated values into arrays' do
60
+ klass.new(status: 'one,three').params[:status].should == ['one', 'three']
61
+ end
62
+
63
+ it 'turns :multiple separated values with custom separator into arrays' do
64
+ klass.new(piped_status: 'one|three').params[:piped_status].should == ['one', 'three']
65
+ end
66
+
67
+ it 'does not turn non-multiple comma-separated values into arrays' do
68
+ klass.new(name: 'foo,bar').params[:name].should == 'foo,bar'
69
+ end
70
+
71
+ it 'filters out undeclared options' do
72
+ klass.new(status: 'one,three,fourteen').params[:status].should == ['one', 'three']
73
+ end
74
+
75
+ it 'defaults empty multiple options to empty array' do
76
+ klass.new().params[:status].should == []
77
+ end
78
+
79
+ it 'wraps single multiple options in array' do
80
+ klass.new(status: 'one').params[:status].should == ['one']
81
+ end
82
+
83
+ it 'does not accept comma-separated values outside of options unless :multiple == true' do
84
+ klass.new(country: 'UK,CL').params[:country].should be_nil
85
+ end
86
+
87
+ it 'does accept single option' do
88
+ klass.new(country: 'UK').params[:country].should == 'UK'
89
+ end
90
+
91
+ it 'does not accept single option if not in declared options' do
92
+ klass.new(country: 'USA').params[:country].should be_nil
93
+ end
94
+ end
95
+
96
+ describe '#available_params' do
97
+ let(:subject) { klass.new(foo: 'bar', name: 'lala', per_page: 20, status: 'four') }
98
+
99
+ it 'only includes declared params with values or defaults' do
100
+ subject.available_params.keys.sort.should == [:emails, :name, :page, :per_page]
101
+ subject.available_params[:emails].should == ["default@email.com"]
102
+ subject.available_params[:name].should == 'lala'
103
+ subject.available_params[:per_page].should == 20
104
+ subject.available_params[:page].should == 1
105
+ end
106
+ end
107
+
108
+ describe '#schema' do
109
+ let(:subject) { klass.new(foo: 'bar', name: 'lala', per_page: 20, status: 'four') }
110
+
111
+ it 'returns full param definitions with populated value' do
112
+ regexp = /\w+@\w+\.\w+/.to_s
113
+
114
+ subject.schema[:name][:label].should == 'User name'
115
+ subject.schema[:name][:value].should == 'lala'
116
+
117
+ subject.schema[:page][:label].should == 'page number'
118
+ subject.schema[:page][:value].should == 1
119
+
120
+ subject.schema[:per_page][:label].should == 'items per page'
121
+ subject.schema[:per_page][:value].should == 20
122
+
123
+ subject.schema[:status][:label].should == 'status'
124
+ subject.schema[:status][:value].should == ''
125
+ subject.schema[:status][:options].should == ['one', 'two', 'three']
126
+ subject.schema[:status][:multiple].should be_true
127
+
128
+ subject.schema[:piped_status][:label].should == 'status with pipes'
129
+ subject.schema[:piped_status][:value].should == ''
130
+ subject.schema[:piped_status][:multiple].should be_true
131
+
132
+ subject.schema[:country][:label].should == 'country'
133
+ subject.schema[:country][:value].should == ''
134
+ subject.schema[:country][:options].should == ['UK', 'CL', 'JPN']
135
+
136
+ subject.schema[:email][:label].should == 'email'
137
+ subject.schema[:email][:value].should == ''
138
+ subject.schema[:email][:match].should == regexp
139
+
140
+ subject.schema[:emails][:label].should == 'emails'
141
+ subject.schema[:emails][:value].should == 'default@email.com'
142
+ subject.schema[:emails][:multiple].should be_true
143
+ subject.schema[:emails][:match].should == regexp
144
+ end
145
+ end
146
+ end
147
+
148
+ describe Parametric::Hash do
149
+ let(:klass) do
150
+ Class.new do
151
+ include Parametric::Hash
152
+ param :name, 'User name'
153
+ param :page, 'page number', default: 1
154
+ param :per_page, 'items per page', default: 50
155
+ end
156
+ end
157
+
158
+ let(:subject) { klass.new(name: 'Ismael', page: 2) }
159
+
160
+ it 'quacks like a hash' do
161
+ subject[:name].should == 'Ismael'
162
+ subject[:page].should == 2
163
+ subject[:per_page].should == 50
164
+ subject.map{|k,v| k}.sort.should == [:name, :page, :per_page]
165
+ subject.keys.sort.should == [:name, :page, :per_page]
166
+ subject.values.map(&:to_s).sort.should == ['2', '50', 'Ismael']
167
+ subject.fetch(:page, 0).should == 2
168
+ subject.fetch(:foo, 0).should == 0
169
+ subject.merge(foo: 22).should == {name: 'Ismael', page: 2, per_page: 50, foo: 22}
170
+ subject.select{|k,v| k == :name}.should == {name: 'Ismael'}
171
+ end
172
+
173
+ it 'has #available_params' do
174
+ subject.available_params[:name].should == 'Ismael'
175
+ end
176
+
177
+ it 'has #schema' do
178
+ subject.schema[:name][:label].should == 'User name'
179
+ subject.schema[:name][:value].should == 'Ismael'
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'parametric'
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parametric
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Ismael Celis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
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'
34
+ type: :development
35
+ prerelease: false
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: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Useful for modelling search or form objects, white-listed query parameters
56
+ and safe parameter defaults.
57
+ email:
58
+ - ismaelct@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - ".travis.yml"
66
+ - Gemfile
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - lib/parametric.rb
71
+ - lib/parametric/hash.rb
72
+ - lib/parametric/params.rb
73
+ - lib/parametric/policies.rb
74
+ - lib/parametric/utils.rb
75
+ - lib/parametric/version.rb
76
+ - parametric.gemspec
77
+ - spec/parametric_spec.rb
78
+ - spec/spec_helper.rb
79
+ homepage: ''
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.1.11
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: DSL for declaring allowed parameters with options, regexp patern and default
103
+ values.
104
+ test_files:
105
+ - spec/parametric_spec.rb
106
+ - spec/spec_helper.rb