lotus-dynamodb 0.1.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 +7 -0
- data/.gitignore +21 -0
- data/.travis.yml +9 -0
- data/.yardopts +5 -0
- data/Gemfile +16 -0
- data/LICENSE.md +22 -0
- data/Procfile +1 -0
- data/README.md +112 -0
- data/Rakefile +17 -0
- data/benchmarks/coercer.rb +76 -0
- data/examples/Gemfile +2 -0
- data/examples/purchase.rb +164 -0
- data/lib/lotus/dynamodb/config.rb +14 -0
- data/lib/lotus/dynamodb/version.rb +8 -0
- data/lib/lotus/model/adapters/dynamodb/coercer.rb +211 -0
- data/lib/lotus/model/adapters/dynamodb/collection.rb +321 -0
- data/lib/lotus/model/adapters/dynamodb/command.rb +117 -0
- data/lib/lotus/model/adapters/dynamodb/query.rb +559 -0
- data/lib/lotus/model/adapters/dynamodb_adapter.rb +190 -0
- data/lib/lotus-dynamodb.rb +3 -0
- data/lotus-dynamodb.gemspec +30 -0
- data/test/fixtures.rb +75 -0
- data/test/model/adapters/dynamodb/coercer_test.rb +269 -0
- data/test/model/adapters/dynamodb/query_test.rb +259 -0
- data/test/model/adapters/dynamodb_adapter_test.rb +940 -0
- data/test/test_helper.rb +46 -0
- data/test/version_test.rb +7 -0
- metadata +203 -0
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'lotus/utils/kernel'
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
module Lotus
|
5
|
+
module Model
|
6
|
+
module Adapters
|
7
|
+
module Dynamodb
|
8
|
+
# Translates values from/to the database with the corresponding Ruby type.
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
class Coercer < Lotus::Model::Mapping::Coercer
|
13
|
+
SKIPPED_KLASSES = [Float, Integer, Set, String]
|
14
|
+
SUPPORTED_KLASSES = [AWS::DynamoDB::Binary, Array, Boolean, Date, DateTime, Hash, Time]
|
15
|
+
|
16
|
+
# Converts value from given type to DynamoDB record value.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.1.0
|
20
|
+
def from_aws_dynamodb_binary(value)
|
21
|
+
return value if value.nil? || value.is_a?(AWS::DynamoDB::Binary)
|
22
|
+
AWS::DynamoDB::Binary.new(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :to_aws_dynamodb_binary, :from_aws_dynamodb_binary
|
26
|
+
|
27
|
+
# Converts value from given type to DynamoDB record value.
|
28
|
+
#
|
29
|
+
# @api private
|
30
|
+
# @since 0.1.0
|
31
|
+
def from_array(value)
|
32
|
+
_serialize(value)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Converts value from DynamoDB record value to given type.
|
36
|
+
#
|
37
|
+
# @api private
|
38
|
+
# @since 0.1.0
|
39
|
+
def to_array(value)
|
40
|
+
_deserialize(value)
|
41
|
+
end
|
42
|
+
|
43
|
+
# Converts value from given type to DynamoDB record value.
|
44
|
+
#
|
45
|
+
# @api private
|
46
|
+
# @since 0.1.0
|
47
|
+
def from_boolean(value)
|
48
|
+
value ? 1 : 0
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts value from DynamoDB record value to given type.
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
# @since 0.1.0
|
55
|
+
def to_boolean(value)
|
56
|
+
value.to_i == 1
|
57
|
+
end
|
58
|
+
|
59
|
+
# Converts value from given type to DynamoDB record value.
|
60
|
+
#
|
61
|
+
# @api private
|
62
|
+
# @since 0.1.0
|
63
|
+
def from_date(value)
|
64
|
+
value.to_time.to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
# Converts value from DynamoDB record value to given type.
|
68
|
+
#
|
69
|
+
# @api private
|
70
|
+
# @since 0.1.0
|
71
|
+
def to_date(value)
|
72
|
+
Time.at(value.to_i).to_date
|
73
|
+
end
|
74
|
+
|
75
|
+
# Converts value from given type to DynamoDB record value.
|
76
|
+
#
|
77
|
+
# @api private
|
78
|
+
# @since 0.1.0
|
79
|
+
def from_datetime(value)
|
80
|
+
value.to_time.to_f
|
81
|
+
end
|
82
|
+
|
83
|
+
# Converts value from DynamoDB record value to given type.
|
84
|
+
#
|
85
|
+
# @api private
|
86
|
+
# @since 0.1.0
|
87
|
+
def to_datetime(value)
|
88
|
+
Time.at(value.to_f).to_datetime
|
89
|
+
end
|
90
|
+
|
91
|
+
# Converts value from given type to DynamoDB record value.
|
92
|
+
#
|
93
|
+
# @api private
|
94
|
+
# @since 0.1.0
|
95
|
+
def from_hash(value)
|
96
|
+
_serialize(value)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Converts value from DynamoDB record value to given type.
|
100
|
+
#
|
101
|
+
# @api private
|
102
|
+
# @since 0.1.0
|
103
|
+
def to_hash(value)
|
104
|
+
_deserialize(value)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Converts value from given type to DynamoDB record value.
|
108
|
+
#
|
109
|
+
# @api private
|
110
|
+
# @since 0.1.0
|
111
|
+
def from_time(value)
|
112
|
+
value.to_f
|
113
|
+
end
|
114
|
+
|
115
|
+
# Converts value from DynamoDB record value to given type.
|
116
|
+
#
|
117
|
+
# @api private
|
118
|
+
# @since 0.1.0
|
119
|
+
def to_time(value)
|
120
|
+
Time.at(value.to_f)
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
# Compile itself for performance boost.
|
125
|
+
#
|
126
|
+
# @api private
|
127
|
+
# @since 0.1.0
|
128
|
+
def _compile!
|
129
|
+
instance_eval(SKIPPED_KLASSES.map do |klass|
|
130
|
+
%{
|
131
|
+
def from_#{_method_name(klass)}(value)
|
132
|
+
value
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_#{_method_name(klass)}(value)
|
136
|
+
value
|
137
|
+
end
|
138
|
+
}
|
139
|
+
end.join("\n"))
|
140
|
+
|
141
|
+
code = @collection.attributes.map do |_,(klass,mapped)|
|
142
|
+
%{
|
143
|
+
def deserialize_#{ mapped }(value)
|
144
|
+
#{kernel_wrap(klass) { "from_#{_method_name(klass)}(value)" }}
|
145
|
+
end
|
146
|
+
|
147
|
+
def serialize_#{ mapped }(value)
|
148
|
+
from_#{_method_name(klass)}(value)
|
149
|
+
end
|
150
|
+
}
|
151
|
+
end.join("\n")
|
152
|
+
|
153
|
+
instance_eval %{
|
154
|
+
def to_record(entity)
|
155
|
+
if entity.id
|
156
|
+
Hash[*[#{ @collection.attributes.map{|name,(klass,mapped)| ":#{mapped},from_#{_method_name(klass)}(entity.#{name})"}.join(',') }]]
|
157
|
+
else
|
158
|
+
Hash[*[#{ @collection.attributes.reject{|name,_| name == @collection.identity }.map{|name,(klass,mapped)| ":#{mapped},from_#{_method_name(klass)}(entity.#{name})"}.join(',') }]]
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def from_record(record)
|
163
|
+
#{ @collection.entity }.new(
|
164
|
+
Hash[*[#{ @collection.attributes.map{|name,(klass,mapped)| ":#{name},#{kernel_wrap(klass) { "to_#{_method_name(klass)}(record[:#{mapped}])" }}"}.join(',') }]]
|
165
|
+
)
|
166
|
+
end
|
167
|
+
|
168
|
+
#{ code }
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
# Wraps string in Lotus::Utils::Kernel call if needed.
|
173
|
+
#
|
174
|
+
# @api private
|
175
|
+
# @since 0.1.0
|
176
|
+
def kernel_wrap(klass)
|
177
|
+
if klass.to_s.include?("::")
|
178
|
+
yield
|
179
|
+
else
|
180
|
+
"Lotus::Utils::Kernel.#{klass}(#{yield})"
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
# Returns method name from klass.
|
185
|
+
#
|
186
|
+
# @api private
|
187
|
+
# @since 0.1.0
|
188
|
+
def _method_name(klass)
|
189
|
+
klass.to_s.downcase.gsub("::", "_")
|
190
|
+
end
|
191
|
+
|
192
|
+
# Serializes value to string.
|
193
|
+
#
|
194
|
+
# @api private
|
195
|
+
# @since 0.1.0
|
196
|
+
def _serialize(value)
|
197
|
+
MultiJson.dump(value)
|
198
|
+
end
|
199
|
+
|
200
|
+
# Deserializes value from string.
|
201
|
+
#
|
202
|
+
# @api private
|
203
|
+
# @since 0.1.0
|
204
|
+
def _deserialize(value)
|
205
|
+
MultiJson.load(value)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'aws-sdk'
|
3
|
+
require 'lotus/utils/hash'
|
4
|
+
|
5
|
+
module Lotus
|
6
|
+
module Model
|
7
|
+
module Adapters
|
8
|
+
module Dynamodb
|
9
|
+
# Acts like table, using AWS::DynamoDB::Client.
|
10
|
+
#
|
11
|
+
# @api private
|
12
|
+
# @since 0.1.0
|
13
|
+
class Collection
|
14
|
+
include AWS::DynamoDB::Types
|
15
|
+
|
16
|
+
# Response interface provides count and entities.
|
17
|
+
#
|
18
|
+
# @api private
|
19
|
+
# @since 0.1.0
|
20
|
+
class Response
|
21
|
+
attr_accessor :count, :entities
|
22
|
+
|
23
|
+
def initialize(count, entities = nil)
|
24
|
+
@count, @entities = count, entities
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# @attr_reader name [String] the name of the collection (eg. `users`)
|
29
|
+
#
|
30
|
+
# @since 0.1.0
|
31
|
+
# @api private
|
32
|
+
attr_reader :name
|
33
|
+
|
34
|
+
# @attr_reader identity [Symbol] the primary key of the collection
|
35
|
+
# (eg. `:id`)
|
36
|
+
#
|
37
|
+
# @since 0.1.0
|
38
|
+
# @api private
|
39
|
+
attr_reader :identity
|
40
|
+
|
41
|
+
# Initialize a collection.
|
42
|
+
#
|
43
|
+
# @param client [AWS::DynamoDB::Client] DynamoDB client
|
44
|
+
# @param coercer [Lotus::Model::Adapters::Dynamodb::Coercer]
|
45
|
+
# @param name [Symbol] the name of the collection (eg. `:users`)
|
46
|
+
# @param identity [Symbol] the primary key of the collection
|
47
|
+
# (eg. `:id`).
|
48
|
+
#
|
49
|
+
# @api private
|
50
|
+
# @since 0.1.0
|
51
|
+
def initialize(client, coercer, name, identity)
|
52
|
+
@client, @coercer = client, coercer
|
53
|
+
@name, @identity = name.to_s, identity
|
54
|
+
@key_schema = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
# Creates a record for the given entity and returns a primary key.
|
58
|
+
#
|
59
|
+
# @param entity [Object] the entity to persist
|
60
|
+
#
|
61
|
+
# @see Lotus::Model::Adapters::Dynamodb::Command#create
|
62
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#put_item-instance_method
|
63
|
+
#
|
64
|
+
# @return the primary key of the just created record.
|
65
|
+
#
|
66
|
+
# @api private
|
67
|
+
# @since 0.1.0
|
68
|
+
def create(entity)
|
69
|
+
entity[identity] ||= SecureRandom.uuid
|
70
|
+
|
71
|
+
@client.put_item(
|
72
|
+
table_name: name,
|
73
|
+
item: serialize_item(entity),
|
74
|
+
)
|
75
|
+
|
76
|
+
entity[identity]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Updates the record corresponding to the given entity.
|
80
|
+
#
|
81
|
+
# @param entity [Object] the entity to persist
|
82
|
+
#
|
83
|
+
# @see Lotus::Model::Adapters::Dynamodb::Command#update
|
84
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#update_item-instance_method
|
85
|
+
#
|
86
|
+
# @api private
|
87
|
+
# @since 0.1.0
|
88
|
+
def update(entity)
|
89
|
+
@client.update_item(
|
90
|
+
table_name: name,
|
91
|
+
key: serialize_key(entity),
|
92
|
+
attribute_updates: serialize_attributes(entity),
|
93
|
+
)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Deletes the record corresponding to the given entity.
|
97
|
+
#
|
98
|
+
# @param entity [Object] the entity to delete
|
99
|
+
#
|
100
|
+
# @see Lotus::Model::Adapters::Dynamodb::Command#delete
|
101
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#delete_item-instance_method
|
102
|
+
#
|
103
|
+
# @api private
|
104
|
+
# @since 0.1.0
|
105
|
+
def delete(entity)
|
106
|
+
@client.delete_item(
|
107
|
+
table_name: name,
|
108
|
+
key: serialize_key(entity),
|
109
|
+
)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Returns an unique record from the given collection, with the given
|
113
|
+
# id.
|
114
|
+
#
|
115
|
+
# @param key [Array] the identity of the object
|
116
|
+
#
|
117
|
+
# @see Lotus::Model::Adapters::Dynamodb::Command#get
|
118
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#get_item-instance_method
|
119
|
+
#
|
120
|
+
# @return [Hash] the serialized record
|
121
|
+
#
|
122
|
+
# @api private
|
123
|
+
# @since 0.1.0
|
124
|
+
def get(key)
|
125
|
+
return if key.any? { |v| v.to_s == "" }
|
126
|
+
return if key.count != key_schema.count
|
127
|
+
|
128
|
+
response = @client.get_item(
|
129
|
+
table_name: name,
|
130
|
+
key: serialize_key(key),
|
131
|
+
)
|
132
|
+
|
133
|
+
deserialize_item(response[:item]) if response[:item]
|
134
|
+
end
|
135
|
+
|
136
|
+
# Performs DynamoDB query operation.
|
137
|
+
#
|
138
|
+
# @param options [Hash] AWS::DynamoDB::Client options
|
139
|
+
#
|
140
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#query-instance_method
|
141
|
+
#
|
142
|
+
# @return [Array<Hash>] the serialized entities
|
143
|
+
#
|
144
|
+
# @api private
|
145
|
+
# @since 0.1.0
|
146
|
+
def query(options = {})
|
147
|
+
response = @client.query(options.merge(table_name: name))
|
148
|
+
deserialize_response(response)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Performs DynamoDB scan operation.
|
152
|
+
#
|
153
|
+
# @param options [Hash] AWS::DynamoDB::Client options
|
154
|
+
#
|
155
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#scan-instance_method
|
156
|
+
#
|
157
|
+
# @return [Array<Hash>] the serialized entities
|
158
|
+
#
|
159
|
+
# @api private
|
160
|
+
# @since 0.1.0
|
161
|
+
def scan(options = {})
|
162
|
+
response = @client.scan(options.merge(table_name: name))
|
163
|
+
deserialize_response(response)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Fetches DynamoDB table schema.
|
167
|
+
#
|
168
|
+
# @see http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/DynamoDB/Client/V20120810.html#describe_table-instance_method
|
169
|
+
#
|
170
|
+
# @return [Hash] table schema definition
|
171
|
+
#
|
172
|
+
# @api private
|
173
|
+
# @since 0.1.0
|
174
|
+
def schema
|
175
|
+
@schema ||= @client.describe_table(table_name: name).fetch(:table)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Maps table key schema to hash with attribute name as key and key
|
179
|
+
# type as value.
|
180
|
+
#
|
181
|
+
# @param index [String] index to check (defaults to table itself)
|
182
|
+
#
|
183
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#schema
|
184
|
+
#
|
185
|
+
# @return [Hash] key schema definition
|
186
|
+
#
|
187
|
+
# @api private
|
188
|
+
# @since 0.1.0
|
189
|
+
def key_schema(index = nil)
|
190
|
+
return @key_schema[index] if @key_schema[index]
|
191
|
+
|
192
|
+
current_schema = if index
|
193
|
+
everything = Array(schema[:local_secondary_indexes]) +
|
194
|
+
Array(schema[:global_secondary_indexes])
|
195
|
+
indexes = Hash[everything.map { |i| [i[:index_name], i] }]
|
196
|
+
indexes[index][:key_schema]
|
197
|
+
else
|
198
|
+
schema[:key_schema]
|
199
|
+
end
|
200
|
+
|
201
|
+
@key_schema[index] ||= Hash[current_schema.to_a.map do |key|
|
202
|
+
[key[:attribute_name].to_sym, key[:key_type]]
|
203
|
+
end]
|
204
|
+
end
|
205
|
+
|
206
|
+
# Checks if given column is in key schema or not.
|
207
|
+
#
|
208
|
+
# @param column [String] column to check
|
209
|
+
# @param index [String] index to check (defaults to table itself)
|
210
|
+
#
|
211
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#key_schema
|
212
|
+
#
|
213
|
+
# @return [Boolean]
|
214
|
+
#
|
215
|
+
# @api private
|
216
|
+
# @since 0.1.0
|
217
|
+
def key?(column, index = nil)
|
218
|
+
key_schema(index).has_key?(column)
|
219
|
+
end
|
220
|
+
|
221
|
+
# Coerce and format attribute value to match DynamoDB type.
|
222
|
+
#
|
223
|
+
# @param column [String] the attribute column
|
224
|
+
# @param value [Object] the attribute value
|
225
|
+
#
|
226
|
+
# @see AWS::DynamoDB::Types
|
227
|
+
#
|
228
|
+
# @return [Hash] the formatted attribute
|
229
|
+
#
|
230
|
+
# @api private
|
231
|
+
# @since 0.1.0
|
232
|
+
def format_attribute(column, value)
|
233
|
+
value = @coercer.public_send(:"serialize_#{ column }", value)
|
234
|
+
format_attribute_value(value)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Serialize given record to have proper attributes for 'item' query.
|
238
|
+
#
|
239
|
+
# @param record [Hash] the serialized record
|
240
|
+
#
|
241
|
+
# @see AWS::DynamoDB::Types
|
242
|
+
#
|
243
|
+
# @return [Hash] the serialized item
|
244
|
+
#
|
245
|
+
# @api private
|
246
|
+
# @since 0.1.0
|
247
|
+
def serialize_item(record)
|
248
|
+
Hash[record.map { |k, v| [k.to_s, format_attribute_value(v)] }]
|
249
|
+
end
|
250
|
+
|
251
|
+
# Serialize given record or primary key to have proper attributes
|
252
|
+
# for 'key' query.
|
253
|
+
#
|
254
|
+
# @param record [Hash,Array] the serialized record or primary key
|
255
|
+
#
|
256
|
+
# @see AWS::DynamoDB::Types
|
257
|
+
#
|
258
|
+
# @return [Hash] the serialized key
|
259
|
+
#
|
260
|
+
# @api private
|
261
|
+
# @since 0.1.0
|
262
|
+
def serialize_key(record)
|
263
|
+
Hash[key_schema.keys.each_with_index.map do |k, idx|
|
264
|
+
v = record.is_a?(Hash) ? record[k] : record[idx]
|
265
|
+
[k.to_s, format_attribute(k, v)]
|
266
|
+
end]
|
267
|
+
end
|
268
|
+
|
269
|
+
# Serialize given entity to exclude key schema attributes.
|
270
|
+
#
|
271
|
+
# @param entity [Hash] the entity
|
272
|
+
#
|
273
|
+
# @see AWS::DynamoDB::Types
|
274
|
+
#
|
275
|
+
# @return [Hash] the serialized attributes
|
276
|
+
#
|
277
|
+
# @api private
|
278
|
+
# @since 0.1.0
|
279
|
+
def serialize_attributes(entity)
|
280
|
+
keys = key_schema.keys
|
281
|
+
Hash[entity.reject { |k, _| keys.include?(k) }.map do |k, v|
|
282
|
+
[k.to_s, { value: format_attribute_value(v), action: "PUT" }]
|
283
|
+
end]
|
284
|
+
end
|
285
|
+
|
286
|
+
# Deserialize DynamoDB scan/query response.
|
287
|
+
#
|
288
|
+
# @param response [Hash] the serialized response
|
289
|
+
#
|
290
|
+
# @return [Hash] the deserialized response
|
291
|
+
#
|
292
|
+
# @api private
|
293
|
+
# @since 0.1.0
|
294
|
+
def deserialize_response(response)
|
295
|
+
result = Response.new(response[:count])
|
296
|
+
|
297
|
+
result.entities = response[:member].map do |item|
|
298
|
+
deserialize_item(item)
|
299
|
+
end if response[:member]
|
300
|
+
|
301
|
+
result
|
302
|
+
end
|
303
|
+
|
304
|
+
# Deserialize item from DynamoDB response.
|
305
|
+
#
|
306
|
+
# @param item [Hash] the serialized item
|
307
|
+
#
|
308
|
+
# @see AWS::DynamoDB::Types
|
309
|
+
#
|
310
|
+
# @return [Hash] the deserialized record
|
311
|
+
#
|
312
|
+
# @api private
|
313
|
+
# @since 0.1.0
|
314
|
+
def deserialize_item(record)
|
315
|
+
Lotus::Utils::Hash.new(values_from_response_hash(record)).symbolize!
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Lotus
|
2
|
+
module Model
|
3
|
+
module Adapters
|
4
|
+
module Dynamodb
|
5
|
+
# Execute a command for the given collection.
|
6
|
+
#
|
7
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection
|
8
|
+
# @see Lotus::Model::Mapping::Collection
|
9
|
+
#
|
10
|
+
# @api private
|
11
|
+
# @since 0.1.0
|
12
|
+
class Command
|
13
|
+
# Initialize a command.
|
14
|
+
#
|
15
|
+
# @param dataset [Lotus::Model::Adapters::Dynamodb::Collection]
|
16
|
+
# @param collection [Lotus::Model::Mapping::Collection]
|
17
|
+
#
|
18
|
+
# @return [Lotus::Model::Adapters::Dynamodb::Command]
|
19
|
+
#
|
20
|
+
# @api private
|
21
|
+
# @since 0.1.0
|
22
|
+
def initialize(dataset, collection)
|
23
|
+
@dataset, @collection = dataset, collection
|
24
|
+
end
|
25
|
+
|
26
|
+
# Creates a record for the given entity.
|
27
|
+
#
|
28
|
+
# @param entity [Object] the entity to persist
|
29
|
+
#
|
30
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#create
|
31
|
+
#
|
32
|
+
# @return the primary key of the just created record.
|
33
|
+
#
|
34
|
+
# @api private
|
35
|
+
# @since 0.1.0
|
36
|
+
def create(entity)
|
37
|
+
@dataset.create(
|
38
|
+
_serialize(entity)
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Updates the corresponding record for the given entity.
|
43
|
+
#
|
44
|
+
# @param entity [Object] the entity to persist
|
45
|
+
#
|
46
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#update
|
47
|
+
#
|
48
|
+
# @api private
|
49
|
+
# @since 0.1.0
|
50
|
+
def update(entity)
|
51
|
+
@dataset.update(
|
52
|
+
_serialize(entity)
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Deletes the corresponding record for the given entity.
|
57
|
+
#
|
58
|
+
# @param entity [Object] the entity to delete
|
59
|
+
#
|
60
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#delete
|
61
|
+
#
|
62
|
+
# @api private
|
63
|
+
# @since 0.1.0
|
64
|
+
def delete(entity)
|
65
|
+
@dataset.delete(
|
66
|
+
_serialize(entity)
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an unique record from the given collection, with the given
|
71
|
+
# id.
|
72
|
+
#
|
73
|
+
# @param key [Array] the identity of the object
|
74
|
+
#
|
75
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#get
|
76
|
+
#
|
77
|
+
# @return [Object] the entity
|
78
|
+
#
|
79
|
+
# @api private
|
80
|
+
# @since 0.1.0
|
81
|
+
def get(key)
|
82
|
+
@collection.deserialize(
|
83
|
+
[@dataset.get(key)].compact
|
84
|
+
).first
|
85
|
+
end
|
86
|
+
|
87
|
+
# Deletes all the records from the table.
|
88
|
+
#
|
89
|
+
# @see Lotus::Model::Adapters::Dynamodb::Collection#scan
|
90
|
+
# @see Lotus::Model::Mapping::Collection
|
91
|
+
#
|
92
|
+
# @api private
|
93
|
+
# @since 0.1.0
|
94
|
+
def clear
|
95
|
+
@collection.deserialize(@dataset.scan.entities).each do |entity|
|
96
|
+
delete(entity)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
# Serialize the given entity before to persist in the database.
|
102
|
+
#
|
103
|
+
# @param entity [Object] the entity
|
104
|
+
#
|
105
|
+
# @return [Hash] the serialized entity
|
106
|
+
#
|
107
|
+
# @api private
|
108
|
+
# @since 0.1.0
|
109
|
+
def _serialize(entity)
|
110
|
+
serialized = @collection.serialize(entity)
|
111
|
+
serialized.delete_if { |_, v| v.nil? }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|