uuid_associations-active_record 0.1.0 → 0.2.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: 6961ceb501c186f2db2b6f47a5c8519dd67479d4568e8d538ce1005eaa73db13
4
- data.tar.gz: cc6fc2bfabc4a25a866f62e1de271fa6ce3cbb98e1404cb9890ee9ecb84940d3
3
+ metadata.gz: 7e1538fc45bf664d391c0a3b2b335247bdf0a66cc1f9133d3936000850175e9c
4
+ data.tar.gz: '092c5dad84a0a0ae487ecc61516b43b7d0b0e19fe7e3a2805f1811602dbbd5ee'
5
5
  SHA512:
6
- metadata.gz: d0284a2a018162316c3698bac28c82b699fcc864c0cffd693809211d15ae009f231b2c8e963cef2b46c77ca32c664e1848769a343febe554786f2937eb91e38c
7
- data.tar.gz: fd35ddf1320b3806f811ef923b488fe9e5062df6c823f57edbe940dcc45586f163d15d6bc91bab0a97f72cf365a92c38af86c1610dabc2e7bfdc7417801ca180
6
+ metadata.gz: 40acb305ecca02b540d97161942ef0bcf9161b1b5b07c4160df0adcb76a039e576da7a3afe53882bcb7501684b394170137f0c5df54df3eecf04fddf61ab7726
7
+ data.tar.gz: f064f70789721a9b789a76f096098548fa409ac69f63b818d8a232b3112a4ee58d524a72e2b7611c3a862596a7b22a17eb556655154cee828319aa7adbf59490
data/.travis.yml CHANGED
@@ -5,9 +5,9 @@ cache: bundler
5
5
 
6
6
  rvm:
7
7
  - 2.2.10
8
- - 2.3.7
9
- - 2.4.4
10
- - 2.5.1
8
+ - 2.3.8
9
+ - 2.4.5
10
+ - 2.5.3
11
11
 
12
12
  gemfile:
13
13
  - gemfiles/active_record_4.2.gemfile
@@ -24,4 +24,4 @@ matrix:
24
24
  - gemfile: gemfiles/active_record_edge.gemfile
25
25
  rvm: 2.2.10
26
26
  - gemfile: gemfiles/active_record_edge.gemfile
27
- rvm: 2.3.7
27
+ rvm: 2.3.8
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # UuidAssociations::ActiveRecord
1
+ # UUID Associations ActiveRecord
2
2
  [![Build Status](https://travis-ci.org/mcelicalderon/uuid_associations-active_record.svg?branch=master)](https://travis-ci.org/mcelicalderon/uuid_associations-active_record)
3
3
  [![Gem Version](https://badge.fury.io/rb/uuid_associations-active_record.svg)](https://badge.fury.io/rb/uuid_associations-active_record)
4
4
 
@@ -12,25 +12,235 @@ gem 'uuid_associations-active_record'
12
12
 
13
13
  And then execute:
14
14
 
15
- $ bundle
15
+ ```bash
16
+ $ bundle
17
+ ```
16
18
 
17
19
  Or install it yourself as:
18
20
 
19
- $ gem install uuid_associations-active_record
21
+ ```bash
22
+ $ gem install uuid_associations-active_record
23
+ ```
24
+
25
+ ## Rationale
26
+
27
+ This gem is the result of some research I did to find out if using UUIDs as DB primary keys is a good thing
28
+ (Rails added support for this!). On the process
29
+ I ran into [this article](https://tomharrisonjr.com/uuid-or-guid-as-primary-keys-be-careful-7b2aa3dcb439) (among many others).
30
+ If you read the article you'll see how UUIDs have benefits over using sequential Int values as primary keys, but also how
31
+ you should be aware of what does that imply in terms of performance or even amount of storage used.
32
+
33
+ One of the author's conclusions is that you should use Int or Bigint columns as your primary keys, but also add a column
34
+ with a UUID that you can use to reference your records when exposing them to the outside world. If you finish reading the article
35
+ you'll find out that not even this is the perfect solution, but at least it's a huge improvement to exposing your sequential
36
+ primary keys. This gem helps you implement this approach.
20
37
 
21
38
  ## Usage
22
39
 
23
- TODO: Write usage instructions here
40
+ Adding the gem to your Gemfile is all you need for the gem to start working if you are using Rails. If you are not, you
41
+ you can always install the gem and require it manually (probably right after you require active_record). Take a look at
42
+ specs if you want to use the gem with plain ActiveRecord as that is how they are setup.
43
+
44
+ What this gem does is add some useful methods to your ActiveRecord models by calling the good old association methods like
45
+ `has_many`, `belongs_to`, `has_and_belongs_to_many`. As you may already know, calling these methods creates multiple
46
+ methods on the calling model for you. I'll explain the ones we are interested in in the next section.
47
+
48
+ This gem also adds a helpful mechanism to handle nested attributes. This will also be explained in the next section.
49
+
50
+ That's it! That is what the gem does. This will allow you to pass UUIDs to your update or create operations instead
51
+ of the actual IDs. Be aware that this will of course require an additional (but simple) DB query. That is the cost of
52
+ hiding the actual IDs (I'd say it's not too costly).
53
+
54
+ Also be aware that the initial version of this gem is not very configurable,
55
+ so the only thing it checks before creating the methods is that the right side association
56
+ on the caller model has a column named `uuid`, doesn't take the column type into account.
57
+ I have tested with string columns in SQlite3 and UUID columns in Postgres.
58
+
59
+ ### Association Methods
60
+
61
+ Lets explore the next example:
62
+
63
+ ```ruby
64
+ # app/models/user.rb
65
+ class User < ActiveRecord::Base
66
+ has_and_belongs_to_many :posts
67
+ # generates
68
+ #
69
+ # def post_ids=(ids)
70
+ # # Adds or deletes the association with posts based on the array of IDs received
71
+ # end
72
+ #
73
+ # def post_ids
74
+ # # returns an array with all the post IDs
75
+ # end
76
+
77
+ has_many :comments
78
+ # generates
79
+ #
80
+ # def comment_ids=(ids)
81
+ # # Adds or deletes the association with comments based on the array of IDs received
82
+ # end
83
+ #
84
+ # def comment_ids
85
+ # # returns an array with all the comment IDs
86
+ # end
87
+ end
88
+
89
+ # app/models/post.rb
90
+ class Post < ActiveRecord::Base
91
+ has_and_belongs_to_many :users
92
+ # generates
93
+ #
94
+ # def user_ids=(ids)
95
+ # # Adds or deletes the association with users based on the array of IDs received
96
+ # end
97
+ #
98
+ # def user_ids
99
+ # # returns an array with all the user IDs
100
+ # end
101
+ end
102
+
103
+ # app/models/comment.rb
104
+ class Comment < ActiveRecord::Base
105
+ belongs_to :user
106
+ # generates
107
+ #
108
+ # def user_id=(id)
109
+ # associates the comment with the user
110
+ # end
111
+
112
+ # def user_id
113
+ # returns the ID of the associated user
114
+ # end
115
+ end
116
+ ```
117
+
118
+ This gem will add two new methods for each call to one of the association methods.
119
+
120
+ #### Generated Methods
121
+
122
+ Calling any of these methods will also add the following methods to your model:
123
+
124
+ ```ruby
125
+ # app/models/user.rb
126
+ class User < ActiveRecord::Base
127
+ has_and_belongs_to_many :posts
128
+ # generates
129
+ #
130
+ # def post_uuids=(uuids)
131
+ # self.post_ids = Post.where(uuid: uuids).pluck(:id)
132
+ # end
133
+ #
134
+ # def post_uuids
135
+ # posts.pluck(:uuid)
136
+ # end
137
+
138
+ has_many :comments
139
+ # generates
140
+ #
141
+ # def comment_uuids=(uuids)
142
+ # self.comment_ids = Comment.where(uuid: uuids).pluck(:id)
143
+ # end
144
+ #
145
+ # def comment_uuids
146
+ # comments.pluck(:uuid)
147
+ # end
148
+ end
149
+
150
+ # app/models/post.rb
151
+ class Post < ActiveRecord::Base
152
+ has_and_belongs_to_many :users
153
+ # generates
154
+ #
155
+ # def user_uuids=(uuids)
156
+ # self.user_ids = User.where(uuid: uuids).pluck(:id)
157
+ # end
158
+ #
159
+ # def user_uuids
160
+ # users.pluck(:uuid)
161
+ # end
162
+ end
163
+
164
+ # app/models/comment.rb
165
+ class Comment < ActiveRecord::Base
166
+ belongs_to :user
167
+ # generates
168
+ #
169
+ # def user_uuid=(uuid)
170
+ # self.user_id = User.find_by!(uuid: uuid)
171
+ # end
172
+
173
+ # def user_id
174
+ # user.uuid
175
+ # end
176
+ end
177
+ ```
178
+
179
+ ### Nested Attributes
180
+
181
+ Nested attributes don't generate additional methods, this gem just modifies one so you can update nested record using
182
+ the record's UUID instead of the actual ID. Let's explore the next example:
183
+
184
+ ```ruby
185
+ class Post < ActiveRecord::Base
186
+ has_many :comments
187
+
188
+ accepts_nested_attributes_for :comments, allow_destroy: true
189
+ # generates
190
+ #
191
+ # def comments_attributes=(attributes)
192
+ # # allows to create or update comments using this method on Post
193
+ # end
194
+ end
195
+ ```
196
+
197
+ ActiveRecord allows for `attributes` to be an array of hashes or a hash of hashes. Here are some examples of the payload
198
+ you can pass to `comments_attributes` by using this gem:
199
+
200
+ ```ruby
201
+ # This is supported without this gem
202
+ [
203
+ { id: 1, comment_body: 'updating comment with ID 1' },
204
+ { id: 2, _destroy: true },
205
+ { comment_body: 'this will create a new comment' }
206
+ ]
207
+
208
+ # With the gem, you can use UUIDs instead
209
+ [
210
+ { uuid: 'some-uuid', comment_body: 'updating comment with UUID: some-uuid' }.
211
+ { uuid: 'other-uuid', _destroy: true },
212
+ { comment_body: 'this will create a new comment' }
213
+ ]
214
+ ```
215
+
216
+ Here are some things to take into account:
217
+
218
+ 1. If the nested model (Comment in the example) does not have a column named `uuid`, the gem will take no action, will
219
+ just preserve the original behavior.
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
+ 1. When the hash has a `:uuid` key and no record is found for that key, a new record will be created using that UUID
222
+ (this will change to raise a not found error instead).
223
+
224
+ ## Future Work
225
+
226
+ 1. Not commonly used by me, but testing and adding these methods to a `has_one` relationship.
227
+ 1. Raise not found error if the array of UUIDs is bigger that the array
228
+ of IDs fetched with the `where` statement (ActiveRecord's behavior).
24
229
 
25
230
  ## Development
26
231
 
27
232
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
28
233
 
29
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
234
+ To run the specs with all the supported versions of ActiveRecord you can use:
235
+
236
+ ```ruby
237
+ $ bundle exec appraisal install
238
+ $ bundle exec appraisal rspec
239
+ ```
30
240
 
31
241
  ## Contributing
32
242
 
33
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/uuid_associations-active_record.
243
+ Bug reports and pull requests are welcome on GitHub at https://github.com/mcelicalderon/uuid_associations-active_record.
34
244
 
35
245
  ## License
36
246
 
@@ -3,7 +3,7 @@ require 'uuid_associations/active_record/relationship_definitions/has_many'
3
3
 
4
4
  module UuidAssociations
5
5
  module ActiveRecord
6
- module MethodDefinitions
6
+ module AssociationMethodDefinitions
7
7
  def has_many(name, scope = nil, **options, &extension)
8
8
  original_payload = super(name, scope, options, &extension)
9
9
  RelationshipDefinitions::HasMany.define_accesors_for(self, original_payload, name)
@@ -1,5 +1,7 @@
1
1
  require 'active_record'
2
2
  require 'active_record/associations'
3
- require 'uuid_associations/active_record/method_definitions'
3
+ require 'uuid_associations/active_record/association_method_definitions'
4
+ require 'uuid_associations/active_record/nested_attributes_method_definitions'
4
5
 
5
- ::ActiveRecord::Associations::ClassMethods.prepend UuidAssociations::ActiveRecord::MethodDefinitions
6
+ ::ActiveRecord::Base.extend(UuidAssociations::ActiveRecord::AssociationMethodDefinitions)
7
+ ::ActiveRecord::Base.prepend(UuidAssociations::ActiveRecord::NestedAttributesMethodDefinitions)
@@ -0,0 +1,49 @@
1
+ module UuidAssociations
2
+ module ActiveRecord
3
+ module NestedAttributes
4
+ class UuidFinder
5
+ def self.replaced_uuids_with_ids(association_klass, attribute_collection)
6
+ new(association_klass, attribute_collection).call
7
+ end
8
+
9
+ def initialize(association_klass, attribute_collection)
10
+ @association_klass = association_klass
11
+ @attribute_collection = attribute_collection
12
+ end
13
+
14
+ def call
15
+ to_replace, to_keep = attribute_collection.partition do |attributes|
16
+ symbol_keys = attributes.keys.map(&:to_sym)
17
+
18
+ (symbol_keys & [:uuid, :id]) == [:uuid]
19
+ end
20
+
21
+ uuids_to_find = to_replace.map { |element| element[:uuid] }
22
+ found_records = association_klass.where(uuid: uuids_to_find)
23
+
24
+ replaced = to_replace.each_with_object([]) do |attributes, collection|
25
+ uuid = attributes.delete(:uuid)
26
+
27
+ record = found_records.find { |found_record| found_record.uuid == uuid }
28
+
29
+ collection << if record.blank?
30
+ attributes
31
+ else
32
+ attributes.merge(id: record.id)
33
+ end
34
+ end
35
+
36
+ to_keep + replaced
37
+ end
38
+
39
+ private
40
+
41
+ def attribute_collection
42
+ @attribute_collection.instance_of?(Hash) ? @attribute_collection.values : @attribute_collection
43
+ end
44
+
45
+ attr_reader :association_klass
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,27 @@
1
+ require 'uuid_associations/active_record/nested_attributes/uuid_finder'
2
+
3
+ module UuidAssociations
4
+ module ActiveRecord
5
+ module NestedAttributesMethodDefinitions
6
+ private
7
+
8
+ def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
9
+ association_klass = association(association_name).reflection.klass
10
+ unless nested_association_uuid_searchable?(association_klass, attributes_collection)
11
+ return super(association_name, attributes_collection)
12
+ end
13
+
14
+ replaced_attributes = ActiveRecord::NestedAttributes::UuidFinder.replaced_uuids_with_ids(
15
+ association_klass,
16
+ attributes_collection
17
+ )
18
+ super(association_name, replaced_attributes)
19
+ end
20
+
21
+ def nested_association_uuid_searchable?(association_klass, attributes_collection)
22
+ association_klass.column_names.include?('uuid') &&
23
+ (attributes_collection.instance_of?(Hash) || attributes_collection.instance_of?(Array))
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,4 +1,5 @@
1
- require 'uuid_associations/active_record/method_definitions'
1
+ require 'uuid_associations/active_record/association_method_definitions'
2
+ require 'uuid_associations/active_record/nested_attributes_method_definitions'
2
3
 
3
4
  module UuidAssociations
4
5
  module ActiveRecord
@@ -7,7 +8,8 @@ module UuidAssociations
7
8
  ActiveSupport.on_load(:active_record) do
8
9
  ::ActiveRecord::Associations.eager_load!
9
10
 
10
- extend UuidAssociations::ActiveRecord::MethodDefinitions
11
+ extend(UuidAssociations::ActiveRecord::AssociationMethodDefinitions)
12
+ prepend(UuidAssociations::ActiveRecord::NestedAttributesMethodDefinitions)
11
13
  end
12
14
  end
13
15
  end
@@ -1,5 +1,5 @@
1
1
  module UuidAssociations
2
2
  module ActiveRecord
3
- VERSION = "0.1.0"
3
+ VERSION = '0.2.0'.freeze
4
4
  end
5
5
  end
@@ -0,0 +1,65 @@
1
+ RSpec.describe 'nested attributes for collection' do
2
+ context 'when nested association has no UUID column' do
3
+ let(:pet) { Pet.create!(name: 'Simba') }
4
+
5
+ it 'does not call UUID finder' do
6
+ expect(UuidAssociations::ActiveRecord::NestedAttributes::UuidFinder).not_to receive(:replaced_uuids_with_ids)
7
+
8
+ pet.update(toys_attributes: [{ name: 'no-uuid-here ;)' }])
9
+ end
10
+ end
11
+
12
+ context 'when creating a new record' do
13
+ it 'creates nested resources when not existing UUID is passed' do
14
+ expect do
15
+ Post.create!(
16
+ uuid: SecureRandom.uuid,
17
+ content: 'post',
18
+ comments_attributes: [
19
+ body: 'New comment',
20
+ uuid: SecureRandom.uuid
21
+ ]
22
+ )
23
+ end.to change(Post, :count).from(0).to(1)
24
+ .and change(Comment, :count).from(0).to(1)
25
+
26
+ expect(Post.first.comments.count).to eq(1)
27
+ end
28
+
29
+ it 'creates nested resources when no UUID or ID is passed' do
30
+ expect do
31
+ Post.create!(
32
+ uuid: SecureRandom.uuid,
33
+ content: 'post',
34
+ comments_attributes: [
35
+ body: 'New comment'
36
+ ]
37
+ )
38
+ end.to change(Post, :count).from(0).to(1)
39
+ .and change(Comment, :count).from(0).to(1)
40
+
41
+ expect(Post.first.comments.count).to eq(1)
42
+ end
43
+ end
44
+
45
+ context 'when updating existing records' do
46
+ let(:comment_uuid) { SecureRandom.uuid }
47
+ let(:post) { Post.create!(uuid: SecureRandom.uuid, content: 'My post') }
48
+ let!(:comment) { Comment.create!(post: post, body: 'My comment', uuid: comment_uuid) }
49
+
50
+ it 'updates nested records when a UUID is passed and no ID' do
51
+ expect do
52
+ post.update(comments_attributes: [{ uuid: comment.uuid, body: 'updated comment' }])
53
+ comment.reload
54
+ end.to change(comment, :body).from('My comment').to('updated comment')
55
+ end
56
+
57
+ it 'updates nested records by ID if ID is passed' do
58
+ expect do
59
+ post.update(comments_attributes: [{ id: comment.id, uuid: 'new-uuid', body: 'updated comment' }])
60
+ comment.reload
61
+ end.to change(comment, :body).from('My comment').to('updated comment')
62
+ .and change(comment, :uuid).from(comment_uuid).to('new-uuid')
63
+ end
64
+ end
65
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,8 @@ require 'support/models/team'
6
6
  require 'support/models/user'
7
7
  require 'support/models/post'
8
8
  require 'support/models/comment'
9
+ require 'support/models/pet'
10
+ require 'support/models/toy'
9
11
 
10
12
  RSpec.configure do |config|
11
13
  # Enable flags like --only-failures and --next-failure
@@ -1,5 +1,9 @@
1
1
  class Pet < ActiveRecord::Base
2
2
  has_and_belongs_to_many :users
3
3
 
4
+ has_many :toys
5
+
4
6
  validates :name, presence: true
7
+
8
+ accepts_nested_attributes_for :toys, allow_destroy: true
5
9
  end
@@ -2,4 +2,6 @@ class Post < ActiveRecord::Base
2
2
  belongs_to :user, required: false
3
3
 
4
4
  has_many :comments
5
+
6
+ accepts_nested_attributes_for :comments, allow_destroy: true
5
7
  end
@@ -0,0 +1,5 @@
1
+ class Toy < ActiveRecord::Base
2
+ belongs_to :pet
3
+
4
+ validates :name, presence: true
5
+ end
@@ -1,5 +1,6 @@
1
1
  class User < ActiveRecord::Base
2
2
  has_and_belongs_to_many :teams
3
+ has_and_belongs_to_many :pets
3
4
 
4
5
  has_many :posts
5
6
 
@@ -10,7 +10,7 @@ ActiveRecord::Schema.define version: 0 do
10
10
  t.timestamps
11
11
  end
12
12
 
13
- create_table :teams_users, foreign_key: false do |t|
13
+ create_table :teams_users, id: false do |t|
14
14
  t.integer :user_id, null: false
15
15
  t.integer :team_id, null: false
16
16
  end
@@ -22,7 +22,7 @@ ActiveRecord::Schema.define version: 0 do
22
22
  t.timestamps
23
23
  end
24
24
 
25
- create_table :pets_users, foreign_key: false do |t|
25
+ create_table :pets_users, id: false do |t|
26
26
  t.integer :user_id, null: false
27
27
  t.integer :pet_id, null: false
28
28
  end
@@ -34,6 +34,13 @@ ActiveRecord::Schema.define version: 0 do
34
34
  t.timestamps
35
35
  end
36
36
 
37
+ create_table :toys do |t|
38
+ t.string :name, null: false
39
+ t.belongs_to :pet, foreign_key: { on_delete: :cascade }
40
+
41
+ t.timestamps
42
+ end
43
+
37
44
  create_table :posts do |t|
38
45
  t.belongs_to :user, foreign_key: { on_delete: :cascade }
39
46
  t.string :uuid
@@ -0,0 +1,71 @@
1
+ require 'uuid_associations/active_record/nested_attributes/uuid_finder'
2
+
3
+ RSpec.describe UuidAssociations::ActiveRecord::NestedAttributes::UuidFinder do
4
+ describe '.replaced_uuids_with_ids' do
5
+ subject { described_class.replaced_uuids_with_ids(klass, attribute_collection) }
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 }
10
+
11
+ context 'when attributes come as an array' do
12
+ context 'when UUID is present, but ID is not' do
13
+ let(:attribute_collection) { [{ uuid: comment.uuid, body: 'updated comment' }] }
14
+
15
+ it { is_expected.to contain_exactly(id: comment.id, body: 'updated comment') }
16
+
17
+ context 'when record with specified UUID does not exist on the sytem' do
18
+ let(:attribute_collection) { [{ uuid: SecureRandom.uuid, body: 'new comment :/' }] }
19
+
20
+ it { is_expected.to match_array(attribute_collection) }
21
+ end
22
+ end
23
+
24
+ context 'when both UUID and ID are present' do
25
+ let(:attribute_collection) do
26
+ [
27
+ { uuid: comment.uuid, id: comment.id, body: 'updated comment' },
28
+ { body: 'new comment' }
29
+ ]
30
+ end
31
+
32
+ it do
33
+ is_expected.to contain_exactly(
34
+ { uuid: comment.uuid, id: comment.id, body: 'updated comment' },
35
+ { body: 'new comment' }
36
+ )
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'when attributes come as a hash' do
42
+ context 'when UUID is present, but ID is not' do
43
+ let(:attribute_collection) { { first: { uuid: comment.uuid, body: 'updated comment' } } }
44
+
45
+ it { is_expected.to contain_exactly(id: comment.id, body: 'updated comment') }
46
+
47
+ context 'when record with specified UUID does not exist on the sytem' do
48
+ let(:attribute_collection) { { first: { uuid: SecureRandom.uuid, body: 'new comment :/' } } }
49
+
50
+ it { is_expected.to match_array(attribute_collection.values) }
51
+ end
52
+ end
53
+
54
+ context 'when both UUID and ID are present' do
55
+ let(:attribute_collection) do
56
+ {
57
+ first: { uuid: comment.uuid, id: comment.id, body: 'updated comment' },
58
+ second: { body: 'new comment' }
59
+ }
60
+ end
61
+
62
+ it do
63
+ is_expected.to contain_exactly(
64
+ { uuid: comment.uuid, id: comment.id, body: 'updated comment' },
65
+ { body: 'new comment' }
66
+ )
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -19,6 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ['lib']
21
21
 
22
+ spec.required_ruby_version = '>= 2.1'
23
+
22
24
  spec.add_dependency 'activerecord', '>= 4.2', '< 6.0'
23
25
 
24
26
  spec.add_development_dependency 'appraisal', '~> 2.0'
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.1.0
4
+ version: 0.2.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: 2018-10-16 00:00:00.000000000 Z
11
+ date: 2018-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -139,23 +139,28 @@ files:
139
139
  - gemfiles/active_record_5.2.gemfile
140
140
  - gemfiles/active_record_edge.gemfile
141
141
  - lib/uuid_associations/active_record.rb
142
+ - lib/uuid_associations/active_record/association_method_definitions.rb
142
143
  - lib/uuid_associations/active_record/inline.rb
143
- - lib/uuid_associations/active_record/method_definitions.rb
144
+ - lib/uuid_associations/active_record/nested_attributes/uuid_finder.rb
145
+ - lib/uuid_associations/active_record/nested_attributes_method_definitions.rb
144
146
  - lib/uuid_associations/active_record/railtie.rb
145
147
  - lib/uuid_associations/active_record/relationship_definitions/base.rb
146
148
  - lib/uuid_associations/active_record/relationship_definitions/belongs_to.rb
147
149
  - lib/uuid_associations/active_record/relationship_definitions/has_many.rb
148
150
  - lib/uuid_associations/active_record/version.rb
151
+ - spec/integration/nested_attributes/collection_spec.rb
152
+ - spec/integration/relationship_definitions/belongs_to_spec.rb
153
+ - spec/integration/relationship_definitions/has_and_belongs_to_many_spec.rb
154
+ - spec/integration/relationship_definitions/has_many_spec.rb
149
155
  - spec/spec_helper.rb
150
156
  - spec/support/models/comment.rb
151
157
  - spec/support/models/pet.rb
152
158
  - spec/support/models/post.rb
153
159
  - spec/support/models/team.rb
160
+ - spec/support/models/toy.rb
154
161
  - spec/support/models/user.rb
155
162
  - spec/support/schema.rb
156
- - spec/uuid_associations/belongs_to_spec.rb
157
- - spec/uuid_associations/has_and_belongs_to_many_spec.rb
158
- - spec/uuid_associations/has_many_spec.rb
163
+ - spec/unit/uuid_associations/active_record/nested_attributes/uuid_finder_spec.rb
159
164
  - uuid_associations-active_record.gemspec
160
165
  homepage: https://github.com/mcelicalderon/uuid_associations-active_record
161
166
  licenses:
@@ -169,7 +174,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
169
174
  requirements:
170
175
  - - ">="
171
176
  - !ruby/object:Gem::Version
172
- version: '0'
177
+ version: '2.1'
173
178
  required_rubygems_version: !ruby/object:Gem::Requirement
174
179
  requirements:
175
180
  - - ">="
@@ -182,13 +187,16 @@ signing_key:
182
187
  specification_version: 4
183
188
  summary: Helper methods for UUID associations in Active Record
184
189
  test_files:
190
+ - spec/integration/nested_attributes/collection_spec.rb
191
+ - spec/integration/relationship_definitions/belongs_to_spec.rb
192
+ - spec/integration/relationship_definitions/has_and_belongs_to_many_spec.rb
193
+ - spec/integration/relationship_definitions/has_many_spec.rb
185
194
  - spec/spec_helper.rb
186
195
  - spec/support/models/comment.rb
187
196
  - spec/support/models/pet.rb
188
197
  - spec/support/models/post.rb
189
198
  - spec/support/models/team.rb
199
+ - spec/support/models/toy.rb
190
200
  - spec/support/models/user.rb
191
201
  - spec/support/schema.rb
192
- - spec/uuid_associations/belongs_to_spec.rb
193
- - spec/uuid_associations/has_and_belongs_to_many_spec.rb
194
- - spec/uuid_associations/has_many_spec.rb
202
+ - spec/unit/uuid_associations/active_record/nested_attributes/uuid_finder_spec.rb