rails_param2 0.10.0

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: 3712d8ce55990ec233da2ae2e2167bf23a8d9ebf
4
+ data.tar.gz: f057f82af9c4da204a379171663ae54c79e5d3f1
5
+ SHA512:
6
+ metadata.gz: ec4cda59e7bdbdcd1ed5508e2cfd1536ac3db85aa5e8ebc21b253e189581e7d72eb8df813608bd3655103c2f306015f53a0a260c3c095f960473b5209f6551e3
7
+ data.tar.gz: 809d2c8687df17816e9f5a029b9330003731aced0d01d73f3cf2e73f06abb3e9b9ac15c57fb330ac9c26b18ce4546687f5f78ad1c38d717bb2b7ec1a05bc139f
data/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # rails_param2
2
+
3
+ forked from [nicolasblanco/rails_param](https://github.com/nicolasblanco/rails_param)
4
+
5
+ _Parameter Validation & Type Coercion for Rails_
6
+
7
+ [![Build Status](https://travis-ci.org/nicolasblanco/rails_param.svg?branch=master)](https://travis-ci.org/nicolasblanco/rails_param)
8
+
9
+ ## Introduction
10
+
11
+ This library is handy if you want to validate a few numbers of parameters directly inside your controller.
12
+
13
+ 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`.
14
+
15
+ ## Important
16
+
17
+ 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.
18
+
19
+ 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.
20
+
21
+ 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.
22
+
23
+ ## Credits
24
+
25
+ This is originally a port of the gem [sinatra-param](https://github.com/mattt/sinatra-param) for the Rails framework.
26
+
27
+ All the credits go to [@mattt](https://twitter.com/mattt).
28
+
29
+ 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.
30
+
31
+ ## Installation
32
+
33
+ As usual, in your Gemfile...
34
+
35
+ ``` ruby
36
+ gem 'rails_param2'
37
+ ```
38
+
39
+ ## Example
40
+
41
+ ``` ruby
42
+ # GET /search?q=example
43
+ # GET /search?q=example&categories=news
44
+ # GET /search?q=example&sort=created_at&order=ASC
45
+ def search
46
+ param! :q, String, required: true
47
+ param! :categories, Array
48
+ param! :sort, String, default: "title"
49
+ param! :order, String, in: %w(asc desc), transform: :downcase, default: "asc"
50
+ param! :price, String, format: /[<\=>]\s*\$\d+/
51
+
52
+ # Access the parameters using the params object (like params[:q]) as you usually do...
53
+ end
54
+ end
55
+ ```
56
+
57
+ ### Parameter Types
58
+
59
+ 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`.
60
+
61
+ - `String`
62
+ - `Integer`
63
+ - `Float`
64
+ - `:boolean/TrueClass/FalseClass` _("1/0", "true/false", "t/f", "yes/no", "y/n")_
65
+ - `Array` _("1,2,3,4,5")_
66
+ - `Hash` _("key1:value1,key2:value2")_
67
+ - `Date`, `Time`, & `DateTime`
68
+ - `BigDecimal` _("$1,000,000")_
69
+
70
+ ### Validations
71
+
72
+ Encapsulate business logic in a consistent way with validations. If a parameter does not satisfy a particular condition, an exception (RailsParam::Param::InvalidParameterError) is raised.
73
+ You may use the [rescue_from](http://api.rubyonrails.org/classes/ActiveSupport/Rescuable/ClassMethods.html#method-i-rescue_from) method in your controller to catch this kind of exception.
74
+
75
+ - `required`
76
+ - `blank`
77
+ - `is`
78
+ - `in`, `within`, `range`
79
+ - `min` / `max`
80
+ - `format`
81
+
82
+ Customize exception message with option `:message`
83
+
84
+ ```ruby
85
+ param! :q, String, required: true, message: "Query not specified"
86
+ ```
87
+
88
+ ### Defaults and Transformations
89
+
90
+ Passing a `default` option will provide a default value for a parameter if none is passed. A `default` can defined as either a default or as a `Proc`:
91
+
92
+ ```ruby
93
+ param! :attribution, String, default: "©"
94
+ param! :year, Integer, default: lambda { Time.now.year }
95
+ ```
96
+
97
+ Use the `transform` option to take even more of the business logic of parameter I/O out of your code. Anything that responds to `to_proc` (including `Proc` and symbols) will do.
98
+
99
+ ```ruby
100
+ param! :order, String, in: ["ASC", "DESC"], transform: :upcase, default: "ASC"
101
+ param! :offset, Integer, min: 0, transform: lambda {|n| n - (n % 10)}
102
+ ```
103
+
104
+ ### Nested Attributes
105
+
106
+ rails_param allows you to apply any of the above mentioned validations to attributes nested in hashes:
107
+
108
+ ```ruby
109
+ param! :book, Hash do |b|
110
+ b.param! :title, String, blank: false
111
+ b.param! :price, BigDecimal, precision: 4, required: true
112
+ b.param! :author, Hash, required: true do |a|
113
+ a.param! :first_name, String
114
+ a.param! :last_name, String, blank: false
115
+ end
116
+ end
117
+ ```
118
+
119
+ ### Arrays
120
+
121
+ Validate every element of your array, including nested hashes and arrays:
122
+
123
+ ```ruby
124
+ # primitive datatype syntax
125
+ param! :integer_array, Array do |array,index|
126
+ array.param! index, Integer, required: true
127
+ end
128
+
129
+ # complex array
130
+ param! :books_array, Array, required: true do |b|
131
+ b.param! :title, String, blank: false
132
+ b.param! :author, Hash, required: true do |a|
133
+ a.param! :first_name, String
134
+ a.param! :last_name, String, required: true
135
+ end
136
+ b.param! :subjects, Array do |s,i|
137
+ s.param! i, String, blank: false
138
+ end
139
+ end
140
+ ```
141
+
142
+ ## Thank you
143
+
144
+ Many thanks to:
145
+
146
+ * [Mattt Thompson (@mattt)](https://twitter.com/mattt)
147
+ * [Vincent Ollivier (@vinc686)](https://twitter.com/vinc686)
148
+
149
+ ## Contact
150
+
151
+ Nicolas Blanco
152
+
153
+ - http://github.com/nicolasblanco
154
+ - http://twitter.com/nblanco_fr
155
+ - nicolas@nicolasblanco.fr
156
+
157
+ ## License
158
+
159
+ rails-param is available under the MIT license. See the LICENSE file for more info.
@@ -0,0 +1,5 @@
1
+ require 'rails_param/param'
2
+
3
+ ActiveSupport.on_load(:action_controller) do
4
+ include RailsParam::Param
5
+ end
@@ -0,0 +1,162 @@
1
+ module RailsParam
2
+ module Param
3
+
4
+ DEFAULT_PRECISION = 14
5
+
6
+ class InvalidParameterError < StandardError
7
+ attr_accessor :param, :options
8
+
9
+ def message
10
+ return options[:message] if options.is_a?(Hash) && options.key?(:message)
11
+ super
12
+ end
13
+ end
14
+
15
+ class MockController
16
+ include RailsParam::Param
17
+ attr_accessor :params
18
+ end
19
+
20
+ def param!(name, type, options = {}, &block)
21
+ name = name.to_s unless name.is_a? Integer # keep index for validating elements
22
+
23
+ return unless params.include?(name) || check_param_presence?(options[:default]) || options[:required]
24
+
25
+ begin
26
+ params[name] = coerce(params[name], type, options)
27
+
28
+ # set default
29
+ if options[:default].respond_to?(:call)
30
+ params[name] = options[:default].call
31
+ elsif params[name].nil? && check_param_presence?(options[:default])
32
+ params[name] = options[:default]
33
+ end
34
+
35
+ # apply tranformation
36
+ if params[name] && options[:transform]
37
+ params[name] = options[:transform].to_proc.call(params[name])
38
+ end
39
+
40
+ # validate
41
+ validate!(params[name], name, options)
42
+
43
+ if block_given?
44
+ if type == Array
45
+ params[name].each_with_index do |element, i|
46
+ if element.is_a?(Hash) || element.is_a?(ActionController::Parameters)
47
+ recurse element, &block
48
+ else
49
+ params[name][i] = recurse({ i => element }, i, &block) # supply index as key unless value is hash
50
+ end
51
+ end
52
+ else
53
+ recurse params[name], &block
54
+ end
55
+ end
56
+ params[name]
57
+
58
+ rescue InvalidParameterError => exception
59
+ exception.param ||= name
60
+ exception.options ||= options
61
+ raise exception
62
+ end
63
+ end
64
+
65
+ # TODO: should we reintegrate this method?
66
+ # def one_of!(*names)
67
+ # count = 0
68
+ # names.each do |name|
69
+ # if params[name] and params[name].present?
70
+ # count += 1
71
+ # next unless count > 1
72
+ #
73
+ # error = "Parameters #{names.join(', ')} are mutually exclusive"
74
+ # if content_type and content_type.match(mime_type(:json))
75
+ # error = {message: error}.to_json
76
+ # end
77
+ #
78
+ # # do something with error object
79
+ # end
80
+ # end
81
+ # end
82
+
83
+ private
84
+
85
+ def check_param_presence? param
86
+ not param.nil?
87
+ end
88
+
89
+ def recurse(params, index = nil)
90
+ raise InvalidParameterError, 'no block given' unless block_given?
91
+ controller = RailsParam::Param::MockController.new
92
+ controller.params = params
93
+ yield(controller, index)
94
+ end
95
+
96
+ def coerce(param, type, options = {})
97
+ begin
98
+ return nil if param.nil?
99
+ return param if (param.is_a?(type) rescue false)
100
+ if (param.is_a?(Array) && type != Array) || ((param.is_a?(Hash) || param.is_a?(ActionController::Parameters)) && type != Hash)
101
+ raise InvalidParameterError, "'#{param}' is not a valid #{type}"
102
+ end
103
+ return param if (param.is_a?(ActionController::Parameters) && type == Hash rescue false)
104
+ return Integer(param) if type == Integer
105
+ return Float(param) if type == Float
106
+ return String(param) if type == String
107
+ return Date.parse(param) if type == Date
108
+ return Time.parse(param) if type == Time
109
+ return DateTime.parse(param) if type == DateTime
110
+ return Array(param.split(options[:delimiter] || ",")) if type == Array
111
+ return Hash[param.split(options[:delimiter] || ",").map { |c| c.split(options[:separator] || ":") }] if type == Hash
112
+ 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
113
+ if type == BigDecimal
114
+ param = param.delete('$,').strip.to_f if param.is_a?(String)
115
+ return BigDecimal.new(param, (options[:precision] || DEFAULT_PRECISION))
116
+ end
117
+ return nil
118
+ rescue ArgumentError
119
+ raise InvalidParameterError, "'#{param}' is not a valid #{type}"
120
+ end
121
+ end
122
+
123
+ def validate!(param, param_name, options)
124
+ options.each do |key, value|
125
+ case key
126
+ when :required
127
+ raise InvalidParameterError, "Parameter #{param_name} is required" if value && param.nil?
128
+ when :blank
129
+ raise InvalidParameterError, "Parameter #{param_name} cannot be blank" if !value && case param
130
+ when String
131
+ !(/\S/ === param)
132
+ when Array, Hash
133
+ param.empty?
134
+ else
135
+ param.nil?
136
+ end
137
+ when :format
138
+ raise InvalidParameterError, "Parameter #{param_name} must be a string if using the format validation" unless param.kind_of?(String)
139
+ raise InvalidParameterError, "Parameter #{param_name} must match format #{value}" unless param =~ value
140
+ when :is
141
+ raise InvalidParameterError, "Parameter #{param_name} must be #{value}" unless param === value
142
+ when :in, :within, :range
143
+ raise InvalidParameterError, "Parameter #{param_name} must be within #{value}" unless param.nil? || case value
144
+ when Range
145
+ value.include?(param)
146
+ else
147
+ Array(value).include?(param)
148
+ end
149
+ when :min
150
+ raise InvalidParameterError, "Parameter #{param_name} cannot be less than #{value}" unless param.nil? || value <= param
151
+ when :max
152
+ raise InvalidParameterError, "Parameter #{param_name} cannot be greater than #{value}" unless param.nil? || value >= param
153
+ when :min_length
154
+ raise InvalidParameterError, "Parameter #{param_name} cannot have length less than #{value}" unless param.nil? || value <= param.length
155
+ when :max_length
156
+ raise InvalidParameterError, "Parameter #{param_name} cannot have length greater than #{value}" unless param.nil? || value >= param.length
157
+ end
158
+ end
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,3 @@
1
+ module RailsParam #:nodoc
2
+ VERSION = "0.10.0"
3
+ end
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_param2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicolas Blanco
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-04-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.4'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.4'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: actionpack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 3.2.0
69
+ description: "\n Parameter Validation and Type Coercion for Rails\n "
70
+ email: nicolas@nicolasblanco.fr
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - README.md
76
+ - lib/rails_param.rb
77
+ - lib/rails_param/param.rb
78
+ - lib/rails_param/version.rb
79
+ homepage: http://github.com/shhavel/rails_param2
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options:
85
+ - "--charset=UTF-8"
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ version: 1.3.6
98
+ requirements: []
99
+ rubyforge_project:
100
+ rubygems_version: 2.6.12
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Parameter Validation and Type Coercion for Rails
104
+ test_files: []