uuid_associations-active_record 0.3.4 → 0.4.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 +4 -4
- data/README.md +2 -1
- data/lib/uuid_associations/active_record/inline.rb +1 -0
- data/lib/uuid_associations/active_record/nested_attributes/uuid_finder.rb +14 -7
- data/lib/uuid_associations/active_record/nested_attributes_method_definitions.rb +21 -1
- data/lib/uuid_associations/active_record/version.rb +1 -1
- data/spec/integration/nested_attributes/collection_spec.rb +19 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/models/attachment.rb +3 -0
- data/spec/support/models/post.rb +2 -0
- data/spec/support/schema.rb +8 -0
- data/spec/unit/uuid_associations/active_record/nested_attributes/uuid_finder_spec.rb +20 -6
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3c431b4006e482177f8e0807950bbfedf98a6178e0fab77b490e66a30e4208af
|
|
4
|
+
data.tar.gz: 6f2c8827ae6e159778e1cef9fc2ac0b0e1caf2d744ee5fdcd49fe79ab501ce5f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c5ddf180335b9ee1363a2a0f512c0b1dca180788888326dad92ff751f27ae1e5e9ffc55ce174d19742b59285c13d394195b4c1deed935fc966b9440dd33a1923
|
|
7
|
+
data.tar.gz: 80558b8f132ea4e07da6ad2e4bb1b07e3a4de675638d731b7ee520992fde697af3a4ed5de4f867944f53bca66a0f4fb9e1b00790a4e341f582b0964d3da22945
|
data/README.md
CHANGED
|
@@ -219,12 +219,13 @@ Here are some things to take into account:
|
|
|
219
219
|
just preserve the original behavior.
|
|
220
220
|
1. If the hash has both the `:id` and `:uuid` keys, the record will be fetched by `id`, and `uuid` will be passed as an attribute.
|
|
221
221
|
1. When the hash has a `:uuid` key and no record is found for that key, an `ActiveRecord::RecordNotFound` error will be raised.
|
|
222
|
+
If you want the behavior to be that a new record is created when not found by UUID, you can set the option `create_missing_uuids: true`
|
|
223
|
+
on the `accepts_nested_attributes_for` call.
|
|
222
224
|
|
|
223
225
|
## Future Work
|
|
224
226
|
|
|
225
227
|
1. Not commonly used by me, but testing and adding these methods to a `has_one` relationship.
|
|
226
228
|
1. Raise not found error if the array of UUIDs is bigger that the array of IDs fetched with the `where` statement (ActiveRecord's behavior).
|
|
227
|
-
1. Allow `accepts_nested_attributes_for` to take a configuration to allow the creation of new records if not found by UUID.
|
|
228
229
|
|
|
229
230
|
## Development
|
|
230
231
|
|
|
@@ -5,3 +5,4 @@ require 'uuid_associations/active_record/nested_attributes_method_definitions'
|
|
|
5
5
|
|
|
6
6
|
::ActiveRecord::Base.extend(UuidAssociations::ActiveRecord::AssociationMethodDefinitions)
|
|
7
7
|
::ActiveRecord::Base.prepend(UuidAssociations::ActiveRecord::NestedAttributesMethodDefinitions)
|
|
8
|
+
::ActiveRecord::Base.extend(UuidAssociations::ActiveRecord::NestedAttributesMethodDefinitions::ClassMethods)
|
|
@@ -2,13 +2,14 @@ module UuidAssociations
|
|
|
2
2
|
module ActiveRecord
|
|
3
3
|
module NestedAttributes
|
|
4
4
|
class UuidFinder
|
|
5
|
-
def self.replaced_uuids_with_ids(association_klass, attribute_collection)
|
|
6
|
-
new(association_klass, attribute_collection).call
|
|
5
|
+
def self.replaced_uuids_with_ids(association_klass, attribute_collection, options)
|
|
6
|
+
new(association_klass, attribute_collection, options).call
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
def initialize(association_klass, attribute_collection)
|
|
9
|
+
def initialize(association_klass, attribute_collection, options)
|
|
10
10
|
@association_klass = association_klass
|
|
11
11
|
@attribute_collection = attribute_collection
|
|
12
|
+
@options = options
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def call
|
|
@@ -26,11 +27,17 @@ module UuidAssociations
|
|
|
26
27
|
|
|
27
28
|
record = found_records.find { |found_record| found_record.uuid == uuid }
|
|
28
29
|
|
|
29
|
-
if
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
if @options[:create_missing_uuids]
|
|
31
|
+
collection << if record.blank?
|
|
32
|
+
attributes.merge(uuid: uuid)
|
|
33
|
+
else
|
|
34
|
+
attributes.merge(id: record.id)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
raise_not_found_error(uuid) if record.blank?
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
collection << attributes.merge(id: record.id)
|
|
40
|
+
end
|
|
34
41
|
end
|
|
35
42
|
|
|
36
43
|
to_keep + replaced
|
|
@@ -3,6 +3,25 @@ require 'uuid_associations/active_record/nested_attributes/uuid_finder'
|
|
|
3
3
|
module UuidAssociations
|
|
4
4
|
module ActiveRecord
|
|
5
5
|
module NestedAttributesMethodDefinitions
|
|
6
|
+
module ClassMethods
|
|
7
|
+
def accepts_nested_attributes_for(*attr_names)
|
|
8
|
+
options = attr_names.extract_options!
|
|
9
|
+
create_missing_uuids = { create_missing_uuids: options.delete(:create_missing_uuids) { false } }
|
|
10
|
+
|
|
11
|
+
original_payload = super(
|
|
12
|
+
*(attr_names + [options])
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
attr_names.each do |association_name|
|
|
16
|
+
nested_attributes_options = self.nested_attributes_options.dup
|
|
17
|
+
nested_attributes_options[association_name.to_sym] = nested_attributes_options[association_name.to_sym].merge(create_missing_uuids)
|
|
18
|
+
self.nested_attributes_options = nested_attributes_options
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
original_payload
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
6
25
|
private
|
|
7
26
|
|
|
8
27
|
def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
|
|
@@ -13,7 +32,8 @@ module UuidAssociations
|
|
|
13
32
|
|
|
14
33
|
replaced_attributes = ActiveRecord::NestedAttributes::UuidFinder.replaced_uuids_with_ids(
|
|
15
34
|
association_klass,
|
|
16
|
-
attributes_collection
|
|
35
|
+
attributes_collection,
|
|
36
|
+
nested_attributes_options[association_name]
|
|
17
37
|
)
|
|
18
38
|
super(association_name, replaced_attributes)
|
|
19
39
|
end
|
|
@@ -39,6 +39,25 @@ RSpec.describe 'nested attributes for collection' do
|
|
|
39
39
|
|
|
40
40
|
expect(Post.first.comments.count).to eq(1)
|
|
41
41
|
end
|
|
42
|
+
|
|
43
|
+
context 'when create_missing_uuids is set to true' do
|
|
44
|
+
let(:provided_uuid) { SecureRandom.uuid }
|
|
45
|
+
|
|
46
|
+
it 'creates a resource even if a uuid is provided' do
|
|
47
|
+
expect do
|
|
48
|
+
Post.create!(
|
|
49
|
+
uuid: SecureRandom.uuid,
|
|
50
|
+
content: 'post',
|
|
51
|
+
attachments_attributes: [
|
|
52
|
+
body: 'New comment', uuid: provided_uuid
|
|
53
|
+
]
|
|
54
|
+
)
|
|
55
|
+
end.to change(Post, :count).from(0).to(1)
|
|
56
|
+
.and change(Attachment, :count).from(0).to(1)
|
|
57
|
+
|
|
58
|
+
expect(Post.first.attachments.first.uuid).to eq(provided_uuid)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
42
61
|
end
|
|
43
62
|
|
|
44
63
|
context 'when updating existing records' do
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/models/post.rb
CHANGED
|
@@ -2,6 +2,8 @@ class Post < ActiveRecord::Base
|
|
|
2
2
|
belongs_to :user, required: false
|
|
3
3
|
|
|
4
4
|
has_many :comments
|
|
5
|
+
has_many :attachments
|
|
5
6
|
|
|
6
7
|
accepts_nested_attributes_for :comments, allow_destroy: true
|
|
8
|
+
accepts_nested_attributes_for :attachments, allow_destroy: true, create_missing_uuids: true
|
|
7
9
|
end
|
data/spec/support/schema.rb
CHANGED
|
@@ -2,11 +2,13 @@ require 'uuid_associations/active_record/nested_attributes/uuid_finder'
|
|
|
2
2
|
|
|
3
3
|
RSpec.describe UuidAssociations::ActiveRecord::NestedAttributes::UuidFinder do
|
|
4
4
|
describe '.replaced_uuids_with_ids' do
|
|
5
|
-
subject { described_class.replaced_uuids_with_ids(klass, attribute_collection) }
|
|
5
|
+
subject { described_class.replaced_uuids_with_ids(klass, attribute_collection, options) }
|
|
6
6
|
|
|
7
|
-
let(:post)
|
|
8
|
-
let(:comment)
|
|
9
|
-
let(:klass)
|
|
7
|
+
let(:post) { Post.create!(content: 'content', uuid: SecureRandom.uuid) }
|
|
8
|
+
let(:comment) { Comment.create!(post: post, body: 'my comment', uuid: SecureRandom.uuid) }
|
|
9
|
+
let(:klass) { Comment }
|
|
10
|
+
let(:options) { {} }
|
|
11
|
+
let(:provided_uuid) { SecureRandom.uuid }
|
|
10
12
|
|
|
11
13
|
context 'when attributes come as an array' do
|
|
12
14
|
context 'when UUID is present, but ID is not' do
|
|
@@ -15,11 +17,17 @@ RSpec.describe UuidAssociations::ActiveRecord::NestedAttributes::UuidFinder do
|
|
|
15
17
|
it { is_expected.to contain_exactly(id: comment.id, body: 'updated comment') }
|
|
16
18
|
|
|
17
19
|
context 'when record with specified UUID does not exist on the sytem' do
|
|
18
|
-
let(:attribute_collection) { [{ uuid:
|
|
20
|
+
let(:attribute_collection) { [{ uuid: provided_uuid, body: 'new comment :/' }] }
|
|
19
21
|
|
|
20
22
|
it 'raises a not found error' do
|
|
21
23
|
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
|
|
22
24
|
end
|
|
25
|
+
|
|
26
|
+
context 'when create_missing_uuids is set' do
|
|
27
|
+
let(:options) { { create_missing_uuids: true } }
|
|
28
|
+
|
|
29
|
+
it { is_expected.to contain_exactly(uuid: provided_uuid, body: 'new comment :/') }
|
|
30
|
+
end
|
|
23
31
|
end
|
|
24
32
|
end
|
|
25
33
|
|
|
@@ -47,11 +55,17 @@ RSpec.describe UuidAssociations::ActiveRecord::NestedAttributes::UuidFinder do
|
|
|
47
55
|
it { is_expected.to contain_exactly(id: comment.id, body: 'updated comment') }
|
|
48
56
|
|
|
49
57
|
context 'when record with specified UUID does not exist on the sytem' do
|
|
50
|
-
let(:attribute_collection) { { first: { uuid:
|
|
58
|
+
let(:attribute_collection) { { first: { uuid: provided_uuid, body: 'new comment :/' } } }
|
|
51
59
|
|
|
52
60
|
it 'raises a not found error' do
|
|
53
61
|
expect { subject }.to raise_error(ActiveRecord::RecordNotFound)
|
|
54
62
|
end
|
|
63
|
+
|
|
64
|
+
context 'when create_missing_uuids is set' do
|
|
65
|
+
let(:options) { { create_missing_uuids: true } }
|
|
66
|
+
|
|
67
|
+
it { is_expected.to contain_exactly(uuid: provided_uuid, body: 'new comment :/') }
|
|
68
|
+
end
|
|
55
69
|
end
|
|
56
70
|
end
|
|
57
71
|
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: uuid_associations-active_record
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mario Celi
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2019-04-
|
|
11
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -153,6 +153,7 @@ files:
|
|
|
153
153
|
- spec/integration/relationship_definitions/has_and_belongs_to_many_spec.rb
|
|
154
154
|
- spec/integration/relationship_definitions/has_many_spec.rb
|
|
155
155
|
- spec/spec_helper.rb
|
|
156
|
+
- spec/support/models/attachment.rb
|
|
156
157
|
- spec/support/models/comment.rb
|
|
157
158
|
- spec/support/models/pet.rb
|
|
158
159
|
- spec/support/models/post.rb
|
|
@@ -193,6 +194,7 @@ test_files:
|
|
|
193
194
|
- spec/integration/relationship_definitions/has_and_belongs_to_many_spec.rb
|
|
194
195
|
- spec/integration/relationship_definitions/has_many_spec.rb
|
|
195
196
|
- spec/spec_helper.rb
|
|
197
|
+
- spec/support/models/attachment.rb
|
|
196
198
|
- spec/support/models/comment.rb
|
|
197
199
|
- spec/support/models/pet.rb
|
|
198
200
|
- spec/support/models/post.rb
|