larva 1.0.0 → 1.0.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: 56edc62f830f8beaa3862dcb8ff381f1cd4b35d2
4
- data.tar.gz: 7a77450848d9d87cb6b50f9ac95486cce0fdd8c5
3
+ metadata.gz: 803859c8d275ec839b7b26e3701e2b2f304d78d3
4
+ data.tar.gz: 783918f6ee9a3a4c7e7c42b58380275ef9cbcaf1
5
5
  SHA512:
6
- metadata.gz: 330518dec7552c9150b65fa6ae78c7f12283da832344be782f4db5a48c3795aee8463cdb2f3809f78dc3d260269467fb43604fe06b204d64421c5009697ec923
7
- data.tar.gz: b928a17b94ce057fd544c39824dfe9be8fcdabbdd72c97b070210ce30339de611cb0d271fe64f2544eff418c9e915109b45ee8a9e2d291b12ac5d08a0827fb71
6
+ metadata.gz: b53f60b7190c3ddddbe9de31304ccb261e408c0cbd389b9f34c9ca7338511a50d92e76ad8c9493fb6d1ecfa20d6481ee9f0c27eda572d813314baf8db37a414f
7
+ data.tar.gz: 2b48aa486cbe746af30ffd777febc4f932d9159884cc5363514ccc8611de3f588ad22d1561a9935e148066545a11763b308d82d0afaf89cfff6866d39ea51014
@@ -1,3 +1,7 @@
1
+ # 1.0.1 / 2014-07-12
2
+ * [BUGFIX] Don't require that the logger is Filum.
3
+ * [BUGFIX] Fix bug with message keys not being detected properly.
4
+
1
5
  # 1.0.0 / 2014-07-12
2
6
  * [FEATURE] Remove Meducation specific code and bump to 1.0.0
3
7
 
@@ -2,6 +2,8 @@ require 'active_support/core_ext'
2
2
  require 'filum'
3
3
  require 'propono'
4
4
 
5
+ require_relative 'larva/hash_with_indifferent_access' unless defined?(HashWithIndifferentAccess)
6
+
5
7
  require_relative 'larva/configuration'
6
8
  require_relative 'larva/configurator'
7
9
  require_relative 'larva/mocker'
@@ -0,0 +1,411 @@
1
+ class Hash
2
+ # Returns a new hash with all keys converted using the block operation.
3
+ #
4
+ # hash = { name: 'Rob', age: '28' }
5
+ #
6
+ # hash.transform_keys{ |key| key.to_s.upcase }
7
+ # # => {"NAME"=>"Rob", "AGE"=>"28"}
8
+ def transform_keys
9
+ result = {}
10
+ each_key do |key|
11
+ result[yield(key)] = self[key]
12
+ end
13
+ result
14
+ end
15
+
16
+ # Destructively convert all keys using the block operations.
17
+ # Same as transform_keys but modifies +self+.
18
+ def transform_keys!
19
+ keys.each do |key|
20
+ self[yield(key)] = delete(key)
21
+ end
22
+ self
23
+ end
24
+
25
+ # Returns a new hash with all keys converted to strings.
26
+ #
27
+ # hash = { name: 'Rob', age: '28' }
28
+ #
29
+ # hash.stringify_keys
30
+ # # => { "name" => "Rob", "age" => "28" }
31
+ def stringify_keys
32
+ transform_keys{ |key| key.to_s }
33
+ end
34
+
35
+ # Destructively convert all keys to strings. Same as
36
+ # +stringify_keys+, but modifies +self+.
37
+ def stringify_keys!
38
+ transform_keys!{ |key| key.to_s }
39
+ end
40
+
41
+ # Returns a new hash with all keys converted to symbols, as long as
42
+ # they respond to +to_sym+.
43
+ #
44
+ # hash = { 'name' => 'Rob', 'age' => '28' }
45
+ #
46
+ # hash.symbolize_keys
47
+ # # => { name: "Rob", age: "28" }
48
+ def symbolize_keys
49
+ transform_keys{ |key| key.to_sym rescue key }
50
+ end
51
+ alias_method :to_options, :symbolize_keys
52
+
53
+ # Destructively convert all keys to symbols, as long as they respond
54
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
55
+ def symbolize_keys!
56
+ transform_keys!{ |key| key.to_sym rescue key }
57
+ end
58
+ alias_method :to_options!, :symbolize_keys!
59
+
60
+ # Validate all keys in a hash match <tt>*valid_keys</tt>, raising ArgumentError
61
+ # on a mismatch. Note that keys are NOT treated indifferently, meaning if you
62
+ # use strings for keys but assert symbols as keys, this will fail.
63
+ #
64
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
65
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
66
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
67
+ def assert_valid_keys(*valid_keys)
68
+ valid_keys.flatten!
69
+ each_key do |k|
70
+ unless valid_keys.include?(k)
71
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
72
+ end
73
+ end
74
+ end
75
+
76
+ # Returns a new hash with all keys converted by the block operation.
77
+ # This includes the keys from the root hash and from all
78
+ # nested hashes.
79
+ #
80
+ # hash = { person: { name: 'Rob', age: '28' } }
81
+ #
82
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
83
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
84
+ def deep_transform_keys(&block)
85
+ result = {}
86
+ each do |key, value|
87
+ result[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys(&block) : value
88
+ end
89
+ result
90
+ end
91
+
92
+ # Destructively convert all keys by using the block operation.
93
+ # This includes the keys from the root hash and from all
94
+ # nested hashes.
95
+ def deep_transform_keys!(&block)
96
+ keys.each do |key|
97
+ value = delete(key)
98
+ self[yield(key)] = value.is_a?(Hash) ? value.deep_transform_keys!(&block) : value
99
+ end
100
+ self
101
+ end
102
+
103
+ # Returns a new hash with all keys converted to strings.
104
+ # This includes the keys from the root hash and from all
105
+ # nested hashes.
106
+ #
107
+ # hash = { person: { name: 'Rob', age: '28' } }
108
+ #
109
+ # hash.deep_stringify_keys
110
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
111
+ def deep_stringify_keys
112
+ deep_transform_keys{ |key| key.to_s }
113
+ end
114
+
115
+ # Destructively convert all keys to strings.
116
+ # This includes the keys from the root hash and from all
117
+ # nested hashes.
118
+ def deep_stringify_keys!
119
+ deep_transform_keys!{ |key| key.to_s }
120
+ end
121
+
122
+ # Returns a new hash with all keys converted to symbols, as long as
123
+ # they respond to +to_sym+. This includes the keys from the root hash
124
+ # and from all nested hashes.
125
+ #
126
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
127
+ #
128
+ # hash.deep_symbolize_keys
129
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
130
+ def deep_symbolize_keys
131
+ deep_transform_keys{ |key| key.to_sym rescue key }
132
+ end
133
+
134
+ # Destructively convert all keys to symbols, as long as they respond
135
+ # to +to_sym+. This includes the keys from the root hash and from all
136
+ # nested hashes.
137
+ def deep_symbolize_keys!
138
+ deep_transform_keys!{ |key| key.to_sym rescue key }
139
+ end
140
+ end
141
+
142
+ module ActiveSupport
143
+ # Implements a hash where keys <tt>:foo</tt> and <tt>"foo"</tt> are considered
144
+ # to be the same.
145
+ #
146
+ # rgb = ActiveSupport::HashWithIndifferentAccess.new
147
+ #
148
+ # rgb[:black] = '#000000'
149
+ # rgb[:black] # => '#000000'
150
+ # rgb['black'] # => '#000000'
151
+ #
152
+ # rgb['white'] = '#FFFFFF'
153
+ # rgb[:white] # => '#FFFFFF'
154
+ # rgb['white'] # => '#FFFFFF'
155
+ #
156
+ # Internally symbols are mapped to strings when used as keys in the entire
157
+ # writing interface (calling <tt>[]=</tt>, <tt>merge</tt>, etc). This
158
+ # mapping belongs to the public interface. For example, given:
159
+ #
160
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
161
+ #
162
+ # You are guaranteed that the key is returned as a string:
163
+ #
164
+ # hash.keys # => ["a"]
165
+ #
166
+ # Technically other types of keys are accepted:
167
+ #
168
+ # hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
169
+ # hash[0] = 0
170
+ # hash # => {"a"=>1, 0=>0}
171
+ #
172
+ # but this class is intended for use cases where strings or symbols are the
173
+ # expected keys and it is convenient to understand both as the same. For
174
+ # example the +params+ hash in Ruby on Rails.
175
+ #
176
+ # Note that core extensions define <tt>Hash#with_indifferent_access</tt>:
177
+ #
178
+ # rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
179
+ #
180
+ # which may be handy.
181
+ class HashWithIndifferentAccess < Hash
182
+ # Returns +true+ so that <tt>Array#extract_options!</tt> finds members of
183
+ # this class.
184
+ def extractable_options?
185
+ true
186
+ end
187
+
188
+ def with_indifferent_access
189
+ dup
190
+ end
191
+
192
+ def nested_under_indifferent_access
193
+ self
194
+ end
195
+
196
+ def initialize(constructor = {})
197
+ if constructor.is_a?(Hash)
198
+ super()
199
+ update(constructor)
200
+ else
201
+ super(constructor)
202
+ end
203
+ end
204
+
205
+ def default(key = nil)
206
+ if key.is_a?(Symbol) && include?(key = key.to_s)
207
+ self[key]
208
+ else
209
+ super
210
+ end
211
+ end
212
+
213
+ def self.new_from_hash_copying_default(hash)
214
+ hash = hash.to_hash
215
+ new(hash).tap do |new_hash|
216
+ new_hash.default = hash.default
217
+ end
218
+ end
219
+
220
+ def self.[](*args)
221
+ new.merge!(Hash[*args])
222
+ end
223
+
224
+ alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
225
+ alias_method :regular_update, :update unless method_defined?(:regular_update)
226
+
227
+ # Assigns a new value to the hash:
228
+ #
229
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
230
+ # hash[:key] = 'value'
231
+ #
232
+ # This value can be later fetched using either +:key+ or +'key'+.
233
+ def []=(key, value)
234
+ regular_writer(convert_key(key), convert_value(value, for: :assignment))
235
+ end
236
+
237
+ alias_method :store, :[]=
238
+
239
+ # Updates the receiver in-place, merging in the hash passed as argument:
240
+ #
241
+ # hash_1 = ActiveSupport::HashWithIndifferentAccess.new
242
+ # hash_1[:key] = 'value'
243
+ #
244
+ # hash_2 = ActiveSupport::HashWithIndifferentAccess.new
245
+ # hash_2[:key] = 'New Value!'
246
+ #
247
+ # hash_1.update(hash_2) # => {"key"=>"New Value!"}
248
+ #
249
+ # The argument can be either an
250
+ # <tt>ActiveSupport::HashWithIndifferentAccess</tt> or a regular +Hash+.
251
+ # In either case the merge respects the semantics of indifferent access.
252
+ #
253
+ # If the argument is a regular hash with keys +:key+ and +"key"+ only one
254
+ # of the values end up in the receiver, but which one is unspecified.
255
+ #
256
+ # When given a block, the value for duplicated keys will be determined
257
+ # by the result of invoking the block with the duplicated key, the value
258
+ # in the receiver, and the value in +other_hash+. The rules for duplicated
259
+ # keys follow the semantics of indifferent access:
260
+ #
261
+ # hash_1[:key] = 10
262
+ # hash_2['key'] = 12
263
+ # hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
264
+ def update(other_hash)
265
+ if other_hash.is_a? HashWithIndifferentAccess
266
+ super(other_hash)
267
+ else
268
+ other_hash.to_hash.each_pair do |key, value|
269
+ if block_given? && key?(key)
270
+ value = yield(convert_key(key), self[key], value)
271
+ end
272
+ regular_writer(convert_key(key), convert_value(value))
273
+ end
274
+ self
275
+ end
276
+ end
277
+
278
+ alias_method :merge!, :update
279
+
280
+ # Checks the hash for a key matching the argument passed in:
281
+ #
282
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
283
+ # hash['key'] = 'value'
284
+ # hash.key?(:key) # => true
285
+ # hash.key?('key') # => true
286
+ def key?(key)
287
+ super(convert_key(key))
288
+ end
289
+
290
+ alias_method :include?, :key?
291
+ alias_method :has_key?, :key?
292
+ alias_method :member?, :key?
293
+
294
+ # Same as <tt>Hash#fetch</tt> where the key passed as argument can be
295
+ # either a string or a symbol:
296
+ #
297
+ # counters = ActiveSupport::HashWithIndifferentAccess.new
298
+ # counters[:foo] = 1
299
+ #
300
+ # counters.fetch('foo') # => 1
301
+ # counters.fetch(:bar, 0) # => 0
302
+ # counters.fetch(:bar) { |key| 0 } # => 0
303
+ # counters.fetch(:zoo) # => KeyError: key not found: "zoo"
304
+ def fetch(key, *extras)
305
+ super(convert_key(key), *extras)
306
+ end
307
+
308
+ # Returns an array of the values at the specified indices:
309
+ #
310
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
311
+ # hash[:a] = 'x'
312
+ # hash[:b] = 'y'
313
+ # hash.values_at('a', 'b') # => ["x", "y"]
314
+ def values_at(*indices)
315
+ indices.collect { |key| self[convert_key(key)] }
316
+ end
317
+
318
+ # Returns an exact copy of the hash.
319
+ def dup
320
+ self.class.new(self).tap do |new_hash|
321
+ new_hash.default = default
322
+ end
323
+ end
324
+
325
+ # This method has the same semantics of +update+, except it does not
326
+ # modify the receiver but rather returns a new hash with indifferent
327
+ # access with the result of the merge.
328
+ def merge(hash, &block)
329
+ self.dup.update(hash, &block)
330
+ end
331
+
332
+ # Like +merge+ but the other way around: Merges the receiver into the
333
+ # argument and returns a new hash with indifferent access as result:
334
+ #
335
+ # hash = ActiveSupport::HashWithIndifferentAccess.new
336
+ # hash['a'] = nil
337
+ # hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
338
+ def reverse_merge(other_hash)
339
+ super(self.class.new_from_hash_copying_default(other_hash))
340
+ end
341
+
342
+ # Same semantics as +reverse_merge+ but modifies the receiver in-place.
343
+ def reverse_merge!(other_hash)
344
+ replace(reverse_merge( other_hash ))
345
+ end
346
+
347
+ # Replaces the contents of this hash with other_hash.
348
+ #
349
+ # h = { "a" => 100, "b" => 200 }
350
+ # h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
351
+ def replace(other_hash)
352
+ super(self.class.new_from_hash_copying_default(other_hash))
353
+ end
354
+
355
+ # Removes the specified key from the hash.
356
+ def delete(key)
357
+ super(convert_key(key))
358
+ end
359
+
360
+ def stringify_keys!; self end
361
+ def deep_stringify_keys!; self end
362
+ def stringify_keys; dup end
363
+ def deep_stringify_keys; dup end
364
+ undef :symbolize_keys!
365
+ undef :deep_symbolize_keys!
366
+ def symbolize_keys; to_hash.symbolize_keys! end
367
+ def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
368
+ def to_options!; self end
369
+
370
+ def select(*args, &block)
371
+ dup.tap { |hash| hash.select!(*args, &block) }
372
+ end
373
+
374
+ def reject(*args, &block)
375
+ dup.tap { |hash| hash.reject!(*args, &block) }
376
+ end
377
+
378
+ # Convert to a regular hash with string keys.
379
+ def to_hash
380
+ _new_hash= {}
381
+ each do |key, value|
382
+ _new_hash[convert_key(key)] = convert_value(value, for: :to_hash)
383
+ end
384
+ Hash.new(default).merge!(_new_hash)
385
+ end
386
+
387
+ protected
388
+ def convert_key(key)
389
+ key.kind_of?(Symbol) ? key.to_s : key
390
+ end
391
+
392
+ def convert_value(value, options = {})
393
+ if value.is_a? Hash
394
+ if options[:for] == :to_hash
395
+ value.to_hash
396
+ else
397
+ value.nested_under_indifferent_access
398
+ end
399
+ elsif value.is_a?(Array)
400
+ unless options[:for] == :assignment
401
+ value = value.dup
402
+ end
403
+ value.map! { |e| convert_value(e, options) }
404
+ else
405
+ value
406
+ end
407
+ end
408
+ end
409
+ end
410
+
411
+ HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
@@ -15,7 +15,7 @@ module Larva
15
15
  queue_name = "#{topic_name}"
16
16
  Propono.config.logger.info "Starting to listen to queue #{queue_name}"
17
17
  Propono.listen_to_queue("#{queue_name}") do |message, context|
18
- Propono.config.logger.context_id = context[:id]
18
+ Propono.config.logger.context_id = context[:id] if Propono.config.logger.respond_to?(:context_id=)
19
19
  Propono.config.logger.info "Received message: #{message}"
20
20
  processor.process(message)
21
21
  end
@@ -5,8 +5,8 @@ module Larva
5
5
  end
6
6
 
7
7
  attr_accessor :message, :action, :entity, :id
8
- def initialize(message)
9
- @message = message
8
+ def initialize(raw_message)
9
+ @message = HashWithIndifferentAccess.new(raw_message)
10
10
  @action = message[:action]
11
11
  @entity = message[:entity]
12
12
  @id = message[:id]
@@ -1,3 +1,3 @@
1
1
  module Larva
2
- VERSION = '1.0.0'
2
+ VERSION = '1.0.1'
3
3
  end
@@ -20,9 +20,20 @@ module Larva
20
20
  assert_equal action, processor.action
21
21
  end
22
22
 
23
+ def test_initialize_should_extract_action_and_entity_when_strings
24
+ entity = "media_file"
25
+ action = "processed"
26
+ id = "8"
27
+ message = {'entity' => entity, 'action' => action, 'id' => "8"}
28
+ processor = Processor.new(message)
29
+ assert_equal entity, processor.entity
30
+ assert_equal action, processor.action
31
+ assert_equal id, processor.message[:id]
32
+ end
33
+
23
34
  def test_process_logs_message
24
35
  message = {entity: "media_file", action: "processed", media_file_id: "8"}
25
- output = "Processing message: #{message}"
36
+ output = "Processing message: #{message.stringify_keys}"
26
37
  Propono.config.logger.stubs(:info)
27
38
  Propono.config.logger.expects(:info).with(output)
28
39
  NormalProcessor.process(message)
@@ -42,7 +53,7 @@ module Larva
42
53
 
43
54
  def test_process_logs_success
44
55
  message = {entity: "media_file", action: "processed", media_file_id: "8"}
45
- output = "Message Processed: #{message}"
56
+ output = "Message Processed: #{message.stringify_keys}"
46
57
  Propono.config.logger.stubs(:info)
47
58
  Propono.config.logger.expects(:info).with(output)
48
59
  NormalProcessor.any_instance.expects(:process).returns(true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: larva
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - iHiD
@@ -131,6 +131,7 @@ files:
131
131
  - lib/larva/configurator.rb
132
132
  - lib/larva/daemon.rb
133
133
  - lib/larva/daemon_creator.rb
134
+ - lib/larva/hash_with_indifferent_access.rb
134
135
  - lib/larva/listener.rb
135
136
  - lib/larva/message_replayer.rb
136
137
  - lib/larva/mocker.rb