dynamodb_record 0.3.5 → 0.4.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.
Files changed (22) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -0
  3. data/lib/dynamodb_record/associations.rb +23 -21
  4. data/lib/dynamodb_record/has_and_belongs_to_many_collection.rb +26 -4
  5. data/lib/dynamodb_record/has_many_collection.rb +18 -0
  6. data/lib/dynamodb_record/persistence.rb +1 -1
  7. data/lib/dynamodb_record/version.rb +1 -1
  8. data/spec/dynamodb_record/association_spec.rb +27 -8
  9. data/spec/dynamodb_record/config_spec.rb +1 -2
  10. data/spec/dynamodb_record/query_spec.rb +1 -1
  11. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_belongs_to/get_object.yml +28 -24
  12. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/{has_and_belongs_to_many_create.yml → _has_and_belongs_to_many/create.yml} +68 -58
  13. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_and_belongs_to_many/destroy.yml +322 -0
  14. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_and_belongs_to_many/only_one_record.yml +216 -0
  15. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/create_item.yml +41 -35
  16. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/create_item_with_.yml +216 -0
  17. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/get_collection.yml +28 -24
  18. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/has_and_belongs_to_many.yml +41 -35
  19. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/has_many_through.yml +28 -78
  20. data/spec/spec_helper.rb +0 -1
  21. metadata +6 -4
  22. data/spec/fixtures/vcr_cassettes/DynamodbRecord_Associations/_has_many/add_list.yml +0 -362
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af02c1c5b3c550bf839dd80ffa8fbb6442d1010580c8a04df52e3f16b3a08398
4
- data.tar.gz: f59bfc3d99eae48c7826051a13883474dd2bab6c9166c4e28ea7571bcabd6ac0
3
+ metadata.gz: b207ff51e2f61f838af62f1e71ac5420435ca474515c776d6ecd86bd36b2e231
4
+ data.tar.gz: f1ee8e9771fad229e20078ca1bacc6df3fa95bd801214a9552c006e58aa1d44a
5
5
  SHA512:
6
- metadata.gz: 36c31a10c2844617be33117e8104ea28835f68b5322e16fd2f9d2ed16319337a138222b938f5dbbab1df62ca1d15567fbe494561b46b5adfd710843f507ecc6e
7
- data.tar.gz: a7c502ca5c3d79fef89e15371f5ed62d6462ba3a9c3405e60f7a5abc928d935d9c83e01410ea7f57a359f390c225259a9701aa0c5032dce81b0c7edb7787434c
6
+ metadata.gz: 12dc3c2e3255b43a7ce21522eb1cf7307ff69fc44b4b841aca7a251117e053d169826b68b5920bffb4bb6ec454ce15d3216415d347025961abeb1783ebb6a309
7
+ data.tar.gz: 70e365459e0c41e6871b0864b53221a2a1dfb8a257c9269b2e217d543e9b1f49bde366418faa09753fd47d3e46455948714d175df6630cbd541bea29e544f4f2
data/README.md CHANGED
@@ -76,6 +76,48 @@ user = User.find('f9b351b0-d06d-4fff-b8d4-8af162e2b8ba')
76
76
  User.find!('f9b351b0-d06d-4fff-b8d4-8af162e2b8ba')
77
77
  ```
78
78
 
79
+ ### The has_many Association
80
+
81
+ Associations are placed in their respective classes
82
+
83
+ **car.rb**
84
+
85
+ ```ruby
86
+ class Car
87
+ include DynamodbRecord::Document
88
+
89
+ field :marca, :string
90
+ has_many :insurances
91
+ end
92
+ ```
93
+
94
+ **insurance.rb**
95
+
96
+ ```ruby
97
+ class Insurance
98
+ include DynamodbRecord::Document
99
+
100
+ field :name, :string
101
+ field :car_id, :string, index: true
102
+ belongs_to :car
103
+ end
104
+ ```
105
+
106
+ There are many ways to generate associations:
107
+
108
+ #### '<<' method
109
+
110
+ ```ruby
111
+ # Find a car with ID 'UVX123'
112
+ car = Car.find('UVX123')
113
+
114
+ # Create a new insurance instance
115
+ insurance = Insurance.new(name: 'Bolivar')
116
+
117
+ # Associate the insurance with the car
118
+ car.insurances << insurance
119
+ ```
120
+
79
121
  ## Contributing
80
122
 
81
123
  1. Fork it ( https://github.com/[my-github-username]/dynamo_record/fork )
@@ -77,29 +77,31 @@ module DynamodbRecord
77
77
  sorted_list = list.sort
78
78
 
79
79
  define_method(associations) do
80
- options = {}
81
- pluralize_name = sorted_list.map(&:pluralize).join('-')
82
- table = Config.namespace ? "#{Config.namespace}-#{pluralize_name}" : pluralize_name
83
- options[:table_name] = table
84
- if sorted_list.first == base_model
85
- field = sorted_list.first
80
+ if @collection.nil?
81
+ options = {}
82
+ pluralize_name = sorted_list.map(&:pluralize).join('-')
83
+ table = Config.namespace ? "#{Config.namespace}-#{pluralize_name}" : pluralize_name
84
+ options[:table_name] = table
85
+ if sorted_list.first == base_model
86
+ field = sorted_list.first
87
+ else
88
+ field = sorted_list.last
89
+ options.merge!(index_name: "#{table}-index")
90
+ end
91
+
92
+ options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
93
+ options.merge!(expression_attribute_names: {"##{field}_id": "#{field}_id"})
94
+
95
+ options.merge!(expression_attribute_values: {":#{field}_id" => id})
96
+
97
+ klass = Object.const_get(relation_model.capitalize)
98
+ # options.merge!(limit: 1)
99
+ # p options
100
+ query = QueryPager.new(options, klass)
101
+ @collection = HasAndBelongsToManyCollection.new(query, self)
86
102
  else
87
- field = sorted_list.last
88
- options.merge!(index_name: "#{table}-index")
103
+ @collection
89
104
  end
90
-
91
- options.merge!(key_condition_expression: "##{field}_id = :#{field}_id")
92
- options.merge!(expression_attribute_names: {"##{field}_id": "#{field}_id"})
93
-
94
- options.merge!(expression_attribute_values: {":#{field}_id" => id})
95
-
96
- klass = Object.const_get(relation_model.capitalize)
97
-
98
- # options.merge!(limit: 1)
99
- # p options
100
-
101
- query = QueryPager.new(options, klass)
102
- HasAndBelongsToManyCollection.new(query, self)
103
105
  end
104
106
  end
105
107
  # rubocop:enable Naming/PredicateName
@@ -41,13 +41,34 @@ module DynamodbRecord
41
41
  self.class.new(@pager.next_page(last_key), @base_object) if last_key
42
42
  end
43
43
 
44
- def <<(object)
44
+ def <<(pluralizable_object)
45
+ pluralizable_object = [pluralizable_object] unless pluralizable_object.is_a?(Array)
46
+
47
+ pluralizable_object.each do |object|
48
+ table_name = @options[:table_name]
49
+ item = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
50
+ item[:"#{@base_model}_id"] = object.id
51
+ item[:created_at] = DateTime.now.to_s
52
+ key = {table_name:, item:}
53
+
54
+ res = @items.none? { |data| data.id == object.id }
55
+ if res
56
+ @klass.client.put_item(key)
57
+ @items << object
58
+ end
59
+ end
60
+
61
+ @items
62
+ end
63
+
64
+ def destroy(object)
45
65
  table_name = @options[:table_name]
46
66
  item = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
47
67
  item[:"#{@base_model}_id"] = object.id
48
- key = {table_name:, item:}
49
- @klass.client.put_item(key)
50
- @items << object
68
+ key = {table_name:, key: item}
69
+ @klass.client.delete_item(key)
70
+ @items.delete_if { |data| data.id == object.id }
71
+ object
51
72
  end
52
73
 
53
74
  def create!(params = {})
@@ -59,6 +80,7 @@ module DynamodbRecord
59
80
  item = @options[:expression_attribute_values].transform_keys { |k| k.delete_prefix(':').to_sym }
60
81
 
61
82
  item[:"#{@klass.to_s.downcase}_id"] = object.id
83
+ item[:created_at] = DateTime.now.to_s
62
84
  key = {table_name:, item:}
63
85
  @klass.client.put_item(key)
64
86
  object
@@ -46,5 +46,23 @@ module DynamodbRecord
46
46
  @items << object
47
47
  object
48
48
  end
49
+
50
+ def <<(pluralizable_object)
51
+ pluralizable_object = [pluralizable_object] unless pluralizable_object.is_a?(Array)
52
+
53
+ pluralizable_object.each do |object|
54
+ res = @items.none? { |data| data.id == object.id }
55
+
56
+ next unless res
57
+
58
+ foreign_attribute = "#{@base_object.class.to_s.downcase}_id="
59
+ object.send(foreign_attribute, @base_object.id)
60
+ object.save!
61
+
62
+ @items << object
63
+ end
64
+
65
+ @items
66
+ end
49
67
  end
50
68
  end
@@ -108,7 +108,7 @@ module DynamodbRecord
108
108
  options = self.class.default_options
109
109
 
110
110
  self.id = SecureRandom.uuid if id.nil?
111
- time = Time.now
111
+ time = DateTime.now.to_s
112
112
  self.created_at = time if created_at.nil?
113
113
  self.updated_at = time
114
114
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamodbRecord
4
- VERSION = '0.3.5'
4
+ VERSION = '0.4.1'
5
5
  end
@@ -15,10 +15,29 @@ RSpec.describe DynamodbRecord::Associations, :vcr do
15
15
  expect(users).to be_an(DynamodbRecord::HasManyThroughCollection)
16
16
  end
17
17
 
18
- it 'has_and_belongs_to_many create' do
19
- car = Car.find!('UVX455')
20
- user = car.users.create!(id: 'hguzman50@gmail.com')
21
- expect(user).to be_an(User)
18
+ describe '#has_and_belongs_to_many' do
19
+ it 'only one record' do
20
+ car = Car.find!('UVX455')
21
+ user = User.find!('hguzman10@gmail.com')
22
+ expect(user.cars.count).to eq(0)
23
+ user.cars << car
24
+ expect(user.cars.count).to eq(1)
25
+ user.cars << car
26
+ expect(user.cars.count).to eq(1)
27
+ end
28
+
29
+ it 'create' do
30
+ car = Car.find!('UVX455')
31
+ user = car.users.create!(id: 'hguzman50@gmail.com')
32
+ expect(user).to be_an(User)
33
+ end
34
+
35
+ it 'destroy' do
36
+ car = Car.find!('UVX455')
37
+ user = User.find('hguzman50@gmail.com')
38
+ car.users.destroy(user)
39
+ expect(car.users.count).to eq(2)
40
+ end
22
41
  end
23
42
 
24
43
  describe '#has_many' do
@@ -34,11 +53,11 @@ RSpec.describe DynamodbRecord::Associations, :vcr do
34
53
  expect(insurance).to be_an(Insurance)
35
54
  end
36
55
 
37
- it 'add list' do
38
- user = User.find!('hguzman10@gmail.com')
56
+ it 'create item with <<' do
39
57
  car = Car.find!('UVX455')
40
- user.cars << car
41
- expect(user.cars.count).to eq(1)
58
+ insurance = Insurance.find!('12')
59
+ car_insurances = car.insurances << insurance
60
+ expect(car_insurances.any? { |item| item.id == insurance.id }).to eq(true)
42
61
  end
43
62
  end
44
63
 
@@ -1,7 +1,6 @@
1
1
  require_relative '../spec_helper'
2
2
 
3
3
  RSpec.describe DynamodbRecord::Config, :vcr do
4
-
5
4
  after do
6
5
  DynamodbRecord::Config.set_defaults
7
6
  end
@@ -25,4 +24,4 @@ RSpec.describe DynamodbRecord::Config, :vcr do
25
24
  expect(DynamodbRecord::Config.region).to eq('region')
26
25
  expect(DynamodbRecord::Config.namespace).to eq('fleteo-v2')
27
26
  end
28
- end
27
+ end
@@ -20,7 +20,7 @@ RSpec.describe DynamodbRecord::Query, :vcr do
20
20
  it 'returns records by limit' do
21
21
  result = User.where(balance: 0, limit: 1)
22
22
  expect(result.count).to eq(1)
23
- expect(result.last_evaluated_key).to eq({'id'=>'hguzman20@gmail.com'})
23
+ expect(result.last_evaluated_key).to eq({'id' => 'hguzman20@gmail.com'})
24
24
  end
25
25
  end
26
26
  end
@@ -9,23 +9,25 @@ http_interactions:
9
9
  headers:
10
10
  Accept-Encoding:
11
11
  - ''
12
+ Amz-Sdk-Invocation-Id:
13
+ - 82a096b7-4dcb-4971-a2f5-2a5422bd6896
12
14
  Content-Type:
13
15
  - application/x-amz-json-1.0
14
16
  X-Amz-Target:
15
17
  - DynamoDB_20120810.GetItem
16
18
  User-Agent:
17
- - aws-sdk-ruby3/3.191.3 ua/2.0 api/dynamodb#1.105.0 os/macos#20 md/x86_64 lang/ruby#3.2.3
19
+ - aws-sdk-ruby3/3.196.1 ua/2.0 api/dynamodb#1.111.0 os/macos#23 md/arm64 lang/ruby#3.2.3
18
20
  md/3.2.3 cfg/retry-mode#legacy
19
21
  Host:
20
22
  - localhost:8000
21
23
  X-Amz-Date:
22
- - 20240514T151341Z
24
+ - 20240531T203020Z
23
25
  X-Amz-Content-Sha256:
24
26
  - efb57ec65a1d5400e11f2c1d7ef1abae0923c0d84b3e4a442db0abcb6408f474
25
27
  Authorization:
26
- - AWS4-HMAC-SHA256 Credential=key/20240514/us-east-1/dynamodb/aws4_request,
27
- SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,
28
- Signature=ee626915d5626ac0c4f324b1eb64101d695f890fa0ea6af9b35ee366e0ebb764
28
+ - AWS4-HMAC-SHA256 Credential=key/20240531/us-east-1/dynamodb/aws4_request,
29
+ SignedHeaders=amz-sdk-invocation-id;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,
30
+ Signature=f0f1f9990edd7886e7c723b18d07574ef1241b6df0a68edd907cab7c8c0675e3
29
31
  Content-Length:
30
32
  - '63'
31
33
  Accept:
@@ -36,21 +38,21 @@ http_interactions:
36
38
  message: OK
37
39
  headers:
38
40
  Date:
39
- - Tue, 14 May 2024 15:13:41 GMT
41
+ - Fri, 31 May 2024 20:30:20 GMT
40
42
  X-Amzn-Requestid:
41
- - 2e572970-2362-4c8e-ab2a-9d498be1cedc
43
+ - 25f44928-cec6-4efc-a435-219587453290
42
44
  Content-Type:
43
45
  - application/x-amz-json-1.0
44
46
  X-Amz-Crc32:
45
- - '4004972195'
47
+ - '1835808279'
46
48
  Content-Length:
47
- - '80'
49
+ - '147'
48
50
  Server:
49
- - Jetty(11.0.17)
51
+ - Jetty(9.4.48.v20220622)
50
52
  body:
51
53
  encoding: UTF-8
52
- string: '{"Item":{"name":{"S":"Colcerautos"},"car_id":{"S":"UVX455"},"id":{"S":"12345"}}}'
53
- recorded_at: Tue, 14 May 2024 15:13:41 GMT
54
+ string: '{"Item":{"created_at":{"S":"2024-05-31T15:29:47-05:00"},"id":{"S":"12345"},"updated_at":{"S":"2024-05-31T15:29:47-05:00"},"car_id":{"S":"UVX455"}}}'
55
+ recorded_at: Fri, 31 May 2024 20:30:20 GMT
54
56
  - request:
55
57
  method: post
56
58
  uri: http://localhost:8000/
@@ -60,23 +62,25 @@ http_interactions:
60
62
  headers:
61
63
  Accept-Encoding:
62
64
  - ''
65
+ Amz-Sdk-Invocation-Id:
66
+ - 2a2bee78-402a-4cb4-8df1-7335168c7e1f
63
67
  Content-Type:
64
68
  - application/x-amz-json-1.0
65
69
  X-Amz-Target:
66
70
  - DynamoDB_20120810.GetItem
67
71
  User-Agent:
68
- - aws-sdk-ruby3/3.191.3 ua/2.0 api/dynamodb#1.105.0 os/macos#20 md/x86_64 lang/ruby#3.2.3
72
+ - aws-sdk-ruby3/3.196.1 ua/2.0 api/dynamodb#1.111.0 os/macos#23 md/arm64 lang/ruby#3.2.3
69
73
  md/3.2.3 cfg/retry-mode#legacy
70
74
  Host:
71
75
  - localhost:8000
72
76
  X-Amz-Date:
73
- - 20240514T151341Z
77
+ - 20240531T203020Z
74
78
  X-Amz-Content-Sha256:
75
79
  - 3f40080fdb7ac1732232c14b86645a9ffbd3f94cf8ecda6b3c584d105288bb8d
76
80
  Authorization:
77
- - AWS4-HMAC-SHA256 Credential=key/20240514/us-east-1/dynamodb/aws4_request,
78
- SignedHeaders=content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,
79
- Signature=6efa4f968328b726cd30c758f09068bad22f44524d301b0bbc9d198a873aac06
81
+ - AWS4-HMAC-SHA256 Credential=key/20240531/us-east-1/dynamodb/aws4_request,
82
+ SignedHeaders=amz-sdk-invocation-id;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-target,
83
+ Signature=6083bcf5e4610b6881eea1980aaf65689809b86ff8deec22777cda31ae753670
80
84
  Content-Length:
81
85
  - '58'
82
86
  Accept:
@@ -87,19 +91,19 @@ http_interactions:
87
91
  message: OK
88
92
  headers:
89
93
  Date:
90
- - Tue, 14 May 2024 15:13:41 GMT
94
+ - Fri, 31 May 2024 20:30:20 GMT
91
95
  X-Amzn-Requestid:
92
- - 25132fc8-9bae-4ed1-86e4-09bb515d7d51
96
+ - 16c19001-7dad-432e-a479-3d8fc978ff97
93
97
  Content-Type:
94
98
  - application/x-amz-json-1.0
95
99
  X-Amz-Crc32:
96
- - '590923779'
100
+ - '2965787765'
97
101
  Content-Length:
98
- - '149'
102
+ - '124'
99
103
  Server:
100
- - Jetty(11.0.17)
104
+ - Jetty(9.4.48.v20220622)
101
105
  body:
102
106
  encoding: UTF-8
103
- string: '{"Item":{"marca":{"S":"Chvrolet"},"created_at":{"S":"2024-05-07T14:09:25-05:00"},"id":{"S":"UVX455"},"updated_at":{"S":"2024-05-07T14:09:25-05:00"}}}'
104
- recorded_at: Tue, 14 May 2024 15:13:41 GMT
107
+ string: '{"Item":{"updated_at":{"S":"2024-05-31T15:29:47-05:00"},"created_at":{"S":"2024-05-31T15:29:47-05:00"},"id":{"S":"UVX455"}}}'
108
+ recorded_at: Fri, 31 May 2024 20:30:20 GMT
105
109
  recorded_with: VCR 6.2.0