paramore 0.2.0 → 1.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 +4 -4
- data/README.md +44 -64
- data/lib/paramore.rb +2 -2
- data/lib/paramore/cast_parameters.rb +65 -0
- data/lib/paramore/cli.rb +2 -10
- data/lib/paramore/configuration.rb +3 -7
- data/lib/paramore/errors.rb +11 -0
- data/lib/paramore/extension.rb +30 -13
- data/lib/paramore/permitted_parameter_argument.rb +37 -0
- data/lib/paramore/railtie.rb +0 -2
- data/lib/paramore/types.rb +52 -0
- data/lib/paramore/validate.rb +13 -28
- data/lib/paratype.rb +32 -0
- metadata +26 -8
- data/lib/paramore/format.rb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d42894f0d3cefbd8979dc3048515ad8285a7f322f1ec1907b19d9941d6f95620
|
4
|
+
data.tar.gz: '0283777104760cb5d2d8774d95a61aa5841adaa38f35a488218cf89865a2571b'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 19def8fd4558111735cb93a28157e3fd7a7905be0b11b4d4515c85ccee3f26f64d6ab1c1d6c464d96230030960a89bac4ff31c96e391603a8786a08c98bdb8a1
|
7
|
+
data.tar.gz: da286395c83d3e13fc5ec1a0344a0232800fbf841bbc8bec14e32072059c32f678caef0d609cb17a6a4780e8ef3b4cd699fd52e2432ecca3dede925156ff0162
|
data/README.md
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
# Paramore
|
2
2
|
|
3
3
|
Paramore is a small gem intended to make strong parameter definitions declarative
|
4
|
-
and provide a unified way to
|
4
|
+
and provide a unified way to typecast and sanitize their values outside of controllers.
|
5
5
|
|
6
6
|
# Installation
|
7
7
|
|
8
|
-
|
9
8
|
In your Gemfile:
|
10
9
|
```ruby
|
11
10
|
gem 'paramore'
|
@@ -18,14 +17,14 @@ $ bundle
|
|
18
17
|
|
19
18
|
# Usage
|
20
19
|
|
21
|
-
<h3>Without
|
20
|
+
<h3>Without typing</h3>
|
22
21
|
|
23
22
|
```ruby
|
24
|
-
|
23
|
+
paramorize :item_params,
|
25
24
|
item: [:name, :description, :for_sale, :price, metadata: [tags: []]]
|
26
25
|
```
|
27
26
|
|
28
|
-
This is completely equivalent (including return type) to
|
27
|
+
This is completely equivalent (including the return type) to
|
29
28
|
|
30
29
|
```ruby
|
31
30
|
def item_params
|
@@ -35,10 +34,10 @@ def item_params
|
|
35
34
|
end
|
36
35
|
```
|
37
36
|
|
38
|
-
<h3>With
|
37
|
+
<h3>With typing</h3>
|
39
38
|
|
40
39
|
A common problem in app development is untrustworthy input given by clients.
|
41
|
-
That input needs to be sanitized and
|
40
|
+
That input needs to be sanitized and typecast for further processing.
|
42
41
|
A naive approach could be:
|
43
42
|
|
44
43
|
```ruby
|
@@ -48,7 +47,7 @@ def item_params
|
|
48
47
|
@item_params ||= begin
|
49
48
|
_params = params
|
50
49
|
.require(:item)
|
51
|
-
.permit(:name, :description, :price, metadata: [tags: []])
|
50
|
+
.permit(:name, :description, :for_sale, :price, metadata: [tags: []])
|
52
51
|
|
53
52
|
_params[:name] = _params[:name].strip.squeeze(' ') if _params[:name]
|
54
53
|
_params[:description] = _params[:description].strip.squeeze(' ') if _params[:description]
|
@@ -70,69 +69,42 @@ The next logical step is extracting those procedures - this is where Paramore st
|
|
70
69
|
```ruby
|
71
70
|
# app/controllers/items_controller.rb
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
name: :Text,
|
77
|
-
description: :Text,
|
78
|
-
for_sale: :Boolean,
|
79
|
-
price: :Decimal,
|
80
|
-
metadata: {
|
81
|
-
tags: :ItemTags
|
82
|
-
}
|
83
|
-
}
|
84
|
-
```
|
85
|
-
|
86
|
-
```ruby
|
87
|
-
# app/formatter/text.rb
|
88
|
-
|
89
|
-
module Formatter::Text
|
90
|
-
module_function
|
91
|
-
def run(input)
|
92
|
-
input.strip.squeeze(' ')
|
72
|
+
class ItemsController < ApplicationController
|
73
|
+
def create
|
74
|
+
Item.create(item_params)
|
93
75
|
end
|
94
|
-
end
|
95
|
-
```
|
96
|
-
```ruby
|
97
|
-
# app/formatter/boolean.rb
|
98
76
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
77
|
+
paramorize :item_params,
|
78
|
+
item: {
|
79
|
+
name: Paratype[Paramore::SanitizedString],
|
80
|
+
description: Paratype[Paramore::StrippedString, null: true],
|
81
|
+
for_sale: Paratype[Paramore::Boolean],
|
82
|
+
price: Paratype[Paramore::Decimal],
|
83
|
+
metadata: Paratype[{
|
84
|
+
tags: Paratype[[Types::ItemTag], compact: true]
|
85
|
+
}]
|
86
|
+
}
|
106
87
|
end
|
107
88
|
```
|
108
|
-
```ruby
|
109
|
-
# app/formatter/decimal.rb
|
110
89
|
|
111
|
-
|
112
|
-
module_function
|
113
|
-
def run(input)
|
114
|
-
input.to_d
|
115
|
-
end
|
116
|
-
end
|
117
|
-
```
|
90
|
+
`Types::ItemTag` could be your own type:
|
118
91
|
```ruby
|
119
|
-
# app/
|
92
|
+
# app/types/item_tag.rb
|
120
93
|
|
121
|
-
module
|
94
|
+
module Types::ItemTag
|
122
95
|
module_function
|
123
|
-
def
|
124
|
-
|
96
|
+
def [](input)
|
97
|
+
Item.tags[input.to_i]
|
125
98
|
end
|
126
99
|
end
|
127
100
|
```
|
128
101
|
|
129
|
-
|
130
102
|
Now, given `params` are:
|
131
103
|
```ruby
|
132
104
|
<ActionController::Parameters {
|
133
105
|
"unpermitted"=>"parameter",
|
134
106
|
"name"=>"Shoe \n",
|
135
|
-
"description"=>"Black, with laces",
|
107
|
+
"description"=>" Black, with laces",
|
136
108
|
"for_sale"=>"true",
|
137
109
|
"price"=>"39.99",
|
138
110
|
"metadata"=><ActionController::Parameters { "tags"=>["38", "112"] } permitted: false>
|
@@ -142,7 +114,7 @@ Calling `item_params` will return:
|
|
142
114
|
```ruby
|
143
115
|
<ActionController::Parameters {
|
144
116
|
"name"=>"Shoe",
|
145
|
-
"description"=>"Black,
|
117
|
+
"description"=>"Black, with laces",
|
146
118
|
"for_sale"=>true,
|
147
119
|
"price"=>39.99,
|
148
120
|
"metadata"=><ActionController::Parameters { "tags"=>[:shoe, :new] } permitted: true>
|
@@ -150,22 +122,30 @@ Calling `item_params` will return:
|
|
150
122
|
```
|
151
123
|
|
152
124
|
This is useful when the values are not used with Rails models, but are passed to simple functions for processing.
|
153
|
-
The
|
154
|
-
|
125
|
+
The types can also be easily reused anywhere in the app, since they are completely decoupled from Rails.
|
126
|
+
|
127
|
+
Notice that the `Paramore::StrippedString` does not perform `.squeeze(' ')`, only `Paramore::SanitizedString` does.
|
128
|
+
|
129
|
+
<h3>nil</h3>
|
130
|
+
|
131
|
+
Types are non-nullable by default and raise exceptions if the param hash misses any.
|
132
|
+
This can be disabled for any type by declaring `Paratype[Paramore::Int, null: true]`.
|
133
|
+
|
134
|
+
nils will usually not reach any of the type classes - if some parameter is nullable, the class will not be called.
|
135
|
+
If a parameter is non-nullable, then a `Paramore::NilParameter` error will be raised before calling the class.
|
136
|
+
If a, say, `item_ids` array is non-nullable, but the received parameter is `['1', '', '3']`, only the `'1'` and `'2'` will get passed to type classes, and the resulting array will contain a nil, eg.: `['1', nil, '3']`.
|
137
|
+
nils inside arrays can still be passed to type classes by declaring `Paratype[[Paramore::Int], empty: true]`.
|
138
|
+
If you wish to get rid of empty array elements, declare `Paratype[Paramore::Int, compact: true]`.
|
155
139
|
|
156
140
|
<h3>Configuration</h3>
|
157
141
|
|
158
142
|
Running `$ paramore` will generate a configuration file located in `config/initializers/paramore.rb`.
|
159
|
-
- `config.
|
160
|
-
(this also allows specifying the formatter object itself, eg.: `name: Formatter::Text`).
|
161
|
-
- `config.formatter_method_name` - default is `run`. Don't set to `nil` :D
|
143
|
+
- `config.type_method_name` - default is `[]`, to allow using, for example, `SuperString["foo"]` syntax. Note that changing this value will preclude you from using built in types.
|
162
144
|
|
163
145
|
<h3>Safety</h3>
|
164
146
|
|
165
|
-
-
|
166
|
-
-
|
167
|
-
and must respond to the configured `formatter_method_name`.
|
168
|
-
This means that all used formatters are loaded when the controller is loaded.
|
147
|
+
- Types will not be called if their parameter is missing (no key in the param hash)
|
148
|
+
- All given types must respond to the configured `type_method_name` and an error will be raised when controllers are loaded if they don't.
|
169
149
|
|
170
150
|
# License
|
171
151
|
|
data/lib/paramore.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
require_relative 'errors'
|
2
|
+
|
3
|
+
module Paramore
|
4
|
+
module CastParameters
|
5
|
+
module_function
|
6
|
+
def run(types_definition, permitted_params)
|
7
|
+
recursive_merge(
|
8
|
+
recursive_typecast(
|
9
|
+
types_definition, permitted_params
|
10
|
+
)
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def recursive_merge(nested_hash_array)
|
15
|
+
nested_hash_array.reduce(:merge).map do |param_name, value|
|
16
|
+
if value.is_a?(Array) && value.all? { |_value| _value.is_a?(Hash) }
|
17
|
+
{ param_name => recursive_merge(value) }
|
18
|
+
else
|
19
|
+
{ param_name => value }
|
20
|
+
end
|
21
|
+
end.reduce(:merge)
|
22
|
+
end
|
23
|
+
|
24
|
+
def recursive_typecast(types_definition, permitted_params)
|
25
|
+
types_definition.map do |param_name, definition|
|
26
|
+
value = permitted_params[param_name]
|
27
|
+
|
28
|
+
if value.nil?
|
29
|
+
if definition.nullable?
|
30
|
+
next { param_name => nil }
|
31
|
+
else
|
32
|
+
raise Paramore::NilParameter, param_name
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
{ param_name => cast(definition, value) }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def cast(definition, value)
|
41
|
+
case definition.type
|
42
|
+
when Hash
|
43
|
+
recursive_typecast(definition.type, value || {})
|
44
|
+
when Array
|
45
|
+
typecast_array(definition, value)
|
46
|
+
else
|
47
|
+
typecast_value(definition.type, value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def typecast_array(definition, array)
|
52
|
+
array
|
53
|
+
.reject { |unit| unit.to_s == '' && definition.compact? }
|
54
|
+
.map do |unit|
|
55
|
+
if unit.to_s != '' || definition.use_empty_strings?
|
56
|
+
typecast_value(definition.type.first, unit)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def typecast_value(type, value)
|
62
|
+
type.send(Paramore.configuration.type_method_name, value)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/lib/paramore/cli.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Paramore
|
4
2
|
module Cli
|
5
3
|
module_function
|
@@ -12,15 +10,9 @@ module Paramore
|
|
12
10
|
end
|
13
11
|
|
14
12
|
File.write(config_file_path, <<~CONF)
|
15
|
-
# frozen_string_literal: true
|
16
|
-
|
17
13
|
Paramore.configure do |config|
|
18
|
-
#
|
19
|
-
#
|
20
|
-
# config.formatter_namespace = 'Formatter'
|
21
|
-
|
22
|
-
# what method name to call formatters with
|
23
|
-
# config.formatter_method_name = 'run'
|
14
|
+
# what method name to call types with
|
15
|
+
# config.type_method_name = :[]
|
24
16
|
end
|
25
17
|
CONF
|
26
18
|
|
@@ -1,15 +1,11 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Paramore
|
4
2
|
class Configuration
|
5
|
-
|
6
|
-
DEFAULT_FORMATTER_METHOD_NAME = 'run'
|
3
|
+
DEFAULT_TYPE_METHOD_NAME = :[]
|
7
4
|
|
8
|
-
attr_accessor :
|
5
|
+
attr_accessor :type_method_name
|
9
6
|
|
10
7
|
def initialize
|
11
|
-
@
|
12
|
-
@formatter_method_name = DEFAULT_FORMATTER_METHOD_NAME
|
8
|
+
@type_method_name = DEFAULT_TYPE_METHOD_NAME
|
13
9
|
end
|
14
10
|
end
|
15
11
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Paramore::NilParameter < StandardError
|
2
|
+
def initialize(param_name)
|
3
|
+
super("Received a nil `#{param_name}`, but it's type is non nullable!")
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
class Paramore::NonParatype < StandardError
|
8
|
+
def initialize(param_name, type)
|
9
|
+
super("`#{param_name}` defined as a `#{type.class}`, expected `Paratype`! Perhaps you declared a plain hash instead of Paratype[{}]?")
|
10
|
+
end
|
11
|
+
end
|
data/lib/paramore/extension.rb
CHANGED
@@ -1,27 +1,44 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
require_relative 'validate'
|
4
|
-
require_relative '
|
2
|
+
require_relative 'cast_parameters'
|
3
|
+
require_relative 'permitted_parameter_argument'
|
5
4
|
|
6
5
|
module Paramore
|
7
6
|
module Extension
|
8
|
-
def
|
9
|
-
|
7
|
+
def paramorize(accessor_name, parameter_configuration)
|
8
|
+
unless parameter_configuration.keys.size == 1
|
9
|
+
raise ArgumentError,
|
10
|
+
"Paramore: exactly one required attribute allowed! Given: #{param_definition.keys}"
|
11
|
+
end
|
10
12
|
|
11
|
-
|
13
|
+
required_parameter_name = parameter_configuration.keys.first
|
14
|
+
types_definition = parameter_configuration.values.first
|
12
15
|
|
13
|
-
|
14
|
-
permitted = param_definition.values.first
|
16
|
+
Paramore::Validate.run(types_definition) if types_definition.is_a?(Hash)
|
15
17
|
|
16
18
|
define_method(accessor_name) do |rails_parameters = params|
|
17
19
|
return instance_variable_get("@#{accessor_name}") if instance_variable_defined?("@#{accessor_name}")
|
18
20
|
|
19
|
-
|
21
|
+
permitted_parameter_argument =
|
22
|
+
if types_definition.is_a?(Hash)
|
23
|
+
Paramore::PermittedParameterArgument.parse(types_definition)
|
24
|
+
else
|
25
|
+
types_definition
|
26
|
+
end
|
27
|
+
|
28
|
+
permitted_params = rails_parameters
|
29
|
+
.require(required_parameter_name)
|
30
|
+
.permit(permitted_parameter_argument)
|
31
|
+
|
32
|
+
parameter_values =
|
33
|
+
if types_definition.is_a?(Hash)
|
34
|
+
permitted_params.merge(
|
35
|
+
Paramore::CastParameters.run(types_definition, permitted_params)
|
36
|
+
).permit!
|
37
|
+
else
|
38
|
+
permitted_params.permit!
|
39
|
+
end
|
20
40
|
|
21
|
-
instance_variable_set(
|
22
|
-
"@#{accessor_name}",
|
23
|
-
permitted_params.merge(Format.run(format_definition, permitted_params)).permit!
|
24
|
-
)
|
41
|
+
instance_variable_set("@#{accessor_name}", parameter_values)
|
25
42
|
end
|
26
43
|
end
|
27
44
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Paramore
|
2
|
+
module PermittedParameterArgument
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def parse(types_definition)
|
6
|
+
merge_hashes(
|
7
|
+
types_definition.map do |key, definition|
|
8
|
+
case definition
|
9
|
+
when Hash
|
10
|
+
{ key => merge_hashes(parse(definition)) }
|
11
|
+
when Paratype
|
12
|
+
case definition.type
|
13
|
+
when Array
|
14
|
+
{ key => [] }
|
15
|
+
when Hash
|
16
|
+
{ key => merge_hashes(parse(definition.type)) }
|
17
|
+
else
|
18
|
+
key
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def merge_hashes(parsed)
|
26
|
+
(flat_parameters(parsed) + nested_parameters(parsed)).compact
|
27
|
+
end
|
28
|
+
|
29
|
+
def flat_parameters(parsed)
|
30
|
+
parsed.select { |arg| arg.is_a?(Symbol) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def nested_parameters(parsed)
|
34
|
+
[parsed.reject { |arg| arg.is_a?(Symbol) }.reduce(:merge)]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/paramore/railtie.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Paramore
|
2
|
+
module BigDecimal
|
3
|
+
module_function
|
4
|
+
def [](input)
|
5
|
+
BigDecimal(input)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Boolean
|
10
|
+
TRUTHY_TEXT_VALUES = %w[t true 1]
|
11
|
+
|
12
|
+
module_function
|
13
|
+
def [](input)
|
14
|
+
input.in?(TRUTHY_TEXT_VALUES)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Float
|
19
|
+
module_function
|
20
|
+
def [](input)
|
21
|
+
input.to_f
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Int
|
26
|
+
module_function
|
27
|
+
def [](input)
|
28
|
+
input.to_i
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
module String
|
33
|
+
module_function
|
34
|
+
def [](input)
|
35
|
+
input.to_s
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module StrippedString
|
40
|
+
module_function
|
41
|
+
def [](input)
|
42
|
+
input.to_s.strip
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module SanitizedString
|
47
|
+
module_function
|
48
|
+
def [](input)
|
49
|
+
Paramore::StrippedString[input].squeeze(' ')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/paramore/validate.rb
CHANGED
@@ -1,39 +1,24 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
1
|
module Paramore
|
4
2
|
module Validate
|
5
3
|
module_function
|
6
|
-
def run(param_definition, format_definition)
|
7
|
-
unless param_definition.keys.size == 1
|
8
|
-
raise ArgumentError,
|
9
|
-
"Paramore: exactly one required attribute allowed! Given: #{param_definition.keys}"
|
10
|
-
end
|
11
|
-
|
12
|
-
return unless format_definition
|
13
4
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
unless formatter.respond_to?(Paramore.configuration.formatter_method_name)
|
23
|
-
raise NoMethodError,
|
24
|
-
"Paramore: formatter `#{formatter_name}` does not respond to " +
|
25
|
-
"`#{Paramore.configuration.formatter_method_name}`!"
|
26
|
-
end
|
5
|
+
def run(types_definition)
|
6
|
+
types(types_definition).each do |type|
|
7
|
+
unless type.respond_to?(Paramore.configuration.type_method_name)
|
8
|
+
raise NoMethodError,
|
9
|
+
"Paramore: type `#{type}` does not respond to " +
|
10
|
+
"`#{Paramore.configuration.type_method_name}`!"
|
11
|
+
end
|
27
12
|
end
|
28
13
|
end
|
29
14
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
value
|
15
|
+
def types(types_definition)
|
16
|
+
types_definition.flat_map do |param_name, paratype|
|
17
|
+
unless paratype.is_a?(Paratype)
|
18
|
+
raise Paramore::NonParatype.new(param_name, paratype)
|
36
19
|
end
|
20
|
+
|
21
|
+
paratype.type.is_a?(Hash) ? types(paratype.type) : paratype.type
|
37
22
|
end.uniq
|
38
23
|
end
|
39
24
|
end
|
data/lib/paratype.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class Paratype
|
2
|
+
def self.[](given_type, null: false, empty: false, compact: false)
|
3
|
+
self.new(given_type, null: null, empty: empty, compact: compact)
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(given_type, null:, empty:, compact:)
|
7
|
+
@given_type = given_type
|
8
|
+
@nullable = null
|
9
|
+
@empty = empty
|
10
|
+
@compact = compact
|
11
|
+
end
|
12
|
+
|
13
|
+
def compact?
|
14
|
+
compact
|
15
|
+
end
|
16
|
+
|
17
|
+
def nullable?
|
18
|
+
nullable
|
19
|
+
end
|
20
|
+
|
21
|
+
def use_empty_strings?
|
22
|
+
empty
|
23
|
+
end
|
24
|
+
|
25
|
+
def type
|
26
|
+
given_type
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
attr_reader :given_type, :nullable, :empty, :compact
|
32
|
+
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: paramore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lukas Kairevičius
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name: rspec
|
14
|
+
name: rspec-rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '2.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: combustion
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rails
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -54,7 +68,7 @@ dependencies:
|
|
54
68
|
version: '5.0'
|
55
69
|
description: |
|
56
70
|
Paramore lets you declare which parameters are permitted and what object is responsible
|
57
|
-
for
|
71
|
+
for typing/sanitizing/type-casting them before they are passed along to your models/domain.
|
58
72
|
It is intended to reduce the amount of imperative code in controllers.
|
59
73
|
email: lukas.kairevicius9@gmail.com
|
60
74
|
executables:
|
@@ -66,18 +80,22 @@ files:
|
|
66
80
|
- README.md
|
67
81
|
- bin/paramore
|
68
82
|
- lib/paramore.rb
|
83
|
+
- lib/paramore/cast_parameters.rb
|
69
84
|
- lib/paramore/cli.rb
|
70
85
|
- lib/paramore/configuration.rb
|
86
|
+
- lib/paramore/errors.rb
|
71
87
|
- lib/paramore/extension.rb
|
72
|
-
- lib/paramore/
|
88
|
+
- lib/paramore/permitted_parameter_argument.rb
|
73
89
|
- lib/paramore/railtie.rb
|
90
|
+
- lib/paramore/types.rb
|
74
91
|
- lib/paramore/validate.rb
|
92
|
+
- lib/paratype.rb
|
75
93
|
homepage: https://github.com/lumzdas/paramore
|
76
94
|
licenses:
|
77
95
|
- MIT
|
78
96
|
metadata: {}
|
79
97
|
post_install_message: |
|
80
|
-
Thank you for installing Paramore 0.
|
98
|
+
Thank you for installing Paramore 1.0.1 !
|
81
99
|
From the command line you can run `paramore` to generate a configuration file
|
82
100
|
|
83
101
|
More details here : https://github.com/lumzdas/paramore/blob/master/README.md
|
@@ -96,8 +114,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
114
|
- !ruby/object:Gem::Version
|
97
115
|
version: '0'
|
98
116
|
requirements: []
|
99
|
-
rubygems_version: 3.0.
|
117
|
+
rubygems_version: 3.0.8
|
100
118
|
signing_key:
|
101
119
|
specification_version: 4
|
102
|
-
summary: A declarative approach to Rails' strong parameter
|
120
|
+
summary: A declarative approach to Rails' strong parameter typing and sanitizing
|
103
121
|
test_files: []
|
data/lib/paramore/format.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Paramore
|
4
|
-
module Format
|
5
|
-
module_function
|
6
|
-
def run(format_definition, permitted_params)
|
7
|
-
return {} unless format_definition
|
8
|
-
|
9
|
-
recursive_merge(
|
10
|
-
recursive_format(
|
11
|
-
format_definition, permitted_params
|
12
|
-
)
|
13
|
-
)
|
14
|
-
end
|
15
|
-
|
16
|
-
def recursive_merge(nested_hash_array)
|
17
|
-
nested_hash_array.reduce(:merge).map do |param_name, value|
|
18
|
-
if value.kind_of?(Array) && value.all? { |_value| _value.kind_of?(Hash) }
|
19
|
-
{ param_name => recursive_merge(value) }
|
20
|
-
else
|
21
|
-
{ param_name => value }
|
22
|
-
end
|
23
|
-
end.reduce(:merge)
|
24
|
-
end
|
25
|
-
|
26
|
-
def recursive_format(format_definition, permitted_params)
|
27
|
-
format_definition.map do |param_name, value|
|
28
|
-
next {} unless permitted_params[param_name]
|
29
|
-
|
30
|
-
if value.kind_of?(Hash)
|
31
|
-
{ param_name => recursive_format(value, permitted_params[param_name]) }
|
32
|
-
else
|
33
|
-
{ param_name => formatted_value(permitted_params[param_name], formatter_for(value)) }
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def formatted_value(value, formatter)
|
39
|
-
formatter.send(Paramore.configuration.formatter_method_name, value)
|
40
|
-
end
|
41
|
-
|
42
|
-
def formatter_for(formatter_name)
|
43
|
-
Object.const_get(
|
44
|
-
[Paramore.configuration.formatter_namespace, formatter_name].compact.join('::'),
|
45
|
-
false # inherit=false - only get exact match
|
46
|
-
)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|