dynamodb_record 0.2.2 → 0.3.1
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 +4 -4
- data/.rubocop.yml +55 -0
- data/dynamodb_record.gemspec +1 -1
- data/lib/dynamodb_record/associations.rb +76 -27
- data/lib/dynamodb_record/collection.rb +18 -27
- data/lib/dynamodb_record/config.rb +2 -0
- data/lib/dynamodb_record/fields.rb +11 -12
- data/lib/dynamodb_record/finders.rb +1 -0
- data/lib/dynamodb_record/has_and_belongs_to_many_collection.rb +67 -0
- data/lib/dynamodb_record/has_many_collection.rb +50 -0
- data/lib/dynamodb_record/has_many_through_collection.rb +44 -0
- data/lib/dynamodb_record/pager.rb +15 -0
- data/lib/dynamodb_record/persistence.rb +19 -19
- data/lib/dynamodb_record/query.rb +12 -9
- data/lib/dynamodb_record/query_pager.rb +28 -0
- data/lib/dynamodb_record/scan_pager.rb +28 -0
- data/lib/dynamodb_record/version.rb +1 -1
- data/lib/dynamodb_record.rb +6 -0
- data/spec/app/models/authorization.rb +0 -1
- data/spec/app/models/car.rb +9 -0
- data/spec/app/models/insurance.rb +9 -0
- data/spec/app/models/service.rb +8 -0
- data/spec/app/models/user.rb +2 -0
- data/spec/dynamodb_record/association_spec.rb +51 -0
- data/spec/dynamodb_record/document_spec.rb +2 -2
- data/spec/dynamodb_record/fields_spec.rb +21 -15
- data/spec/dynamodb_record/persistence_spec.rb +3 -2
- data/spec/dynamodb_record/query_spec.rb +5 -3
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_belongs_to/get_object.yml +105 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/add_list.yml +311 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/create_item.yml +156 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/get_collection.yml +105 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/has_and_belongs_to_many.yml +157 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/has_and_belongs_to_many_create.yml +207 -0
- data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/has_many_through.yml +157 -0
- data/spec/spec_helper.rb +3 -2
- metadata +23 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 90c0fa26f80217dbc4d6a3f2e3fa0197a485fdcaf4bb845232c276d67c2c678e
|
4
|
+
data.tar.gz: 61d5b4ca06cfb8906902aee1ae6bafc0c4613f03edfb402447514f9877317143
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea0d8a245f9f6a41c47d4cf0ef9f5ba056c31712588146b9b14f0c0886f36b487fa691c79383e93bbe34e3c87ceebdd5e8b80bb3b4f1a4ed48812944a9970985
|
7
|
+
data.tar.gz: 3c734251bd6e00ebc3ab048e702b9ed133296e0acdc09690b6da12b8c9ec7edb3f13d09a28c837d2393dc637359e228c36e334365e1a497f11890145d8db92e9
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 3.2
|
3
|
+
NewCops: enable
|
4
|
+
Exclude:
|
5
|
+
- 'spec/dummy/bin/*'
|
6
|
+
- vendor/**
|
7
|
+
- 'vendor/**/*'
|
8
|
+
- vendor/bundle/**/*
|
9
|
+
- bin/**
|
10
|
+
Layout/SpaceInsideHashLiteralBraces:
|
11
|
+
EnforcedStyle: no_space
|
12
|
+
Metrics/BlockLength:
|
13
|
+
Max: 36
|
14
|
+
Exclude:
|
15
|
+
- spec/**/*.rb
|
16
|
+
- fleteo.gemspec
|
17
|
+
|
18
|
+
Lint/ConstantDefinitionInBlock:
|
19
|
+
Exclude:
|
20
|
+
- spec/**/**/*.rb
|
21
|
+
Metrics/BlockNesting:
|
22
|
+
Max: 2
|
23
|
+
Metrics/MethodLength:
|
24
|
+
CountComments: false
|
25
|
+
Max: 15
|
26
|
+
Metrics/ModuleLength:
|
27
|
+
Max: 120
|
28
|
+
Metrics/ClassLength:
|
29
|
+
Max: 120
|
30
|
+
Metrics/ParameterLists:
|
31
|
+
Max: 5
|
32
|
+
CountKeywordArgs: true
|
33
|
+
Style/CollectionMethods:
|
34
|
+
Enabled: true
|
35
|
+
PreferredMethods:
|
36
|
+
collect: 'map'
|
37
|
+
collect!: 'map!'
|
38
|
+
inject: 'reduce'
|
39
|
+
find: 'detect'
|
40
|
+
find_all: 'select'
|
41
|
+
delete: 'gsub'
|
42
|
+
Layout/DotPosition:
|
43
|
+
EnforcedStyle: trailing
|
44
|
+
|
45
|
+
#Layout/LineLength:
|
46
|
+
# Max: 100
|
47
|
+
|
48
|
+
Style/TrailingCommaInArrayLiteral:
|
49
|
+
EnforcedStyleForMultiline: 'no_comma'
|
50
|
+
|
51
|
+
Style/TrailingCommaInHashLiteral:
|
52
|
+
EnforcedStyleForMultiline: 'no_comma'
|
53
|
+
|
54
|
+
Gemspec/DevelopmentDependencies:
|
55
|
+
EnforcedStyle: gemspec
|
data/dynamodb_record.gemspec
CHANGED
@@ -16,7 +16,6 @@ Gem::Specification.new do |spec|
|
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
19
|
spec.require_paths = ['lib']
|
21
20
|
|
22
21
|
spec.add_dependency 'activesupport', '~> 7.1', '>= 7.1.3.2'
|
@@ -29,4 +28,5 @@ Gem::Specification.new do |spec|
|
|
29
28
|
spec.add_development_dependency 'rubocop', '~> 1.62'
|
30
29
|
spec.add_development_dependency 'vcr', '~> 6.2'
|
31
30
|
spec.add_development_dependency 'webmock', '~> 3.23'
|
31
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
32
32
|
end
|
@@ -5,24 +5,66 @@ module DynamodbRecord
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
class_methods do
|
8
|
+
def belongs_to(association)
|
9
|
+
association = association.to_s
|
10
|
+
|
11
|
+
define_method(association) do
|
12
|
+
id = send("#{association}_id")
|
13
|
+
klass = Object.const_get(association.capitalize)
|
14
|
+
klass.find!(id)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop:disable Naming/PredicateName
|
8
19
|
def has_many(associations)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
options = { table_name: associations }
|
14
|
-
options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
|
15
|
-
options.merge!(expression_attribute_names: { "##{field}_id": "#{field}_id" })
|
16
|
-
options.merge!(expression_attribute_values: { ":#{field}_id" => id })
|
20
|
+
base_model = to_s.downcase
|
21
|
+
model = associations.to_s.chop
|
22
|
+
# field = self.class.to_s.downcase
|
23
|
+
table = Config.namespace ? "#{Config.namespace}-#{associations}" : associations
|
17
24
|
|
18
|
-
|
25
|
+
options = {table_name: table}
|
26
|
+
options.merge!(key_condition_expression: "##{base_model}_id = :#{base_model}_id")
|
27
|
+
options.merge!(expression_attribute_names: {"##{base_model}_id": "#{base_model}_id"})
|
28
|
+
options.merge!(index_name: "#{base_model}_id_index")
|
19
29
|
|
30
|
+
define_method(associations) do
|
31
|
+
options.merge!(expression_attribute_values: {":#{base_model}_id" => id})
|
20
32
|
klass = Object.const_get(model.capitalize)
|
21
|
-
|
22
|
-
|
33
|
+
query = QueryPager.new(options, klass)
|
34
|
+
HasManyCollection.new(query, self)
|
35
|
+
end
|
36
|
+
end
|
23
37
|
|
24
|
-
|
25
|
-
|
38
|
+
def has_many_through(associations, table)
|
39
|
+
base_model = to_s.downcase
|
40
|
+
relation_model = associations.to_s.chop
|
41
|
+
list = []
|
42
|
+
list << base_model
|
43
|
+
list << relation_model
|
44
|
+
sorted_list = list.sort
|
45
|
+
options = {table_name: table.to_s}
|
46
|
+
|
47
|
+
field = if sorted_list.first == base_model
|
48
|
+
sorted_list.first
|
49
|
+
else
|
50
|
+
sorted_list.last
|
51
|
+
end
|
52
|
+
options.merge!(index_name: "#{field}_id_index")
|
53
|
+
options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
|
54
|
+
options.merge!(expression_attribute_names: {"##{field}_id": "#{field}_id"})
|
55
|
+
|
56
|
+
define_method(associations) do
|
57
|
+
options.merge!(expression_attribute_values: {":#{field}_id" => id})
|
58
|
+
# p options
|
59
|
+
|
60
|
+
klass = Object.const_get(relation_model.capitalize)
|
61
|
+
|
62
|
+
# options.merge!(limit: 1)
|
63
|
+
# p options
|
64
|
+
|
65
|
+
query = QueryPager.new(options, klass)
|
66
|
+
|
67
|
+
HasManyThroughCollection.new(query, self)
|
26
68
|
end
|
27
69
|
end
|
28
70
|
|
@@ -33,27 +75,34 @@ module DynamodbRecord
|
|
33
75
|
list << base_model
|
34
76
|
list << relation_model
|
35
77
|
sorted_list = list.sort
|
36
|
-
|
78
|
+
options = {}
|
79
|
+
pluralize_name = sorted_list.map(&:pluralize).join('-')
|
80
|
+
|
81
|
+
table = Config.namespace ? "#{Config.namespace}-#{pluralize_name}" : pluralize_name
|
82
|
+
options[:table_name] = table
|
83
|
+
if sorted_list.first == base_model
|
84
|
+
field = sorted_list.first
|
85
|
+
else
|
86
|
+
field = sorted_list.last
|
87
|
+
options.merge!(index_name: "#{table}-index")
|
88
|
+
end
|
89
|
+
|
90
|
+
options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
|
91
|
+
options.merge!(expression_attribute_names: {"##{field}_id": "#{field}_id"})
|
37
92
|
|
38
93
|
define_method(associations) do
|
39
|
-
options
|
40
|
-
|
41
|
-
if sorted_list.first == base_model
|
42
|
-
field = sorted_list.first
|
43
|
-
else
|
44
|
-
field = sorted_list.last
|
45
|
-
options.merge!(index_name: "#{table}_index")
|
46
|
-
end
|
47
|
-
options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
|
48
|
-
options.merge!(expression_attribute_names: { "##{field}_id": "#{field}_id" })
|
49
|
-
options.merge!(expression_attribute_values: { ":#{field}_id" => id })
|
94
|
+
options.merge!(expression_attribute_values: {":#{field}_id" => id})
|
50
95
|
|
51
96
|
klass = Object.const_get(relation_model.capitalize)
|
52
|
-
response = self.class.client.query(options)
|
53
97
|
|
54
|
-
|
98
|
+
# options.merge!(limit: 1)
|
99
|
+
# p options
|
100
|
+
|
101
|
+
query = QueryPager.new(options, klass)
|
102
|
+
HasAndBelongsToManyCollection.new(query, self)
|
55
103
|
end
|
56
104
|
end
|
105
|
+
# rubocop:enable Naming/PredicateName
|
57
106
|
end
|
58
107
|
end
|
59
108
|
end
|
@@ -6,42 +6,33 @@ module DynamodbRecord
|
|
6
6
|
|
7
7
|
# attr_reader :last_evaluated_key
|
8
8
|
|
9
|
-
def initialize(pager,
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def last_evaluated_key
|
18
|
-
if @last_evaluated_key.nil?
|
19
|
-
nil
|
20
|
-
else
|
21
|
-
json_string = JSON.dump(@last_evaluated_key)
|
22
|
-
Base64.urlsafe_encode64(json_string)
|
23
|
-
end
|
9
|
+
def initialize(pager, base_object)
|
10
|
+
@base_object = base_object
|
11
|
+
@pager = pager
|
12
|
+
@klass = @pager.klass
|
13
|
+
@options = @pager.options
|
14
|
+
items = @pager.items
|
15
|
+
@items = items.map { |item| @klass.send(:from_database, item) }
|
24
16
|
end
|
25
17
|
|
26
18
|
def each(&)
|
27
19
|
@items.each(&)
|
28
20
|
end
|
29
21
|
|
22
|
+
def last_evaluated_key
|
23
|
+
@pager.last_evaluated_key
|
24
|
+
end
|
25
|
+
|
30
26
|
def next_page?
|
31
|
-
|
27
|
+
@pager ? @pager.next_page? : false
|
28
|
+
end
|
29
|
+
|
30
|
+
def next_page
|
31
|
+
self.class.new(@pager.next_page, @base_object)
|
32
32
|
end
|
33
33
|
|
34
|
-
def
|
35
|
-
|
36
|
-
object = @klass.create!(items)
|
37
|
-
unless @klass.to_s.pluralize.downcase == @table_name.to_s
|
38
|
-
|
39
|
-
client = @klass.client
|
40
|
-
@foreign_key.merge!({ "#{@klass.to_s.downcase}_id": object.id, created_at: Time.now.to_i })
|
41
|
-
client.put_item({ table_name: @table_name, item: @foreign_key })
|
42
|
-
end
|
43
|
-
@items << object
|
44
|
-
object
|
34
|
+
def page(last_key)
|
35
|
+
self.class.new(@pager.next_page(last_key), @base_object) if last_key
|
45
36
|
end
|
46
37
|
end
|
47
38
|
end
|
@@ -19,7 +19,7 @@ module DynamodbRecord
|
|
19
19
|
def field(name, type = :string, opts = {})
|
20
20
|
named = name.to_s
|
21
21
|
# Add attributes
|
22
|
-
attributes.merge!(name => {
|
22
|
+
attributes.merge!(name => {type:, options: opts})
|
23
23
|
|
24
24
|
# self.hash_key = name if opts[:hash_key]
|
25
25
|
# self.range_key = name if opts[:range_key]
|
@@ -60,11 +60,10 @@ module DynamodbRecord
|
|
60
60
|
DateTime.parse(value)
|
61
61
|
end
|
62
62
|
when :array
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
63
|
+
raise ArgumentError, 'Array column' unless value.is_a?(Array)
|
64
|
+
|
65
|
+
value
|
66
|
+
|
68
67
|
else
|
69
68
|
raise ArgumentError, "Unknown type #{options[:type]}"
|
70
69
|
end
|
@@ -84,21 +83,21 @@ module DynamodbRecord
|
|
84
83
|
def unload(attrs)
|
85
84
|
{}.tap do |hash|
|
86
85
|
attrs.each do |key, value|
|
87
|
-
# if attributes[key.to_sym][:options][:hash_key]
|
88
|
-
# hash[:pk] = dump_field(value, attributes[key.to_sym])
|
89
|
-
# end
|
90
|
-
|
91
86
|
hash[key] = dump_field(value, attributes[key.to_sym])
|
92
87
|
end
|
93
88
|
end
|
94
89
|
end
|
95
90
|
|
96
91
|
def hash_key
|
97
|
-
@hash_key = attributes.select { |_k,v| v[:options][:hash_key] }.keys.first || :id
|
92
|
+
@hash_key = attributes.select { |_k, v| v[:options][:hash_key] }.keys.first || :id
|
98
93
|
end
|
99
94
|
|
100
95
|
def range_key
|
101
|
-
@range_key ||=
|
96
|
+
@range_key ||= begin
|
97
|
+
attributes.select { |_k, v| v[:options][:range_key] }.keys.first
|
98
|
+
rescue StandardError
|
99
|
+
nil
|
100
|
+
end
|
102
101
|
end
|
103
102
|
|
104
103
|
def secondary_indexes
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamodbRecord
|
4
|
+
# +Dynamodb::ManyToManyCollection+ is a class that represent a ManyToManyCollection
|
5
|
+
class HasAndBelongsToManyCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(pager, base_object)
|
9
|
+
@base_object = base_object
|
10
|
+
@pager = pager
|
11
|
+
@klass = @pager.klass
|
12
|
+
@options = @pager.options
|
13
|
+
@items = []
|
14
|
+
@pager.items.each do |item|
|
15
|
+
# p item
|
16
|
+
object = @klass.client.get_item(
|
17
|
+
table_name: @klass.table_name,
|
18
|
+
key: {id: item["#{@klass.to_s.downcase}_id"]}
|
19
|
+
)
|
20
|
+
@items << @klass.send(:from_database, object.item)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&)
|
25
|
+
@items.each(&)
|
26
|
+
end
|
27
|
+
|
28
|
+
def last_evaluated_key
|
29
|
+
@pager.last_evaluated_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_page?
|
33
|
+
@pager ? @pager.next_page? : false
|
34
|
+
end
|
35
|
+
|
36
|
+
def next_page
|
37
|
+
self.class.new(@pager.next_page, @base_object)
|
38
|
+
end
|
39
|
+
|
40
|
+
def page(last_key)
|
41
|
+
self.class.new(@pager.next_page(last_key), @base_object) if last_key
|
42
|
+
end
|
43
|
+
|
44
|
+
def <<(object)
|
45
|
+
table_name = @options[:table_name]
|
46
|
+
item = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
|
47
|
+
item[:"#{@klass.to_s.downcase}_id"] = object.id
|
48
|
+
key = {table_name:, item:}
|
49
|
+
@klass.client.put_item(key)
|
50
|
+
@items << object
|
51
|
+
end
|
52
|
+
|
53
|
+
def create!(params = {})
|
54
|
+
raise "#{@base_object.class} must be saved" if @base_object.new_record
|
55
|
+
|
56
|
+
object = @klass.send(:from_database, params)
|
57
|
+
object.save!
|
58
|
+
table_name = @options[:table_name]
|
59
|
+
item = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
|
60
|
+
|
61
|
+
item[:"#{@klass.to_s.downcase}_id"] = object.id
|
62
|
+
key = {table_name:, item:}
|
63
|
+
@klass.client.put_item(key)
|
64
|
+
object
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamodbRecord
|
4
|
+
# +Dynamodb::ManyToManyCollection+ is a class that represent a ManyToManyCollection
|
5
|
+
class HasManyCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(pager, base_object)
|
9
|
+
@base_object = base_object
|
10
|
+
@pager = pager
|
11
|
+
@klass = @pager.klass
|
12
|
+
@options = @pager.options
|
13
|
+
@foreign_key = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
|
14
|
+
@items = []
|
15
|
+
@pager.items.each do |object|
|
16
|
+
@items << @klass.send(:from_database, object)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def each(&)
|
21
|
+
@items.each(&)
|
22
|
+
end
|
23
|
+
|
24
|
+
def last_evaluated_key
|
25
|
+
@pager.last_evaluated_key
|
26
|
+
end
|
27
|
+
|
28
|
+
def next_page?
|
29
|
+
@pager ? @pager.next_page? : false
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_page
|
33
|
+
self.class.new(@pager.next_page, @base_object)
|
34
|
+
end
|
35
|
+
|
36
|
+
def page(last_key)
|
37
|
+
self.class.new(@pager.next_page(last_key), @base_object) if last_key
|
38
|
+
end
|
39
|
+
|
40
|
+
def create!(params = {})
|
41
|
+
raise "#{@base_object.class} must be saved" if @base_object.new_record
|
42
|
+
|
43
|
+
params.merge!(@foreign_key)
|
44
|
+
object = @klass.send(:from_database, params)
|
45
|
+
object.save!
|
46
|
+
@items << object
|
47
|
+
object
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamodbRecord
|
4
|
+
# +Dynamodb::HasManyThroughCollection+ is a class that represent a ManyToManyCollection
|
5
|
+
class HasManyThroughCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def initialize(pager, base_object)
|
9
|
+
@base_object = base_object
|
10
|
+
@pager = pager
|
11
|
+
@klass = @pager.klass
|
12
|
+
@options = @pager.options
|
13
|
+
@items = []
|
14
|
+
@pager.items.each do |item|
|
15
|
+
# p item
|
16
|
+
object = @klass.client.get_item(
|
17
|
+
table_name: @klass.table_name,
|
18
|
+
key: {id: item["#{@klass.to_s.downcase}_id"]}
|
19
|
+
)
|
20
|
+
@items << @klass.send(:from_database, object.item)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&)
|
25
|
+
@items.each(&)
|
26
|
+
end
|
27
|
+
|
28
|
+
def last_evaluated_key
|
29
|
+
@pager.last_evaluated_key
|
30
|
+
end
|
31
|
+
|
32
|
+
def next_page?
|
33
|
+
@pager ? @pager.next_page? : false
|
34
|
+
end
|
35
|
+
|
36
|
+
def next_page
|
37
|
+
self.class.new(@pager.next_page, @base_object)
|
38
|
+
end
|
39
|
+
|
40
|
+
def page(last_key)
|
41
|
+
self.class.new(@pager.next_page(last_key), @base_object) if last_key
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module DynamodbRecord
|
2
|
+
# +Dynamodb::Pager+ is a abstract class to paginate
|
3
|
+
class Pager
|
4
|
+
attr_reader :klass
|
5
|
+
|
6
|
+
def initialize(options, klass)
|
7
|
+
@options = options
|
8
|
+
@klass = klass
|
9
|
+
end
|
10
|
+
|
11
|
+
def last_evaluated_key
|
12
|
+
raise NotImplementedError, 'Este método debe ser implementado por las subclases'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -12,7 +12,7 @@ module DynamodbRecord
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def client
|
15
|
-
opts = {
|
15
|
+
opts = {region: DynamodbRecord::Config.region}
|
16
16
|
opts[:endpoint] = DynamodbRecord::Config.endpoint if DynamodbRecord::Config.endpoint
|
17
17
|
opts[:access_key_id] = DynamodbRecord::Config.access_key_id if DynamodbRecord::Config.access_key_id
|
18
18
|
opts[:secret_access_key] = DynamodbRecord::Config.access_key_id if DynamodbRecord::Config.secret_access_key
|
@@ -20,7 +20,7 @@ module DynamodbRecord
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def default_options
|
23
|
-
{
|
23
|
+
{table_name:}
|
24
24
|
end
|
25
25
|
|
26
26
|
def describe_table
|
@@ -36,16 +36,16 @@ module DynamodbRecord
|
|
36
36
|
key_schema = []
|
37
37
|
|
38
38
|
# Default id hash key
|
39
|
-
attribute_definitions << {
|
40
|
-
|
41
|
-
key_schema << {
|
42
|
-
|
39
|
+
attribute_definitions << {attribute_name: 'id',
|
40
|
+
attribute_type: 'S'}
|
41
|
+
key_schema << {attribute_name: 'id',
|
42
|
+
key_type: 'HASH'}
|
43
43
|
|
44
44
|
if range_key
|
45
|
-
attribute_definitions << {
|
46
|
-
|
47
|
-
key_schema << {
|
48
|
-
|
45
|
+
attribute_definitions << {attribute_name: range_key.to_s,
|
46
|
+
attribute_type: dynamodb_type(attributes[range_key][:type])}
|
47
|
+
key_schema << {attribute_name: range_key.to_s,
|
48
|
+
key_type: 'RANGE'}
|
49
49
|
end
|
50
50
|
|
51
51
|
# Global secondary indexes
|
@@ -54,20 +54,20 @@ module DynamodbRecord
|
|
54
54
|
indexes << key if value[:options][:index]
|
55
55
|
end
|
56
56
|
|
57
|
-
global_secoglobal_secondary_indexesndary_indexes = []
|
57
|
+
# global_secoglobal_secondary_indexesndary_indexes = []
|
58
58
|
indexes.each do |index|
|
59
59
|
index_definition = {}
|
60
60
|
index_definition[:index_name] = "#{index}_index"
|
61
|
-
index_definition[:key_schema] = [{
|
62
|
-
{
|
63
|
-
index_definition[:projection] = {
|
61
|
+
index_definition[:key_schema] = [{attribute_name: index, key_type: 'HASH'},
|
62
|
+
{attribute_name: 'id', key_type: 'RANGE'}]
|
63
|
+
index_definition[:projection] = {projection_type: 'ALL'}
|
64
64
|
index_definition[:provisioned_throughput] = {
|
65
65
|
read_capacity_units: 1,
|
66
66
|
write_capacity_units: 1
|
67
67
|
}
|
68
68
|
global_secondary_indexes << index_definition
|
69
|
-
attribute_definitions << {
|
70
|
-
|
69
|
+
attribute_definitions << {attribute_name: index.to_s,
|
70
|
+
attribute_type: dynamodb_type(attributes[index][:type])}
|
71
71
|
end
|
72
72
|
|
73
73
|
options = {
|
@@ -113,7 +113,7 @@ module DynamodbRecord
|
|
113
113
|
self.updated_at = time
|
114
114
|
|
115
115
|
if @new_record # New item. Don't overwrite if id exists
|
116
|
-
options.merge!(condition_expression: 'id <> :s', expression_attribute_values: {
|
116
|
+
options.merge!(condition_expression: 'id <> :s', expression_attribute_values: {':s' => id})
|
117
117
|
end
|
118
118
|
|
119
119
|
options.merge!(item: self.class.unload(attributes))
|
@@ -127,10 +127,10 @@ module DynamodbRecord
|
|
127
127
|
hash_key = self.class.hash_key
|
128
128
|
range_key = self.class.range_key
|
129
129
|
key = {}
|
130
|
-
key[hash_key] = self.class.dump_field(
|
130
|
+
key[hash_key] = self.class.dump_field(read_attribute(hash_key), self.class.attributes[hash_key])
|
131
131
|
|
132
132
|
if range_key.present?
|
133
|
-
key[range_key] = self.class.dump_field(
|
133
|
+
key[range_key] = self.class.dump_field(read_attribute(range_key), self.class.attributes[range_key])
|
134
134
|
end
|
135
135
|
|
136
136
|
self.class.client.delete_item(options.merge(key:))
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# rubocop:disable Style/FrozenStringLiteralComment
|
1
2
|
|
2
3
|
module DynamodbRecord
|
3
4
|
# Query Module
|
@@ -9,8 +10,8 @@ module DynamodbRecord
|
|
9
10
|
def all(opts = {})
|
10
11
|
options = default_options
|
11
12
|
options.merge!(opts.slice(:limit))
|
12
|
-
|
13
|
-
|
13
|
+
scan_pager = ScanPager.new(options, self)
|
14
|
+
Collection.new(scan_pager, self)
|
14
15
|
end
|
15
16
|
|
16
17
|
# search table
|
@@ -23,7 +24,7 @@ module DynamodbRecord
|
|
23
24
|
expression_attribute_values = {}
|
24
25
|
filter_expression = ''
|
25
26
|
opts.each do |key, value|
|
26
|
-
expression_attribute_names["##{key}"
|
27
|
+
expression_attribute_names[:"##{key}"] = key.to_s
|
27
28
|
expression_attribute_values[":#{key}"] = value
|
28
29
|
filter_expression << if filter_expression.empty?
|
29
30
|
"##{key} = :#{key}"
|
@@ -37,13 +38,15 @@ module DynamodbRecord
|
|
37
38
|
options.merge!(expression_attribute_names:) if expression_attribute_names.present?
|
38
39
|
options.merge!(expression_attribute_values:) if expression_attribute_values.present?
|
39
40
|
options.merge!(filter_expression:) if filter_expression.present?
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
|
42
|
+
options.merge!(exclusive_start_key:) if exclusive_start_key
|
43
|
+
|
44
|
+
scan_pager = ScanPager.new(options, self)
|
45
|
+
Collection.new(scan_pager, self)
|
46
|
+
|
47
|
+
# DynamodbRecord::Collection.new(client.scan(options), self)
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
49
51
|
end
|
52
|
+
# rubocop:enable Style/FrozenStringLiteralComment
|