better_params 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: af64b05bc75c0e695f916a16c20cd9b6aeea3037637e8254407210932af06c94
4
+ data.tar.gz: e43f0a8bf5b81b16ffe8e8f40eb5fdadc29e442d26896a0baa0b55c920860ac6
5
+ SHA512:
6
+ metadata.gz: b400e185ed05996e1a3924b1018803b671dcf9d13ff1c4adf2b6f5e33fad915d81a03ef630b2a3990d543ff5d0c66e8103dcfeba96cb9df5a314fa7e6c131d03
7
+ data.tar.gz: 5737d14e62aab364364ef1c3481bcda2f2e203f3e216a130352e1b06e1051aaab24206a09a5060c84d4a03f9ceb0cef5111d2843ffae365ea145ae4abb03944f
@@ -0,0 +1,20 @@
1
+ Copyright 2020
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,154 @@
1
+ # BetterParams
2
+ Adds useful methods to `ActionController::Parameters` for modifying parameters.
3
+
4
+ ## Usage
5
+ `ActionController::Parameters` has useful methods for modifying parameters.
6
+
7
+ ### AddDestroyInfo
8
+ Adds the *_destroy* attribute to existing *has_many* associations that were not passed for modification.
9
+ The method accepts 2 parameters: an Active Record Object and a symbolic list of association names.
10
+ Supports nested lists.
11
+ ```ruby
12
+ object.association_a.ids
13
+ # result
14
+ [1,2]
15
+
16
+ object.association_b.ids
17
+ # result
18
+ [1,2]
19
+
20
+ ActionController::Parameters.new(
21
+ a: 'a',
22
+ association_a: [
23
+ { id: 1, name: 'X1' },
24
+ { name: 'Y1' }
25
+ ],
26
+ association_b: [
27
+ { id: 1, name: 'X2' },
28
+ { name: 'Y2' }
29
+ ]
30
+ ).add_destroy_info(object, :association_a)
31
+ # result
32
+ {
33
+ a: 'a',
34
+ association_a: [
35
+ { id: 1, name: 'X1' },
36
+ { id: 2, _destroy: true },
37
+ { name: 'Y1' },
38
+ ],
39
+ association_b: [
40
+ { id: 1, name: 'X2' },
41
+ { name: 'Y2' },
42
+ ]
43
+ }
44
+ ```
45
+
46
+ ### Booleans
47
+ Converts a parameter to a Boolean value.
48
+ The method accepts 1 parameters: Symbolic list of attribute names.
49
+ Supports nested lists.
50
+ ```ruby
51
+ ActionController::Parameters.new(a: 'true', b: 'false', c: 'not_bool', d: 'true')
52
+ .booleans(:a, :b, :c)
53
+ # result
54
+ { a: true, b: false, c: false, d: 'true' }
55
+ ```
56
+
57
+ ### Datetimes
58
+ Converts a parameter to a Time value.
59
+ The method accepts 1 parameters: Symbolic list of attribute names.
60
+ Supports nested lists.
61
+ ```ruby
62
+ ActionController::Parameters.new(a: '2020-01-01', b: '2020-01-01')
63
+ .datetimes(:a)
64
+ # result
65
+ { a: 2020-01-01 00:00:00 +0700, b: '2020-01-01' }
66
+ ```
67
+
68
+ ### PrepareNestedAttributes
69
+ Adds the *_attributes* Postfix to nested parameters, which allows creating a group of related entities using the `assign_attributes` method.
70
+ The method accepts 1 parameters: Symbolic list of association names.
71
+ Supports nested lists.
72
+ ```ruby
73
+ ActionController::Parameters.new(
74
+ a: 'a',
75
+ association_a: [{ a: 'a' }],
76
+ association_b: [
77
+ {
78
+ b: 'b',
79
+ association_b_a: [{ ba: 'b_a' }]
80
+ }
81
+ ]
82
+ ).prepare_nested_attributes(
83
+ :association_a,
84
+ association_b: [:association_b_a]
85
+ )
86
+ # result
87
+ {
88
+ a: 'a',
89
+ association_a_attributes: [{ a: 'a' }],
90
+ association_b_attributes: [
91
+ {
92
+ b: 'b',
93
+ association_b_a_attributes: [{ ba: 'ba' }]
94
+ }
95
+ ]
96
+ }
97
+ ```
98
+
99
+ ### RemoveBlanks
100
+ Deletes keys with empty values.
101
+ Not supports nested lists.
102
+ ```ruby
103
+ ActionController::Parameters.new(a: 'a', b: '')
104
+ .remove_blanks
105
+ # result
106
+ { a: 'a' }
107
+ ```
108
+
109
+ ### ReplaceBlanksByNil
110
+ Replaces blanks by nil.
111
+ The method accepts 1 parameters: Symbolic list of attribute names.
112
+ Supports nested lists.
113
+ ```ruby
114
+ ActionController::Parameters.new(a: '', b: '')
115
+ .replace_blanks_by_nil(:a)
116
+ # result
117
+ { a: nil, b: '' }
118
+ ```
119
+
120
+ ### StripValues
121
+ Removes leading and trailing spaces.
122
+ The method accepts 1 parameters: Symbolic list of attribute names.
123
+ Supports nested lists.
124
+ ```ruby
125
+ ActionController::Parameters.new(a: ' a ', b: ' b ')
126
+ .strip_values(:a)
127
+ # result
128
+ { a: 'a', b: ' b ' }
129
+ ```
130
+
131
+ Note: For all parameters, you must make a permit
132
+
133
+ ## Installation
134
+ Add this line to your application's Gemfile:
135
+
136
+ ```ruby
137
+ gem 'better_params'
138
+ ```
139
+
140
+ And then execute:
141
+ ```bash
142
+ $ bundle
143
+ ```
144
+
145
+ Or install it yourself as:
146
+ ```bash
147
+ $ gem install better_params
148
+ ```
149
+
150
+ ## Contributing
151
+ Contribution directions go here.
152
+
153
+ ## License
154
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,27 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'BetterParams'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ require 'bundler/gem_tasks'
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'test'
23
+ t.pattern = 'test/**/*_test.rb'
24
+ t.verbose = false
25
+ end
26
+
27
+ task default: :test
@@ -0,0 +1,7 @@
1
+ require 'better_params/railtie'
2
+ require 'better_params/base'
3
+
4
+ module BetterParams
5
+ end
6
+
7
+ ActionController::Parameters.include BetterParams::Base
@@ -0,0 +1,31 @@
1
+ require 'better_params/converters'
2
+ require 'better_params/params_destroy_info'
3
+
4
+ require 'better_params/base/convert_keys'
5
+ require 'better_params/base/transform_values_for_keys'
6
+
7
+ require 'better_params/base/add_destroy_info'
8
+ require 'better_params/base/booleans'
9
+ require 'better_params/base/datetimes'
10
+ require 'better_params/base/prepare_nested_attributes'
11
+ require 'better_params/base/remove_blanks'
12
+ require 'better_params/base/replace_blanks_by_nil'
13
+ require 'better_params/base/strip_values'
14
+
15
+ module BetterParams
16
+ # The module depends on the 'params' controller instance variable
17
+ module Base
18
+ extend ActiveSupport::Concern
19
+
20
+ include ConvertKeys
21
+ include TransformValuesForKeys
22
+
23
+ include AddDestroyInfo
24
+ include Booleans
25
+ include Datetimes
26
+ include PrepareNestedAttributes
27
+ include RemoveBlanks
28
+ include ReplaceBlanksByNil
29
+ include StripValues
30
+ end
31
+ end
@@ -0,0 +1,9 @@
1
+ module BetterParams
2
+ module Base
3
+ module AddDestroyInfo
4
+ def add_destroy_info(object, *keys)
5
+ ParamsDestroyInfo.add(self, object, *keys)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ module BetterParams
2
+ module Base
3
+ module Booleans
4
+ def booleans(*keys)
5
+ transform_values_for_keys(*keys) do |value|
6
+ Converters.to_b(value) if value
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,44 @@
1
+ module BetterParams
2
+ module Base
3
+ module ConvertKeys
4
+ # Not used directly
5
+ def convert_keys(keys, &block)
6
+ merge_attributes = ->(params, key, attributes) do
7
+ params.merge(block.call(key) => attributes).except(key)
8
+ end
9
+
10
+ params = self
11
+ keys.each do |key|
12
+ if key.is_a? Hash
13
+ key.each do |nested_key, key_from_key|
14
+ nested_params = params[nested_key]
15
+ next if nested_params.nil?
16
+
17
+ nested_attributes =
18
+ if nested_params.is_a?(Array)
19
+ nested_params.map do |item|
20
+ item.convert_keys(key_from_key, &block)
21
+ end
22
+ else
23
+ nested_params.convert_keys(key_from_key, &block)
24
+ end
25
+
26
+ params = merge_attributes.call(
27
+ params,
28
+ nested_key,
29
+ nested_attributes
30
+ )
31
+ end
32
+ else
33
+ attributes = params[key]
34
+ next if attributes.nil?
35
+
36
+ params = merge_attributes.call(params, key, attributes)
37
+ end
38
+ end
39
+
40
+ params
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ module BetterParams
2
+ module Base
3
+ module Datetimes
4
+ def datetimes(*keys)
5
+ transform_values_for_keys(*keys) { |value| value && Time.parse(value) }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module BetterParams
2
+ module Base
3
+ module PrepareNestedAttributes
4
+ def prepare_nested_attributes(*keys)
5
+ convert_keys(keys) { |key| "#{key}_attributes".to_sym }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module BetterParams
2
+ module Base
3
+ module RemoveBlanks
4
+ def remove_blanks
5
+ select { |_key, value| value.present? }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module BetterParams
2
+ module Base
3
+ module ReplaceBlanksByNil
4
+ def replace_blanks_by_nil(*keys)
5
+ transform_values_for_keys(*keys) { |value| value.blank? ? nil : value }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ module BetterParams
2
+ module Base
3
+ module StripValues
4
+ def strip_values(*keys)
5
+ keys.reduce(self) do |result, key|
6
+ if key.is_a?(Hash)
7
+ key.reduce(result) do |hash_result, (hash_key, hash_value)|
8
+ next hash_result unless hash_result.key?(hash_key)
9
+
10
+ nested = hash_result[hash_key]
11
+ next hash_result if nested.nil?
12
+
13
+ nested =
14
+ if nested.is_a?(Array)
15
+ nested.map do |nested_object|
16
+ nested_object.strip_values(*hash_value)
17
+ end
18
+ else
19
+ nested.strip_values(*hash_value)
20
+ end
21
+
22
+ hash_result.merge(hash_key => nested)
23
+ end
24
+ else
25
+ next result unless result.key?(key)
26
+
27
+ result.merge(key => result[key]&.strip)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,10 @@
1
+ module BetterParams
2
+ module Base
3
+ module TransformValuesForKeys
4
+ # Not used directly
5
+ def transform_values_for_keys(*keys, &block)
6
+ merge(slice(*keys).transform_values { |value| block.call(value) })
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,12 @@
1
+ module BetterParams
2
+ # Auxiliary class for converting values
3
+ class Converters
4
+ # Converts to a Boolean value
5
+ def self.to_b(value)
6
+ return true if value.is_a? TrueClass
7
+ return false if value.is_a? FalseClass
8
+
9
+ value.to_s.downcase == 'true'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,74 @@
1
+ module BetterParams
2
+ class ParamsDestroyInfo
3
+ def self.add(*args)
4
+ new.add(*args)
5
+ end
6
+
7
+ # For all has_many relations from a keys array adds information
8
+ # about destroying objects by an algorythm:
9
+ # If a nested object doesn't exists in a passed object it will be destroyed.
10
+ def add(original_params, object, *keys)
11
+ return original_params if object.nil?
12
+
13
+ # Process every key and merge updated information to params
14
+ prepare_keys(keys).reduce(original_params) do |params, (key, nested_keys)|
15
+ # Don't needs to process key if params is not passed
16
+ nested_params = params[key]
17
+ next params if nested_params.nil?
18
+
19
+ # Can't process key if a nested object doesn't exists
20
+ relation = object.public_send(key)
21
+ next params if relation.nil?
22
+
23
+ if relation.is_a? Enumerable
24
+ # If a relation is a has_many, needs to add information about destroying
25
+ nested_params = add_destroy_info(nested_params, relation)
26
+
27
+ # Needs to go deeper to the every object in an array if has nested keys
28
+ unless nested_keys.nil?
29
+ nested_params = add_nested_destroy_info(
30
+ nested_params, relation, nested_keys
31
+ )
32
+ end
33
+ else
34
+ # If a relation is a single object we needs to go deeper
35
+ nested_params = add(nested_params, relation, *nested_keys)
36
+ end
37
+
38
+ next params.merge(key => nested_params)
39
+ end
40
+ end
41
+
42
+ protected
43
+
44
+ # Converts all keys to the same format -
45
+ # hash with array values where value can be nil
46
+ def prepare_keys(keys)
47
+ keys.reduce({}) do |hash, key|
48
+ hash.merge(key.is_a?(Hash) ? key : { key => nil })
49
+ end
50
+ end
51
+
52
+ # Adds { id: 1, _destroy: true } objects to an array if an object with id
53
+ # is not exists in the array but exists in a relation
54
+ def add_destroy_info(params_array, relation)
55
+ existed_ids = relation.map(&:id)
56
+ passed_ids = params_array.map { |attributes| attributes[:id] }.compact
57
+ ids_to_destroy = existed_ids - passed_ids
58
+ params_array + ids_to_destroy.map do |id|
59
+ ActionController::Parameters.new(id: id, _destroy: true).permit!
60
+ end
61
+ end
62
+
63
+ def add_nested_destroy_info(params_array, relation, nested_keys)
64
+ nested_objects_by_id = relation.group_by(&:id).transform_values(&:first)
65
+ params_array.map do |attributes|
66
+ id = attributes[:id]
67
+ nested_object = nested_objects_by_id[id]
68
+ next attributes if nested_object.nil?
69
+
70
+ add(attributes, nested_object, *nested_keys)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,4 @@
1
+ module BetterParams
2
+ class Railtie < ::Rails::Railtie
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module BetterParams
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :better_params do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_params
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Bazov Peter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
33
+ - !ruby/object:Gem::Dependency
34
+ name: sqlite3
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ description: Extension for default Rails params with useful features.
48
+ email:
49
+ - petr@sequenia.com
50
+ - sb.truefalse@gmail.com
51
+ executables: []
52
+ extensions: []
53
+ extra_rdoc_files: []
54
+ files:
55
+ - MIT-LICENSE
56
+ - README.md
57
+ - Rakefile
58
+ - lib/better_params.rb
59
+ - lib/better_params/base.rb
60
+ - lib/better_params/base/add_destroy_info.rb
61
+ - lib/better_params/base/booleans.rb
62
+ - lib/better_params/base/convert_keys.rb
63
+ - lib/better_params/base/datetimes.rb
64
+ - lib/better_params/base/prepare_nested_attributes.rb
65
+ - lib/better_params/base/remove_blanks.rb
66
+ - lib/better_params/base/replace_blanks_by_nil.rb
67
+ - lib/better_params/base/strip_values.rb
68
+ - lib/better_params/base/transform_values_for_keys.rb
69
+ - lib/better_params/converters.rb
70
+ - lib/better_params/params_destroy_info.rb
71
+ - lib/better_params/railtie.rb
72
+ - lib/better_params/version.rb
73
+ - lib/tasks/better_params_tasks.rake
74
+ homepage: http://sequenia.com/
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubygems_version: 3.0.3
94
+ signing_key:
95
+ specification_version: 4
96
+ summary: Better Params
97
+ test_files: []