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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04434300525cb3350da2af614944510ac429d8daa8b8af49307d77d9f2256162
4
- data.tar.gz: dafecc48f8fc8f310d64918b969dd9604f626756a84f5d30b63ac85ec1d46e4e
3
+ metadata.gz: 3c431b4006e482177f8e0807950bbfedf98a6178e0fab77b490e66a30e4208af
4
+ data.tar.gz: 6f2c8827ae6e159778e1cef9fc2ac0b0e1caf2d744ee5fdcd49fe79ab501ce5f
5
5
  SHA512:
6
- metadata.gz: 7def67cca35d303168a43a9fe6d150b9a4015b200fc06f0ad64ecce01e4cafcb6c8b073f35b5e2bf47a8d061586486496d90e856d2401b5c2dd2e832eb816482
7
- data.tar.gz: b667b979c70bc6dd31f462f7bb199b6db0b7958f62b5dc07b60c1ed833a9ae5503976453ba48282843dab64fc54877a0581007b2e50c622a1b74afb91c54a75f
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 record.blank?
30
- raise_not_found_error(uuid)
31
- end
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
- collection << attributes.merge(id: record.id)
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
@@ -1,5 +1,5 @@
1
1
  module UuidAssociations
2
2
  module ActiveRecord
3
- VERSION = '0.3.4'.freeze
3
+ VERSION = '0.4.0'.freeze
4
4
  end
5
5
  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
@@ -8,6 +8,7 @@ require 'support/models/post'
8
8
  require 'support/models/comment'
9
9
  require 'support/models/pet'
10
10
  require 'support/models/toy'
11
+ require 'support/models/attachment'
11
12
 
12
13
  RSpec.configure do |config|
13
14
  # Enable flags like --only-failures and --next-failure
@@ -0,0 +1,3 @@
1
+ class Attachment < ActiveRecord::Base
2
+ belongs_to :post, required: false
3
+ end
@@ -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
@@ -56,4 +56,12 @@ ActiveRecord::Schema.define version: 0 do
56
56
 
57
57
  t.timestamps
58
58
  end
59
+
60
+ create_table :attachments do |t|
61
+ t.belongs_to :post, foreign_key: { on_delete: :cascade }
62
+ t.string :uuid
63
+ t.string :body
64
+
65
+ t.timestamps
66
+ end
59
67
  end
@@ -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) { Post.create!(content: 'content', uuid: SecureRandom.uuid) }
8
- let(:comment) { Comment.create!(post: post, body: 'my comment', uuid: SecureRandom.uuid) }
9
- let(:klass) { Comment }
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: SecureRandom.uuid, body: 'new comment :/' }] }
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: SecureRandom.uuid, body: 'new comment :/' } } }
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.3.4
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-06 00:00:00.000000000 Z
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