rails_param 0.0.3 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +66 -9
- data/lib/rails_param/param.rb +77 -38
- data/lib/rails_param/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 372c36387af839acafd00fac76073bcdd666b19e
|
4
|
+
data.tar.gz: 2d9d467a8352bf7f0e671ab8324af3993fcc64f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c616739e789c723637b6f1b545ecf261a957645f8d92c7bafe456850e49d99420be36d775c3b1af7727ed4d1eac307658390215d94e6e49cfdfec01ee0c66849
|
7
|
+
data.tar.gz: 5079e1ba2ff3c5f1b634ad8cc0e9760633a07fa449d601030e079eeb7505512293de6a45559303885e8ae2e9708bb105e609b89fe132916ef1b2e07ecbfc9cf2
|
data/README.md
CHANGED
@@ -3,17 +3,35 @@ _Parameter Validation & Type Coercion for Rails_
|
|
3
3
|
|
4
4
|
[![Build Status](https://travis-ci.org/nicolasblanco/rails_param.svg?branch=master)](https://travis-ci.org/nicolasblanco/rails_param)
|
5
5
|
|
6
|
-
|
6
|
+
## Introduction
|
7
|
+
|
8
|
+
This library is handy if you want to validate a few numbers of parameters directly inside your controller.
|
9
|
+
|
10
|
+
For example : you are building a search action and want to validate that the `sort` parameter is set and only set to something like `desc` or `asc`.
|
11
|
+
|
12
|
+
## Important
|
13
|
+
|
14
|
+
This library should not be used to validate a large number of parameters or parameters sent via a form or namespaced (like `params[:user][:first_name]`). There is already a great framework included in Rails (ActiveModel::Model) which can be used to create virtual classes with all the validations you already know and love from Rails. Remember to always try to stay in the “thin controller” rule.
|
15
|
+
|
16
|
+
See [this](http://blog.remarkablelabs.com/2012/12/activemodel-model-rails-4-countdown-to-2013) page to see an example on how to build a contact form using ActiveModel::Model.
|
17
|
+
|
18
|
+
But sometimes, it’s not practical to create an external class just to validate and convert a few parameters. In this case, you may use this gem. It allows you to easily do validations and conversion of the parameters directly in your controller actions using a simple method call.
|
19
|
+
|
20
|
+
## Credits
|
21
|
+
|
22
|
+
This is originally a port of the gem [sinatra-param](https://github.com/mattt/sinatra-param) for the Rails framework.
|
23
|
+
|
7
24
|
All the credits go to [@mattt](https://twitter.com/mattt).
|
8
|
-
It has all the features of the sinatra-param gem, I used bang methods (like param!) to indicate that they are destructive as they change the controller params object and may raise an exception.
|
9
25
|
|
10
|
-
|
26
|
+
It has all the features of the sinatra-param gem, I used bang methods (like param!) to indicate that they are destructive as they change the controller params object and may raise an exception.
|
11
27
|
|
12
|
-
|
28
|
+
## Installation
|
13
29
|
|
14
|
-
|
30
|
+
As usual, in your Gemfile...
|
15
31
|
|
16
|
-
|
32
|
+
``` ruby
|
33
|
+
gem 'rails_param'
|
34
|
+
```
|
17
35
|
|
18
36
|
## Example
|
19
37
|
|
@@ -26,16 +44,16 @@ This Rails extension takes a first step to solving this problem on the developer
|
|
26
44
|
param! :categories, Array
|
27
45
|
param! :sort, String, default: "title"
|
28
46
|
param! :order, String, in: %w(asc desc), transform: :downcase, default: "asc"
|
29
|
-
param! :price, String, format:
|
47
|
+
param! :price, String, format: /[<\=>]\s*\$\d+/
|
30
48
|
|
31
|
-
|
49
|
+
# Access the parameters using the params object (like params[:q]) as you usually do...
|
32
50
|
end
|
33
51
|
end
|
34
52
|
```
|
35
53
|
|
36
54
|
### Parameter Types
|
37
55
|
|
38
|
-
By declaring parameter types, incoming parameters will automatically be transformed into an object of that type. For instance, if a param is
|
56
|
+
By declaring parameter types, incoming parameters will automatically be transformed into an object of that type. For instance, if a param is `:boolean`, values of `'1'`, `'true'`, `'t'`, `'yes'`, and `'y'` will be automatically transformed into `true`. `BigDecimal` defaults to a precision of 14, but this can but changed by passing in the optional `precision:` argument. Any `$` and `,` are automatically stripped when converting to `BigDecimal`.
|
39
57
|
|
40
58
|
- `String`
|
41
59
|
- `Integer`
|
@@ -44,6 +62,7 @@ By declaring parameter types, incoming parameters will automatically be transfor
|
|
44
62
|
- `Array` _("1,2,3,4,5")_
|
45
63
|
- `Hash` _("key1:value1,key2:value2")_
|
46
64
|
- `Date`, `Time`, & `DateTime`
|
65
|
+
- `BigDecimal` _("$1,000,000")_
|
47
66
|
|
48
67
|
### Validations
|
49
68
|
|
@@ -73,6 +92,44 @@ param! :order, String, in: ["ASC", "DESC"], transform: :upcase, default: "ASC"
|
|
73
92
|
param! :offset, Integer, min: 0, transform: lambda {|n| n - (n % 10)}
|
74
93
|
```
|
75
94
|
|
95
|
+
### Nested Attributes
|
96
|
+
|
97
|
+
rails_param allows you to apply any of the above mentioned validations to attributes nested in hashes:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
param! :book, Hash do |b|
|
101
|
+
b.param! :title, String, blank: false
|
102
|
+
b.param! :price, BigDecimal, precision: 4, required: true
|
103
|
+
b.param! :author, Hash, required: true do |a|
|
104
|
+
a.param! :first_name, String
|
105
|
+
a.param! :last_name, String, blank: false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
### Arrays
|
111
|
+
|
112
|
+
Validate every element of your array, including nested hashes and arrays:
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
# primitive datatype syntax
|
116
|
+
param! :integer_array, Array do |array,index|
|
117
|
+
array.param! index, Integer, required: true
|
118
|
+
end
|
119
|
+
|
120
|
+
# complex array
|
121
|
+
param! :books_array, Array, required: true do |b|
|
122
|
+
b.param! :title, String, blank: false
|
123
|
+
b.param! :author, Hash, required: true do |a|
|
124
|
+
a.param! :first_name, String
|
125
|
+
a.param! :last_name, String, required: true
|
126
|
+
end
|
127
|
+
b.param! :subjects, Array do |s,i|
|
128
|
+
s.param! i, String, blank: false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
76
133
|
## Thank you
|
77
134
|
|
78
135
|
Many thanks to:
|
data/lib/rails_param/param.rb
CHANGED
@@ -1,22 +1,46 @@
|
|
1
1
|
module RailsParam
|
2
2
|
module Param
|
3
3
|
|
4
|
+
DEFAULT_PRECISION = 14
|
5
|
+
|
4
6
|
class InvalidParameterError < StandardError
|
5
7
|
attr_accessor :param, :options
|
6
8
|
end
|
7
9
|
|
8
|
-
|
9
|
-
|
10
|
+
class MockController
|
11
|
+
include RailsParam::Param
|
12
|
+
attr_accessor :params
|
13
|
+
end
|
10
14
|
|
11
|
-
|
15
|
+
def param!(name, type, options = {}, &block)
|
16
|
+
name = name.to_s unless name.is_a? Integer # keep index for validating elements
|
17
|
+
|
18
|
+
return unless params.member?(name) || check_param_presence?(options[:default]) || options[:required]
|
12
19
|
|
13
20
|
begin
|
14
21
|
params[name] = coerce(params[name], type, options)
|
15
|
-
params[name] = (options[:default].call if options[:default].respond_to?(:call)) || options[:default] if params[name].nil? and options[:default]
|
22
|
+
params[name] = (options[:default].call if options[:default].respond_to?(:call)) || options[:default] if params[name].nil? and check_param_presence?(options[:default])
|
16
23
|
params[name] = options[:transform].to_proc.call(params[name]) if params[name] and options[:transform]
|
17
24
|
validate!(params[name], options)
|
25
|
+
|
26
|
+
if block_given?
|
27
|
+
if type == Array
|
28
|
+
params[name].each_with_index do |element, i|
|
29
|
+
if element.is_a?(Hash)
|
30
|
+
recurse element, &block
|
31
|
+
else
|
32
|
+
params[name][i] = recurse({ i => element }, i, &block) # supply index as key unless value is hash
|
33
|
+
end
|
34
|
+
end
|
35
|
+
else
|
36
|
+
recurse params[name], &block
|
37
|
+
end
|
38
|
+
end
|
39
|
+
params[name]
|
40
|
+
|
18
41
|
rescue InvalidParameterError => exception
|
19
|
-
exception.param
|
42
|
+
exception.param ||= name
|
43
|
+
exception.options ||= options
|
20
44
|
raise exception
|
21
45
|
end
|
22
46
|
end
|
@@ -41,6 +65,17 @@ module RailsParam
|
|
41
65
|
|
42
66
|
private
|
43
67
|
|
68
|
+
def check_param_presence? param
|
69
|
+
not param.nil?
|
70
|
+
end
|
71
|
+
|
72
|
+
def recurse(params, index = nil)
|
73
|
+
raise InvalidParameterError, 'no block given' unless block_given?
|
74
|
+
controller = RailsParam::Param::MockController.new
|
75
|
+
controller.params = params
|
76
|
+
yield(controller, index)
|
77
|
+
end
|
78
|
+
|
44
79
|
def coerce(param, type, options = {})
|
45
80
|
begin
|
46
81
|
return nil if param.nil?
|
@@ -52,8 +87,12 @@ module RailsParam
|
|
52
87
|
return Time.parse(param) if type == Time
|
53
88
|
return DateTime.parse(param) if type == DateTime
|
54
89
|
return Array(param.split(options[:delimiter] || ",")) if type == Array
|
55
|
-
return Hash[param.split(options[:delimiter] || ",").map{|c| c.split(options[:separator] || ":")}] if type == Hash
|
56
|
-
return (
|
90
|
+
return Hash[param.split(options[:delimiter] || ",").map { |c| c.split(options[:separator] || ":") }] if type == Hash
|
91
|
+
return (/^(false|f|no|n|0)$/i === param.to_s ? false : (/^(true|t|yes|y|1)$/i === param.to_s ? true : (raise ArgumentError))) if type == TrueClass || type == FalseClass || type == :boolean
|
92
|
+
if type == BigDecimal
|
93
|
+
param = param.delete('$,').strip.to_f if param.is_a?(String)
|
94
|
+
return BigDecimal.new(param, (options[:precision] || DEFAULT_PRECISION))
|
95
|
+
end
|
57
96
|
return nil
|
58
97
|
rescue ArgumentError
|
59
98
|
raise InvalidParameterError, "'#{param}' is not a valid #{type}"
|
@@ -63,37 +102,37 @@ module RailsParam
|
|
63
102
|
def validate!(param, options)
|
64
103
|
options.each do |key, value|
|
65
104
|
case key
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
105
|
+
when :required
|
106
|
+
raise InvalidParameterError, "Parameter is required" if value && param.nil?
|
107
|
+
when :blank
|
108
|
+
raise InvalidParameterError, "Parameter cannot be blank" if !value && case param
|
109
|
+
when String
|
110
|
+
!(/\S/ === param)
|
111
|
+
when Array, Hash
|
112
|
+
param.empty?
|
113
|
+
else
|
114
|
+
param.nil?
|
115
|
+
end
|
116
|
+
when :format
|
117
|
+
raise InvalidParameterError, "Parameter must be a string if using the format validation" unless param.kind_of?(String)
|
118
|
+
raise InvalidParameterError, "Parameter must match format #{value}" unless param =~ value
|
119
|
+
when :is
|
120
|
+
raise InvalidParameterError, "Parameter must be #{value}" unless param === value
|
121
|
+
when :in, :within, :range
|
122
|
+
raise InvalidParameterError, "Parameter must be within #{value}" unless param.nil? || case value
|
123
|
+
when Range
|
124
|
+
value.include?(param)
|
125
|
+
else
|
126
|
+
Array(value).include?(param)
|
127
|
+
end
|
128
|
+
when :min
|
129
|
+
raise InvalidParameterError, "Parameter cannot be less than #{value}" unless param.nil? || value <= param
|
130
|
+
when :max
|
131
|
+
raise InvalidParameterError, "Parameter cannot be greater than #{value}" unless param.nil? || value >= param
|
132
|
+
when :min_length
|
133
|
+
raise InvalidParameterError, "Parameter cannot have length less than #{value}" unless param.nil? || value <= param.length
|
134
|
+
when :max_length
|
135
|
+
raise InvalidParameterError, "Parameter cannot have length greater than #{value}" unless param.nil? || value >= param.length
|
97
136
|
end
|
98
137
|
end
|
99
138
|
end
|
data/lib/rails_param/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_param
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolas Blanco
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -97,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
97
|
version: 1.3.6
|
98
98
|
requirements: []
|
99
99
|
rubyforge_project:
|
100
|
-
rubygems_version: 2.
|
100
|
+
rubygems_version: 2.4.8
|
101
101
|
signing_key:
|
102
102
|
specification_version: 4
|
103
103
|
summary: Parameter Validation and Type Coercion for Rails
|