formeze 4.3.0 → 5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 65adcff0153dbcbf39d46bbdb6ad7a60765e57e8329b89d3003ed1e4c9c9bcf5
4
- data.tar.gz: 99f871b6b7228ec472abaf8a2dbe820ea33a7cc5b3f3ef6dcd83f95a18410bda
3
+ metadata.gz: d48156472abef4843eb20d0f3a5fce2c17ae7551aeaf34d1fe0da1c8d6547cd2
4
+ data.tar.gz: 922345d41f4edd5b694156841e23c52c8b1a35cbbe476925430fef299470122a
5
5
  SHA512:
6
- metadata.gz: d1a01576d7f38d324e8aa7c33279fd25f36227d49e124b8f53f6f56605cd632478e88616cf13c9e4c37994472905bea37cc7fe211f85ac6e98aca5dbe2bf37c1
7
- data.tar.gz: 12564e8c34d417f605c886fe43202fdde129aea2370699ee8411cb3e4703f99fbeb4ba5a4ad054a295ae8387708da3fe6db80454a5de3f779c69852e3c7777db
6
+ metadata.gz: 19c9850c142de6097c31a52e8badb70e475e4342359dcd45787858775bbfec1c6e21a759e9628c8a08529513c2493ad92aee0331999fe303ef6162e08ed1b541
7
+ data.tar.gz: 6c2c2cfbab1abe61e814a8531ace2ed05edf3d00e8c4afbba048b862d02b8f3b351eee94c549ef80e22caa2cb51c351149728a5f6a82eef84d41c237b603e1fd
data/CHANGES.md CHANGED
@@ -1,3 +1,35 @@
1
+ # 5.1.0
2
+
3
+ * Added `Formeze.exclude` attribute to configure which parameters are excluded
4
+
5
+ # 5.0.0
6
+
7
+ * Added a `fill` field option to specify how to fill a field. For example:
8
+
9
+ class ExampleForm < Formeze::Form
10
+ field :year, required: false, fill: ->{ _1.date&.year }
11
+ end
12
+
13
+ * Added functionality for defining field specific error messages via i18n.
14
+
15
+ Add translations to your locale files like this:
16
+
17
+ ExampleForm:
18
+ errors:
19
+ comments:
20
+ required: 'are required'
21
+
22
+ * Removed support for older rubies. **Required ruby version is now 3.0.0**
23
+
24
+ * Changed from cgi to rack for parsing form data, adding support for parsing
25
+ requests with different methods e.g. PUT and PATCH instead of just POST.
26
+
27
+ Whilst this should largely be backwards compatible there are some differences,
28
+ for example uploaded files will be instances of `Rack::Multipart::UploadedFile`
29
+ instead of `StringIO` instances as they were before.
30
+
31
+ * Changed the default blank value to `nil`
32
+
1
33
  # 4.3.0
2
34
 
3
35
  * Added dependency on cgi gem
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2024 TIMCRAFT
1
+ Copyright (c) 2012-2025 TIMCRAFT
2
2
 
3
3
  This is an Open Source project licensed under the terms of the LGPLv3 license.
4
4
  Please see <http://www.gnu.org/licenses/lgpl-3.0.html> for license text.
data/README.md CHANGED
@@ -3,19 +3,19 @@
3
3
  ![Gem Version](https://badge.fury.io/rb/formeze.svg)
4
4
  ![Test Status](https://github.com/readysteady/formeze/actions/workflows/test.yml/badge.svg)
5
5
 
6
- Ruby gem for validating form data.
6
+ Ruby gem for parsing and validating form data.
7
7
 
8
8
 
9
9
  ## Motivation
10
10
 
11
- Most web apps built for end users will need to process url-encoded form data.
11
+ Most web applications built for end users will need to process form data.
12
12
  Registration forms, profile forms, checkout forms, contact forms, and forms
13
13
  for adding/editing application specific data.
14
14
 
15
- As developers we would like to process this data safely, to minimise the
16
- possibility of security holes within our application that could be exploited.
17
- Formeze adopts the approach of being "strict by default", forcing the application
18
- code to be explicit in what it accepts as input.
15
+ With formeze you can define form objects that explicitly define what your
16
+ application expects as input. This is more secure, and leads to much better
17
+ separation of responsibilities, and also allows for implementing different
18
+ validation rules in different contexts.
19
19
 
20
20
 
21
21
  ## Install
@@ -53,7 +53,9 @@ else
53
53
  end
54
54
  ```
55
55
 
56
- Formeze will automatically ignore the Rails "utf8" and "authenticity_token" parameters.
56
+ Formeze will exclude any parameters defined in `Formeze.exclude`, which by
57
+ default includes framework defined parameters like `_method`, `authenticity_token`,
58
+ `commit`, and `utf8`.
57
59
 
58
60
  If you prefer not to inherit from the `Formeze::Form` class then you can
59
61
  instead call the `Formeze.setup` method on your classes like this:
@@ -89,9 +91,9 @@ messages specific to a single field.
89
91
 
90
92
  ## Field options
91
93
 
92
- By default fields cannot be blank, they are limited to 64 characters,
93
- and they cannot contain newlines. These restrictions can be overridden
94
- by setting various field options.
94
+ By default fields are required (i.e. they cannot be blank), they are limited
95
+ to 64 characters, and they cannot contain newlines. These restrictions can be
96
+ overridden by setting various field options.
95
97
 
96
98
  Defining a field without any options works well for a simple text input.
97
99
  If the default length limit is too big or too small you can override it
@@ -101,11 +103,14 @@ by setting the `maxlength` option. For example:
101
103
  field :title, maxlength: 200
102
104
  ```
103
105
 
104
- Similarly there is a `minlength` option for validating fields that should
105
- have a minimum number of characters (e.g. passwords).
106
+ Similarly there is a `minlength` option for defining a minimum length:
107
+
108
+ ```ruby
109
+ field :password, minlength: 8
110
+ ```
106
111
 
107
112
  Fields are required by default. Specify the `required` option if the field
108
- is not required, i.e. the value of the field can be blank/empty. For example:
113
+ is optional. For example:
109
114
 
110
115
  ```ruby
111
116
  field :title, required: false
@@ -308,11 +313,11 @@ would include the value of the `formeze.errors.does_not_match` I18n key.
308
313
 
309
314
  ## I18n integration
310
315
 
311
- Formeze integrates with [I18n](http://edgeguides.rubyonrails.org/i18n.html)
316
+ Formeze integrates with the [i18n gem](https://rubygems.org/gems/i18n)
312
317
  so that you can define custom error messages and field labels within your
313
318
  locales (useful both for localization, and when working with designers).
314
- For example, here is how you would change the "required" error message
315
- (which defaults to "is required"):
319
+
320
+ Here is an example of how you would change the "required" error message:
316
321
 
317
322
  ```yaml
318
323
  # config/locales/en.yml
@@ -322,8 +327,20 @@ en:
322
327
  required: "cannot be blank"
323
328
  ```
324
329
 
325
- And here is an example of how you would set a custom label for fields named
326
- "first_name" (for which the default label would be "First name"):
330
+ Error messages defined in this way apply globally to all Formeze forms.
331
+
332
+ You can also change error messages on a per field basis, for example:
333
+
334
+ ```yaml
335
+ # config/locales/en.yml
336
+ en:
337
+ ExampleForm:
338
+ errors:
339
+ comments:
340
+ required: 'are required'
341
+ ```
342
+
343
+ Here is an example of how to define a custom label for "first_name" fields:
327
344
 
328
345
  ```yaml
329
346
  # config/locales/en.yml
data/formeze.gemspec CHANGED
@@ -1,15 +1,15 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'formeze'
3
- s.version = '4.3.0'
3
+ s.version = '5.1.0'
4
4
  s.license = 'LGPL-3.0'
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ['Tim Craft']
7
- s.email = ['mail@timcraft.com']
7
+ s.email = ['email@timcraft.com']
8
8
  s.homepage = 'https://github.com/readysteady/formeze'
9
- s.description = 'Ruby gem for validating form data'
9
+ s.description = 'Ruby gem for parsing and validating form data'
10
10
  s.summary = 'See description'
11
11
  s.files = Dir.glob('lib/**/*.rb') + %w(CHANGES.md LICENSE.txt README.md formeze.gemspec)
12
- s.required_ruby_version = '>= 2.4.0'
12
+ s.required_ruby_version = '>= 3.0.0'
13
13
  s.require_path = 'lib'
14
14
  s.metadata = {
15
15
  'homepage' => 'https://github.com/readysteady/formeze',
@@ -17,5 +17,5 @@ Gem::Specification.new do |s|
17
17
  'bug_tracker_uri' => 'https://github.com/readysteady/formeze/issues',
18
18
  'changelog_uri' => 'https://github.com/readysteady/formeze/blob/main/CHANGES.md'
19
19
  }
20
- s.add_dependency 'cgi'
20
+ s.add_dependency 'rack', '~> 3'
21
21
  end
@@ -1,4 +1,4 @@
1
- module Formeze::Condition
1
+ module Formeze::Block
2
2
  def self.evaluate(instance, block)
3
3
  block = block.to_proc
4
4
 
@@ -1,11 +1,26 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Formeze::Errors
2
4
  SCOPE = [:formeze, :errors].freeze
3
5
 
4
- def self.translate(error, default)
5
- if defined?(I18n)
6
- return I18n.translate(error, scope: SCOPE, default: default)
7
- end
6
+ DEFAULT = {
7
+ bad_value: 'is invalid',
8
+ not_accepted: 'is not an accepted file type',
9
+ not_multiline: 'cannot contain newlines',
10
+ no_match: 'is invalid',
11
+ required: 'is required',
12
+ too_large: 'is too large',
13
+ too_long: 'is too long',
14
+ too_short: 'is too short',
15
+ }
16
+
17
+ def self.translate(error, scope:)
18
+ default = DEFAULT[error] || 'is invalid'
19
+
20
+ return default unless defined?(I18n)
21
+
22
+ message = I18n.translate(error, scope: scope, default: nil)
8
23
 
9
- default
24
+ message || I18n.translate(error, scope: SCOPE, default: default)
10
25
  end
11
26
  end
data/lib/formeze/field.rb CHANGED
@@ -16,7 +16,7 @@ class Formeze::Field
16
16
  if String === value
17
17
  value = validate(value, form)
18
18
  else
19
- form.add_error(self, :not_accepted, 'is not an accepted file type') unless acceptable_file?(value)
19
+ form.add_error(self, :not_accepted) unless acceptable_file?(value)
20
20
 
21
21
  size += value.size
22
22
  end
@@ -26,26 +26,26 @@ class Formeze::Field
26
26
  form.send(:"#{name}=", value)
27
27
  end
28
28
 
29
- form.add_error(self, :too_large, 'is too large') if maxsize? && size > maxsize
29
+ form.add_error(self, :too_large) if maxsize? && size > maxsize
30
30
  end
31
31
 
32
32
  def validate(value, form)
33
33
  value = Formeze.scrub(value, @options[:scrub])
34
34
 
35
35
  if blank?(value)
36
- form.add_error(self, :required, 'is required') if required?
36
+ form.add_error(self, :required) if required?
37
37
 
38
- value = blank_value if blank_value?
38
+ value = blank_value
39
39
  else
40
- form.add_error(self, :not_multiline, 'cannot contain newlines') if !multiline? && value.lines.count > 1
40
+ form.add_error(self, :not_multiline) if !multiline? && value.lines.count > 1
41
41
 
42
- form.add_error(self, :too_long, 'is too long') if too_long?(value)
42
+ form.add_error(self, :too_long) if too_long?(value)
43
43
 
44
- form.add_error(self, :too_short, 'is too short') if too_short?(value)
44
+ form.add_error(self, :too_short) if too_short?(value)
45
45
 
46
- form.add_error(self, :no_match, 'is invalid') if no_match?(value)
46
+ form.add_error(self, :no_match) if no_match?(value)
47
47
 
48
- form.add_error(self, :bad_value, 'is invalid') if values? && !values.include?(value)
48
+ form.add_error(self, :bad_value) if values? && !values.include?(value)
49
49
  end
50
50
 
51
51
  value
@@ -95,6 +95,10 @@ class Formeze::Field
95
95
  @options.fetch(:maxsize)
96
96
  end
97
97
 
98
+ def accept?
99
+ @options.key?(:accept)
100
+ end
101
+
98
102
  def accept
99
103
  @accept ||= @options.fetch(:accept).split(',').flat_map { |type| MIME::Types[type] }
100
104
  end
@@ -111,12 +115,8 @@ class Formeze::Field
111
115
  @options.key?(:pattern) && value !~ @options[:pattern]
112
116
  end
113
117
 
114
- def blank_value?
115
- @options.key?(:blank)
116
- end
117
-
118
118
  def blank_value
119
- @options.fetch(:blank)
119
+ @options[:blank]
120
120
  end
121
121
 
122
122
  def values?
@@ -142,4 +142,22 @@ class Formeze::Field
142
142
  def defined_unless
143
143
  @options.fetch(:defined_unless)
144
144
  end
145
+
146
+ def undefined?(form)
147
+ if defined_if?
148
+ !Formeze::Block.evaluate(form, defined_if)
149
+ elsif defined_unless?
150
+ Formeze::Block.evaluate(form, defined_unless)
151
+ else
152
+ false
153
+ end
154
+ end
155
+
156
+ def fill_proc?
157
+ @options.key?(:fill)
158
+ end
159
+
160
+ def fill_proc
161
+ @options[:fill]
162
+ end
145
163
  end
@@ -1,23 +1,53 @@
1
- require 'cgi'
1
+ # frozen_string_literal: true
2
+ require 'rack'
2
3
 
3
4
  module Formeze::FormData
4
- class CGI < ::CGI
5
- def env_table
6
- @options[:request].env
5
+ def self.parse(input)
6
+ if input.is_a?(String)
7
+ query_parser.parse_query(input)
8
+ elsif input.respond_to?(:env)
9
+ body = input.body
10
+ body.rewind if body.respond_to?(:rewind)
11
+ case input.media_type
12
+ when 'multipart/form-data'
13
+ Rack::Multipart.parse_multipart(input.env, Params)
14
+ when 'application/x-www-form-urlencoded'
15
+ query_parser.parse_query(body.read)
16
+ else
17
+ raise ArgumentError, "can't parse #{input.media_type.inspect} form data"
18
+ end
19
+ else
20
+ raise ArgumentError, "can't parse #{input.class} form data"
21
+ end
22
+ end
23
+
24
+ module Params
25
+ def self.make_params
26
+ ParamsHash.new { |h, k| h[k] = Array.new }
7
27
  end
8
28
 
9
- def stdinput
10
- @options[:request].body.tap do |body|
11
- body.rewind if body.respond_to?(:rewind)
29
+ def self.normalize_params(params, key, value)
30
+ if value.is_a?(Hash)
31
+ value = Rack::Multipart::UploadedFile.new(io: value[:tempfile], filename: value[:filename], content_type: value[:type])
12
32
  end
33
+
34
+ params[key] << value
13
35
  end
14
36
  end
15
37
 
16
- def self.parse(input)
17
- if input.is_a?(String)
18
- CGI.parse(input)
19
- else
20
- CGI.new(request: input).params
38
+ class ParamsHash < ::Hash
39
+ alias_method :to_params_hash, :to_h
40
+ end
41
+
42
+ class QueryParser < Rack::QueryParser
43
+ def make_params
44
+ Hash.new { |h, k| h[k] = Array.new }
21
45
  end
22
46
  end
47
+
48
+ def self.query_parser
49
+ @query_parser ||= QueryParser.new(nil, 0)
50
+ end
51
+
52
+ private_class_method :query_parser
23
53
  end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  class Formeze::Validation
4
2
  include Formeze::Presence
5
3
 
@@ -14,7 +12,7 @@ class Formeze::Validation
14
12
  end
15
13
 
16
14
  def validates?(form)
17
- @precondition ? Formeze::Condition.evaluate(form, @precondition) : true
15
+ @precondition ? Formeze::Block.evaluate(form, @precondition) : true
18
16
  end
19
17
 
20
18
  def field_value?(form)
@@ -33,7 +31,7 @@ class Formeze::Validation
33
31
  form.instance_eval(&@block)
34
32
  end
35
33
 
36
- form.add_error(@field, @error, 'is invalid') unless return_value
34
+ form.add_error(@field, @error) unless return_value
37
35
  end
38
36
  end
39
37
  end
data/lib/formeze.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Formeze
4
- autoload :Condition, 'formeze/condition'
4
+ autoload :Block, 'formeze/block'
5
5
  autoload :Errors, 'formeze/errors'
6
6
  autoload :Field, 'formeze/field'
7
7
  autoload :Form, 'formeze/form'
@@ -36,16 +36,24 @@ module Formeze
36
36
 
37
37
  class ValueError < StandardError; end
38
38
 
39
- class ValidationError < StandardError; end
39
+ class ValidationError < StandardError
40
+ def initialize(field, message)
41
+ @field = field
40
42
 
41
- RAILS_FORM_KEYS = %w[utf8 authenticity_token commit]
43
+ super("#{field.label} #{message}")
44
+ end
42
45
 
43
- private_constant :RAILS_FORM_KEYS
46
+ def field_name
47
+ @field.name
48
+ end
49
+ end
44
50
 
45
51
  module InstanceMethods
46
52
  def fill(object)
47
53
  self.class.fields.each_value do |field|
48
- if Hash === object && object.key?(field.name)
54
+ if field.fill_proc?
55
+ send(:"#{field.name}=", Formeze::Block.evaluate(object, field.fill_proc))
56
+ elsif Hash === object && object.key?(field.name)
49
57
  send(:"#{field.name}=", object[field.name])
50
58
  elsif object.respond_to?(field.name)
51
59
  send(:"#{field.name}=", object.send(field.name))
@@ -59,27 +67,29 @@ module Formeze
59
67
  form_data = FormData.parse(input)
60
68
 
61
69
  self.class.fields.each_value do |field|
62
- next unless field_defined?(field)
70
+ next if field.undefined?(self)
63
71
 
64
72
  unless form_data.key?(field.key)
65
73
  next if field.multiple? || !field.key_required?
66
74
 
67
- raise KeyError, "missing form key: #{field.key}"
75
+ raise KeyError, "missing form key: #{field.key}" unless field.accept?
68
76
  end
69
77
 
70
78
  values = form_data.delete(field.key)
71
79
 
72
- if values.length > 1
73
- raise ValueError unless field.multiple?
74
- end
80
+ if values.is_a?(Array)
81
+ if values.length > 1
82
+ raise ValueError, "multiple values for #{field.key} field" unless field.multiple?
83
+ end
75
84
 
76
- field.validate_all(values, self)
85
+ field.validate_all(values, self)
86
+ else
87
+ field.validate(values, self)
88
+ end
77
89
  end
78
90
 
79
- if defined?(Rails)
80
- RAILS_FORM_KEYS.each do |key|
81
- form_data.delete(key)
82
- end
91
+ Formeze.exclude.each do |key|
92
+ form_data.delete(key)
83
93
  end
84
94
 
85
95
  unless form_data.empty?
@@ -93,14 +103,10 @@ module Formeze
93
103
  return self
94
104
  end
95
105
 
96
- def add_error(field, message, default = nil)
97
- message = Formeze::Errors.translate(message, default) unless default.nil?
98
-
99
- error = ValidationError.new("#{field.label} #{message}")
106
+ def add_error(field, error)
107
+ message = Formeze::Errors.translate(error, scope: "#{self.class.name}.errors.#{field.name}")
100
108
 
101
- errors << error
102
-
103
- field_errors[field.name] << error
109
+ errors << ValidationError.new(field, message)
104
110
  end
105
111
 
106
112
  def valid?
@@ -116,11 +122,11 @@ module Formeze
116
122
  end
117
123
 
118
124
  def errors_on?(field_name)
119
- field_errors[field_name].size > 0
125
+ errors.any? { |error| error.field_name == field_name }
120
126
  end
121
127
 
122
128
  def errors_on(field_name)
123
- field_errors[field_name]
129
+ errors.select { |error| error.field_name == field_name }
124
130
  end
125
131
 
126
132
  def to_h
@@ -130,22 +136,16 @@ module Formeze
130
136
  end
131
137
 
132
138
  alias_method :to_hash, :to_h
139
+ end
133
140
 
134
- private
135
-
136
- def field_defined?(field)
137
- if field.defined_if?
138
- Formeze::Condition.evaluate(self, field.defined_if)
139
- elsif field.defined_unless?
140
- !Formeze::Condition.evaluate(self, field.defined_unless)
141
- else
142
- true
143
- end
144
- end
141
+ class << self
142
+ attr_accessor :exclude
143
+ end
145
144
 
146
- def field_errors
147
- @field_errors ||= Hash.new { |h, k| h[k] = [] }
148
- end
145
+ if defined?(Rails)
146
+ self.exclude = %w[_method authenticity_token commit utf8]
147
+ else
148
+ self.exclude = %w[_method _csrf]
149
149
  end
150
150
 
151
151
  def self.label(field_name)
@@ -154,11 +154,11 @@ module Formeze
154
154
 
155
155
  def self.scrub_methods
156
156
  @scrub_methods ||= {
157
- :strip => :strip.to_proc,
158
- :upcase => :upcase.to_proc,
159
- :downcase => :downcase.to_proc,
160
- :squeeze => proc { |string| string.squeeze(' ') },
161
- :squeeze_lines => proc { |string| string.gsub(/(\r?\n)(\r?\n)(\r?\n)+/, '\\1\\2') }
157
+ strip: :strip.to_proc,
158
+ upcase: :upcase.to_proc,
159
+ downcase: :downcase.to_proc,
160
+ squeeze: proc { |string| string.squeeze(' ') },
161
+ squeeze_lines: proc { |string| string.gsub(/(\r?\n)(\r?\n)(\r?\n)+/, '\\1\\2') }
162
162
  }
163
163
  end
164
164
 
metadata CHANGED
@@ -1,32 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: formeze
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.3.0
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Craft
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-04-05 00:00:00.000000000 Z
10
+ date: 2025-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: cgi
13
+ name: rack
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
- - - ">="
16
+ - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '0'
18
+ version: '3'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
- - - ">="
23
+ - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '0'
27
- description: Ruby gem for validating form data
25
+ version: '3'
26
+ description: Ruby gem for parsing and validating form data
28
27
  email:
29
- - mail@timcraft.com
28
+ - email@timcraft.com
30
29
  executables: []
31
30
  extensions: []
32
31
  extra_rdoc_files: []
@@ -36,7 +35,7 @@ files:
36
35
  - README.md
37
36
  - formeze.gemspec
38
37
  - lib/formeze.rb
39
- - lib/formeze/condition.rb
38
+ - lib/formeze/block.rb
40
39
  - lib/formeze/errors.rb
41
40
  - lib/formeze/field.rb
42
41
  - lib/formeze/form.rb
@@ -52,7 +51,6 @@ metadata:
52
51
  source_code_uri: https://github.com/readysteady/formeze
53
52
  bug_tracker_uri: https://github.com/readysteady/formeze/issues
54
53
  changelog_uri: https://github.com/readysteady/formeze/blob/main/CHANGES.md
55
- post_install_message:
56
54
  rdoc_options: []
57
55
  require_paths:
58
56
  - lib
@@ -60,15 +58,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
60
58
  requirements:
61
59
  - - ">="
62
60
  - !ruby/object:Gem::Version
63
- version: 2.4.0
61
+ version: 3.0.0
64
62
  required_rubygems_version: !ruby/object:Gem::Requirement
65
63
  requirements:
66
64
  - - ">="
67
65
  - !ruby/object:Gem::Version
68
66
  version: '0'
69
67
  requirements: []
70
- rubygems_version: 3.5.3
71
- signing_key:
68
+ rubygems_version: 3.6.2
72
69
  specification_version: 4
73
70
  summary: See description
74
71
  test_files: []