better_params 0.1.0

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.
@@ -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: []