workarea-core 3.4.22 → 3.4.23
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/workarea/data_file/csv.rb +8 -6
- data/app/models/workarea/data_file/json.rb +20 -1
- data/app/models/workarea/insights/customer_acquisition.rb +9 -5
- data/app/models/workarea/insights/trending_products.rb +2 -2
- data/app/models/workarea/insights/trending_searches.rb +2 -2
- data/app/models/workarea/metrics/product_for_last_week.rb +11 -5
- data/app/models/workarea/metrics/search_for_last_week.rb +11 -5
- data/app/models/workarea/metrics/user.rb +1 -1
- data/app/models/workarea/pricing/discount/redemption.rb +1 -0
- data/app/queries/workarea/reports/average_order_value.rb +1 -1
- data/app/queries/workarea/reports/first_time_vs_returning_sales.rb +1 -1
- data/app/queries/workarea/reports/group_by_time.rb +17 -13
- data/app/queries/workarea/reports/sales_by_category.rb +1 -1
- data/app/queries/workarea/reports/sales_by_country.rb +1 -1
- data/app/queries/workarea/reports/sales_by_discount.rb +1 -1
- data/app/queries/workarea/reports/sales_by_menu.rb +1 -1
- data/app/queries/workarea/reports/sales_by_product.rb +1 -1
- data/app/queries/workarea/reports/sales_by_sku.rb +1 -1
- data/app/queries/workarea/reports/sales_by_traffic_referrer.rb +1 -1
- data/app/queries/workarea/reports/sales_over_time.rb +1 -1
- data/app/queries/workarea/reports/searches.rb +1 -1
- data/app/queries/workarea/reports/searches_over_time.rb +1 -1
- data/app/queries/workarea/reports/searches_without_results_over_time.rb +1 -1
- data/lib/workarea/core.rb +4 -1
- data/lib/workarea/version.rb +1 -1
- data/test/models/workarea/data_file/csv_test.rb +48 -0
- data/test/models/workarea/data_file/json_test.rb +40 -0
- data/workarea-core.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 686c73972fed5bca039dfbcc68b316eecdf9bbe668e502cc55628e89da8a3e63
|
4
|
+
data.tar.gz: 337c6251e9d7bd78856667ba6fbf2376c331a94369d80e18b3b72c2c818cc821
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df055b0a4b585593cd340502cda626ee1d8615c8d86cb189120b797b7d0c2b273976f0fe64c7bf16ab491c21a8ed60c7c3d155fe7e7e1d0f46651358cad93bbf
|
7
|
+
data.tar.gz: ca98a2b2e54d16619ff2c5dbe365ba827bd3386b60fd9b9dbe0c21578762c8452d510a81cb98b3ba274b5cbb8cc748c5049e91a2fb1e06ec80c2fcbf59a591f4
|
@@ -48,6 +48,8 @@ module Workarea
|
|
48
48
|
|
49
49
|
def assign_attributes(model, attrs)
|
50
50
|
model.fields.each do |name, metadata|
|
51
|
+
next if name == 'updated_at'
|
52
|
+
|
51
53
|
value = CsvFields.deserialize_from(attrs, field: metadata, model: model)
|
52
54
|
model.send("#{name}=", value) if value.present?
|
53
55
|
end
|
@@ -86,17 +88,17 @@ module Workarea
|
|
86
88
|
]
|
87
89
|
|
88
90
|
if unnamespaced_attrs.values.any?(&:present?)
|
91
|
+
klass = attrs["#{name}_type"].constantize if attrs["#{name}_type"].present?
|
92
|
+
klass ||= root.relations[name].class_name.constantize
|
93
|
+
|
89
94
|
if metadata.many?
|
90
95
|
id = attrs["#{name}_id"]
|
91
|
-
instance =
|
92
|
-
|
93
|
-
else
|
94
|
-
root.send(name).build
|
95
|
-
end
|
96
|
+
instance = root.send(name).find_by(id: id) rescue nil
|
97
|
+
instance ||= root.send(name).build({}, klass)
|
96
98
|
|
97
99
|
assign_attributes(instance, unnamespaced_attrs)
|
98
100
|
else
|
99
|
-
instance = root.send(name) || root.send("build_#{name}")
|
101
|
+
instance = root.send(name) || root.send("build_#{name}", {}, klass)
|
100
102
|
assign_attributes(instance, unnamespaced_attrs)
|
101
103
|
end
|
102
104
|
end
|
@@ -45,12 +45,31 @@ module Workarea
|
|
45
45
|
|
46
46
|
if id.present?
|
47
47
|
result = model_class.find_or_initialize_by(id: id)
|
48
|
-
result.attributes = attributes
|
48
|
+
result.attributes = attributes_without_updated_at(attributes)
|
49
49
|
result
|
50
50
|
else
|
51
51
|
model_class.new(attributes)
|
52
52
|
end
|
53
53
|
end
|
54
|
+
|
55
|
+
def attributes_without_updated_at(attrs)
|
56
|
+
return attrs unless attrs.respond_to?(:each_with_object)
|
57
|
+
|
58
|
+
attrs.each_with_object({}) do |(key, value), attributes|
|
59
|
+
next if key.to_s == 'updated_at'
|
60
|
+
|
61
|
+
attributes[key] = case value
|
62
|
+
when Hash
|
63
|
+
attributes_without_updated_at(value)
|
64
|
+
when Array
|
65
|
+
value.map do |item|
|
66
|
+
attributes_without_updated_at(item)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
54
73
|
end
|
55
74
|
end
|
56
75
|
end
|
@@ -37,8 +37,8 @@ module Workarea
|
|
37
37
|
{
|
38
38
|
'$match' => {
|
39
39
|
'first_order_at' => {
|
40
|
-
'$gte' => beginning_of_last_month,
|
41
|
-
'$lte' => end_of_last_month
|
40
|
+
'$gte' => beginning_of_last_month.utc,
|
41
|
+
'$lte' => end_of_last_month.utc
|
42
42
|
}
|
43
43
|
}
|
44
44
|
}
|
@@ -48,14 +48,18 @@ module Workarea
|
|
48
48
|
{
|
49
49
|
'$group' => {
|
50
50
|
'_id' => {
|
51
|
-
'year' => { '$year' =>
|
52
|
-
'month' => { '$month' =>
|
53
|
-
'day' => { '$dayOfMonth' =>
|
51
|
+
'year' => { '$year' => first_order_at_in_time_zone },
|
52
|
+
'month' => { '$month' => first_order_at_in_time_zone },
|
53
|
+
'day' => { '$dayOfMonth' => first_order_at_in_time_zone }
|
54
54
|
},
|
55
55
|
'new_customers' => { '$sum' => 1 }
|
56
56
|
}
|
57
57
|
}
|
58
58
|
end
|
59
|
+
|
60
|
+
def first_order_at_in_time_zone
|
61
|
+
{ 'date' => '$first_order_at', 'timezone' => Time.zone.tzinfo.name }
|
62
|
+
end
|
59
63
|
end
|
60
64
|
end
|
61
65
|
end
|
@@ -35,8 +35,8 @@ module Workarea
|
|
35
35
|
{
|
36
36
|
'$match' => {
|
37
37
|
'reporting_on' => {
|
38
|
-
'$gte' => Time.current.last_week,
|
39
|
-
'$lte' => Time.current.last_week.end_of_week
|
38
|
+
'$gte' => Time.current.last_week.utc,
|
39
|
+
'$lte' => Time.current.last_week.end_of_week.utc
|
40
40
|
}
|
41
41
|
}
|
42
42
|
}
|
@@ -70,8 +70,8 @@ module Workarea
|
|
70
70
|
'$expr' => {
|
71
71
|
'$and' => [
|
72
72
|
{ '$eq' => ['$product_id', '$$product_id'] },
|
73
|
-
{ '$gte' => ['$reporting_on', Time.current.last_week - 1.week] },
|
74
|
-
{ '$lte' => ['$reporting_on', Time.current.last_week.end_of_week - 1.week] }
|
73
|
+
{ '$gte' => ['$reporting_on', (Time.current.last_week - 1.week).utc] },
|
74
|
+
{ '$lte' => ['$reporting_on', (Time.current.last_week.end_of_week - 1.week).utc] }
|
75
75
|
]
|
76
76
|
}
|
77
77
|
}
|
@@ -144,7 +144,13 @@ module Workarea
|
|
144
144
|
'$addFields' => {
|
145
145
|
'_id' => {
|
146
146
|
'$concat' => [
|
147
|
-
{
|
147
|
+
{
|
148
|
+
'$dateToString' => {
|
149
|
+
'format' => '%Y%m%d',
|
150
|
+
'date' => '$reporting_on',
|
151
|
+
'timezone' => Time.zone.tzinfo.name
|
152
|
+
}
|
153
|
+
},
|
148
154
|
'-',
|
149
155
|
'$product_id'
|
150
156
|
]
|
@@ -36,8 +36,8 @@ module Workarea
|
|
36
36
|
{
|
37
37
|
'$match' => {
|
38
38
|
'reporting_on' => {
|
39
|
-
'$gte' => Time.current.last_week,
|
40
|
-
'$lte' => Time.current.last_week.end_of_week
|
39
|
+
'$gte' => Time.current.last_week.utc,
|
40
|
+
'$lte' => Time.current.last_week.end_of_week.utc
|
41
41
|
}
|
42
42
|
}
|
43
43
|
}
|
@@ -77,8 +77,8 @@ module Workarea
|
|
77
77
|
'$expr' => {
|
78
78
|
'$and' => [
|
79
79
|
{ '$eq' => ['$query_id', '$$query_id'] },
|
80
|
-
{ '$gte' => ['$reporting_on', Time.current.last_week - 1.week] },
|
81
|
-
{ '$lte' => ['$reporting_on', Time.current.last_week.end_of_week - 1.week] }
|
80
|
+
{ '$gte' => ['$reporting_on', (Time.current.last_week - 1.week).utc] },
|
81
|
+
{ '$lte' => ['$reporting_on', (Time.current.last_week.end_of_week - 1.week).utc] }
|
82
82
|
]
|
83
83
|
}
|
84
84
|
}
|
@@ -151,7 +151,13 @@ module Workarea
|
|
151
151
|
'$addFields' => {
|
152
152
|
'_id' => {
|
153
153
|
'$concat' => [
|
154
|
-
{
|
154
|
+
{
|
155
|
+
'$dateToString' => {
|
156
|
+
'format' => '%Y%m%d',
|
157
|
+
'date' => '$reporting_on',
|
158
|
+
'timezone' => Time.zone.tzinfo.name
|
159
|
+
}
|
160
|
+
},
|
155
161
|
'-',
|
156
162
|
'$query_id'
|
157
163
|
]
|
@@ -14,7 +14,7 @@ module Workarea
|
|
14
14
|
def filter_date_range_and_zeroes
|
15
15
|
{
|
16
16
|
'$match' => {
|
17
|
-
'reporting_on' => { '$gte' => starts_at, '$lte' => ends_at },
|
17
|
+
'reporting_on' => { '$gte' => starts_at.utc, '$lte' => ends_at.utc },
|
18
18
|
'orders' => { '$gt' => 0 },
|
19
19
|
'revenue' => { '$gt' => 0 }
|
20
20
|
}
|
@@ -25,46 +25,50 @@ module Workarea
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
+
def reporting_on_in_time_zone
|
29
|
+
{ 'date' => '$reporting_on', 'timezone' => Time.zone.tzinfo.name }
|
30
|
+
end
|
31
|
+
|
28
32
|
def day_id
|
29
33
|
{
|
30
|
-
'year' => { '$year' =>
|
31
|
-
'month' => { '$month' =>
|
32
|
-
'day' => { '$dayOfMonth' =>
|
34
|
+
'year' => { '$year' => reporting_on_in_time_zone },
|
35
|
+
'month' => { '$month' => reporting_on_in_time_zone },
|
36
|
+
'day' => { '$dayOfMonth' => reporting_on_in_time_zone }
|
33
37
|
}
|
34
38
|
end
|
35
39
|
|
36
40
|
def week_id
|
37
41
|
{
|
38
|
-
'year' => { '$year' =>
|
39
|
-
'week' => { '$isoWeek' =>
|
42
|
+
'year' => { '$year' => reporting_on_in_time_zone },
|
43
|
+
'week' => { '$isoWeek' => reporting_on_in_time_zone }
|
40
44
|
}
|
41
45
|
end
|
42
46
|
|
43
47
|
def day_of_week_id
|
44
|
-
{ 'day_of_week' => { '$dayOfWeek' =>
|
48
|
+
{ 'day_of_week' => { '$dayOfWeek' => reporting_on_in_time_zone } }
|
45
49
|
end
|
46
50
|
|
47
51
|
def month_id
|
48
52
|
{
|
49
|
-
'year' => { '$year' =>
|
50
|
-
'month' => { '$month' =>
|
53
|
+
'year' => { '$year' => reporting_on_in_time_zone },
|
54
|
+
'month' => { '$month' => reporting_on_in_time_zone }
|
51
55
|
}
|
52
56
|
end
|
53
57
|
|
54
58
|
def quarter_id
|
55
59
|
{
|
56
|
-
'year' => { '$year' =>
|
60
|
+
'year' => { '$year' => reporting_on_in_time_zone },
|
57
61
|
'quarter' => {
|
58
62
|
'$cond' => [
|
59
|
-
{ '$lte' => [{ '$month' =>
|
63
|
+
{ '$lte' => [{ '$month' => reporting_on_in_time_zone }, 3] },
|
60
64
|
1,
|
61
65
|
{
|
62
66
|
'$cond' => [
|
63
|
-
{ '$lte' => [{ '$month' =>
|
67
|
+
{ '$lte' => [{ '$month' => reporting_on_in_time_zone }, 6] },
|
64
68
|
2,
|
65
69
|
{
|
66
70
|
'$cond' => [
|
67
|
-
{ '$lte' => [{ '$month' =>
|
71
|
+
{ '$lte' => [{ '$month' => reporting_on_in_time_zone }, 9] },
|
68
72
|
3,
|
69
73
|
4
|
70
74
|
]
|
@@ -77,7 +81,7 @@ module Workarea
|
|
77
81
|
end
|
78
82
|
|
79
83
|
def year_id
|
80
|
-
{ 'year' => { '$year' =>
|
84
|
+
{ 'year' => { '$year' => reporting_on_in_time_zone } }
|
81
85
|
end
|
82
86
|
end
|
83
87
|
end
|
@@ -13,7 +13,7 @@ module Workarea
|
|
13
13
|
def filter
|
14
14
|
{
|
15
15
|
'$match' => {
|
16
|
-
'reporting_on' => { '$gte' => starts_at, '$lte' => ends_at },
|
16
|
+
'reporting_on' => { '$gte' => starts_at.utc, '$lte' => ends_at.utc },
|
17
17
|
'$or' => [
|
18
18
|
{ 'orders' => { '$gt' => 0 } },
|
19
19
|
{ 'units_sold' => { '$gt' => 0 } }
|
@@ -13,7 +13,7 @@ module Workarea
|
|
13
13
|
def filter
|
14
14
|
{
|
15
15
|
'$match' => {
|
16
|
-
'reporting_on' => { '$gte' => starts_at, '$lte' => ends_at },
|
16
|
+
'reporting_on' => { '$gte' => starts_at.utc, '$lte' => ends_at.utc },
|
17
17
|
'$or' => [
|
18
18
|
{ 'orders' => { '$gt' => 0 } },
|
19
19
|
{ 'units_sold' => { '$gt' => 0 } }
|
@@ -17,7 +17,7 @@ module Workarea
|
|
17
17
|
def filter
|
18
18
|
result = {
|
19
19
|
'$match' => {
|
20
|
-
'reporting_on' => { '$gte' => starts_at, '$lte' => ends_at },
|
20
|
+
'reporting_on' => { '$gte' => starts_at.utc, '$lte' => ends_at.utc },
|
21
21
|
'$or' => [
|
22
22
|
{ 'orders' => { '$gt' => 0 } },
|
23
23
|
{ 'units_sold' => { '$gt' => 0 } }
|
data/lib/workarea/core.rb
CHANGED
@@ -208,11 +208,14 @@ require 'workarea/string_id'
|
|
208
208
|
require 'workarea/mail_interceptor'
|
209
209
|
|
210
210
|
#
|
211
|
-
#
|
211
|
+
# Engines
|
212
212
|
#
|
213
213
|
#
|
214
214
|
require 'workarea/version'
|
215
215
|
require 'workarea/core/engine'
|
216
|
+
require 'workarea/admin/engine'
|
217
|
+
require 'workarea/storefront/engine'
|
218
|
+
require 'workarea/testing/engine' if Rails.env.test?
|
216
219
|
|
217
220
|
#
|
218
221
|
# Testing
|
data/lib/workarea/version.rb
CHANGED
@@ -47,6 +47,10 @@ module Workarea
|
|
47
47
|
embedded_in :foo
|
48
48
|
end
|
49
49
|
|
50
|
+
class Qoo < Bar
|
51
|
+
field :qoo, type: String
|
52
|
+
end
|
53
|
+
|
50
54
|
def test_merging_rows_for_embedded
|
51
55
|
model = Foo.create!(
|
52
56
|
bars: [{ name: '1' }, { name: '2' }],
|
@@ -418,6 +422,50 @@ module Workarea
|
|
418
422
|
|
419
423
|
assert_equal('653911', product.id)
|
420
424
|
end
|
425
|
+
|
426
|
+
def test_embedded_subclasses
|
427
|
+
model = Foo.create!(bars: [{ name: '1' }, { _type: Qoo.name, qoo: '2' }])
|
428
|
+
csv = Csv.new.serialize(model)
|
429
|
+
results = CSV.parse(csv, headers: :first_row).map(&:to_h)
|
430
|
+
|
431
|
+
assert_equal(2, results.size)
|
432
|
+
results.each { |r| assert_equal(model.id.to_s, r['_id']) }
|
433
|
+
assert_equal('1', results.first['bars_name'])
|
434
|
+
assert_equal(Qoo.name, results.second['bars_type'])
|
435
|
+
assert_equal('2', results.second['bars_qoo'])
|
436
|
+
|
437
|
+
import = create_import(
|
438
|
+
model_type: Foo.name,
|
439
|
+
file: create_tempfile(csv, extension: 'csv'),
|
440
|
+
file_type: 'csv'
|
441
|
+
)
|
442
|
+
|
443
|
+
model.destroy
|
444
|
+
Csv.new(import).import!
|
445
|
+
|
446
|
+
model = Foo.first
|
447
|
+
assert_equal(2, model.bars.size)
|
448
|
+
assert_equal(Bar, model.bars.first.class)
|
449
|
+
assert_equal('1', model.bars.first.name)
|
450
|
+
assert_equal(Qoo, model.bars.second.class)
|
451
|
+
assert_equal('2', model.bars.second.qoo)
|
452
|
+
end
|
453
|
+
|
454
|
+
def test_exclude_updated_at
|
455
|
+
original_date = 2.days.ago
|
456
|
+
model = Foo.create!(name: '1', updated_at: original_date)
|
457
|
+
model.name = '2'
|
458
|
+
csv = Csv.new.serialize(model)
|
459
|
+
import = create_import(
|
460
|
+
model_type: Foo.name,
|
461
|
+
file: create_tempfile(csv, extension: 'csv'),
|
462
|
+
file_type: 'csv'
|
463
|
+
)
|
464
|
+
|
465
|
+
assert_changes -> { model.reload.updated_at.to_date } do
|
466
|
+
Csv.new(import).import!
|
467
|
+
end
|
468
|
+
end
|
421
469
|
end
|
422
470
|
end
|
423
471
|
end
|
@@ -7,6 +7,16 @@ module Workarea
|
|
7
7
|
include ApplicationDocument
|
8
8
|
field :name, type: String
|
9
9
|
field :ignore, type: Integer
|
10
|
+
|
11
|
+
embeds_many :bars, class_name: Foo.name
|
12
|
+
end
|
13
|
+
|
14
|
+
class Bar
|
15
|
+
include ApplicationDocument
|
16
|
+
|
17
|
+
field :name, type: String
|
18
|
+
|
19
|
+
embedded_in :foo, class_name: Foo.name
|
10
20
|
end
|
11
21
|
|
12
22
|
def test_ignored_fields
|
@@ -75,6 +85,36 @@ module Workarea
|
|
75
85
|
|
76
86
|
assert_equal 'Bar', user.reload.first_name
|
77
87
|
end
|
88
|
+
|
89
|
+
def test_exclude_updated_at
|
90
|
+
model = Foo.create!(name: '1', updated_at: 2.days.ago)
|
91
|
+
json = [model.as_json.merge(name: '2')].to_json
|
92
|
+
import = create_import(
|
93
|
+
model_type: Foo.name,
|
94
|
+
file: create_tempfile(json, extension: 'json'),
|
95
|
+
file_type: 'json'
|
96
|
+
)
|
97
|
+
|
98
|
+
assert_changes -> { model.reload.updated_at.to_date } do
|
99
|
+
Json.new(import).import!
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def test_exclude_updated_at_when_embedded
|
104
|
+
original_date = 2.days.ago
|
105
|
+
parent = Foo.create!(updated_at: original_date)
|
106
|
+
model = parent.bars.create!(name: '1', updated_at: original_date)
|
107
|
+
json = [model.as_json.merge(name: '2')].to_json
|
108
|
+
import = create_import(
|
109
|
+
model_type: Foo.name,
|
110
|
+
file: create_tempfile(json, extension: 'json'),
|
111
|
+
file_type: 'json'
|
112
|
+
)
|
113
|
+
|
114
|
+
assert_changes -> { model.reload.updated_at.to_date } do
|
115
|
+
Json.new(import).import!
|
116
|
+
end
|
117
|
+
end
|
78
118
|
end
|
79
119
|
end
|
80
120
|
end
|
data/workarea-core.gemspec
CHANGED
@@ -91,7 +91,7 @@ Gem::Specification.new do |s|
|
|
91
91
|
s.add_dependency 'serviceworker-rails', '~> 0.5.5'
|
92
92
|
s.add_dependency 'logstasher', '~> 1.2.2'
|
93
93
|
s.add_dependency 'chartkick', '~> 3.3.0'
|
94
|
-
s.add_dependency 'puma', '
|
94
|
+
s.add_dependency 'puma', '>= 4.3.1'
|
95
95
|
|
96
96
|
# HACK for vendoring active_shipping
|
97
97
|
s.add_dependency 'active_utils', '~> 3.3.1'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workarea-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.4.
|
4
|
+
version: 3.4.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Crouse
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -1098,16 +1098,16 @@ dependencies:
|
|
1098
1098
|
name: puma
|
1099
1099
|
requirement: !ruby/object:Gem::Requirement
|
1100
1100
|
requirements:
|
1101
|
-
- - "
|
1101
|
+
- - ">="
|
1102
1102
|
- !ruby/object:Gem::Version
|
1103
|
-
version:
|
1103
|
+
version: 4.3.1
|
1104
1104
|
type: :runtime
|
1105
1105
|
prerelease: false
|
1106
1106
|
version_requirements: !ruby/object:Gem::Requirement
|
1107
1107
|
requirements:
|
1108
|
-
- - "
|
1108
|
+
- - ">="
|
1109
1109
|
- !ruby/object:Gem::Version
|
1110
|
-
version:
|
1110
|
+
version: 4.3.1
|
1111
1111
|
- !ruby/object:Gem::Dependency
|
1112
1112
|
name: active_utils
|
1113
1113
|
requirement: !ruby/object:Gem::Requirement
|