compony 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/Gemfile.lock +3 -3
- data/README.md +41 -0
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/compony.gemspec +5 -5
- data/doc/ComponentGenerator.html +1 -1
- data/doc/Components.html +1 -1
- data/doc/ComponentsGenerator.html +1 -1
- data/doc/Compony/Component.html +9 -9
- data/doc/Compony/ComponentMixins/Default/Labelling.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/ResourcefulVerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone/StandaloneDsl.html +6 -6
- data/doc/Compony/ComponentMixins/Default/Standalone/VerbDsl.html +1 -1
- data/doc/Compony/ComponentMixins/Default/Standalone.html +1 -1
- data/doc/Compony/ComponentMixins/Default.html +1 -1
- data/doc/Compony/ComponentMixins/Resourceful.html +1 -1
- data/doc/Compony/ComponentMixins.html +1 -1
- data/doc/Compony/Components/Button.html +1 -1
- data/doc/Compony/Components/Destroy.html +1 -1
- data/doc/Compony/Components/Edit.html +18 -18
- data/doc/Compony/Components/Form.html +316 -90
- data/doc/Compony/Components/New.html +18 -18
- data/doc/Compony/Components/WithForm.html +94 -19
- data/doc/Compony/Components.html +1 -1
- data/doc/Compony/ControllerMixin.html +1 -1
- data/doc/Compony/Engine.html +1 -1
- data/doc/Compony/MethodAccessibleHash.html +1 -1
- data/doc/Compony/ModelFields/Anchormodel.html +1 -1
- data/doc/Compony/ModelFields/Association.html +1 -1
- data/doc/Compony/ModelFields/Attachment.html +1 -1
- data/doc/Compony/ModelFields/Base.html +1 -1
- data/doc/Compony/ModelFields/Boolean.html +1 -1
- data/doc/Compony/ModelFields/Color.html +1 -1
- data/doc/Compony/ModelFields/Currency.html +1 -1
- data/doc/Compony/ModelFields/Date.html +1 -1
- data/doc/Compony/ModelFields/Datetime.html +1 -1
- data/doc/Compony/ModelFields/Decimal.html +1 -1
- data/doc/Compony/ModelFields/Email.html +1 -1
- data/doc/Compony/ModelFields/Float.html +1 -1
- data/doc/Compony/ModelFields/Integer.html +1 -1
- data/doc/Compony/ModelFields/Percentage.html +1 -1
- data/doc/Compony/ModelFields/Phone.html +1 -1
- data/doc/Compony/ModelFields/RichText.html +1 -1
- data/doc/Compony/ModelFields/String.html +1 -1
- data/doc/Compony/ModelFields/Text.html +1 -1
- data/doc/Compony/ModelFields/Time.html +1 -1
- data/doc/Compony/ModelFields/Url.html +1 -1
- data/doc/Compony/ModelFields.html +1 -1
- data/doc/Compony/ModelMixin.html +26 -26
- data/doc/Compony/NaturalOrdering.html +1 -1
- data/doc/Compony/RequestContext.html +1 -1
- data/doc/Compony/Version.html +1 -1
- data/doc/Compony/ViewHelpers.html +1 -1
- data/doc/Compony.html +2 -2
- data/doc/ComponyController.html +1 -1
- data/doc/_index.html +1 -1
- data/doc/file.README.html +42 -1
- data/doc/index.html +42 -1
- data/doc/method_list.html +122 -98
- data/doc/top-level-namespace.html +1 -1
- data/lib/compony/component.rb +4 -4
- data/lib/compony/component_mixins/default/standalone/standalone_dsl.rb +3 -3
- data/lib/compony/components/edit.rb +4 -1
- data/lib/compony/components/form.rb +74 -9
- data/lib/compony/components/new.rb +4 -1
- data/lib/compony/components/with_form.rb +12 -1
- data/lib/compony/model_mixin.rb +8 -1
- data/lib/compony.rb +1 -1
- metadata +5 -5
@@ -102,7 +102,7 @@
|
|
102
102
|
</div>
|
103
103
|
|
104
104
|
<div id="footer">
|
105
|
-
Generated on
|
105
|
+
Generated on Tue Jun 11 11:15:53 2024 by
|
106
106
|
<a href="https://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
107
107
|
0.9.36 (ruby-3.2.2).
|
108
108
|
</div>
|
data/lib/compony/component.rb
CHANGED
@@ -118,9 +118,9 @@ module Compony
|
|
118
118
|
# @param [Symbol,String] name The name of the before_render block, defaults to `:main`
|
119
119
|
# @param [nil,Symbol,String] before If nil, the block will be added to the bottom of the before_render chain. Otherwise, pass the name of another block.
|
120
120
|
# @param [Proc] block The block that should be run as part of the before_render pipeline. Will run in the component's context.
|
121
|
-
def before_render(name = :main, before: nil,
|
121
|
+
def before_render(name = :main, before: nil, **, &block)
|
122
122
|
fail("`before_render` expects a block in #{inspect}.") unless block_given?
|
123
|
-
@before_render_blocks.natural_push(name, block, before:, **
|
123
|
+
@before_render_blocks.natural_push(name, block, before:, **)
|
124
124
|
end
|
125
125
|
|
126
126
|
# DSL method
|
@@ -129,12 +129,12 @@ module Compony
|
|
129
129
|
# @param [nil,Symbol,String] before If nil, the block will be added to the bottom of the content chain. Otherwise, pass the name of another block.
|
130
130
|
# @param [Hash] kwargs If hidden is true, the content will not be rendered by default, allowing you to nest it in another content block.
|
131
131
|
# @param [Proc] block The block that should be run as part of the content pipeline. Will run in the component's context. You can use Dyny here.
|
132
|
-
def content(name = :main, before: nil,
|
132
|
+
def content(name = :main, before: nil, **, &block)
|
133
133
|
# A block is required here, but if this is an override (e.g. to hide another content block), we can tolerate the missing block.
|
134
134
|
if !block_given? && @content_blocks.find { |b| b.name == name }.nil?
|
135
135
|
fail("`content` expects a block in #{inspect}.")
|
136
136
|
end
|
137
|
-
@content_blocks.natural_push(name, block || :missing, before:, **
|
137
|
+
@content_blocks.natural_push(name, block || :missing, before:, **)
|
138
138
|
end
|
139
139
|
|
140
140
|
# DSL method
|
@@ -37,18 +37,18 @@ module Compony
|
|
37
37
|
# DSL call for defining a config for a verb. The block runs within the verb DSL, positional and named arguments are passed to the verb DSL.
|
38
38
|
# @param verb [Symbol] The HTTP verb the config is for (e.g. :get, :post etc.)
|
39
39
|
# @see Compony::ComponentMixins::Default::Standalone::VerbDsl
|
40
|
-
def verb(verb,
|
40
|
+
def verb(verb, *, **nargs, &)
|
41
41
|
verb = verb.to_sym
|
42
42
|
verb_dsl_class = @component.resourceful? ? ResourcefulVerbDsl : VerbDsl
|
43
43
|
if @verbs[verb]
|
44
|
-
@verbs[verb].deep_merge! verb_dsl_class.new(@component, verb,
|
44
|
+
@verbs[verb].deep_merge! verb_dsl_class.new(@component, verb, *, **nargs).to_conf(provide_defaults: false, &)
|
45
45
|
else
|
46
46
|
# Note about provide_defaults:
|
47
47
|
# - We must pass false if this is the second time `standalone` was called for this component -> see @provide_defaults
|
48
48
|
# - We musst pass false if this is the second time `verb` was called for this component -> handled by the if statement (other branch)
|
49
49
|
# - We must pass true otherwise (handled by this branch)
|
50
50
|
@verbs[verb] = Compony::MethodAccessibleHash.new(
|
51
|
-
verb_dsl_class.new(@component, verb,
|
51
|
+
verb_dsl_class.new(@component, verb, *, **nargs).to_conf(provide_defaults: @provide_defaults, &)
|
52
52
|
)
|
53
53
|
end
|
54
54
|
end
|
@@ -30,6 +30,8 @@ module Compony
|
|
30
30
|
label(:short) { |_| I18n.t('compony.components.edit.label.short') }
|
31
31
|
icon { :pencil }
|
32
32
|
|
33
|
+
form_cancancan_action :edit
|
34
|
+
|
33
35
|
action :back_to_owner do
|
34
36
|
next if data_class.owner_model_attr.blank?
|
35
37
|
Compony.button(:show, @data.send(data_class.owner_model_attr), icon: :xmark, color: :secondary, label: I18n.t('compony.cancel'))
|
@@ -47,12 +49,13 @@ module Compony
|
|
47
49
|
# Validate params against the form's schema
|
48
50
|
local_form_comp = form_comp # Capture form_comp for usage in the Schemacop call
|
49
51
|
local_data = @data # Capture data for usage in the Schemacop call
|
52
|
+
local_controller = controller # Capture controller for usage in the Schemacop call
|
50
53
|
schema = Schemacop::Schema3.new :hash, additional_properties: true do
|
51
54
|
any_of! :id do
|
52
55
|
str
|
53
56
|
int cast_str: true
|
54
57
|
end
|
55
|
-
hsh? local_form_comp.schema_wrapper_key_for(local_data), &local_form_comp.schema_block_for(local_data)
|
58
|
+
hsh? local_form_comp.schema_wrapper_key_for(local_data), &local_form_comp.schema_block_for(local_data, local_controller)
|
56
59
|
end
|
57
60
|
validated_params = schema.validate!(controller.request.params)
|
58
61
|
attrs_to_assign = validated_params[form_comp.schema_wrapper_key_for(@data)]
|
@@ -3,8 +3,9 @@ module Compony
|
|
3
3
|
# @api description
|
4
4
|
# This component is used for the _form partial in the Rails paradigm.
|
5
5
|
class Form < Component
|
6
|
-
def initialize(
|
6
|
+
def initialize(*args, cancancan_action: :missing, **kwargs)
|
7
7
|
@schema_lines_for_data = [] # Array of procs taking data returning a Schemacop proc
|
8
|
+
@cancancan_action = cancancan_action
|
8
9
|
super
|
9
10
|
end
|
10
11
|
|
@@ -12,6 +13,9 @@ module Compony
|
|
12
13
|
before_render do
|
13
14
|
# Make sure the error message is going to be nice if form_fields were not implemented
|
14
15
|
fail "#{component.inspect} requires config.form_fields do ..." if @form_fields.nil?
|
16
|
+
if @cancancan_action == :missing
|
17
|
+
fail("Missing cancancan_action for #{component.inspect}, you must provide one (e.g. :edit) or pass nil explicitely.")
|
18
|
+
end
|
15
19
|
|
16
20
|
# Calculate paths
|
17
21
|
@submit_path = @comp_opts[:submit_path]
|
@@ -32,7 +36,7 @@ module Compony
|
|
32
36
|
|
33
37
|
content do
|
34
38
|
form_html = simple_form_for(data, method: @comp_opts[:submit_verb], url: @submit_path) do |f|
|
35
|
-
component.with_simpleform(f) do
|
39
|
+
component.with_simpleform(f, controller) do
|
36
40
|
instance_exec(&form_fields)
|
37
41
|
div class: 'compony-form-buttons' do
|
38
42
|
content(:buttons)
|
@@ -60,7 +64,7 @@ module Compony
|
|
60
64
|
end
|
61
65
|
|
62
66
|
# Attr reader for @schema_block with auto-calculated default
|
63
|
-
def schema_block_for(data)
|
67
|
+
def schema_block_for(data, controller)
|
64
68
|
if @schema_block
|
65
69
|
return @schema_block
|
66
70
|
else
|
@@ -68,7 +72,8 @@ module Compony
|
|
68
72
|
local_schema_lines_for_data = @schema_lines_for_data
|
69
73
|
return proc do
|
70
74
|
local_schema_lines_for_data.each do |schema_line|
|
71
|
-
|
75
|
+
schema_line_proc = schema_line.call(data, controller) # This may return nil, e.g. is the user is not authorized to set a field
|
76
|
+
instance_exec(&schema_line_proc) unless schema_line_proc.nil?
|
72
77
|
end
|
73
78
|
end
|
74
79
|
end
|
@@ -78,21 +83,32 @@ module Compony
|
|
78
83
|
# methods from inside `form_fields`. This is a workaround required because the form does not exist when the
|
79
84
|
# RequestContext is being built, and we want the method `field` to be available inside the `form_fields` block.
|
80
85
|
# @todo Refactor? Could this be greatly simplified by having `form_field to |f|` ?
|
81
|
-
def with_simpleform(simpleform)
|
86
|
+
def with_simpleform(simpleform, controller)
|
82
87
|
@simpleform = simpleform
|
88
|
+
@controller = controller
|
83
89
|
@focus_given = false
|
84
90
|
yield
|
85
91
|
@simpleform = nil
|
92
|
+
@controller = nil
|
86
93
|
end
|
87
94
|
|
88
95
|
# Called inside the form_fields block. This makes the method `field` available in the block.
|
89
96
|
# See also notes for `with_simpleform`.
|
90
97
|
def field(name, **input_opts)
|
91
98
|
fail("The `field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
|
99
|
+
name = name.to_sym
|
100
|
+
|
101
|
+
# Check per-field authorization
|
102
|
+
if @cancancan_action.present? && @controller.current_ability.permitted_attributes(@cancancan_action, @simpleform.object).exclude?(name)
|
103
|
+
Rails.logger.debug do
|
104
|
+
"Skipping form field #{name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{@simpleform.object}."
|
105
|
+
end
|
106
|
+
return
|
107
|
+
end
|
92
108
|
|
93
109
|
hidden = input_opts.delete(:hidden)
|
94
|
-
model_field = @simpleform.object.fields[name
|
95
|
-
fail("Field #{name.
|
110
|
+
model_field = @simpleform.object.fields[name]
|
111
|
+
fail("Field #{name.inspect} is not defined on #{@simpleform.object.inspect} but was requested in #{inspect}.") unless model_field
|
96
112
|
|
97
113
|
if hidden
|
98
114
|
return model_field.simpleform_input_hidden(@simpleform, self, **input_opts)
|
@@ -105,6 +121,28 @@ module Compony
|
|
105
121
|
end
|
106
122
|
end
|
107
123
|
|
124
|
+
# Called inside the form_fields block. This makes the method pw_field available in the block.
|
125
|
+
# This method should be called for the fields :password and :password_confirmation
|
126
|
+
# Note that :hidden is not supported here, as this would make no sense in conjunction with :password or :password_confirmation.
|
127
|
+
def pw_field(name, **input_opts)
|
128
|
+
fail("The `pw_field` method may only be called inside `form_fields` for #{inspect}.") unless @simpleform
|
129
|
+
name = name.to_sym
|
130
|
+
|
131
|
+
# Check for authorization
|
132
|
+
unless @cancancan_action.nil? || @controller.current_ability.can?(:set_password, @simpleform.object)
|
133
|
+
Rails.logger.debug do
|
134
|
+
"Skipping form pw_field #{name.inspect} because the current user is not allowed to perform :set_password on #{@simpleform.object}."
|
135
|
+
end
|
136
|
+
return
|
137
|
+
end
|
138
|
+
|
139
|
+
unless @focus_given || @skip_autofocus
|
140
|
+
input_opts[:autofocus] = true unless input_opts.key? :autofocus
|
141
|
+
@focus_given = true
|
142
|
+
end
|
143
|
+
return @simpleform.input name, **input_opts
|
144
|
+
end
|
145
|
+
|
108
146
|
# Called inside the form_fields block. This makes the method `f` available in the block.
|
109
147
|
# See also notes for `with_simpleform`.
|
110
148
|
def f
|
@@ -120,19 +158,46 @@ module Compony
|
|
120
158
|
protected
|
121
159
|
|
122
160
|
# DSL method, adds a new line to the schema whitelisting a single param inside the schema's wrapper
|
161
|
+
# The block should be something like `str? :foo` and will run in a Schemacop3 context.
|
123
162
|
def schema_line(&block)
|
124
|
-
@schema_lines_for_data << proc { block }
|
163
|
+
@schema_lines_for_data << proc { |_data, _controller| block }
|
125
164
|
end
|
126
165
|
|
127
166
|
# DSL method, adds a new field to the schema whitelisting a single field of data_class
|
128
167
|
# This auto-generates the correct schema line for the field.
|
129
168
|
def schema_field(field_name)
|
130
|
-
|
169
|
+
# This runs upon component setup.
|
170
|
+
@schema_lines_for_data << proc do |data, controller|
|
171
|
+
# This runs within a request context.
|
131
172
|
field = data.class.fields[field_name.to_sym] || fail("No field #{field_name.to_sym.inspect} found for #{data.inspect} in #{inspect}.")
|
173
|
+
# Check per-field authorization
|
174
|
+
if @cancancan_action.present? && controller.current_ability.permitted_attributes(@cancancan_action.to_sym, data).exclude?(field.name.to_sym)
|
175
|
+
Rails.logger.debug do
|
176
|
+
"Skipping form schema_field #{field_name.inspect} because the current user is not allowed to perform #{@cancancan_action.inspect} on #{data}."
|
177
|
+
end
|
178
|
+
next nil
|
179
|
+
end
|
132
180
|
next field.schema_line
|
133
181
|
end
|
134
182
|
end
|
135
183
|
|
184
|
+
# DSL method, adds a new password field to the schema whitelisting
|
185
|
+
# This checks for the permission :set_password and auto-generates the correct schema line for the field.
|
186
|
+
def schema_pw_field(field_name)
|
187
|
+
# This runs upon component setup.
|
188
|
+
@schema_lines_for_data << proc do |data, controller|
|
189
|
+
# This runs within a request context.
|
190
|
+
# Check per-field authorization
|
191
|
+
unless @cancancan_action.nil? || controller.current_ability.can?(:set_password, data)
|
192
|
+
Rails.logger.debug do
|
193
|
+
"Skipping form schema_pw_field #{name.inspect} because the current user is not allowed to perform :set_password on #{data}."
|
194
|
+
end
|
195
|
+
next nil
|
196
|
+
end
|
197
|
+
next proc { obj? field_name.to_sym }
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
136
201
|
# DSL method, mass-assigns schema fields
|
137
202
|
def schema_fields(*field_names)
|
138
203
|
field_names.each { |field_name| schema_field(field_name) }
|
@@ -32,6 +32,8 @@ module Compony
|
|
32
32
|
label(:short) { I18n.t('compony.components.new.label.short') }
|
33
33
|
icon { :plus }
|
34
34
|
|
35
|
+
form_cancancan_action :new
|
36
|
+
|
35
37
|
content :label do
|
36
38
|
h2 component.label
|
37
39
|
end
|
@@ -43,8 +45,9 @@ module Compony
|
|
43
45
|
assign_attributes do
|
44
46
|
local_form_comp = form_comp # Capture form_comp for usage in the Schemacop call
|
45
47
|
local_data = @data # Capture data for usage in the Schemacop call
|
48
|
+
local_controller = controller # Capture controller for usage in the Schemacop call
|
46
49
|
schema = Schemacop::Schema3.new :hash, additional_properties: true do
|
47
|
-
hsh? local_form_comp.schema_wrapper_key_for(local_data), &local_form_comp.schema_block_for(local_data)
|
50
|
+
hsh? local_form_comp.schema_wrapper_key_for(local_data), &local_form_comp.schema_block_for(local_data, local_controller)
|
48
51
|
end
|
49
52
|
validated_params = schema.validate!(controller.request.params)
|
50
53
|
attrs_to_assign = validated_params[form_comp.schema_wrapper_key_for(@data)]
|
@@ -7,6 +7,7 @@ module Compony
|
|
7
7
|
def initialize(...)
|
8
8
|
# TODO: On the next line, use Compony.path instead? Likely, this was implemented before that method existed.
|
9
9
|
@submit_path_block = ->(controller) { controller.helpers.send("#{Compony.path_helper_name(comp_name, family_name)}_path") }
|
10
|
+
@form_cancancan_action = :missing
|
10
11
|
super
|
11
12
|
end
|
12
13
|
|
@@ -17,7 +18,8 @@ module Compony
|
|
17
18
|
self,
|
18
19
|
submit_verb:,
|
19
20
|
# If applicable, Rails adds the route keys automatically, thus, e.g. :id does not need to be passed here, as it comes from the request.
|
20
|
-
submit_path:
|
21
|
+
submit_path: @submit_path_block,
|
22
|
+
cancancan_action: form_cancancan_action
|
21
23
|
)
|
22
24
|
end
|
23
25
|
|
@@ -39,6 +41,15 @@ module Compony
|
|
39
41
|
@form_comp_class ||= new_form_comp_class
|
40
42
|
end
|
41
43
|
|
44
|
+
# DSL method
|
45
|
+
# Sets and gets the form's cancancan action (for cancancan's accessible_attributes)
|
46
|
+
def form_cancancan_action(new_form_cancancan_action = :missing)
|
47
|
+
if new_form_cancancan_action != :missing
|
48
|
+
@form_cancancan_action = new_form_cancancan_action
|
49
|
+
end
|
50
|
+
return @form_cancancan_action
|
51
|
+
end
|
52
|
+
|
42
53
|
# DSL method
|
43
54
|
# Overrides the submit path which would otherwise default to this component
|
44
55
|
# This takes a block that will be called and given a controller
|
data/lib/compony/model_mixin.rb
CHANGED
@@ -22,7 +22,14 @@ module Compony
|
|
22
22
|
def field(name, type, **extra_attrs)
|
23
23
|
name = name.to_sym
|
24
24
|
self.fields = fields.dup
|
25
|
-
|
25
|
+
field = Compony.model_field_class_for(type.to_s.camelize).new(name, self, **extra_attrs)
|
26
|
+
# Handle the case where ActiveType would interfere with attribute registration
|
27
|
+
if defined?(ActiveType) && self <= ActiveType::Object && !include?(ActiveModel::Attributes)
|
28
|
+
fail "Please add `include ActiveModel::Attributes` at the top of the class #{self}, as attributes cannot be registered otherwise with ActiveType."
|
29
|
+
end
|
30
|
+
# Register the field as an attribute
|
31
|
+
attribute(name)
|
32
|
+
fields[name] = field
|
26
33
|
end
|
27
34
|
|
28
35
|
# DSL method, sets the containing model.
|
data/lib/compony.rb
CHANGED
@@ -237,7 +237,7 @@ module Compony
|
|
237
237
|
end
|
238
238
|
return_value = block.call
|
239
239
|
# Restore previous value
|
240
|
-
keys_to_overwrite.
|
240
|
+
keys_to_overwrite.each_key do |key|
|
241
241
|
RequestStore.store[:button_defaults][key] = old_values[key]
|
242
242
|
end
|
243
243
|
# Undefine keys that were not there previously
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sandro Kalbermatter
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-06-
|
12
|
+
date: 2024-06-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: yard
|
@@ -157,14 +157,14 @@ dependencies:
|
|
157
157
|
requirements:
|
158
158
|
- - "~>"
|
159
159
|
- !ruby/object:Gem::Version
|
160
|
-
version: 3.
|
160
|
+
version: 3.6.1
|
161
161
|
type: :runtime
|
162
162
|
prerelease: false
|
163
163
|
version_requirements: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
165
|
- - "~>"
|
166
166
|
- !ruby/object:Gem::Version
|
167
|
-
version: 3.
|
167
|
+
version: 3.6.1
|
168
168
|
description:
|
169
169
|
email:
|
170
170
|
executables: []
|
@@ -323,7 +323,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
323
323
|
requirements:
|
324
324
|
- - ">="
|
325
325
|
- !ruby/object:Gem::Version
|
326
|
-
version: 3.
|
326
|
+
version: 3.2.2
|
327
327
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
328
328
|
requirements:
|
329
329
|
- - ">="
|