dynamini 1.7.7 → 1.8.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.
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