dynamini 1.7.7 → 1.8.0

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: 7130407abb9dbe1185b3ef9fb6eebacbeced2895
4
- data.tar.gz: 962468987cde482861fa02ca24c078bbdccc3ca6
3
+ metadata.gz: 5b2c47d2bbbe481f882f553c5be6bbd19e55c3ea
4
+ data.tar.gz: 896d9cf814087ab94a553b6442544b08736d4936
5
5
  SHA512:
6
- metadata.gz: 996a125425f9f8344339ad153498f5c234114320e87145358d2d8d88915927da62455aeea868d1836944fc9999381a2a2dcacf7617aaec589f9bb5268fb5bd97
7
- data.tar.gz: db9208b0bf5d17161d03fbc5b480d7cff583b6e03fc020aa25bfccc102d29f20a050a8c6bc4b7e04827bbc6783aa85152676cb8052636744efd824fc438b3120
6
+ metadata.gz: 1fa38ebcab26e62bc0b8096d1aacf64d067589f50a4ddd37dce1fb6a3566d8201ea4a81719672c6c18531e02891c871fe590105b09f34b401aee3cf5aabfa9b1
7
+ data.tar.gz: 0430d5c20bd42e61bb99c9ce7765aae89eb05899aaa08e9248ef0b9d87c9f6d118049d8d273f6d4e4ac7f1be2c13fd80ab125c3d4b92c558e1166ff3b8b4f5df
data/lib/dynamini/base.rb CHANGED
@@ -133,6 +133,18 @@ module Dynamini
133
133
  objects
134
134
  end
135
135
 
136
+ def query(args = {})
137
+ fail ArgumentError, 'You must provide a :hash_key.' unless args[:hash_key]
138
+ fail TypeError, 'Your range key must be handled as an integer, float, date, or time.' unless self.range_is_numeric?
139
+
140
+ response = self.dynamo_query(args)
141
+ objects = []
142
+ response.items.each do |item|
143
+ objects << new(item.symbolize_keys, false)
144
+ end
145
+ objects
146
+ end
147
+
136
148
  def enqueue_for_save(attributes, options = {})
137
149
  model = new(attributes, true)
138
150
  model.generate_timestamps! unless options[:skip_timestamps]
@@ -314,6 +326,37 @@ module Dynamini
314
326
  client.batch_write_item(request_options)
315
327
  end
316
328
 
329
+ def self.dynamo_query(args)
330
+ expression_attribute_values = self.build_expression_attribute_values(args)
331
+ key_condition_expression = self.build_key_condition_expression(args)
332
+
333
+ client.query(
334
+ table_name: table_name,
335
+ key_condition_expression: key_condition_expression,
336
+ expression_attribute_values: expression_attribute_values
337
+ )
338
+ end
339
+
340
+ def self.build_expression_attribute_values(args)
341
+ expression_values = {}
342
+ expression_values[':h'] = args[:hash_key]
343
+ expression_values[':s'] = args[:start] if args[:start]
344
+ expression_values[':e'] = args[:end] if args[:end]
345
+ expression_values
346
+ end
347
+
348
+ def self.build_key_condition_expression(args)
349
+ expression = "#{hash_key} = :h"
350
+ if args[:start] && args[:end]
351
+ expression += " AND #{range_key} BETWEEN :s AND :e"
352
+ elsif args[:start]
353
+ expression += " AND #{range_key} >= :s"
354
+ elsif args[:end]
355
+ expression += " AND #{range_key} <= :e"
356
+ end
357
+ expression
358
+ end
359
+
317
360
  def key
318
361
  key_hash = { self.class.hash_key => @attributes[self.class.hash_key] }
319
362
  key_hash[self.class.range_key] = @attributes[self.class.range_key] if self.class.range_key
@@ -326,6 +369,30 @@ module Dynamini
326
369
  key_hash
327
370
  end
328
371
 
372
+ def self.build_range_expression(start_value, end_value)
373
+ operator = (
374
+ if start_value && end_value
375
+ 'BETWEEN'
376
+ elsif start_value
377
+ 'GE'
378
+ elsif end_value
379
+ 'LE'
380
+ end
381
+ )
382
+ attribute_value_list = []
383
+
384
+ if handle = handles[range_key.to_sym]
385
+ attribute_value_list << attribute_callback(SETTER_PROCS, handle, start_value) if start_value
386
+ attribute_value_list << attribute_callback(SETTER_PROCS, handle, end_value) if end_value
387
+ else
388
+ attribute_value_list << start_value if start_value
389
+ attribute_value_list << end_value if end_value
390
+ end
391
+
392
+ {attribute_value_list: attribute_value_list, comparison_operator: operator}
393
+ end
394
+
395
+
329
396
  def attribute_updates
330
397
  changes.reduce({}) do |updates, (key, value)|
331
398
  current_value = value[1]
@@ -434,5 +501,9 @@ module Dynamini
434
501
  self.class.handles
435
502
  end
436
503
 
504
+ def self.range_is_numeric?
505
+ handles[@range_key] && [:integer, :time, :float, :date].include?(handles[@range_key][:format])
506
+ end
507
+
437
508
  end
438
509
  end
@@ -90,6 +90,43 @@ module Dynamini
90
90
  @data[args[:table_name]].delete(args[:key][hash_key_attr])
91
91
  end
92
92
 
93
+ def query(args = {})
94
+ # Possible key condition structures:
95
+ # "foo = val"
96
+ # "foo = val AND bar <= val2"
97
+ # "foo = val AND bar >= val2"
98
+ # "foo = val AND bar BETWEEN val2 AND val3"
99
+
100
+ args[:expression_attribute_values].each do |symbol, value|
101
+ args[:key_condition_expression].gsub!(symbol, value.to_s)
102
+ end
103
+
104
+ tokens = args[:key_condition_expression].split(/\s+/)
105
+ hash_key = tokens[2]
106
+ case tokens[5]
107
+ when ">="
108
+ start_val = tokens[6]
109
+ end_val = nil
110
+ when "<="
111
+ start_val = nil
112
+ end_val = tokens[6]
113
+ when "BETWEEN"
114
+ start_val = tokens[6]
115
+ end_val = tokens[8]
116
+ else
117
+ start_val = nil
118
+ end_val = nil
119
+ end
120
+ parent = @data[args[:table_name]][hash_key]
121
+ return OpenStruct.new(items:[]) unless parent
122
+
123
+ selected = parent.values
124
+ selected = selected.select{ |item| item[@range_key_attr] >= start_val.to_f } if start_val
125
+ selected = selected.select{ |item| item[@range_key_attr] <= end_val.to_f } if end_val
126
+
127
+ OpenStruct.new(items: selected)
128
+ end
129
+
93
130
  def reset
94
131
  @data = {}
95
132
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamini
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.7.7
4
+ version: 1.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Greg Ward
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2015-11-12 00:00:00.000000000 Z
18
+ date: 2015-12-10 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: activemodel