parametric 0.0.1

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