forest_admin_datasource_customizer 1.24.1 → 2.0.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.
Potentially problematic release.
This version of forest_admin_datasource_customizer might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/forest_admin_datasource_customizer.gemspec +0 -3
- data/lib/forest_admin_datasource_customizer/composite_datasource.rb +4 -5
- data/lib/forest_admin_datasource_customizer/datasource_customizer.rb +1 -1
- data/lib/forest_admin_datasource_customizer/decorators/action/context/action_context.rb +0 -1
- data/lib/forest_admin_datasource_customizer/decorators/computed/utils/flattener.rb +2 -8
- data/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb +17 -23
- data/lib/forest_admin_datasource_customizer/decorators/rename_collection/rename_collection_datasource_decorator.rb +14 -0
- data/lib/forest_admin_datasource_customizer/decorators/rename_collection/rename_collection_decorator.rb +10 -157
- data/lib/forest_admin_datasource_customizer/dsl/builders/form_builder.rb +2 -3
- data/lib/forest_admin_datasource_customizer/version.rb +1 -1
- metadata +2 -44
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 99861571fab21e188babeeae7244a3106510e8aee39a9bc3713d30f262df97d2
|
|
4
|
+
data.tar.gz: 6af3a7eb53f5d7b79aae3bd87c5f8925c9be6d259bb8f67c6b7a4d43e54f528a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 300ac4146409e2cb043abf8d40b60c67190a16c18e250c7878a8bcdcf5290d57c175389f91f57f431422c0947b1941f5c7d67750a02326f447712369f9d7326f
|
|
7
|
+
data.tar.gz: ea5cc31eb428bce00bdcd0826919fb50d4372afde061438a800332d8cd3ed8ed3930e0a432599c84e3ef9b9a4c2a97f92b879350e1866a9b5523d0a0936e5adb
|
|
@@ -35,11 +35,8 @@ admin work on any Ruby application."
|
|
|
35
35
|
|
|
36
36
|
spec.add_dependency "activesupport", ">= 6.1"
|
|
37
37
|
spec.add_dependency "base64"
|
|
38
|
-
spec.add_dependency "benchmark"
|
|
39
38
|
spec.add_dependency "bigdecimal"
|
|
40
|
-
spec.add_dependency "cgi"
|
|
41
39
|
spec.add_dependency "csv"
|
|
42
|
-
spec.add_dependency "logger"
|
|
43
40
|
spec.add_dependency 'marcel', '~> 1.0', '>= 1.0.4'
|
|
44
41
|
spec.add_dependency "mutex_m"
|
|
45
42
|
spec.add_dependency "ostruct"
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
module ForestAdminDatasourceCustomizer
|
|
2
2
|
class CompositeDatasource
|
|
3
|
-
attr_reader :datasources
|
|
4
|
-
|
|
5
3
|
def initialize
|
|
6
4
|
@datasources = []
|
|
7
5
|
end
|
|
@@ -54,9 +52,10 @@ module ForestAdminDatasourceCustomizer
|
|
|
54
52
|
end
|
|
55
53
|
|
|
56
54
|
def add_data_source(datasource)
|
|
57
|
-
existing_names = collections.
|
|
58
|
-
datasource.collections.
|
|
59
|
-
|
|
55
|
+
existing_names = collections.map { |c| c.respond_to?(:name) ? c.name : c.to_s }
|
|
56
|
+
datasource.collections.each do |c|
|
|
57
|
+
new_name = c.respond_to?(:name) ? c.name : c.to_s
|
|
58
|
+
raise ArgumentError, "Collection '#{new_name}' already exists" if existing_names.include?(new_name)
|
|
60
59
|
end
|
|
61
60
|
|
|
62
61
|
existing_charts = schema[:charts]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module ForestAdminDatasourceCustomizer
|
|
2
2
|
class DatasourceCustomizer
|
|
3
3
|
include DSL::DatasourceHelpers
|
|
4
|
-
attr_reader :stack, :
|
|
4
|
+
attr_reader :stack, :datasources
|
|
5
5
|
|
|
6
6
|
def initialize(_db_config = {})
|
|
7
7
|
@composite_datasource = ForestAdminDatasourceCustomizer::CompositeDatasource.new
|
|
@@ -17,22 +17,16 @@ module ForestAdminDatasourceCustomizer
|
|
|
17
17
|
|
|
18
18
|
MARKER_NAME = '__null_marker'.freeze
|
|
19
19
|
def self.with_null_marker(projection)
|
|
20
|
-
seen = Set.new(projection)
|
|
21
20
|
new_projection = Projection.new(projection)
|
|
22
|
-
|
|
23
21
|
projection.each do |path|
|
|
24
22
|
parts = path.split(':')
|
|
25
23
|
|
|
26
24
|
parts.slice(1, parts.size).each_with_index do |_item, index|
|
|
27
|
-
|
|
28
|
-
next if seen.include?(marker)
|
|
29
|
-
|
|
30
|
-
seen << marker
|
|
31
|
-
new_projection << marker
|
|
25
|
+
new_projection << "#{parts.slice(0, index + 1).join(":")}:#{MARKER_NAME}"
|
|
32
26
|
end
|
|
33
27
|
end
|
|
34
28
|
|
|
35
|
-
new_projection
|
|
29
|
+
new_projection.uniq
|
|
36
30
|
end
|
|
37
31
|
|
|
38
32
|
def self.flatten(records, projection)
|
data/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb
CHANGED
|
@@ -240,36 +240,30 @@ module ForestAdminDatasourceCustomizer
|
|
|
240
240
|
|
|
241
241
|
def re_project_relation_in_place(caller, records, name, projection)
|
|
242
242
|
field_schema = schema[:fields][name]
|
|
243
|
+
|
|
243
244
|
return if field_schema.type == 'PolymorphicManyToOne'
|
|
244
245
|
|
|
246
|
+
association = datasource.get_collection(field_schema.foreign_collection)
|
|
247
|
+
|
|
245
248
|
if !@relations[name]
|
|
246
|
-
association = datasource.get_collection(field_schema.foreign_collection)
|
|
247
249
|
association.re_project_in_place(caller, records.filter_map { |r| r[name] }, projection)
|
|
248
250
|
elsif field_schema.type == 'ManyToOne'
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
end
|
|
253
|
-
end
|
|
251
|
+
ids = records.filter_map { |record| record[field_schema.foreign_key] }.uniq
|
|
252
|
+
sub_filter = Filter.new(condition_tree: ConditionTreeLeaf.new(field_schema.foreign_key_target, 'In', ids))
|
|
253
|
+
sub_records = association.list(caller, sub_filter, projection.union([field_schema.foreign_key_target]))
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
records.each { |record| record[name] = sub_records_by_key[record[field_schema.foreign_key]] }
|
|
263
|
-
end
|
|
264
|
-
|
|
265
|
-
def assign_to_one_or_many_records(caller, records, name, field_schema, projection)
|
|
266
|
-
association = datasource.get_collection(field_schema.foreign_collection)
|
|
267
|
-
ids = records.each_with_object(Set.new) { |record, set| set << record[field_schema.origin_key_target] }.delete(nil).to_a
|
|
268
|
-
sub_filter = Filter.new(condition_tree: ConditionTreeLeaf.new(field_schema.origin_key, 'In', ids))
|
|
269
|
-
sub_records = association.list(caller, sub_filter, projection.union([field_schema.origin_key]))
|
|
270
|
-
sub_records_by_key = sub_records.to_h { |sr| [sr[field_schema.origin_key], sr] }
|
|
255
|
+
records.each do |record|
|
|
256
|
+
record[name] = sub_records.find { |sr| sr[field_schema.foreign_key_target] == record[field_schema.foreign_key] }
|
|
257
|
+
end
|
|
258
|
+
elsif ['OneToOne', 'OneToMany'].include?(field_schema.type)
|
|
259
|
+
ids = records.filter_map { |record| record[field_schema.origin_key_target] }.uniq
|
|
260
|
+
sub_filter = Filter.new(condition_tree: ConditionTreeLeaf.new(field_schema.origin_key, 'In', ids))
|
|
261
|
+
sub_records = association.list(caller, sub_filter, projection.union([field_schema.origin_key]))
|
|
271
262
|
|
|
272
|
-
|
|
263
|
+
records.each do |record|
|
|
264
|
+
record[name] = sub_records.find { |sr| sr[field_schema.origin_key] == record[field_schema.origin_key_target] }
|
|
265
|
+
end
|
|
266
|
+
end
|
|
273
267
|
end
|
|
274
268
|
end
|
|
275
269
|
end
|
|
@@ -47,6 +47,9 @@ module ForestAdminDatasourceCustomizer
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def rename_collection(current_name, new_name)
|
|
50
|
+
# Check collection exists
|
|
51
|
+
collection = get_collection(current_name)
|
|
52
|
+
|
|
50
53
|
return unless current_name != new_name
|
|
51
54
|
|
|
52
55
|
# Check new name is not already used
|
|
@@ -61,6 +64,17 @@ module ForestAdminDatasourceCustomizer
|
|
|
61
64
|
"Cannot rename a collection twice: #{@to_child_name[current_name]}->#{current_name}->#{new_name}"
|
|
62
65
|
end
|
|
63
66
|
|
|
67
|
+
polymorphic_relations = %w[PolymorphicOneToOne PolymorphicOneToMany]
|
|
68
|
+
collection.schema[:fields].each do |field_name, field_schema|
|
|
69
|
+
next unless polymorphic_relations.include?(field_schema.type)
|
|
70
|
+
|
|
71
|
+
reverse_relation_name = Utils::Collection.get_inverse_relation(get_collection(current_name), field_name)
|
|
72
|
+
|
|
73
|
+
raise Exceptions::ForestException,
|
|
74
|
+
"Cannot rename collection #{current_name} because it's a target of a polymorphic relation " \
|
|
75
|
+
"'#{field_schema.foreign_collection}.#{reverse_relation_name}'"
|
|
76
|
+
end
|
|
77
|
+
|
|
64
78
|
@from_child_name[current_name] = new_name
|
|
65
79
|
@to_child_name[new_name] = current_name
|
|
66
80
|
|
|
@@ -9,46 +9,21 @@ module ForestAdminDatasourceCustomizer
|
|
|
9
9
|
datasource.get_collection_name(super)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def
|
|
13
|
-
|
|
14
|
-
records = @child_collection.list(caller, refined_filter, projection)
|
|
15
|
-
|
|
16
|
-
transform_records_polymorphic_values(records)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def create(caller, data)
|
|
20
|
-
transformed_data = transform_data_polymorphic_values(data)
|
|
21
|
-
result = @child_collection.create(caller, transformed_data)
|
|
22
|
-
|
|
23
|
-
transform_record_polymorphic_values(result)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def update(caller, filter, patch)
|
|
27
|
-
refined_filter = refine_filter(caller, filter)
|
|
28
|
-
transformed_patch = transform_data_polymorphic_values(patch)
|
|
29
|
-
|
|
30
|
-
@child_collection.update(caller, refined_filter, transformed_patch)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def refine_filter(_caller, filter)
|
|
34
|
-
return filter unless filter&.condition_tree
|
|
35
|
-
|
|
36
|
-
type_fields = polymorphic_type_fields
|
|
12
|
+
def refine_schema(sub_schema)
|
|
13
|
+
fields = {}
|
|
37
14
|
|
|
38
|
-
|
|
39
|
-
if
|
|
40
|
-
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
else
|
|
44
|
-
leaf.override(value: transformed_value)
|
|
15
|
+
sub_schema[:fields].each do |name, old_schema|
|
|
16
|
+
if old_schema.type != 'Column' && old_schema.type != 'PolymorphicManyToOne'
|
|
17
|
+
old_schema.foreign_collection = datasource.get_collection_name(old_schema.foreign_collection)
|
|
18
|
+
if old_schema.type == 'ManyToMany'
|
|
19
|
+
old_schema.through_collection = datasource.get_collection_name(old_schema.through_collection)
|
|
45
20
|
end
|
|
46
|
-
else
|
|
47
|
-
leaf
|
|
48
21
|
end
|
|
22
|
+
|
|
23
|
+
fields[name] = old_schema
|
|
49
24
|
end
|
|
50
25
|
|
|
51
|
-
|
|
26
|
+
sub_schema
|
|
52
27
|
end
|
|
53
28
|
|
|
54
29
|
# rubocop:disable Lint/UselessMethodDefinition
|
|
@@ -56,128 +31,6 @@ module ForestAdminDatasourceCustomizer
|
|
|
56
31
|
super
|
|
57
32
|
end
|
|
58
33
|
# rubocop:enable Lint/UselessMethodDefinition
|
|
59
|
-
|
|
60
|
-
private
|
|
61
|
-
|
|
62
|
-
def polymorphic_type_fields
|
|
63
|
-
type_fields = []
|
|
64
|
-
child_schema = @child_collection.schema
|
|
65
|
-
return type_fields unless child_schema && child_schema[:fields]
|
|
66
|
-
|
|
67
|
-
child_schema[:fields].each_value do |field_schema|
|
|
68
|
-
case field_schema.type
|
|
69
|
-
when 'PolymorphicManyToOne'
|
|
70
|
-
type_fields << field_schema.foreign_key_type_field
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
type_fields
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def transform_data_polymorphic_values(data)
|
|
77
|
-
return data unless data
|
|
78
|
-
|
|
79
|
-
type_fields = polymorphic_type_fields
|
|
80
|
-
transformed_data = data.dup
|
|
81
|
-
|
|
82
|
-
type_fields.each do |type_field|
|
|
83
|
-
next unless transformed_data.key?(type_field)
|
|
84
|
-
|
|
85
|
-
original_value = transformed_data[type_field]
|
|
86
|
-
transformed_value = reverse_collection_name(original_value)
|
|
87
|
-
transformed_data[type_field] = transformed_value if transformed_value != original_value
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
transformed_data
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def transform_polymorphic_value(value)
|
|
94
|
-
return value unless value
|
|
95
|
-
|
|
96
|
-
# Handle both single values and arrays (for IN/NOT_IN operators)
|
|
97
|
-
if value.is_a?(Array)
|
|
98
|
-
value.map { |v| reverse_collection_name(v) }
|
|
99
|
-
else
|
|
100
|
-
reverse_collection_name(value)
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
# convert new collection name back to old name for db queries
|
|
105
|
-
def reverse_collection_name(collection_name)
|
|
106
|
-
to_child_name = datasource.instance_variable_get(:@to_child_name)
|
|
107
|
-
to_child_name[collection_name] || collection_name
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
# convert old collection name to new name for returned data
|
|
111
|
-
def forward_collection_name(collection_name)
|
|
112
|
-
from_child_name = datasource.instance_variable_get(:@from_child_name)
|
|
113
|
-
from_child_name[collection_name] || collection_name
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def transform_records_polymorphic_values(records)
|
|
117
|
-
return records unless records.is_a?(Array)
|
|
118
|
-
|
|
119
|
-
type_fields = polymorphic_type_fields
|
|
120
|
-
return records if type_fields.empty?
|
|
121
|
-
|
|
122
|
-
records.map do |record|
|
|
123
|
-
transform_record_polymorphic_values(record)
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def transform_record_polymorphic_values(record)
|
|
128
|
-
return record unless record.is_a?(Hash)
|
|
129
|
-
|
|
130
|
-
type_fields = polymorphic_type_fields
|
|
131
|
-
return record if type_fields.empty?
|
|
132
|
-
|
|
133
|
-
transformed_record = record.dup
|
|
134
|
-
|
|
135
|
-
type_fields.each do |type_field|
|
|
136
|
-
next unless transformed_record.key?(type_field)
|
|
137
|
-
|
|
138
|
-
old_value = transformed_record[type_field]
|
|
139
|
-
new_value = forward_collection_name(old_value)
|
|
140
|
-
transformed_record[type_field] = new_value if new_value != old_value
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
transformed_record
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
protected
|
|
147
|
-
|
|
148
|
-
def refine_schema(sub_schema)
|
|
149
|
-
current_collection_name = @child_collection.name
|
|
150
|
-
|
|
151
|
-
sub_schema[:fields].each_value do |old_schema|
|
|
152
|
-
case old_schema.type
|
|
153
|
-
when 'PolymorphicOneToOne', 'PolymorphicOneToMany'
|
|
154
|
-
refine_polymorphic_one_schema(old_schema, current_collection_name)
|
|
155
|
-
when 'PolymorphicManyToOne'
|
|
156
|
-
refine_polymorphic_many_schema(old_schema)
|
|
157
|
-
when 'ManyToOne', 'OneToMany', 'OneToOne'
|
|
158
|
-
old_schema.foreign_collection = datasource.get_collection_name(old_schema.foreign_collection)
|
|
159
|
-
when 'ManyToMany'
|
|
160
|
-
old_schema.foreign_collection = datasource.get_collection_name(old_schema.foreign_collection)
|
|
161
|
-
old_schema.through_collection = datasource.get_collection_name(old_schema.through_collection)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
sub_schema
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
def refine_polymorphic_one_schema(schema, current_collection_name)
|
|
169
|
-
if schema.origin_type_value == current_collection_name
|
|
170
|
-
schema.origin_type_value = datasource.get_collection_name(current_collection_name)
|
|
171
|
-
end
|
|
172
|
-
schema.foreign_collection = datasource.get_collection_name(schema.foreign_collection)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def refine_polymorphic_many_schema(schema)
|
|
176
|
-
schema.foreign_collections = schema.foreign_collections.map { |fc| datasource.get_collection_name(fc) }
|
|
177
|
-
schema.foreign_key_targets = schema.foreign_key_targets.transform_keys do |key|
|
|
178
|
-
datasource.get_collection_name(key)
|
|
179
|
-
end
|
|
180
|
-
end
|
|
181
34
|
end
|
|
182
35
|
end
|
|
183
36
|
end
|
|
@@ -20,9 +20,8 @@ module ForestAdminDatasourceCustomizer
|
|
|
20
20
|
# form do
|
|
21
21
|
# field :amount, type: :number, required: true
|
|
22
22
|
# field :reason, type: :string,
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
# if_condition: ->(ctx) { ctx.form_value(:amount).to_i > 500 }
|
|
23
|
+
# required: ->(ctx) { ctx.get_form_value('amount').to_i > 1000 },
|
|
24
|
+
# if_condition: ->(ctx) { ctx.get_form_value('amount').to_i > 500 }
|
|
26
25
|
# end
|
|
27
26
|
class FormBuilder
|
|
28
27
|
attr_reader :fields
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: forest_admin_datasource_customizer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 2.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matthieu
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: exe
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2025-12-11 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activesupport
|
|
@@ -39,20 +39,6 @@ dependencies:
|
|
|
39
39
|
- - ">="
|
|
40
40
|
- !ruby/object:Gem::Version
|
|
41
41
|
version: '0'
|
|
42
|
-
- !ruby/object:Gem::Dependency
|
|
43
|
-
name: benchmark
|
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
|
45
|
-
requirements:
|
|
46
|
-
- - ">="
|
|
47
|
-
- !ruby/object:Gem::Version
|
|
48
|
-
version: '0'
|
|
49
|
-
type: :runtime
|
|
50
|
-
prerelease: false
|
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
-
requirements:
|
|
53
|
-
- - ">="
|
|
54
|
-
- !ruby/object:Gem::Version
|
|
55
|
-
version: '0'
|
|
56
42
|
- !ruby/object:Gem::Dependency
|
|
57
43
|
name: bigdecimal
|
|
58
44
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -67,20 +53,6 @@ dependencies:
|
|
|
67
53
|
- - ">="
|
|
68
54
|
- !ruby/object:Gem::Version
|
|
69
55
|
version: '0'
|
|
70
|
-
- !ruby/object:Gem::Dependency
|
|
71
|
-
name: cgi
|
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
|
73
|
-
requirements:
|
|
74
|
-
- - ">="
|
|
75
|
-
- !ruby/object:Gem::Version
|
|
76
|
-
version: '0'
|
|
77
|
-
type: :runtime
|
|
78
|
-
prerelease: false
|
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
80
|
-
requirements:
|
|
81
|
-
- - ">="
|
|
82
|
-
- !ruby/object:Gem::Version
|
|
83
|
-
version: '0'
|
|
84
56
|
- !ruby/object:Gem::Dependency
|
|
85
57
|
name: csv
|
|
86
58
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -95,20 +67,6 @@ dependencies:
|
|
|
95
67
|
- - ">="
|
|
96
68
|
- !ruby/object:Gem::Version
|
|
97
69
|
version: '0'
|
|
98
|
-
- !ruby/object:Gem::Dependency
|
|
99
|
-
name: logger
|
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
|
101
|
-
requirements:
|
|
102
|
-
- - ">="
|
|
103
|
-
- !ruby/object:Gem::Version
|
|
104
|
-
version: '0'
|
|
105
|
-
type: :runtime
|
|
106
|
-
prerelease: false
|
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
-
requirements:
|
|
109
|
-
- - ">="
|
|
110
|
-
- !ruby/object:Gem::Version
|
|
111
|
-
version: '0'
|
|
112
70
|
- !ruby/object:Gem::Dependency
|
|
113
71
|
name: marcel
|
|
114
72
|
requirement: !ruby/object:Gem::Requirement
|