deferred_associations 0.6.4 → 0.6.5
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/CHANGELOG +4 -0
- data/Readme.markdown +17 -1
- data/deferred_associations.gemspec +2 -2
- data/lib/array_to_association_wrapper.rb +8 -4
- data/lib/has_and_belongs_to_many_with_deferred_save.rb +13 -6
- data/lib/has_many_with_deferred_save.rb +12 -7
- data/spec/habtm_ar4_spec.rb +9 -9
- data/spec/has_and_belongs_to_many_with_deferred_save_spec.rb +23 -7
- data/spec/has_many_with_deferred_save_spec.rb +1 -1
- data/spec/models/room.rb +5 -1
- data/spec/spec_helper.rb +7 -3
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9b5f99b0963214fda3ba967f00208785fc8732e
|
4
|
+
data.tar.gz: f0617535e1cd7d2ecd07be537bdb90e19bf75a38
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18e808f2555625e6cf6a6a25b3e8966a056c71fac0814475ed4a2745574822ce9c5635b65c9283407da093eac6de784f650cc4ee49ec57a6c5d7fb6e5936662d
|
7
|
+
data.tar.gz: 0d0801311814c39772939b09f28936bebd89e6b115c59d0dfbf3b47d2fd6f7c34ce70f0b6a9af5b851e289d565c393935968949feda58dead0743af97c7d259f
|
data/CHANGELOG
CHANGED
data/Readme.markdown
CHANGED
@@ -46,7 +46,7 @@ end
|
|
46
46
|
Compatibility
|
47
47
|
=============
|
48
48
|
|
49
|
-
Tested with Rails 2.3.18, 3.2.22, 4.1.
|
49
|
+
Tested with Rails 2.3.18, 3.2.22, 4.1.16, 4.2.20, 5.1.4 on Ruby 1.9.3, 2.2.8, 2.3.5 and JRuby 1.7, JRuby 9.1.9.0
|
50
50
|
|
51
51
|
Note, that Rails 3.2.14 associations are partly broken under JRuby cause of https://github.com/rails/rails/issues/11595
|
52
52
|
You'll need to upgrade activerecord-jdbc-adapter to >= 1.3.0.beta1, if you want to use this combination.
|
@@ -94,6 +94,22 @@ methods are not working:
|
|
94
94
|
room.updated_at # => got touched!
|
95
95
|
```
|
96
96
|
|
97
|
+
4. If you use the ID getter, you get a copy of the IDs of the objects. So changing the entries in the array won't change
|
98
|
+
the IDs for real.
|
99
|
+
Rails 5 acts a little bit different - it lets you change the entry, but also doesn't save it.
|
100
|
+
deferred_associations will act the same way as in Rails 3&4.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
room = Room.find(...)
|
104
|
+
room.people_ids # [1]
|
105
|
+
room.people_ids << 2
|
106
|
+
room.people_ids # Rails 4: [1]
|
107
|
+
room.people_ids # Rails 5: [1, 2], but with deferred associations, it stays at [1]
|
108
|
+
room.save!
|
109
|
+
room.reload
|
110
|
+
room.people_ids # Rails 4&5: [1] # even Rails 5 doesn't save the changed array
|
111
|
+
```
|
112
|
+
|
97
113
|
Bugs
|
98
114
|
====
|
99
115
|
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'deferred_associations'
|
5
|
-
s.version = '0.6.
|
5
|
+
s.version = '0.6.5'
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ['Martin Koerner', 'Tyler Rick', 'Alessio Caiazza']
|
9
|
-
s.date = '
|
9
|
+
s.date = '2017-12-23'
|
10
10
|
s.description = "Makes ActiveRecord defer/postpone saving the records you add to an habtm (has_and_belongs_to_many) or has_many\n association until you call model.save, allowing validation in the style of normal attributes. Additionally you\n can check inside before_save filters, if the association was altered."
|
11
11
|
s.email = 'martin.koerner@objectfab.de'
|
12
12
|
s.licenses = 'MIT'
|
@@ -20,7 +20,8 @@ class ArrayToAssociationWrapper < Array
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
alias_method(:include_without_deferred_save?, :include?)
|
24
|
+
alias_method(:include?, :include_with_deferred_save?)
|
24
25
|
|
25
26
|
def find_with_deferred_save(*args)
|
26
27
|
if @association_owner.present?
|
@@ -30,7 +31,8 @@ class ArrayToAssociationWrapper < Array
|
|
30
31
|
end
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
+
alias_method(:find_without_deferred_save, :find)
|
35
|
+
alias_method(:find, :find_with_deferred_save)
|
34
36
|
|
35
37
|
def first_with_deferred_save(*args)
|
36
38
|
if @association_owner.present?
|
@@ -40,7 +42,8 @@ class ArrayToAssociationWrapper < Array
|
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
|
-
|
45
|
+
alias_method(:first_without_deferred_save, :first)
|
46
|
+
alias_method(:first, :first_with_deferred_save)
|
44
47
|
|
45
48
|
def last_with_deferred_save(*args)
|
46
49
|
if @association_owner.present?
|
@@ -50,7 +53,8 @@ class ArrayToAssociationWrapper < Array
|
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
|
-
|
56
|
+
alias_method(:last_without_deferred_save, :last)
|
57
|
+
alias_method(:last, :last_with_deferred_save)
|
54
58
|
|
55
59
|
define_method :method_missing do |method, *args|
|
56
60
|
# puts "#{self.class}.method_missing(#{method}) (#{collection_without_deferred_save.inspect})"
|
@@ -41,8 +41,10 @@ module ActiveRecord
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
alias_method(:"#{collection_name}_without_deferred_save=", :"#{collection_name}=")
|
45
|
+
alias_method(:"#{collection_name}=", :"#{collection_name}_with_deferred_save=")
|
46
|
+
alias_method(:"#{collection_name}_without_deferred_save", :"#{collection_name}")
|
47
|
+
alias_method(:"#{collection_name}", :"#{collection_name}_with_deferred_save")
|
46
48
|
|
47
49
|
define_method "#{collection_singular_ids}_with_deferred_save" do |*method_args|
|
48
50
|
if send("use_original_collection_reader_behavior_for_#{collection_name}")
|
@@ -53,7 +55,8 @@ module ActiveRecord
|
|
53
55
|
end
|
54
56
|
end
|
55
57
|
|
56
|
-
|
58
|
+
alias_method(:"#{collection_singular_ids}_without_deferred_save", :"#{collection_singular_ids}")
|
59
|
+
alias_method(:"#{collection_singular_ids}", :"#{collection_singular_ids}_with_deferred_save")
|
57
60
|
|
58
61
|
# only needed for ActiveRecord >= 3.0
|
59
62
|
if ActiveRecord::VERSION::STRING >= '3'
|
@@ -63,7 +66,9 @@ module ActiveRecord
|
|
63
66
|
new_values = reflection_wrapper.klass.find(ids)
|
64
67
|
send("#{collection_name}=", new_values)
|
65
68
|
end
|
66
|
-
|
69
|
+
|
70
|
+
alias_method(:"#{collection_singular_ids}_without_deferred_save=", :"#{collection_singular_ids}=")
|
71
|
+
alias_method(:"#{collection_singular_ids}=", :"#{collection_singular_ids}_with_deferred_save=")
|
67
72
|
end
|
68
73
|
|
69
74
|
define_method "do_#{collection_name}_save!" do
|
@@ -87,7 +92,7 @@ module ActiveRecord
|
|
87
92
|
end
|
88
93
|
true
|
89
94
|
end
|
90
|
-
after_save "do_#{collection_name}_save!"
|
95
|
+
after_save :"do_#{collection_name}_save!"
|
91
96
|
|
92
97
|
define_method "reload_with_deferred_save_for_#{collection_name}" do |*method_args|
|
93
98
|
# Reload from the *database*, discarding any unsaved changes.
|
@@ -97,7 +102,9 @@ module ActiveRecord
|
|
97
102
|
# unsaved_collection that it had before the reload.
|
98
103
|
end
|
99
104
|
end
|
100
|
-
|
105
|
+
|
106
|
+
alias_method(:"reload_without_deferred_save_for_#{collection_name}", :reload)
|
107
|
+
alias_method(:reload, :"reload_with_deferred_save_for_#{collection_name}")
|
101
108
|
|
102
109
|
define_method "initialize_unsaved_#{collection_name}" do |*method_args|
|
103
110
|
elements = send("#{collection_name}_without_deferred_save", *method_args)
|
@@ -13,7 +13,7 @@ module ActiveRecord
|
|
13
13
|
logger.warn "You are using the option :through on #{name}##{collection_name}. This was not tested very much with has_many_with_deferred_save. Please write many tests for your functionality!"
|
14
14
|
end
|
15
15
|
|
16
|
-
after_save "hmwds_update_#{collection_name}"
|
16
|
+
after_save :"hmwds_update_#{collection_name}"
|
17
17
|
|
18
18
|
define_obj_setter collection_name
|
19
19
|
define_obj_getter collection_name
|
@@ -30,8 +30,8 @@ module ActiveRecord
|
|
30
30
|
attribute_will_change!(collection_name) if objs != send("#{collection_name}_without_deferred_save")
|
31
31
|
end
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
alias_method(:"#{collection_name}_without_deferred_save=", :"#{collection_name}=")
|
34
|
+
alias_method(:"#{collection_name}=", :"#{collection_name}_with_deferred_save=")
|
35
35
|
end
|
36
36
|
|
37
37
|
def define_obj_getter(collection_name)
|
@@ -55,7 +55,8 @@ module ActiveRecord
|
|
55
55
|
result
|
56
56
|
end
|
57
57
|
|
58
|
-
|
58
|
+
alias_method(:"#{collection_name}_without_deferred_save", :"#{collection_name}")
|
59
|
+
alias_method(:"#{collection_name}", :"#{collection_name}_with_deferred_save")
|
59
60
|
end
|
60
61
|
|
61
62
|
def define_id_setter(collection_name, collection_singular_ids)
|
@@ -66,7 +67,9 @@ module ActiveRecord
|
|
66
67
|
new_values = send("#{collection_name}_without_deferred_save").klass.find(ids)
|
67
68
|
send("#{collection_name}=", new_values)
|
68
69
|
end
|
69
|
-
|
70
|
+
|
71
|
+
alias_method(:"#{collection_singular_ids}_without_deferred_save=", :"#{collection_singular_ids}=")
|
72
|
+
alias_method(:"#{collection_singular_ids}=", :"#{collection_singular_ids}_with_deferred_save=")
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
@@ -74,7 +77,8 @@ module ActiveRecord
|
|
74
77
|
define_method "#{collection_singular_ids}_with_deferred_save" do
|
75
78
|
send(collection_name).map { |e| e[:id] }
|
76
79
|
end
|
77
|
-
|
80
|
+
alias_method(:"#{collection_singular_ids}_without_deferred_save", :"#{collection_singular_ids}")
|
81
|
+
alias_method(:"#{collection_singular_ids}", :"#{collection_singular_ids}_with_deferred_save")
|
78
82
|
end
|
79
83
|
|
80
84
|
def define_update_method(collection_name)
|
@@ -100,7 +104,8 @@ module ActiveRecord
|
|
100
104
|
instance_variable_set "@hmwds_temp_#{collection_name}", nil
|
101
105
|
end
|
102
106
|
end
|
103
|
-
|
107
|
+
alias_method(:"reload_without_deferred_save_for_#{collection_name}", :reload)
|
108
|
+
alias_method(:reload, :"reload_with_deferred_save_for_#{collection_name}")
|
104
109
|
end
|
105
110
|
end
|
106
111
|
end
|
data/spec/habtm_ar4_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'has_and_belongs_to_many_with_deferred_save'
|
3
3
|
|
4
|
-
if
|
5
|
-
describe 'ActiveRecord4 specials' do
|
4
|
+
if ar4_or_more?
|
5
|
+
describe 'ActiveRecord4/5 specials' do
|
6
6
|
before :all do
|
7
7
|
#ActiveRecord::Base.logger = Logger.new(STDOUT) # uncomment for debugging statements
|
8
8
|
@people = []
|
@@ -64,21 +64,21 @@ if ar4?
|
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'should preload with non-deferred association' do
|
67
|
-
rooms = Room.where(id: [@room1.id, @room2.id, @room3.id]).preload(:
|
67
|
+
rooms = Room.where(id: [@room1.id, @room2.id, @room3.id]).preload(:people_without_deferring)
|
68
68
|
rooms = rooms.to_a # execute original query, together with preloading the association
|
69
69
|
room1 = rooms.first
|
70
70
|
room2 = rooms.second
|
71
71
|
room3 = rooms.third
|
72
72
|
# association is autoloaded
|
73
|
-
expect(room1.
|
74
|
-
expect(room2.
|
75
|
-
expect(room3.
|
73
|
+
expect(room1.people_without_deferring.loaded?).to be true
|
74
|
+
expect(room2.people_without_deferring.loaded?).to be true
|
75
|
+
expect(room3.people_without_deferring.loaded?).to be true
|
76
76
|
|
77
77
|
expect(ActiveRecord::Base).not_to receive(:connection)
|
78
78
|
|
79
|
-
expect(room1.
|
80
|
-
expect(room2.
|
81
|
-
expect(room3.
|
79
|
+
expect(room1.people_without_deferring.map(&:name)).to match_array(%w(Miguel Rainer))
|
80
|
+
expect(room2.people_without_deferring.map(&:name)).to match_array(%w(Filbert Miguel))
|
81
|
+
expect(room3.people_without_deferring.map(&:name)).to match_array(%w())
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -113,14 +113,14 @@ describe 'has_and_belongs_to_many_with_deferred_save' do
|
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'still lets you do find' do
|
116
|
-
if
|
117
|
-
expect(@room.
|
116
|
+
if ar4_or_more?
|
117
|
+
expect(@room.people_without_deferring.where(name: 'Filbert').first).to eq(@people[0])
|
118
118
|
expect(@room.people_without_deferred_save.where(name: 'Filbert').first).to eq(@people[0])
|
119
119
|
expect(@room.people.where(name: 'Filbert').first).to eq(@people[0])
|
120
120
|
else
|
121
|
-
expect(@room.
|
121
|
+
expect(@room.people_without_deferring. find(:first, conditions: { name: 'Filbert' })).to eq(@people[0])
|
122
122
|
expect(@room.people_without_deferred_save.find(:first, conditions: { name: 'Filbert' })).to eq(@people[0])
|
123
|
-
expect(@room.
|
123
|
+
expect(@room.people_without_deferring.first(conditions: { name: 'Filbert' })).to eq(@people[0])
|
124
124
|
expect(@room.people_without_deferred_save.first(conditions: { name: 'Filbert' })).to eq(@people[0])
|
125
125
|
|
126
126
|
expect(@room.people.find(:first, conditions: { name: 'Filbert' })).to eq(@people[0])
|
@@ -163,15 +163,31 @@ describe 'has_and_belongs_to_many_with_deferred_save' do
|
|
163
163
|
@room.people = [@people[0]]
|
164
164
|
@room.save
|
165
165
|
@room = Room.find(@room.id) # we don't want to let id and object setters interfere with each other
|
166
|
-
@room.
|
167
|
-
|
166
|
+
@room.people_without_deferring_ids << @people[1].id
|
167
|
+
|
168
|
+
if ar5_or_more?
|
169
|
+
# In Rails 5, ID array manipulation is taken into account, but only temporarily,
|
170
|
+
# therefore deferred_association doesn't mimic this behavior
|
171
|
+
expect(@room.people_without_deferring_ids).to eq([@people[0].id, @people[1].id])
|
172
|
+
else
|
173
|
+
# ID array manipulation is ignored
|
174
|
+
expect(@room.people_without_deferring_ids).to eq([@people[0].id])
|
175
|
+
end
|
168
176
|
|
169
177
|
expect(@room.person_ids.size).to eq(1)
|
170
178
|
@room.person_ids << @people[1].id
|
179
|
+
|
180
|
+
# deferred_association doesn't remember the additional ID, no matter, which AR version
|
181
|
+
# we are in
|
171
182
|
expect(@room.person_ids).to eq([@people[0].id])
|
172
183
|
expect(Room.find(@room.id).person_ids).to eq([@people[0].id])
|
173
184
|
expect(@room.save).to be true
|
174
|
-
|
185
|
+
|
186
|
+
# Original association didn't save the temporarily saved changes,
|
187
|
+
# the deferred association also looses the change on reload
|
188
|
+
@room = Room.find(@room.id)
|
189
|
+
expect(@room.people_without_deferring_ids).to eq([@people[0].id])
|
190
|
+
expect(@room.person_ids).to eq([@people[0].id])
|
175
191
|
end
|
176
192
|
|
177
193
|
it 'should work with id setters' do
|
@@ -84,7 +84,7 @@ describe 'has_many_with_deferred_save' do
|
|
84
84
|
|
85
85
|
it 'should defer association methods' do
|
86
86
|
expect(@room.chairs.first).to eq(@chair1)
|
87
|
-
if
|
87
|
+
if ar4_or_more?
|
88
88
|
expect(@room.chairs.where(name: 'First')).to eq([@chair1])
|
89
89
|
else
|
90
90
|
expect(@room.chairs.find(:all, conditions: { name: 'First' })).to eq([@chair1])
|
data/spec/models/room.rb
CHANGED
@@ -7,9 +7,13 @@ class Room < ActiveRecord::Base
|
|
7
7
|
before_save :diff_before_module
|
8
8
|
|
9
9
|
has_and_belongs_to_many_with_deferred_save :people, before_add: :before_adding_person
|
10
|
-
has_and_belongs_to_many :
|
10
|
+
has_and_belongs_to_many :people_without_deferring, class_name: 'Person'
|
11
11
|
has_and_belongs_to_many_with_deferred_save :doors
|
12
12
|
|
13
|
+
if ar5_or_more?
|
14
|
+
# without it, AR5 would throw a deprecation warning
|
15
|
+
attribute :tables
|
16
|
+
end
|
13
17
|
has_many_with_deferred_save :tables
|
14
18
|
has_many_with_deferred_save :chairs, through: :tables # TODO: test compatibility with through associations
|
15
19
|
|
data/spec/spec_helper.rb
CHANGED
@@ -18,8 +18,6 @@ ActiveRecord::Base.establish_connection(:sqlite3mem)
|
|
18
18
|
ActiveRecord::Migration.verbose = false
|
19
19
|
load(File.join(plugin_test_dir, 'db', 'schema.rb'))
|
20
20
|
|
21
|
-
Dir["#{plugin_test_dir}/models/*.rb"].each { |file| require file }
|
22
|
-
|
23
21
|
RSpec.configure do |config|
|
24
22
|
config.raise_errors_for_deprecations!
|
25
23
|
|
@@ -44,6 +42,12 @@ def ar2?
|
|
44
42
|
ActiveRecord::VERSION::STRING < '3'
|
45
43
|
end
|
46
44
|
|
47
|
-
def
|
45
|
+
def ar4_or_more?
|
48
46
|
ActiveRecord::VERSION::STRING >= '4'
|
49
47
|
end
|
48
|
+
|
49
|
+
def ar5_or_more?
|
50
|
+
ActiveRecord::VERSION::STRING >= '5'
|
51
|
+
end
|
52
|
+
|
53
|
+
Dir["#{plugin_test_dir}/models/*.rb"].each { |file| require file }
|
metadata
CHANGED
@@ -1,40 +1,40 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deferred_associations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Koerner
|
8
8
|
- Tyler Rick
|
9
9
|
- Alessio Caiazza
|
10
|
-
autorequire:
|
10
|
+
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2017-12-23 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
17
18
|
requirements:
|
18
19
|
- - ">="
|
19
20
|
- !ruby/object:Gem::Version
|
20
21
|
version: '0'
|
21
|
-
name: activerecord
|
22
|
-
prerelease: false
|
23
22
|
type: :runtime
|
23
|
+
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - ">="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
version: '0'
|
29
29
|
- !ruby/object:Gem::Dependency
|
30
|
+
name: rspec
|
30
31
|
requirement: !ruby/object:Gem::Requirement
|
31
32
|
requirements:
|
32
33
|
- - ">="
|
33
34
|
- !ruby/object:Gem::Version
|
34
35
|
version: '0'
|
35
|
-
name: rspec
|
36
|
-
prerelease: false
|
37
36
|
type: :development
|
37
|
+
prerelease: false
|
38
38
|
version_requirements: !ruby/object:Gem::Requirement
|
39
39
|
requirements:
|
40
40
|
- - ">="
|
@@ -76,7 +76,7 @@ homepage: http://github.com/MartinKoerner/deferred_associations
|
|
76
76
|
licenses:
|
77
77
|
- MIT
|
78
78
|
metadata: {}
|
79
|
-
post_install_message:
|
79
|
+
post_install_message:
|
80
80
|
rdoc_options: []
|
81
81
|
require_paths:
|
82
82
|
- lib
|
@@ -91,9 +91,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
91
|
- !ruby/object:Gem::Version
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|
94
|
-
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
96
|
-
signing_key:
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 2.5.1
|
96
|
+
signing_key:
|
97
97
|
specification_version: 3
|
98
98
|
summary: Makes ActiveRecord defer/postpone habtm or has_many associations
|
99
99
|
test_files: []
|