chewy 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7aa20726080ec98870f97d0c0ef730a3eb7bc4f
4
- data.tar.gz: 66b15afd916e7ed479bf7e9bacc3286a9ce9dc25
3
+ metadata.gz: f9741190c8e67f2cf5a4ae0a7270eb7716884b70
4
+ data.tar.gz: fc86af473569d271c43d3b39cd0f710234adae76
5
5
  SHA512:
6
- metadata.gz: 5800f28ff7480f5c7052c5860a5b3f3e6547ebee02e88f82d59e4aa2df6764d3330ee5c00ee3b36cff26c74ebec5d3713641868618d465718c6c615bae12ef85
7
- data.tar.gz: eb17d5fa79ec63472fdb0adac109d8612af6a9693bcda2afe05efe20f32b9d221933403049ba27731a9410752e6c955e522fceab4e7d6c372b38b64f21d87708
6
+ metadata.gz: 50ee0a42f751e1aba5639b139e236056aa067f07524eb7d3d1c7bfc80f47b73ad8d7c9f5ae4df2cceda03d9b22d1896def3dc311c9f348e17bfec241bdb6102d
7
+ data.tar.gz: bee6ca569f2568ab4c33f3fcc23ffca5e5cb121a1145a07e8dcb9f09a0d5333999e454f2ff220621b2aebaf14dc29a9ba4254e0e6cb0f195d8c83fd2d9a1a942
@@ -1,5 +1,23 @@
1
1
  # master
2
2
 
3
+ # Version 0.10.1
4
+
5
+ ## Changes
6
+
7
+ * Improved parallel worker titles (#558)
8
+
9
+ ## Bugfixes
10
+
11
+ * Fixed request strategy initial debug message (#557)
12
+
13
+ * Fixed will objects paginated array initialization when pagination was not used (#556)
14
+
15
+ * Fixed fields symbol/string value (#555)
16
+
17
+ * Fixed root field value proc (#554)
18
+
19
+ # Version 0.10.0
20
+
3
21
  ## Breaking changes
4
22
 
5
23
  * Changed behavior of `Chewy::Index.index_name`, it doesn't cache the values anymore.
@@ -8,7 +26,9 @@
8
26
 
9
27
  ## Changes
10
28
 
11
- * Parallel import and rake tasks.
29
+ * Less noisy strategies logging (@Borzik, #543)
30
+
31
+ * Parallel import and the corresponding rake tasks.
12
32
 
13
33
  * `:shoryuken` async strategy (@josephchoe, #532)
14
34
 
data/README.md CHANGED
@@ -228,7 +228,7 @@ If you would like to use AWS's ElasticSearch using an IAM user policy, you will
228
228
  ```
229
229
 
230
230
  [See index settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html).
231
- [See root object settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-root-object-type.html).
231
+ [See root object settings here](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-field-mapping.html).
232
232
 
233
233
  See [mapping.rb](lib/chewy/type/mapping.rb) for more details.
234
234
 
@@ -357,7 +357,7 @@ end
357
357
  ```
358
358
  ### Geo Point fields
359
359
 
360
- You can use [Elasticsearch's geo mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-geo-point-type.html) with the `geo_point` field type, allowing you to query, filter and order by latitude and longitude. You can use the following hash format:
360
+ You can use [Elasticsearch's geo mapping](https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html) with the `geo_point` field type, allowing you to query, filter and order by latitude and longitude. You can use the following hash format:
361
361
 
362
362
  ```ruby
363
363
  field :coordinates, type: 'geo_point', value: ->{ {lat: latitude, lon: longitude} }
@@ -32,34 +32,14 @@ module Chewy
32
32
  end
33
33
 
34
34
  def compose(*objects)
35
- object = objects.first
35
+ result = evaluate(objects)
36
36
 
37
- result =
38
- if value && value.is_a?(Proc)
39
- if value.arity.zero?
40
- object.instance_exec(&value)
41
- elsif value.arity < 0
42
- value.call(*object)
43
- else
44
- value.call(*objects.first(value.arity))
45
- end
46
- elsif object.is_a?(Hash)
47
- if object.key?(name)
48
- object[name]
49
- else
50
- object[name.to_s]
51
- end
37
+ if children.present? && !multi_field?
38
+ result = if result.respond_to?(:to_ary)
39
+ result.to_ary.map { |item| compose_children(item, *objects) }
52
40
  else
53
- object.send(name)
41
+ compose_children(result, *objects)
54
42
  end
55
-
56
- if children.present? && !multi_field?
57
- result =
58
- if result.respond_to?(:to_ary)
59
- result.to_ary.map { |item| compose_children(item, *objects) }
60
- else
61
- compose_children(result, *objects)
62
- end
63
43
  end
64
44
 
65
45
  {name => result}
@@ -67,6 +47,32 @@ module Chewy
67
47
 
68
48
  private
69
49
 
50
+ def evaluate(objects)
51
+ object = objects.first
52
+
53
+ if value.is_a?(Proc)
54
+ if value.arity.zero?
55
+ object.instance_exec(&value)
56
+ elsif value.arity < 0
57
+ value.call(*object)
58
+ else
59
+ value.call(*objects.first(value.arity))
60
+ end
61
+ else
62
+ message = value.is_a?(Symbol) || value.is_a?(String) ? value.to_sym : name
63
+
64
+ if object.is_a?(Hash)
65
+ if object.key?(message)
66
+ object[message]
67
+ else
68
+ object[message.to_s]
69
+ end
70
+ else
71
+ object.send(message)
72
+ end
73
+ end
74
+ end
75
+
70
76
  def compose_children(value, *parent_objects)
71
77
  return unless value
72
78
 
@@ -12,6 +12,7 @@ module Chewy
12
12
  @id = @options.delete(:id) || options.delete(:_id)
13
13
  @parent = @options.delete(:parent) || options.delete(:_parent)
14
14
  @parent_id = @options.delete(:parent_id)
15
+ @value ||= -> { self }
15
16
  @dynamic_templates = []
16
17
  @options.delete(:type)
17
18
  end
@@ -67,6 +68,8 @@ module Chewy
67
68
  # @param fields [Array<Symbol>] a list of fields to compose, every field will be composed if empty
68
69
  # @return [Hash] JSON-ready heash with stringifyed keys
69
70
  def compose(object, crutches = nil, fields: [])
71
+ result = evaluate([object, crutches])
72
+
70
73
  if children.present?
71
74
  child_fields = if fields.present?
72
75
  child_hash.slice(*fields).values
@@ -74,13 +77,13 @@ module Chewy
74
77
  children
75
78
  end
76
79
 
77
- child_fields.each_with_object({}) do |field, result|
78
- result.merge!(field.compose(object, crutches) || {})
80
+ child_fields.each_with_object({}) do |field, memo|
81
+ memo.merge!(field.compose(result, crutches) || {})
79
82
  end.as_json
80
83
  elsif fields.present?
81
- object.as_json(only: fields)
84
+ result.as_json(only: fields)
82
85
  else
83
- object.as_json
86
+ result.as_json
84
87
  end
85
88
  end
86
89
 
@@ -7,7 +7,6 @@ module Chewy
7
7
  class RequestStrategy
8
8
  def initialize(app)
9
9
  @app = app
10
- Chewy.logger.debug("Chewy strategies stack: [1] <- #{Chewy.request_strategy}")
11
10
  end
12
11
 
13
12
  def call(env)
@@ -15,6 +14,8 @@ module Chewy
15
14
  if Rails.application.config.respond_to?(:assets) && env['PATH_INFO'].start_with?(Rails.application.config.assets.prefix)
16
15
  @app.call(env)
17
16
  else
17
+ Chewy.logger.info("Chewy request strategy is `#{Chewy.request_strategy}`") if @request_strategy != Chewy.request_strategy
18
+ @request_strategy = Chewy.request_strategy
18
19
  Chewy.strategy(Chewy.request_strategy) { @app.call(env) }
19
20
  end
20
21
  end
@@ -49,6 +50,7 @@ module Chewy
49
50
  else
50
51
  Chewy.strategy(:urgent)
51
52
  end
53
+ Chewy.logger.info("Chewy console strategy is `#{Chewy.strategy.current.name}`")
52
54
  end
53
55
 
54
56
  initializer 'chewy.logger', after: 'active_record.logger' do
@@ -31,7 +31,9 @@ module Chewy
31
31
  private
32
32
 
33
33
  def paginated_collection(collection)
34
- ::WillPaginate::Collection.create(current_page, per_page, total_entries) do |pager|
34
+ page = current_page || 1
35
+ per = per_page || ::WillPaginate.per_page
36
+ ::WillPaginate::Collection.create(page, per, total_entries) do |pager|
35
37
  pager.replace collection
36
38
  end
37
39
  end
@@ -8,8 +8,8 @@ module Chewy
8
8
  module Import
9
9
  extend ActiveSupport::Concern
10
10
 
11
- IMPORT_WORKER = lambda do |type, options, ids|
12
- ::Process.setproctitle("chewy import #{type}[#{::Parallel.worker_number}]")
11
+ IMPORT_WORKER = lambda do |type, options, total, ids, index|
12
+ ::Process.setproctitle("chewy [#{type}]: import data (#{index + 1}/#{total})")
13
13
  routine = Routine.new(type, options)
14
14
  type.adapter.import(*ids, routine.options) do |action_objects|
15
15
  routine.process(**action_objects)
@@ -17,8 +17,8 @@ module Chewy
17
17
  {errors: routine.errors, import: routine.stats, leftovers: routine.leftovers}
18
18
  end
19
19
 
20
- LEFTOVERS_WORKER = lambda do |type, options, body|
21
- ::Process.setproctitle("chewy import #{type}[#{::Parallel.worker_number}]")
20
+ LEFTOVERS_WORKER = lambda do |type, options, total, body, index|
21
+ ::Process.setproctitle("chewy [#{type}]: import leftovers (#{index + 1}/#{total})")
22
22
  routine = Routine.new(type, options)
23
23
  routine.perform_bulk(body)
24
24
  routine.errors
@@ -155,13 +155,13 @@ module Chewy
155
155
  batches = adapter.import_references(*objects, routine.options.slice(:batch_size)).to_a
156
156
 
157
157
  ::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base)
158
- results = ::Parallel.map(batches, routine.parallel_options, &IMPORT_WORKER.curry[self, routine.options])
158
+ results = ::Parallel.map_with_index(batches, routine.parallel_options, &IMPORT_WORKER.curry[self, routine.options, batches.size])
159
159
  ::ActiveRecord::Base.connection.reconnect! if defined?(::ActiveRecord::Base)
160
160
  errors, import, leftovers = process_parallel_import_results(results)
161
161
 
162
162
  if leftovers.present?
163
163
  batches = leftovers.each_slice(routine.options[:batch_size])
164
- results = ::Parallel.map(batches, routine.parallel_options, &LEFTOVERS_WORKER.curry[self, routine.options])
164
+ results = ::Parallel.map_with_index(batches, routine.parallel_options, &LEFTOVERS_WORKER.curry[self, routine.options, batches.size])
165
165
  errors.concat(results.flatten(1))
166
166
  end
167
167
 
@@ -28,7 +28,8 @@ module Chewy
28
28
  class Syncer
29
29
  DEFAULT_SYNC_BATCH_SIZE = 20_000
30
30
  ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
31
- OUTDATED_IDS_WORKER = lambda do |outdated_sync_field_type, source_data_hash, index_data|
31
+ OUTDATED_IDS_WORKER = lambda do |outdated_sync_field_type, source_data_hash, type, total, index_data|
32
+ ::Process.setproctitle("chewy [#{type}]: sync outdated calculation (#{::Parallel.worker_number + 1}/#{total})") if type
32
33
  index_data.each_with_object([]) do |(id, index_sync_value), result|
33
34
  next unless source_data_hash[id]
34
35
 
@@ -41,14 +42,15 @@ module Chewy
41
42
  result.push(id) if outdated
42
43
  end
43
44
  end
44
- SOURCE_OR_INDEX_DATA_WORKER = lambda do |syncer, type|
45
- result = case type
45
+ SOURCE_OR_INDEX_DATA_WORKER = lambda do |syncer, type, kind|
46
+ ::Process.setproctitle("chewy [#{type}]: sync fetching data (#{kind})")
47
+ result = case kind
46
48
  when :source
47
49
  syncer.send(:fetch_source_data)
48
50
  when :index
49
51
  syncer.send(:fetch_index_data)
50
52
  end
51
- {type => result}
53
+ {kind => result}
52
54
  end
53
55
 
54
56
  def self.typecast_date(string)
@@ -143,7 +145,7 @@ module Chewy
143
145
  @source_and_index_data ||= begin
144
146
  if @parallel
145
147
  ::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base)
146
- result = ::Parallel.map(%i[source index], @parallel, &SOURCE_OR_INDEX_DATA_WORKER.curry[self])
148
+ result = ::Parallel.map(%i[source index], @parallel, &SOURCE_OR_INDEX_DATA_WORKER.curry[self, @type])
147
149
  ::ActiveRecord::Base.connection.reconnect! if defined?(::ActiveRecord::Base)
148
150
  if result.first.keys.first == :source
149
151
  [result.first.values.first, result.second.values.first]
@@ -182,7 +184,7 @@ module Chewy
182
184
  end
183
185
 
184
186
  def linear_outdated_ids
185
- OUTDATED_IDS_WORKER.call(outdated_sync_field_type, source_data.to_h, index_data)
187
+ OUTDATED_IDS_WORKER.call(outdated_sync_field_type, source_data.to_h, nil, nil, index_data)
186
188
  end
187
189
 
188
190
  def parallel_outdated_ids
@@ -190,7 +192,7 @@ module Chewy
190
192
  batches = index_data.each_slice(size)
191
193
 
192
194
  ::ActiveRecord::Base.connection.close if defined?(::ActiveRecord::Base)
193
- result = ::Parallel.map(batches, @parallel, &OUTDATED_IDS_WORKER.curry[outdated_sync_field_type, source_data.to_h]).flatten(1)
195
+ result = ::Parallel.map(batches, @parallel, &OUTDATED_IDS_WORKER.curry[outdated_sync_field_type, source_data.to_h, @type, batches.size]).flatten(1)
194
196
  ::ActiveRecord::Base.connection.reconnect! if defined?(::ActiveRecord::Base)
195
197
  result
196
198
  end
@@ -102,14 +102,16 @@ module Chewy
102
102
  (if #{object}.is_a?(Hash)
103
103
  {
104
104
  #{non_proc_fields.map do |f|
105
- fetcher = "#{object}.has_key?(:#{f.name}) ? #{object}[:#{f.name}] : #{object}['#{f.name}']"
105
+ key_name = f.value.is_a?(Symbol) || f.value.is_a?(String) ? f.value : f.name
106
+ fetcher = "#{object}.has_key?(:#{key_name}) ? #{object}[:#{key_name}] : #{object}['#{key_name}']"
106
107
  "'#{f.name}'.freeze => #{composed_value(f, fetcher, nesting)}"
107
108
  end.join(', ')}
108
109
  }
109
110
  else
110
111
  {
111
112
  #{non_proc_fields.map do |f|
112
- "'#{f.name}'.freeze => #{composed_value(f, "#{object}.#{f.name}", nesting)}"
113
+ method_name = f.value.is_a?(Symbol) || f.value.is_a?(String) ? f.value : f.name
114
+ "'#{f.name}'.freeze => #{composed_value(f, "#{object}.#{method_name}", nesting)}"
113
115
  end.join(', ')}
114
116
  }
115
117
  end)
@@ -137,7 +139,7 @@ module Chewy
137
139
 
138
140
  def non_proc_fields_for(parent, nesting)
139
141
  return [] unless parent
140
- fields = (parent.children || []).reject { |field| field.value && field.value.is_a?(Proc) }
142
+ fields = (parent.children || []).reject { |field| field.value.is_a?(Proc) }
141
143
 
142
144
  if nesting.zero? && @fields.present?
143
145
  fields.select { |f| @fields.include?(f.name) }
@@ -148,7 +150,7 @@ module Chewy
148
150
 
149
151
  def proc_fields_for(parent, nesting)
150
152
  return [] unless parent
151
- fields = (parent.children || []).select { |field| field.value && field.value.is_a?(Proc) }
153
+ fields = (parent.children || []).select { |field| field.value.is_a?(Proc) }
152
154
 
153
155
  if nesting.zero? && @fields.present?
154
156
  fields.select { |f| @fields.include?(f.name) }
@@ -1,3 +1,3 @@
1
1
  module Chewy
2
- VERSION = '0.10.0'.freeze
2
+ VERSION = '0.10.1'.freeze
3
3
  end
@@ -10,6 +10,8 @@ describe Chewy::Fields::Base do
10
10
  specify { expect(field.compose(double(value: 'hello'))).to eq(name: 'hello') }
11
11
  specify { expect(field.compose(double(value: %w[hello world]))).to eq(name: %w[hello world]) }
12
12
 
13
+ specify { expect(described_class.new(:name, value: :last_name).compose(double(last_name: 'hello'))).to eq(name: 'hello') }
14
+ specify { expect(described_class.new(:name, value: :last_name).compose('last_name' => 'hello')).to eq(name: 'hello') }
13
15
  specify { expect(described_class.new(:name).compose(double(name: 'hello'))).to eq(name: 'hello') }
14
16
  specify { expect(described_class.new(:false_value).compose(false_value: false)).to eq(false_value: false) }
15
17
  specify { expect(described_class.new(:true_value).compose(true_value: true)).to eq(true_value: true) }
@@ -82,6 +82,53 @@ describe Chewy::Fields::Root do
82
82
  .to eq('name' => 'London')
83
83
  end
84
84
  end
85
+
86
+ context 'root value provided' do
87
+ before do
88
+ stub_index(:places) do
89
+ define_type :city do
90
+ root value: ->(o) { {name: o.name + 'Modified', rating: o.rating.next} }
91
+ end
92
+ end
93
+ end
94
+
95
+ let(:city) { double(name: 'London', rating: 100) }
96
+
97
+ specify do
98
+ expect(PlacesIndex::City.send(:build_root).compose(city))
99
+ .to eq('name' => 'LondonModified', 'rating' => 101)
100
+ end
101
+
102
+ specify do
103
+ expect(PlacesIndex::City.send(:build_root).compose(city, fields: %i[name borogoves]))
104
+ .to eq('name' => 'LondonModified')
105
+ end
106
+ end
107
+
108
+ context 'complex evaluations' do
109
+ before do
110
+ stub_index(:places) do
111
+ define_type :city do
112
+ root value: ->(o) { {name: o.name + 'Modified', rating: o.rating.next} } do
113
+ field :name, value: ->(o) { o[:name] + 'Modified' }
114
+ field :rating
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ let(:city) { double(name: 'London', rating: 100) }
121
+
122
+ specify do
123
+ expect(PlacesIndex::City.send(:build_root).compose(city))
124
+ .to eq('name' => 'LondonModifiedModified', 'rating' => 101)
125
+ end
126
+
127
+ specify do
128
+ expect(PlacesIndex::City.send(:build_root).compose(city, fields: %i[name borogoves]))
129
+ .to eq('name' => 'LondonModifiedModified')
130
+ end
131
+ end
85
132
  end
86
133
 
87
134
  describe '#child_hash' do
@@ -3,13 +3,17 @@ require 'chewy/search/pagination/kaminari_examples'
3
3
  describe Chewy::Search::Pagination::Kaminari do
4
4
  it_behaves_like :kaminari, Chewy::Search::Request do
5
5
  describe '#objects' do
6
- let(:data) { Array.new(10) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } }
6
+ let(:data) { Array.new(12) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } }
7
7
 
8
8
  before { ProductsIndex::Product.import!(data.map { |h| double(h) }) }
9
- before { allow(::Kaminari.config).to receive_messages(default_per_page: 3) }
9
+ before { allow(::Kaminari.config).to receive_messages(default_per_page: 17) }
10
10
 
11
+ specify { expect(search.objects.class).to eq(Kaminari::PaginatableArray) }
12
+ specify { expect(search.objects.total_count).to eq(12) }
13
+ specify { expect(search.objects.limit_value).to eq(17) }
14
+ specify { expect(search.objects.offset_value).to eq(0) }
11
15
  specify { expect(search.per(2).page(3).objects.class).to eq(Kaminari::PaginatableArray) }
12
- specify { expect(search.per(2).page(3).objects.total_count).to eq(10) }
16
+ specify { expect(search.per(2).page(3).objects.total_count).to eq(12) }
13
17
  specify { expect(search.per(2).page(3).objects.limit_value).to eq(2) }
14
18
  specify { expect(search.per(2).page(3).objects.offset_value).to eq(4) }
15
19
  end
@@ -3,13 +3,19 @@ require 'chewy/search/pagination/will_paginate_examples'
3
3
  describe Chewy::Search::Pagination::WillPaginate do
4
4
  it_behaves_like :will_paginate, Chewy::Search::Request do
5
5
  describe '#objects' do
6
- let(:data) { Array.new(10) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } }
6
+ let(:data) { Array.new(12) { |i| {id: i.next.to_s, name: "Name#{i.next}", age: 10 * i.next}.stringify_keys! } }
7
7
 
8
8
  before { ProductsIndex::Product.import!(data.map { |h| double(h) }) }
9
- before { allow(::WillPaginate).to receive_messages(per_page: 3) }
9
+ before { allow(::WillPaginate).to receive_messages(per_page: 17) }
10
10
 
11
+ # specify { expect(search.current_page).to eq(1) }
12
+ # specify { expect(search.per_page).to eq(0) }
13
+ specify { expect(search.objects.class).to eq(WillPaginate::Collection) }
14
+ specify { expect(search.objects.total_entries).to eq(12) }
15
+ specify { expect(search.objects.per_page).to eq(17) }
16
+ specify { expect(search.objects.current_page).to eq(1) }
11
17
  specify { expect(search.paginate(per_page: 2, page: 3).objects.class).to eq(WillPaginate::Collection) }
12
- specify { expect(search.paginate(per_page: 2, page: 3).objects.total_entries).to eq(10) }
18
+ specify { expect(search.paginate(per_page: 2, page: 3).objects.total_entries).to eq(12) }
13
19
  specify { expect(search.paginate(per_page: 2, page: 3).objects.per_page).to eq(2) }
14
20
  specify { expect(search.paginate(per_page: 2, page: 3).objects.current_page).to eq(3) }
15
21
  end
@@ -212,5 +212,21 @@ describe Chewy::Type::Witchcraft do
212
212
  specify { expect(type.cauldron.brew(object)).to eq(attributes.as_json) }
213
213
  end
214
214
  end
215
+
216
+ context 'symbol value' do
217
+ mapping do
218
+ field :name, value: :last_name
219
+ end
220
+
221
+ context do
222
+ let(:object) { double(last_name: 'Name') }
223
+ specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) }
224
+ end
225
+
226
+ context do
227
+ let(:object) { {'last_name' => 'Name'} }
228
+ specify { expect(type.cauldron.brew(object)).to eq({name: 'Name'}.as_json) }
229
+ end
230
+ end
215
231
  end
216
232
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chewy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - pyromaniac
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-27 00:00:00.000000000 Z
11
+ date: 2017-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake