easy_params 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e5797272eae09e65c24f46558c801f19126e71e4ca940bdfaeecfaab478fe7d
4
- data.tar.gz: 95d1a80d4f0635013658713c6dccc45058e707cae9e90ec88036313c673819ee
3
+ metadata.gz: a707b8082dc9c58012a4b8f93c93d2c8543b3ee85d96f64d972b9a074b3bed29
4
+ data.tar.gz: 2d0a8eeea15d0418f91c4fb48e128d1f965db24773a81a9ac4f23d6c2b01500e
5
5
  SHA512:
6
- metadata.gz: 1e76c8c64f7568d0ef3633eb3ca86a1cf1f03f331d528aa7a941c8197a2030dbbeb3fc77149b7dd0416b4776b3a8b547a6e0c451a6e1c3af92835b25e2d6815c
7
- data.tar.gz: 82f361cf4ebce4db3ab3bbc9fd7ca196a3dc57a91c3156df1b2e18d443922a900998f58c43b5a12571346de047c1f9e803ad45e109dcb32c028840c44ebf0681
6
+ metadata.gz: 941a6c062c86638aa540eba6ac2fc697ba9177b7521c344bed4ae71b88747b5419c1c8b15cf44da9d5dea5098bf6a6de910125173bdfa75cb4838f353f28caec
7
+ data.tar.gz: 7a07ba572c6fe6890368b7b1b0458cf934ee07953e4bd84a60728945c5f852d2a8206fe0e6cf83b70be343dda5683927b9e29d49292cb8181461ffa567611cb9
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.1
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in easy_params.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'ostruct'
8
9
  gem 'pry'
9
10
  gem 'rake', '~> 12.0'
10
11
  gem 'rspec', '~> 3.0'
data/Gemfile.lock CHANGED
@@ -1,96 +1,111 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- easy_params (0.5.0)
4
+ easy_params (0.6.1)
5
5
  activemodel (>= 3.2)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- activemodel (7.1.3)
11
- activesupport (= 7.1.3)
12
- activesupport (7.1.3)
10
+ activemodel (8.0.2)
11
+ activesupport (= 8.0.2)
12
+ activesupport (8.0.2)
13
13
  base64
14
+ benchmark (>= 0.3)
14
15
  bigdecimal
15
- concurrent-ruby (~> 1.0, >= 1.0.2)
16
+ concurrent-ruby (~> 1.0, >= 1.3.1)
16
17
  connection_pool (>= 2.2.5)
17
18
  drb
18
19
  i18n (>= 1.6, < 2)
20
+ logger (>= 1.4.2)
19
21
  minitest (>= 5.1)
20
- mutex_m
21
- tzinfo (~> 2.0)
22
- ast (2.4.2)
23
- base64 (0.2.0)
24
- bigdecimal (3.1.6)
22
+ securerandom (>= 0.3)
23
+ tzinfo (~> 2.0, >= 2.0.5)
24
+ uri (>= 0.13.1)
25
+ ast (2.4.3)
26
+ base64 (0.3.0)
27
+ benchmark (0.4.1)
28
+ bigdecimal (3.2.2)
25
29
  coderay (1.1.3)
26
- concurrent-ruby (1.2.3)
27
- connection_pool (2.4.1)
28
- diff-lcs (1.4.4)
29
- docile (1.3.5)
30
- drb (2.2.0)
31
- ruby2_keywords
32
- i18n (1.14.1)
30
+ concurrent-ruby (1.3.5)
31
+ connection_pool (2.5.3)
32
+ diff-lcs (1.6.2)
33
+ docile (1.4.1)
34
+ drb (2.2.3)
35
+ i18n (1.14.7)
33
36
  concurrent-ruby (~> 1.0)
34
- json (2.6.3)
35
- method_source (1.0.0)
36
- minitest (5.21.2)
37
- mutex_m (0.2.0)
38
- parallel (1.23.0)
39
- parser (3.2.2.3)
37
+ json (2.13.2)
38
+ language_server-protocol (3.17.0.5)
39
+ lint_roller (1.1.0)
40
+ logger (1.7.0)
41
+ method_source (1.1.0)
42
+ minitest (5.25.5)
43
+ ostruct (0.6.2)
44
+ parallel (1.27.0)
45
+ parser (3.3.9.0)
40
46
  ast (~> 2.4.1)
41
47
  racc
42
- pry (0.14.2)
48
+ prism (1.4.0)
49
+ pry (0.15.2)
43
50
  coderay (~> 1.1)
44
51
  method_source (~> 1.0)
45
- racc (1.7.1)
52
+ racc (1.8.1)
46
53
  rainbow (3.1.1)
47
54
  rake (12.3.3)
48
- regexp_parser (2.8.1)
49
- rexml (3.2.5)
50
- rspec (3.10.0)
51
- rspec-core (~> 3.10.0)
52
- rspec-expectations (~> 3.10.0)
53
- rspec-mocks (~> 3.10.0)
54
- rspec-core (3.10.0)
55
- rspec-support (~> 3.10.0)
56
- rspec-expectations (3.10.0)
55
+ regexp_parser (2.10.0)
56
+ rspec (3.13.1)
57
+ rspec-core (~> 3.13.0)
58
+ rspec-expectations (~> 3.13.0)
59
+ rspec-mocks (~> 3.13.0)
60
+ rspec-core (3.13.5)
61
+ rspec-support (~> 3.13.0)
62
+ rspec-expectations (3.13.5)
57
63
  diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.10.0)
59
- rspec-mocks (3.10.0)
64
+ rspec-support (~> 3.13.0)
65
+ rspec-mocks (3.13.5)
60
66
  diff-lcs (>= 1.2.0, < 2.0)
61
- rspec-support (~> 3.10.0)
62
- rspec-support (3.10.0)
67
+ rspec-support (~> 3.13.0)
68
+ rspec-support (3.13.4)
63
69
  rspec_vars_helper (0.1.0)
64
70
  rspec (>= 2.4)
65
- rubocop (1.52.1)
71
+ rubocop (1.79.0)
66
72
  json (~> 2.3)
73
+ language_server-protocol (~> 3.17.0.2)
74
+ lint_roller (~> 1.1.0)
67
75
  parallel (~> 1.10)
68
- parser (>= 3.2.2.3)
76
+ parser (>= 3.3.0.2)
69
77
  rainbow (>= 2.2.2, < 4.0)
70
- regexp_parser (>= 1.8, < 3.0)
71
- rexml (>= 3.2.5, < 4.0)
72
- rubocop-ast (>= 1.28.0, < 2.0)
78
+ regexp_parser (>= 2.9.3, < 3.0)
79
+ rubocop-ast (>= 1.46.0, < 2.0)
73
80
  ruby-progressbar (~> 1.7)
74
- unicode-display_width (>= 2.4.0, < 3.0)
75
- rubocop-ast (1.29.0)
76
- parser (>= 3.2.1.0)
81
+ tsort (>= 0.2.0)
82
+ unicode-display_width (>= 2.4.0, < 4.0)
83
+ rubocop-ast (1.46.0)
84
+ parser (>= 3.3.7.2)
85
+ prism (~> 1.4)
77
86
  ruby-progressbar (1.13.0)
78
- ruby2_keywords (0.0.5)
79
- simplecov (0.21.2)
87
+ securerandom (0.4.1)
88
+ simplecov (0.22.0)
80
89
  docile (~> 1.1)
81
90
  simplecov-html (~> 0.11)
82
91
  simplecov_json_formatter (~> 0.1)
83
- simplecov-html (0.12.3)
84
- simplecov_json_formatter (0.1.2)
92
+ simplecov-html (0.13.2)
93
+ simplecov_json_formatter (0.1.4)
94
+ tsort (0.2.0)
85
95
  tzinfo (2.0.6)
86
96
  concurrent-ruby (~> 1.0)
87
- unicode-display_width (2.4.2)
97
+ unicode-display_width (3.1.4)
98
+ unicode-emoji (~> 4.0, >= 4.0.4)
99
+ unicode-emoji (4.0.4)
100
+ uri (1.0.3)
88
101
 
89
102
  PLATFORMS
103
+ arm64-darwin-24
90
104
  ruby
91
105
 
92
106
  DEPENDENCIES
93
107
  easy_params!
108
+ ostruct
94
109
  pry
95
110
  rake (~> 12.0)
96
111
  rspec (~> 3.0)
@@ -99,4 +114,4 @@ DEPENDENCIES
99
114
  simplecov (~> 0.17)
100
115
 
101
116
  BUNDLED WITH
102
- 2.2.3
117
+ 2.7.1
data/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # EasyParams
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/nina.svg)](https://badge.fury.io/rb/nina)
3
+ [![Gem Version](https://badge.fury.io/rb/easy_params.svg)](https://badge.fury.io/rb/easy_params)
4
4
  [![Maintainability](https://api.codeclimate.com/v1/badges/17872804ce576b8b0df2/maintainability)](https://codeclimate.com/github/andriy-baran/easy_params/maintainability)
5
5
  [![Test Coverage](https://api.codeclimate.com/v1/badges/17872804ce576b8b0df2/test_coverage)](https://codeclimate.com/github/andriy-baran/easy_params/test_coverage)
6
6
 
7
- Provides an easy way define structure, validation rules, type coercion and set default values for any hash-like structure. It's built on top of `active_model`.
7
+ Provides an easy way to define structure, validation rules, type coercion, and default values for any hash-like structure. It's built on top of `ActiveModel`.
8
8
 
9
9
  ## Types
10
10
 
11
- Dry types are wrapped by class methods. Avaliable types: `integer`, `decimal`, `float`, `bool`, `string`, `array`, `date`, `datetime`, `time`
11
+ Available types: `integer`, `decimal`, `float`, `bool`, `string`, `array`, `date`, `datetime`, `time`
12
12
 
13
13
  ## Installation
14
14
 
@@ -32,20 +32,54 @@ To define attribute we have a set of methods which match types list. Ex.
32
32
  ```ruby
33
33
  integer(param_name, default: nil, normalize: nil, **validations)
34
34
  ```
35
- * `:default` provides a value to return if got `nil` as input or there were errors during coersion.
36
- * `normalize` a proc or lambda that accepts single argument and changes it in some way. It's get called before coercion.
37
- * `validations` mimics `activemodel/validation` can be any supported validation `presence: true, numericality: { only_integer: true, greater_than: 0 }`
35
+ * `:default` provides a value to return if we get `nil` as input or there were errors during coercion.
36
+ * `:normalize` is a Proc or lambda that accepts a single argument and transforms it. It gets called before coercion.
37
+ * `validations` mimic ActiveModel validations; can be any supported validation, e.g., `presence: true, numericality: { only_integer: true, greater_than: 0 }`
38
38
 
39
- In addition we have special option for an `array` type
39
+ In addition, there is a special option for the `array` type:
40
40
  * `:of` accepts `:integer`, `:decimal`, `:float`, `:bool`, `:string`, `:date`, `:datetime`, `:time` (`:array` is not supported)
41
41
 
42
42
  There are two special types:
43
43
 
44
44
  | type | method to define | default |
45
45
  |-------------------|------------------|---------|
46
- | :struct | has | {} |
46
+ | :struct | has | nil |
47
47
  | :array_of_structs | each | [] |
48
48
 
49
+ ### Defaults for nested types
50
+
51
+ - **has (struct)**: `default:` must be a Hash. When the input is `nil`, the nested struct is instantiated with that hash; otherwise the provided input is used. If no `default:` is given and the input is `nil`, the value will be `nil`.
52
+
53
+ ```ruby
54
+ has :shipping_address, default: { country: 'US' } do
55
+ string :country, default: 'US'
56
+ string :city
57
+ end
58
+ ```
59
+
60
+ - **each (array_of_structs)**: `default:` should be an Array (typically an array of hashes). When the input is `nil`, the collection defaults to an empty array `[]`. If you provide a default array, each element will be coerced into the nested struct.
61
+
62
+ ```ruby
63
+ each :items, default: [{ qty: 1 }] do
64
+ integer :qty, default: 1
65
+ end
66
+ ```
67
+
68
+ - **Override precedence**: Container-level defaults override attribute-level defaults for the same keys. Attribute defaults apply only when the key is absent (or `nil`) in the provided default/input.
69
+
70
+ ```ruby
71
+ has :user, default: { role: 'admin' } do
72
+ string :role, default: 'guest'
73
+ string :name, default: 'Anonymous'
74
+ end
75
+ # input: nil => role: 'admin', name: 'Anonymous'
76
+
77
+ each :items, default: [{ qty: 2 }, {}] do
78
+ integer :qty, default: 1
79
+ end
80
+ # input: nil => items.map(&:qty) == [2, 1]
81
+ ```
82
+
49
83
  ```ruby
50
84
  # app/params/api/v2/icqa/move_params.rb
51
85
  class Api::V1::Carts::MoveParams < EasyParams::Base
@@ -83,7 +117,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
83
117
 
84
118
  ## Contributing
85
119
 
86
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/easy_params. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/[USERNAME]/easy_params/blob/master/CODE_OF_CONDUCT.md).
120
+ Bug reports and pull requests are welcome on GitHub at [github.com/andriy-baran/easy_params](https://github.com/andriy-baran/easy_params). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/andriy-baran/easy_params/blob/master/CODE_OF_CONDUCT.md).
87
121
 
88
122
 
89
123
  ## License
@@ -92,4 +126,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
92
126
 
93
127
  ## Code of Conduct
94
128
 
95
- Everyone interacting in the EasyParams project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/easy_params/blob/master/CODE_OF_CONDUCT.md).
129
+ Everyone interacting in the EasyParams project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/andriy-baran/easy_params/blob/master/CODE_OF_CONDUCT.md).
data/easy_params.gemspec CHANGED
@@ -31,5 +31,5 @@ Gem::Specification.new do |spec|
31
31
 
32
32
  version_string = ['>= 3.2']
33
33
 
34
- spec.add_runtime_dependency 'activemodel', version_string
34
+ spec.add_dependency 'activemodel', version_string
35
35
  end
@@ -7,9 +7,11 @@ module EasyParams
7
7
  include EasyParams::Types::Struct
8
8
  include EasyParams::Validation
9
9
 
10
+ attr_writer :default
11
+
10
12
  def initialize(params = {})
11
13
  self.class.schema.each do |attr, type|
12
- public_send("#{attr}=", type.coerce(params[attr])) if params
14
+ public_send("#{attr}=", type.coerce(params.to_h[attr]))
13
15
  end
14
16
  end
15
17
 
@@ -28,25 +30,33 @@ module EasyParams
28
30
  @schema ||= {}
29
31
  end
30
32
 
31
- def each(param_name, normalize: nil, **validations, &block)
33
+ def each(param_name, definition = nil, default: nil, normalize: nil, **validations, &block)
32
34
  validates param_name, **validations if validations.any?
33
- type = EasyParams::Types::Each.with_type(&block)
34
- type = customize_type(type, nil, &normalize)
35
- public_send(:attribute, param_name, type)
35
+ if definition && !(definition < EasyParams::Base)
36
+ raise ArgumentError, "definition for attribute #{param_name.inspect} must be a subclass of EasyParams::Base"
37
+ end
38
+
39
+ type = EasyParams::Types::Each.with_type(definition, &block)
40
+ type = customize_type(type, default, &normalize)
41
+ attribute(param_name, type)
36
42
  end
37
43
 
38
- def has(param_name, normalize: nil, **validations, &block)
44
+ def has(param_name, definition = nil, default: nil, normalize: nil, **validations, &block)
39
45
  validates param_name, **validations if validations.any?
40
- type = Class.new(EasyParams::Types::Struct.class).tap { |c| c.class_eval(&block) }.new
41
- type = customize_type(type, nil, &normalize)
42
- public_send(:attribute, param_name, type)
46
+ if definition && !(definition < EasyParams::Base)
47
+ raise ArgumentError, "definition for attribute #{param_name.inspect} must be a subclass of EasyParams::Base"
48
+ end
49
+
50
+ type = (definition || Class.new(EasyParams::Base).tap { |c| c.class_eval(&block) }).new
51
+ type = customize_type(type, default, &normalize)
52
+ attribute(param_name, type)
43
53
  end
44
54
 
45
- def array(param_name, of:, normalize: nil, **validations)
55
+ def array(param_name, of:, default: nil, normalize: nil, **validations)
46
56
  validates param_name, **validations if validations.any?
47
57
  type = EasyParams::Types::Array.of(EasyParams::Types.const_get(of.to_s.camelcase))
48
- type = customize_type(type, nil, &normalize)
49
- public_send(:attribute, param_name, type)
58
+ type = customize_type(type, default, &normalize)
59
+ attribute(param_name, type)
50
60
  end
51
61
 
52
62
  private
@@ -64,7 +74,7 @@ module EasyParams
64
74
  validates param_name, **validations if validations.any?
65
75
  type = EasyParams::Types.const_get(type_name)
66
76
  type = customize_type(type, default, &normalize)
67
- public_send(:attribute, param_name, type)
77
+ attribute(param_name, type)
68
78
  end
69
79
  end
70
80
 
@@ -81,7 +91,7 @@ module EasyParams
81
91
  result[key] = case value
82
92
  when EasyParams::Types::StructsCollection
83
93
  value.map(&:to_h)
84
- when EasyParams::Types::Struct.class
94
+ when EasyParams::Base
85
95
  value.to_h
86
96
  else
87
97
  value
@@ -16,20 +16,16 @@ module EasyParams
16
16
  end
17
17
 
18
18
  def coerce(value)
19
- value = @normalize_proc.call(Array(value)) if @normalize_proc
20
- self.class.new(@title, Array(value).map do |v|
21
- @of_type.coerce(v)
22
- end, @normalize_proc, of: @of_type, &@coerce_proc)
19
+ input = value || @default
20
+ input = @normalize_proc.call(Array(input)) if @normalize_proc
21
+ coerced = Array(input).map { |v| @of_type.coerce(v) }
22
+ self.class.new(@title, coerced, @normalize_proc, of: @of_type, &@coerce_proc)
23
23
  end
24
24
 
25
25
  def normalize(&block)
26
26
  self.class.new(@title, @default, block, of: @of_type, &@coerce_proc)
27
27
  end
28
28
 
29
- def self.optional
30
- self.class.new(@title, @default, @normalize_proc, of: @of_type, &@coerce_proc)
31
- end
32
-
33
29
  def default(value)
34
30
  self.class.new(@title, value, @normalize_proc, of: @of_type, &@coerce_proc)
35
31
  end
@@ -41,8 +37,8 @@ module EasyParams
41
37
 
42
38
  # base interface for array of structs type
43
39
  class StructsCollection < Collection
44
- def with_type(&block)
45
- of_type = Class.new(EasyParams::Types::Struct.class).tap { |c| c.class_eval(&block) }.new
40
+ def with_type(definition = nil, &block)
41
+ of_type = (definition || Class.new(EasyParams::Base).tap { |c| c.class_eval(&block) }).new
46
42
  self.class.new(@title, @default, @normalize_proc, of: of_type)
47
43
  end
48
44
  end
@@ -19,14 +19,6 @@ module EasyParams
19
19
  self.class.new(@title, value, @normalize_proc, &@coerce_proc)
20
20
  end
21
21
 
22
- def optional
23
- self.class.new(@title, @default, @normalize_proc, &@coerce_proc)
24
- end
25
-
26
- def optional?
27
- @optional
28
- end
29
-
30
22
  def normalize(&block)
31
23
  self.class.new(@title, @default, block, &@coerce_proc)
32
24
  end
@@ -8,8 +8,14 @@ module EasyParams
8
8
  false
9
9
  end
10
10
 
11
+ def default(value)
12
+ self.default = value
13
+ self
14
+ end
15
+
11
16
  def coerce(input)
12
- return if input.blank?
17
+ return if input.nil? && @default.nil?
18
+ return self.class.new(@default) if input.nil? && @default.is_a?(Hash)
13
19
 
14
20
  self.class.new(input)
15
21
  end
@@ -9,7 +9,7 @@ module EasyParams
9
9
  { '0' => false, 'f' => false, 'false' => false, 'False' => false, 'FALSE' => false, 'F' => false }
10
10
  ).freeze
11
11
 
12
- Struct = Class.new(EasyParams::Base).new
12
+ Struct = EasyParams::Base.new
13
13
  Array = Collection.new(:array)
14
14
  Each = StructsCollection.new(:array_of_structs)
15
15
  Integer = Generic.new(:integer, &:to_i)
@@ -10,7 +10,7 @@ module EasyParams
10
10
  case value
11
11
  when EasyParams::Types::StructsCollection
12
12
  value.each(&:valid?)
13
- when EasyParams::Types::Struct.class
13
+ when EasyParams::Base
14
14
  value.valid?
15
15
  end
16
16
  end
@@ -24,7 +24,7 @@ module EasyParams
24
24
  value.each.with_index do |element, i|
25
25
  aggregate_nested_errors[attr_name, element, "[#{i}]", error_key_prefix]
26
26
  end
27
- when EasyParams::Types::Struct.class
27
+ when EasyParams::Base
28
28
  handle_nested_errors(value, error_key_prefix, attr_name, array_index)
29
29
  end
30
30
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EasyParams
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_params
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrii Baran
8
- autorequire:
9
8
  bindir: exe
10
9
  cert_chain: []
11
- date: 2024-01-31 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activemodel
@@ -36,6 +35,7 @@ files:
36
35
  - ".gitignore"
37
36
  - ".rspec"
38
37
  - ".rubocop.yml"
38
+ - ".ruby-version"
39
39
  - ".travis.yml"
40
40
  - CODE_OF_CONDUCT.md
41
41
  - Gemfile
@@ -61,7 +61,6 @@ metadata:
61
61
  allowed_push_host: https://rubygems.org
62
62
  homepage_uri: https://github.com/andriy-baran/easy_params
63
63
  source_code_uri: https://github.com/andriy-baran/easy_params
64
- post_install_message:
65
64
  rdoc_options: []
66
65
  require_paths:
67
66
  - lib
@@ -76,8 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
76
75
  - !ruby/object:Gem::Version
77
76
  version: '0'
78
77
  requirements: []
79
- rubygems_version: 3.3.26
80
- signing_key:
78
+ rubygems_version: 3.7.1
81
79
  specification_version: 4
82
80
  summary: A tool that handles common tasks needed when working with params in Rails
83
81
  test_files: []