paper_trail 4.2.0 → 5.0.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/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +28 -9
- data/.github/ISSUE_TEMPLATE.md +13 -0
- data/.gitignore +2 -1
- data/.rubocop.yml +100 -0
- data/.rubocop_todo.yml +14 -0
- data/.travis.yml +8 -9
- data/Appraisals +41 -0
- data/CHANGELOG.md +49 -9
- data/Gemfile +1 -1
- data/README.md +130 -109
- data/Rakefile +19 -19
- data/doc/bug_report_template.rb +20 -14
- data/gemfiles/ar3.gemfile +10 -53
- data/gemfiles/ar4.gemfile +7 -0
- data/gemfiles/ar5.gemfile +13 -0
- data/lib/generators/paper_trail/install_generator.rb +26 -18
- data/lib/generators/paper_trail/templates/add_object_changes_to_versions.rb +4 -2
- data/lib/generators/paper_trail/templates/add_transaction_id_column_to_versions.rb +2 -0
- data/lib/generators/paper_trail/templates/create_version_associations.rb +9 -4
- data/lib/generators/paper_trail/templates/create_versions.rb +39 -5
- data/lib/paper_trail.rb +169 -146
- data/lib/paper_trail/attributes_serialization.rb +89 -17
- data/lib/paper_trail/cleaner.rb +15 -9
- data/lib/paper_trail/config.rb +28 -11
- data/lib/paper_trail/frameworks/active_record.rb +4 -0
- data/lib/paper_trail/frameworks/active_record/models/paper_trail/version.rb +5 -1
- data/lib/paper_trail/frameworks/active_record/models/paper_trail/version_association.rb +6 -2
- data/lib/paper_trail/frameworks/cucumber.rb +1 -0
- data/lib/paper_trail/frameworks/rails.rb +2 -7
- data/lib/paper_trail/frameworks/rails/controller.rb +29 -9
- data/lib/paper_trail/frameworks/rails/engine.rb +7 -1
- data/lib/paper_trail/frameworks/rspec.rb +5 -5
- data/lib/paper_trail/frameworks/rspec/helpers.rb +3 -1
- data/lib/paper_trail/frameworks/sinatra.rb +6 -4
- data/lib/paper_trail/has_paper_trail.rb +199 -106
- data/lib/paper_trail/record_history.rb +1 -3
- data/lib/paper_trail/reifier.rb +297 -118
- data/lib/paper_trail/serializers/json.rb +3 -3
- data/lib/paper_trail/serializers/yaml.rb +27 -8
- data/lib/paper_trail/version_association_concern.rb +3 -1
- data/lib/paper_trail/version_concern.rb +75 -35
- data/lib/paper_trail/version_number.rb +6 -9
- data/paper_trail.gemspec +44 -51
- data/spec/generators/install_generator_spec.rb +24 -25
- data/spec/generators/paper_trail/templates/create_versions_spec.rb +51 -0
- data/spec/models/animal_spec.rb +12 -12
- data/spec/models/boolit_spec.rb +8 -8
- data/spec/models/callback_modifier_spec.rb +47 -47
- data/spec/models/car_spec.rb +13 -0
- data/spec/models/fluxor_spec.rb +3 -3
- data/spec/models/gadget_spec.rb +19 -19
- data/spec/models/joined_version_spec.rb +3 -3
- data/spec/models/json_version_spec.rb +23 -24
- data/spec/models/kitchen/banana_spec.rb +3 -3
- data/spec/models/not_on_update_spec.rb +7 -4
- data/spec/models/post_with_status_spec.rb +13 -3
- data/spec/models/skipper_spec.rb +10 -10
- data/spec/models/thing_spec.rb +4 -4
- data/spec/models/truck_spec.rb +5 -0
- data/spec/models/vehicle_spec.rb +5 -0
- data/spec/models/version_spec.rb +103 -59
- data/spec/models/widget_spec.rb +82 -52
- data/spec/modules/paper_trail_spec.rb +2 -2
- data/spec/modules/version_concern_spec.rb +11 -12
- data/spec/modules/version_number_spec.rb +2 -4
- data/spec/paper_trail/config_spec.rb +10 -29
- data/spec/paper_trail_spec.rb +16 -14
- data/spec/rails_helper.rb +10 -9
- data/spec/requests/articles_spec.rb +11 -7
- data/spec/spec_helper.rb +41 -22
- data/spec/support/alt_db_init.rb +8 -13
- data/test/custom_json_serializer.rb +3 -3
- data/test/dummy/Rakefile +2 -2
- data/test/dummy/app/controllers/application_controller.rb +21 -8
- data/test/dummy/app/controllers/articles_controller.rb +11 -8
- data/test/dummy/app/controllers/widgets_controller.rb +13 -12
- data/test/dummy/app/models/animal.rb +1 -1
- data/test/dummy/app/models/article.rb +19 -11
- data/test/dummy/app/models/authorship.rb +1 -1
- data/test/dummy/app/models/bar_habtm.rb +4 -0
- data/test/dummy/app/models/book.rb +4 -4
- data/test/dummy/app/models/boolit.rb +1 -1
- data/test/dummy/app/models/callback_modifier.rb +6 -6
- data/test/dummy/app/models/car.rb +3 -0
- data/test/dummy/app/models/chapter.rb +4 -4
- data/test/dummy/app/models/customer.rb +1 -1
- data/test/dummy/app/models/document.rb +2 -2
- data/test/dummy/app/models/editor.rb +1 -1
- data/test/dummy/app/models/foo_habtm.rb +4 -0
- data/test/dummy/app/models/fruit.rb +2 -2
- data/test/dummy/app/models/gadget.rb +1 -1
- data/test/dummy/app/models/kitchen/banana.rb +1 -1
- data/test/dummy/app/models/legacy_widget.rb +2 -2
- data/test/dummy/app/models/line_item.rb +1 -1
- data/test/dummy/app/models/not_on_update.rb +1 -1
- data/test/dummy/app/models/person.rb +6 -6
- data/test/dummy/app/models/post.rb +1 -1
- data/test/dummy/app/models/post_with_status.rb +1 -1
- data/test/dummy/app/models/quotation.rb +1 -1
- data/test/dummy/app/models/section.rb +1 -1
- data/test/dummy/app/models/skipper.rb +2 -2
- data/test/dummy/app/models/song.rb +13 -4
- data/test/dummy/app/models/thing.rb +2 -2
- data/test/dummy/app/models/translation.rb +2 -2
- data/test/dummy/app/models/truck.rb +4 -0
- data/test/dummy/app/models/vehicle.rb +4 -0
- data/test/dummy/app/models/whatchamajigger.rb +1 -1
- data/test/dummy/app/models/widget.rb +7 -6
- data/test/dummy/app/versions/joined_version.rb +4 -3
- data/test/dummy/app/versions/json_version.rb +1 -1
- data/test/dummy/app/versions/kitchen/banana_version.rb +1 -1
- data/test/dummy/app/versions/post_version.rb +2 -2
- data/test/dummy/config.ru +1 -1
- data/test/dummy/config/application.rb +20 -9
- data/test/dummy/config/boot.rb +5 -5
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/development.rb +4 -3
- data/test/dummy/config/environments/production.rb +3 -2
- data/test/dummy/config/environments/test.rb +15 -5
- data/test/dummy/config/initializers/backtrace_silencers.rb +4 -2
- data/test/dummy/config/initializers/paper_trail.rb +1 -2
- data/test/dummy/config/initializers/secret_token.rb +3 -1
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/dummy/config/routes.rb +2 -2
- data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +120 -74
- data/test/dummy/db/schema.rb +29 -6
- data/test/dummy/script/rails +6 -4
- data/test/functional/controller_test.rb +34 -35
- data/test/functional/enabled_for_controller_test.rb +6 -7
- data/test/functional/modular_sinatra_test.rb +43 -38
- data/test/functional/sinatra_test.rb +49 -40
- data/test/functional/thread_safety_test.rb +4 -6
- data/test/paper_trail_test.rb +15 -14
- data/test/test_helper.rb +68 -44
- data/test/time_travel_helper.rb +1 -15
- data/test/unit/associations_test.rb +517 -251
- data/test/unit/cleaner_test.rb +66 -60
- data/test/unit/inheritance_column_test.rb +17 -17
- data/test/unit/model_test.rb +611 -504
- data/test/unit/protected_attrs_test.rb +16 -12
- data/test/unit/serializer_test.rb +44 -43
- data/test/unit/serializers/json_test.rb +17 -18
- data/test/unit/serializers/mixin_json_test.rb +15 -14
- data/test/unit/serializers/mixin_yaml_test.rb +20 -16
- data/test/unit/serializers/yaml_test.rb +12 -13
- data/test/unit/timestamp_test.rb +10 -12
- data/test/unit/version_test.rb +7 -7
- metadata +92 -40
data/test/time_travel_helper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "test_helper"
|
2
|
+
require "time_travel_helper"
|
3
3
|
|
4
4
|
class AssociationsTest < ActiveSupport::TestCase
|
5
5
|
CHAPTER_NAMES = [
|
@@ -15,11 +15,15 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
15
15
|
"The Lobster Quadrille",
|
16
16
|
"Who Stole the Tarts?",
|
17
17
|
"Alice's Evidence"
|
18
|
-
]
|
18
|
+
].freeze
|
19
19
|
|
20
20
|
# These would have been done in test_helper.rb if using_mysql? is true
|
21
21
|
unless using_mysql?
|
22
|
-
|
22
|
+
if respond_to? :use_transactional_tests=
|
23
|
+
self.use_transactional_tests = false
|
24
|
+
else
|
25
|
+
self.use_transactional_fixtures = false
|
26
|
+
end
|
23
27
|
setup { DatabaseCleaner.start }
|
24
28
|
end
|
25
29
|
|
@@ -30,103 +34,103 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
30
34
|
end
|
31
35
|
|
32
36
|
context "a has_one association" do
|
33
|
-
setup { @widget = Widget.create :
|
37
|
+
setup { @widget = Widget.create name: "widget_0" }
|
34
38
|
|
35
|
-
context
|
39
|
+
context "before the associated was created" do
|
36
40
|
setup do
|
37
|
-
@widget.update_attributes :
|
38
|
-
@wotsit = @widget.create_wotsit :
|
41
|
+
@widget.update_attributes name: "widget_1"
|
42
|
+
@wotsit = @widget.create_wotsit name: "wotsit_0"
|
39
43
|
end
|
40
44
|
|
41
|
-
context
|
42
|
-
setup { @widget_0 = @widget.versions.last.reify(:
|
45
|
+
context "when reified" do
|
46
|
+
setup { @widget_0 = @widget.versions.last.reify(has_one: true) }
|
43
47
|
|
44
|
-
should
|
48
|
+
should "see the associated as it was at the time" do
|
45
49
|
assert_nil @widget_0.wotsit
|
46
50
|
end
|
47
51
|
|
48
|
-
should
|
49
|
-
assert_equal @wotsit, @widget.wotsit
|
52
|
+
should "not persist changes to the live association" do
|
53
|
+
assert_equal @wotsit, @widget.reload.wotsit
|
50
54
|
end
|
51
55
|
end
|
52
56
|
end
|
53
57
|
|
54
|
-
context
|
58
|
+
context "where the association is created between model versions" do
|
55
59
|
setup do
|
56
|
-
@wotsit = @widget.create_wotsit :
|
60
|
+
@wotsit = @widget.create_wotsit name: "wotsit_0"
|
57
61
|
Timecop.travel 1.second.since
|
58
|
-
@widget.update_attributes :
|
62
|
+
@widget.update_attributes name: "widget_1"
|
59
63
|
end
|
60
64
|
|
61
|
-
context
|
62
|
-
setup { @widget_0 = @widget.versions.last.reify(:
|
65
|
+
context "when reified" do
|
66
|
+
setup { @widget_0 = @widget.versions.last.reify(has_one: true) }
|
63
67
|
|
64
|
-
should
|
65
|
-
assert_equal
|
68
|
+
should "see the associated as it was at the time" do
|
69
|
+
assert_equal "wotsit_0", @widget_0.wotsit.name
|
66
70
|
end
|
67
71
|
|
68
|
-
should
|
69
|
-
assert_equal @wotsit, @widget.wotsit
|
72
|
+
should "not persist changes to the live association" do
|
73
|
+
assert_equal @wotsit, @widget.reload.wotsit
|
70
74
|
end
|
71
75
|
end
|
72
76
|
|
73
|
-
context
|
77
|
+
context "and then the associated is updated between model versions" do
|
74
78
|
setup do
|
75
|
-
@wotsit.update_attributes :
|
76
|
-
@wotsit.update_attributes :
|
79
|
+
@wotsit.update_attributes name: "wotsit_1"
|
80
|
+
@wotsit.update_attributes name: "wotsit_2"
|
77
81
|
Timecop.travel 1.second.since
|
78
|
-
@widget.update_attributes :
|
79
|
-
@wotsit.update_attributes :
|
82
|
+
@widget.update_attributes name: "widget_2"
|
83
|
+
@wotsit.update_attributes name: "wotsit_3"
|
80
84
|
end
|
81
85
|
|
82
|
-
context
|
83
|
-
setup { @widget_1 = @widget.versions.last.reify(:
|
86
|
+
context "when reified" do
|
87
|
+
setup { @widget_1 = @widget.versions.last.reify(has_one: true) }
|
84
88
|
|
85
|
-
should
|
86
|
-
assert_equal
|
89
|
+
should "see the associated as it was at the time" do
|
90
|
+
assert_equal "wotsit_2", @widget_1.wotsit.name
|
87
91
|
end
|
88
92
|
|
89
|
-
should
|
90
|
-
assert_equal
|
93
|
+
should "not persist changes to the live association" do
|
94
|
+
assert_equal "wotsit_3", @widget.reload.wotsit.name
|
91
95
|
end
|
92
96
|
end
|
93
97
|
|
94
|
-
context
|
95
|
-
setup { @widget_1 = @widget.versions.last.reify(:
|
98
|
+
context "when reified opting out of has_one reification" do
|
99
|
+
setup { @widget_1 = @widget.versions.last.reify(has_one: false) }
|
96
100
|
|
97
|
-
should
|
98
|
-
assert_equal
|
101
|
+
should "see the associated as it is live" do
|
102
|
+
assert_equal "wotsit_3", @widget_1.wotsit.name
|
99
103
|
end
|
100
104
|
end
|
101
105
|
end
|
102
106
|
|
103
|
-
context
|
107
|
+
context "and then the associated is destroyed" do
|
104
108
|
setup do
|
105
109
|
@wotsit.destroy
|
106
110
|
end
|
107
111
|
|
108
|
-
context
|
109
|
-
setup { @widget_1 = @widget.versions.last.reify(:
|
112
|
+
context "when reify" do
|
113
|
+
setup { @widget_1 = @widget.versions.last.reify(has_one: true) }
|
110
114
|
|
111
|
-
should
|
115
|
+
should "see the associated as it was at the time" do
|
112
116
|
assert_equal @wotsit, @widget_1.wotsit
|
113
117
|
end
|
114
118
|
|
115
|
-
should
|
116
|
-
assert_nil @widget.wotsit
|
119
|
+
should "not persist changes to the live association" do
|
120
|
+
assert_nil @widget.reload.wotsit
|
117
121
|
end
|
118
122
|
end
|
119
123
|
|
120
|
-
context
|
124
|
+
context "and then the model is updated" do
|
121
125
|
setup do
|
122
126
|
Timecop.travel 1.second.since
|
123
|
-
@widget.update_attributes :
|
127
|
+
@widget.update_attributes name: "widget_3"
|
124
128
|
end
|
125
129
|
|
126
|
-
context
|
127
|
-
setup { @widget_2 = @widget.versions.last.reify(:
|
130
|
+
context "when reified" do
|
131
|
+
setup { @widget_2 = @widget.versions.last.reify(has_one: true) }
|
128
132
|
|
129
|
-
should
|
133
|
+
should "see the associated as it was at the time" do
|
130
134
|
assert_nil @widget_2.wotsit
|
131
135
|
end
|
132
136
|
end
|
@@ -136,168 +140,176 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
136
140
|
end
|
137
141
|
|
138
142
|
context "a has_many association" do
|
139
|
-
setup { @customer = Customer.create :
|
143
|
+
setup { @customer = Customer.create name: "customer_0" }
|
140
144
|
|
141
|
-
context
|
145
|
+
context "updated before the associated was created" do
|
142
146
|
setup do
|
143
|
-
@customer.update_attributes! :
|
144
|
-
@customer.orders.create! :
|
147
|
+
@customer.update_attributes! name: "customer_1"
|
148
|
+
@customer.orders.create! order_date: Date.today
|
145
149
|
end
|
146
150
|
|
147
|
-
context
|
148
|
-
setup { @customer_0 = @customer.versions.last.reify(:
|
151
|
+
context "when reified" do
|
152
|
+
setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
|
149
153
|
|
150
|
-
should
|
154
|
+
should "see the associated as it was at the time" do
|
151
155
|
assert_equal [], @customer_0.orders
|
152
156
|
end
|
153
157
|
|
154
|
-
should
|
155
|
-
assert_not_equal [], @customer.orders
|
158
|
+
should "not persist changes to the live association" do
|
159
|
+
assert_not_equal [], @customer.orders.reload
|
156
160
|
end
|
157
161
|
end
|
158
162
|
|
159
|
-
context
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
+
context "when reified with option mark_for_destruction" do
|
164
|
+
should "mark the associated for destruction" do
|
165
|
+
@customer_0 = @customer.versions.last.reify(
|
166
|
+
has_many: true,
|
167
|
+
mark_for_destruction: true
|
168
|
+
)
|
163
169
|
assert_equal [true], @customer_0.orders.map(&:marked_for_destruction?)
|
164
170
|
end
|
165
171
|
end
|
166
172
|
end
|
167
173
|
|
168
|
-
context
|
174
|
+
context "where the association is created between model versions" do
|
169
175
|
setup do
|
170
|
-
@order = @customer.orders.create! :
|
176
|
+
@order = @customer.orders.create! order_date: "order_date_0"
|
171
177
|
Timecop.travel 1.second.since
|
172
|
-
@customer.update_attributes :
|
178
|
+
@customer.update_attributes name: "customer_1"
|
173
179
|
end
|
174
180
|
|
175
|
-
context
|
176
|
-
setup { @customer_0 = @customer.versions.last.reify(:
|
181
|
+
context "when reified" do
|
182
|
+
setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
|
177
183
|
|
178
|
-
should
|
179
|
-
assert_equal [
|
184
|
+
should "see the associated as it was at the time" do
|
185
|
+
assert_equal ["order_date_0"], @customer_0.orders.map(&:order_date)
|
180
186
|
end
|
181
187
|
end
|
182
188
|
|
183
|
-
context
|
189
|
+
context "and then a nested has_many association is created" do
|
184
190
|
setup do
|
185
|
-
@order.line_items.create! :
|
191
|
+
@order.line_items.create! product: "product_0"
|
186
192
|
end
|
187
193
|
|
188
|
-
context
|
189
|
-
setup { @customer_0 = @customer.versions.last.reify(:
|
194
|
+
context "when reified" do
|
195
|
+
setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
|
190
196
|
|
191
|
-
should
|
192
|
-
assert_equal [
|
197
|
+
should "see the live version of the nested association" do
|
198
|
+
assert_equal ["product_0"], @customer_0.orders.first.line_items.map(&:product)
|
193
199
|
end
|
194
200
|
end
|
195
201
|
end
|
196
202
|
|
197
|
-
context
|
203
|
+
context "and then the associated is updated between model versions" do
|
198
204
|
setup do
|
199
|
-
@order.update_attributes :
|
200
|
-
@order.update_attributes :
|
205
|
+
@order.update_attributes order_date: "order_date_1"
|
206
|
+
@order.update_attributes order_date: "order_date_2"
|
201
207
|
Timecop.travel 1.second.since
|
202
|
-
@customer.update_attributes :
|
203
|
-
@order.update_attributes :
|
208
|
+
@customer.update_attributes name: "customer_2"
|
209
|
+
@order.update_attributes order_date: "order_date_3"
|
204
210
|
end
|
205
211
|
|
206
|
-
context
|
207
|
-
setup { @customer_1 = @customer.versions.last.reify(:
|
212
|
+
context "when reified" do
|
213
|
+
setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
|
208
214
|
|
209
|
-
should
|
210
|
-
assert_equal [
|
215
|
+
should "see the associated as it was at the time" do
|
216
|
+
assert_equal ["order_date_2"], @customer_1.orders.map(&:order_date)
|
211
217
|
end
|
212
218
|
|
213
|
-
should
|
214
|
-
assert_equal [
|
219
|
+
should "not persist changes to the live association" do
|
220
|
+
assert_equal ["order_date_3"], @customer.orders.reload.map(&:order_date)
|
215
221
|
end
|
216
222
|
end
|
217
223
|
|
218
|
-
context
|
219
|
-
setup { @customer_1 = @customer.versions.last.reify(:
|
224
|
+
context "when reified opting out of has_many reification" do
|
225
|
+
setup { @customer_1 = @customer.versions.last.reify(has_many: false) }
|
220
226
|
|
221
|
-
should
|
222
|
-
assert_equal [
|
227
|
+
should "see the associated as it is live" do
|
228
|
+
assert_equal ["order_date_3"], @customer_1.orders.map(&:order_date)
|
223
229
|
end
|
224
230
|
end
|
225
231
|
|
226
|
-
context
|
232
|
+
context "and then the associated is destroyed" do
|
227
233
|
setup do
|
228
234
|
@order.destroy
|
229
235
|
end
|
230
236
|
|
231
|
-
context
|
232
|
-
setup { @customer_1 = @customer.versions.last.reify(:
|
237
|
+
context "when reified" do
|
238
|
+
setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
|
233
239
|
|
234
|
-
should
|
235
|
-
assert_equal [
|
240
|
+
should "see the associated as it was at the time" do
|
241
|
+
assert_equal ["order_date_2"], @customer_1.orders.map(&:order_date)
|
236
242
|
end
|
237
243
|
|
238
|
-
should
|
239
|
-
assert_equal [], @customer.orders
|
244
|
+
should "not persist changes to the live association" do
|
245
|
+
assert_equal [], @customer.orders.reload
|
240
246
|
end
|
241
247
|
end
|
242
248
|
end
|
243
249
|
end
|
244
250
|
|
245
|
-
context
|
251
|
+
context "and then the associated is destroyed" do
|
246
252
|
setup do
|
247
253
|
@order.destroy
|
248
254
|
end
|
249
255
|
|
250
|
-
context
|
251
|
-
setup { @customer_1 = @customer.versions.last.reify(:
|
256
|
+
context "when reified" do
|
257
|
+
setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
|
252
258
|
|
253
|
-
should
|
259
|
+
should "see the associated as it was at the time" do
|
254
260
|
assert_equal [@order.order_date], @customer_1.orders.map(&:order_date)
|
255
261
|
end
|
256
262
|
|
257
|
-
should
|
258
|
-
assert_equal [], @customer.orders
|
263
|
+
should "not persist changes to the live association" do
|
264
|
+
assert_equal [], @customer.orders.reload
|
259
265
|
end
|
260
266
|
end
|
261
267
|
end
|
262
268
|
|
263
|
-
context
|
269
|
+
context "and then the associated is destroyed between model versions" do
|
264
270
|
setup do
|
265
271
|
@order.destroy
|
266
272
|
Timecop.travel 1.second.since
|
267
|
-
@customer.update_attributes :
|
273
|
+
@customer.update_attributes name: "customer_2"
|
268
274
|
end
|
269
275
|
|
270
|
-
context
|
271
|
-
setup { @customer_1 = @customer.versions.last.reify(:
|
276
|
+
context "when reified" do
|
277
|
+
setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
|
272
278
|
|
273
|
-
should
|
279
|
+
should "see the associated as it was at the time" do
|
274
280
|
assert_equal [], @customer_1.orders
|
275
281
|
end
|
276
282
|
end
|
277
283
|
end
|
278
284
|
|
279
|
-
context
|
285
|
+
context "and then another association is added" do
|
280
286
|
setup do
|
281
|
-
@customer.orders.create! :
|
287
|
+
@customer.orders.create! order_date: "order_date_1"
|
282
288
|
end
|
283
289
|
|
284
|
-
context
|
285
|
-
setup { @customer_0 = @customer.versions.last.reify(:
|
290
|
+
context "when reified" do
|
291
|
+
setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
|
286
292
|
|
287
|
-
should
|
288
|
-
assert_equal [
|
293
|
+
should "see the associated as it was at the time" do
|
294
|
+
assert_equal ["order_date_0"], @customer_0.orders.map(&:order_date)
|
289
295
|
end
|
290
296
|
|
291
|
-
should
|
292
|
-
assert_equal
|
297
|
+
should "not persist changes to the live association" do
|
298
|
+
assert_equal %w(order_date_0 order_date_1),
|
299
|
+
@customer.orders.reload.map(&:order_date).sort
|
293
300
|
end
|
294
301
|
end
|
295
302
|
|
296
|
-
context
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
303
|
+
context "when reified with option mark_for_destruction" do
|
304
|
+
should "mark the newly associated for destruction" do
|
305
|
+
@customer_0 = @customer.versions.last.reify(
|
306
|
+
has_many: true,
|
307
|
+
mark_for_destruction: true
|
308
|
+
)
|
309
|
+
assert @customer_0.
|
310
|
+
orders.
|
311
|
+
detect { |o| o.order_date == "order_date_1" }.
|
312
|
+
marked_for_destruction?
|
301
313
|
end
|
302
314
|
end
|
303
315
|
end
|
@@ -306,251 +318,285 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
306
318
|
|
307
319
|
context "has_many through associations" do
|
308
320
|
context "Books, Authors, and Authorships" do
|
309
|
-
setup { @book = Book.create :
|
321
|
+
setup { @book = Book.create title: "book_0" }
|
310
322
|
|
311
|
-
context
|
323
|
+
context "updated before the associated was created" do
|
312
324
|
setup do
|
313
|
-
@book.update_attributes! :
|
314
|
-
@book.authors.create! :
|
325
|
+
@book.update_attributes! title: "book_1"
|
326
|
+
@book.authors.create! name: "author_0"
|
315
327
|
end
|
316
328
|
|
317
|
-
context
|
318
|
-
setup { @book_0 = @book.versions.last.reify(:
|
329
|
+
context "when reified" do
|
330
|
+
setup { @book_0 = @book.versions.last.reify(has_many: true) }
|
319
331
|
|
320
|
-
should
|
332
|
+
should "see the associated as it was at the time" do
|
321
333
|
assert_equal [], @book_0.authors
|
322
334
|
end
|
323
335
|
|
324
|
-
should
|
325
|
-
assert_equal [
|
336
|
+
should "not persist changes to the live association" do
|
337
|
+
assert_equal ["author_0"], @book.authors.reload.map(&:name)
|
326
338
|
end
|
327
339
|
end
|
328
340
|
|
329
|
-
context
|
330
|
-
setup
|
341
|
+
context "when reified with option mark_for_destruction" do
|
342
|
+
setup do
|
343
|
+
@book_0 = @book.versions.last.reify(
|
344
|
+
has_many: true,
|
345
|
+
mark_for_destruction: true
|
346
|
+
)
|
347
|
+
end
|
331
348
|
|
332
|
-
should
|
349
|
+
should "mark the associated for destruction" do
|
333
350
|
assert_equal [true], @book_0.authors.map(&:marked_for_destruction?)
|
334
351
|
end
|
335
352
|
|
336
|
-
should
|
353
|
+
should "mark the associated-through for destruction" do
|
337
354
|
assert_equal [true], @book_0.authorships.map(&:marked_for_destruction?)
|
338
355
|
end
|
339
356
|
end
|
340
357
|
end
|
341
358
|
|
342
|
-
context
|
359
|
+
context "updated before it is associated with an existing one" do
|
343
360
|
setup do
|
344
|
-
person_existing = Person.create(:
|
361
|
+
person_existing = Person.create(name: "person_existing")
|
345
362
|
Timecop.travel 1.second.since
|
346
|
-
@book.update_attributes! :
|
363
|
+
@book.update_attributes! title: "book_1"
|
347
364
|
@book.authors << person_existing
|
348
365
|
end
|
349
366
|
|
350
|
-
context
|
351
|
-
setup
|
367
|
+
context "when reified" do
|
368
|
+
setup do
|
369
|
+
@book_0 = @book.versions.last.reify(has_many: true)
|
370
|
+
end
|
352
371
|
|
353
|
-
should
|
372
|
+
should "see the associated as it was at the time" do
|
354
373
|
assert_equal [], @book_0.authors
|
355
374
|
end
|
356
375
|
end
|
357
376
|
|
358
|
-
context
|
359
|
-
setup
|
377
|
+
context "when reified with option mark_for_destruction" do
|
378
|
+
setup do
|
379
|
+
@book_0 = @book.versions.last.reify(
|
380
|
+
has_many: true,
|
381
|
+
mark_for_destruction: true
|
382
|
+
)
|
383
|
+
end
|
360
384
|
|
361
|
-
should
|
385
|
+
should "not mark the associated for destruction" do
|
362
386
|
assert_equal [false], @book_0.authors.map(&:marked_for_destruction?)
|
363
387
|
end
|
364
388
|
|
365
|
-
should
|
389
|
+
should "mark the associated-through for destruction" do
|
366
390
|
assert_equal [true], @book_0.authorships.map(&:marked_for_destruction?)
|
367
391
|
end
|
368
392
|
end
|
369
393
|
end
|
370
394
|
|
371
|
-
context
|
395
|
+
context "where the association is created between model versions" do
|
372
396
|
setup do
|
373
|
-
@author = @book.authors.create! :
|
374
|
-
@person_existing = Person.create(:
|
397
|
+
@author = @book.authors.create! name: "author_0"
|
398
|
+
@person_existing = Person.create(name: "person_existing")
|
375
399
|
Timecop.travel 1.second.since
|
376
|
-
@book.update_attributes! :
|
400
|
+
@book.update_attributes! title: "book_1"
|
377
401
|
end
|
378
402
|
|
379
|
-
context
|
380
|
-
setup { @book_0 = @book.versions.last.reify(:
|
403
|
+
context "when reified" do
|
404
|
+
setup { @book_0 = @book.versions.last.reify(has_many: true) }
|
381
405
|
|
382
|
-
should
|
383
|
-
assert_equal [
|
406
|
+
should "see the associated as it was at the time" do
|
407
|
+
assert_equal ["author_0"], @book_0.authors.map(&:name)
|
384
408
|
end
|
385
409
|
end
|
386
410
|
|
387
|
-
context
|
411
|
+
context "and then the associated is updated between model versions" do
|
388
412
|
setup do
|
389
|
-
@author.update_attributes :
|
390
|
-
@author.update_attributes :
|
413
|
+
@author.update_attributes name: "author_1"
|
414
|
+
@author.update_attributes name: "author_2"
|
391
415
|
Timecop.travel 1.second.since
|
392
|
-
@book.update_attributes :
|
393
|
-
@author.update_attributes :
|
416
|
+
@book.update_attributes title: "book_2"
|
417
|
+
@author.update_attributes name: "author_3"
|
394
418
|
end
|
395
419
|
|
396
|
-
context
|
397
|
-
setup { @book_1 = @book.versions.last.reify(:
|
420
|
+
context "when reified" do
|
421
|
+
setup { @book_1 = @book.versions.last.reify(has_many: true) }
|
398
422
|
|
399
|
-
should
|
400
|
-
assert_equal [
|
423
|
+
should "see the associated as it was at the time" do
|
424
|
+
assert_equal ["author_2"], @book_1.authors.map(&:name)
|
401
425
|
end
|
402
426
|
|
403
|
-
should
|
404
|
-
assert_equal [
|
427
|
+
should "not persist changes to the live association" do
|
428
|
+
assert_equal ["author_3"], @book.authors.reload.map(&:name)
|
405
429
|
end
|
406
430
|
end
|
407
431
|
|
408
|
-
context
|
409
|
-
setup { @book_1 = @book.versions.last.reify(:
|
432
|
+
context "when reified opting out of has_many reification" do
|
433
|
+
setup { @book_1 = @book.versions.last.reify(has_many: false) }
|
410
434
|
|
411
|
-
should
|
412
|
-
assert_equal [
|
435
|
+
should "see the associated as it is live" do
|
436
|
+
assert_equal ["author_3"], @book_1.authors.map(&:name)
|
413
437
|
end
|
414
438
|
end
|
415
439
|
end
|
416
440
|
|
417
|
-
context
|
441
|
+
context "and then the associated is destroyed" do
|
418
442
|
setup do
|
419
443
|
@author.destroy
|
420
444
|
end
|
421
445
|
|
422
|
-
context
|
423
|
-
setup { @book_1 = @book.versions.last.reify(:
|
446
|
+
context "when reified" do
|
447
|
+
setup { @book_1 = @book.versions.last.reify(has_many: true) }
|
424
448
|
|
425
|
-
should
|
449
|
+
should "see the associated as it was at the time" do
|
426
450
|
assert_equal [@author.name], @book_1.authors.map(&:name)
|
427
451
|
end
|
428
452
|
|
429
|
-
should
|
430
|
-
assert_equal [], @book.authors
|
453
|
+
should "not persist changes to the live association" do
|
454
|
+
assert_equal [], @book.authors.reload
|
431
455
|
end
|
432
456
|
end
|
433
457
|
end
|
434
458
|
|
435
|
-
context
|
459
|
+
context "and then the associated is destroyed between model versions" do
|
436
460
|
setup do
|
437
461
|
@author.destroy
|
438
462
|
Timecop.travel 1.second.since
|
439
|
-
@book.update_attributes :
|
463
|
+
@book.update_attributes title: "book_2"
|
440
464
|
end
|
441
465
|
|
442
|
-
context
|
443
|
-
setup { @book_1 = @book.versions.last.reify(:
|
466
|
+
context "when reified" do
|
467
|
+
setup { @book_1 = @book.versions.last.reify(has_many: true) }
|
444
468
|
|
445
|
-
should
|
469
|
+
should "see the associated as it was at the time" do
|
446
470
|
assert_equal [], @book_1.authors
|
447
471
|
end
|
448
472
|
end
|
449
473
|
end
|
450
474
|
|
451
|
-
context
|
475
|
+
context "and then the associated is dissociated between model versions" do
|
452
476
|
setup do
|
453
477
|
@book.authors = []
|
454
478
|
Timecop.travel 1.second.since
|
455
|
-
@book.update_attributes :
|
479
|
+
@book.update_attributes title: "book_2"
|
456
480
|
end
|
457
481
|
|
458
|
-
context
|
459
|
-
setup { @book_1 = @book.versions.last.reify(:
|
482
|
+
context "when reified" do
|
483
|
+
setup { @book_1 = @book.versions.last.reify(has_many: true) }
|
460
484
|
|
461
|
-
should
|
485
|
+
should "see the associated as it was at the time" do
|
462
486
|
assert_equal [], @book_1.authors
|
463
487
|
end
|
464
488
|
end
|
465
489
|
end
|
466
490
|
|
467
|
-
context
|
491
|
+
context "and then another associated is created" do
|
468
492
|
setup do
|
469
|
-
@book.authors.create! :
|
493
|
+
@book.authors.create! name: "author_1"
|
470
494
|
end
|
471
495
|
|
472
|
-
context
|
473
|
-
setup { @book_0 = @book.versions.last.reify(:
|
496
|
+
context "when reified" do
|
497
|
+
setup { @book_0 = @book.versions.last.reify(has_many: true) }
|
474
498
|
|
475
|
-
should
|
476
|
-
assert_equal [
|
499
|
+
should "only see the first associated" do
|
500
|
+
assert_equal ["author_0"], @book_0.authors.map(&:name)
|
477
501
|
end
|
478
502
|
|
479
|
-
should
|
480
|
-
assert_equal
|
503
|
+
should "not persist changes to the live association" do
|
504
|
+
assert_equal %w(author_0 author_1), @book.authors.reload.map(&:name)
|
481
505
|
end
|
482
506
|
end
|
483
507
|
|
484
|
-
context
|
485
|
-
setup
|
508
|
+
context "when reified with option mark_for_destruction" do
|
509
|
+
setup do
|
510
|
+
@book_0 = @book.versions.last.reify(
|
511
|
+
has_many: true,
|
512
|
+
mark_for_destruction: true
|
513
|
+
)
|
514
|
+
end
|
486
515
|
|
487
|
-
should
|
488
|
-
assert @book_0.
|
516
|
+
should "mark the newly associated for destruction" do
|
517
|
+
assert @book_0.
|
518
|
+
authors.
|
519
|
+
detect { |a| a.name == "author_1" }.
|
520
|
+
marked_for_destruction?
|
489
521
|
end
|
490
522
|
|
491
|
-
should
|
492
|
-
assert @book_0.
|
523
|
+
should "mark the newly associated-through for destruction" do
|
524
|
+
assert @book_0.
|
525
|
+
authorships.
|
526
|
+
detect { |as| as.author.name == "author_1" }.
|
527
|
+
marked_for_destruction?
|
493
528
|
end
|
494
529
|
end
|
495
530
|
end
|
496
531
|
|
497
|
-
context
|
532
|
+
context "and then an existing one is associated" do
|
498
533
|
setup do
|
499
534
|
@book.authors << @person_existing
|
500
535
|
end
|
501
536
|
|
502
|
-
context
|
503
|
-
setup { @book_0 = @book.versions.last.reify(:
|
537
|
+
context "when reified" do
|
538
|
+
setup { @book_0 = @book.versions.last.reify(has_many: true) }
|
504
539
|
|
505
|
-
should
|
506
|
-
assert_equal [
|
540
|
+
should "only see the first associated" do
|
541
|
+
assert_equal ["author_0"], @book_0.authors.map(&:name)
|
507
542
|
end
|
508
543
|
|
509
|
-
should
|
510
|
-
assert_equal
|
544
|
+
should "not persist changes to the live association" do
|
545
|
+
assert_equal %w(author_0 person_existing), @book.authors.reload.map(&:name).sort
|
511
546
|
end
|
512
547
|
end
|
513
548
|
|
514
|
-
context
|
515
|
-
setup
|
549
|
+
context "when reified with option mark_for_destruction" do
|
550
|
+
setup do
|
551
|
+
@book_0 = @book.versions.last.reify(
|
552
|
+
has_many: true,
|
553
|
+
mark_for_destruction: true
|
554
|
+
)
|
555
|
+
end
|
516
556
|
|
517
|
-
should
|
518
|
-
assert !@book_0.
|
557
|
+
should "not mark the newly associated for destruction" do
|
558
|
+
assert !@book_0.
|
559
|
+
authors.
|
560
|
+
detect { |a| a.name == "person_existing" }.
|
561
|
+
marked_for_destruction?
|
519
562
|
end
|
520
563
|
|
521
|
-
should
|
522
|
-
assert @book_0.
|
564
|
+
should "mark the newly associated-through for destruction" do
|
565
|
+
assert @book_0.
|
566
|
+
authorships.
|
567
|
+
detect { |as| as.author.name == "person_existing" }.
|
568
|
+
marked_for_destruction?
|
523
569
|
end
|
524
570
|
end
|
525
571
|
end
|
526
572
|
end
|
527
573
|
|
528
|
-
context
|
574
|
+
context "updated before the associated without paper_trail was created" do
|
529
575
|
setup do
|
530
|
-
@book.update_attributes! :
|
531
|
-
@book.editors.create! :
|
576
|
+
@book.update_attributes! title: "book_1"
|
577
|
+
@book.editors.create! name: "editor_0"
|
532
578
|
end
|
533
579
|
|
534
|
-
context
|
535
|
-
setup { @book_0 = @book.versions.last.reify(:
|
580
|
+
context "when reified" do
|
581
|
+
setup { @book_0 = @book.versions.last.reify(has_many: true) }
|
536
582
|
|
537
|
-
should
|
538
|
-
assert_equal [
|
583
|
+
should "see the live association" do
|
584
|
+
assert_equal ["editor_0"], @book_0.editors.map(&:name)
|
539
585
|
end
|
540
586
|
end
|
541
587
|
end
|
542
588
|
end
|
543
589
|
|
544
590
|
context "Chapters, Sections, Paragraphs, Quotations, and Citations" do
|
545
|
-
setup { @chapter = Chapter.create(:
|
591
|
+
setup { @chapter = Chapter.create(name: CHAPTER_NAMES[0]) }
|
546
592
|
|
547
593
|
context "before any associations are created" do
|
548
594
|
setup do
|
549
|
-
@chapter.update_attributes(:
|
595
|
+
@chapter.update_attributes(name: CHAPTER_NAMES[1])
|
550
596
|
end
|
551
597
|
|
552
598
|
should "not reify any associations" do
|
553
|
-
chapter_v1 = @chapter.versions[1].reify(:
|
599
|
+
chapter_v1 = @chapter.versions[1].reify(has_many: true)
|
554
600
|
assert_equal CHAPTER_NAMES[0], chapter_v1.name
|
555
601
|
assert_equal [], chapter_v1.sections
|
556
602
|
assert_equal [], chapter_v1.paragraphs
|
@@ -560,36 +606,36 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
560
606
|
context "after the first has_many through relationship is created" do
|
561
607
|
setup do
|
562
608
|
assert_equal 1, @chapter.versions.size
|
563
|
-
@chapter.update_attributes :
|
609
|
+
@chapter.update_attributes name: CHAPTER_NAMES[1]
|
564
610
|
assert_equal 2, @chapter.versions.size
|
565
611
|
|
566
612
|
Timecop.travel 1.second.since
|
567
|
-
@chapter.sections.create :
|
613
|
+
@chapter.sections.create name: "section 1"
|
568
614
|
Timecop.travel 1.second.since
|
569
|
-
@chapter.sections.first.update_attributes :
|
615
|
+
@chapter.sections.first.update_attributes name: "section 2"
|
570
616
|
Timecop.travel 1.second.since
|
571
|
-
@chapter.update_attributes :
|
617
|
+
@chapter.update_attributes name: CHAPTER_NAMES[2]
|
572
618
|
assert_equal 3, @chapter.versions.size
|
573
619
|
|
574
620
|
Timecop.travel 1.second.since
|
575
|
-
@chapter.sections.first.update_attributes :
|
621
|
+
@chapter.sections.first.update_attributes name: "section 3"
|
576
622
|
end
|
577
623
|
|
578
624
|
context "version 1" do
|
579
625
|
should "have no sections" do
|
580
|
-
chapter_v1 = @chapter.versions[1].reify(:
|
626
|
+
chapter_v1 = @chapter.versions[1].reify(has_many: true)
|
581
627
|
assert_equal [], chapter_v1.sections
|
582
628
|
end
|
583
629
|
end
|
584
630
|
|
585
631
|
context "version 2" do
|
586
632
|
should "have one section" do
|
587
|
-
chapter_v2 = @chapter.versions[2].reify(:
|
633
|
+
chapter_v2 = @chapter.versions[2].reify(has_many: true)
|
588
634
|
assert_equal 1, chapter_v2.sections.size
|
589
635
|
|
590
636
|
# Shows the value of the section as it was before
|
591
637
|
# the chapter was updated.
|
592
|
-
assert_equal [
|
638
|
+
assert_equal ["section 2"], chapter_v2.sections.map(&:name)
|
593
639
|
|
594
640
|
# Shows the value of the chapter as it was before
|
595
641
|
assert_equal CHAPTER_NAMES[1], chapter_v2.name
|
@@ -598,15 +644,15 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
598
644
|
|
599
645
|
context "version 2, before the section was destroyed" do
|
600
646
|
setup do
|
601
|
-
@chapter.update_attributes :
|
647
|
+
@chapter.update_attributes name: CHAPTER_NAMES[2]
|
602
648
|
Timecop.travel 1.second.since
|
603
649
|
@chapter.sections.destroy_all
|
604
650
|
Timecop.travel 1.second.since
|
605
651
|
end
|
606
652
|
|
607
653
|
should "have the one section" do
|
608
|
-
chapter_v2 = @chapter.versions[2].reify(:
|
609
|
-
assert_equal [
|
654
|
+
chapter_v2 = @chapter.versions[2].reify(has_many: true)
|
655
|
+
assert_equal ["section 2"], chapter_v2.sections.map(&:name)
|
610
656
|
end
|
611
657
|
end
|
612
658
|
|
@@ -614,12 +660,12 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
614
660
|
setup do
|
615
661
|
@chapter.sections.destroy_all
|
616
662
|
Timecop.travel 1.second.since
|
617
|
-
@chapter.update_attributes :
|
663
|
+
@chapter.update_attributes name: CHAPTER_NAMES[3]
|
618
664
|
Timecop.travel 1.second.since
|
619
665
|
end
|
620
666
|
|
621
667
|
should "have no sections" do
|
622
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
668
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
623
669
|
assert_equal 0, chapter_v3.sections.size
|
624
670
|
end
|
625
671
|
end
|
@@ -629,7 +675,7 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
629
675
|
assert_equal 3, @chapter.versions.size
|
630
676
|
@section = @chapter.sections.first
|
631
677
|
Timecop.travel 1.second.since
|
632
|
-
@paragraph = @section.paragraphs.create :
|
678
|
+
@paragraph = @section.paragraphs.create name: "para1"
|
633
679
|
end
|
634
680
|
|
635
681
|
context "new chapter version" do
|
@@ -637,11 +683,11 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
637
683
|
initial_section_name = @section.name
|
638
684
|
initial_paragraph_name = @paragraph.name
|
639
685
|
Timecop.travel 1.second.since
|
640
|
-
@chapter.update_attributes :
|
686
|
+
@chapter.update_attributes name: CHAPTER_NAMES[4]
|
641
687
|
assert_equal 4, @chapter.versions.size
|
642
688
|
Timecop.travel 1.second.since
|
643
|
-
@paragraph.update_attributes :
|
644
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
689
|
+
@paragraph.update_attributes name: "para3"
|
690
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
645
691
|
assert_equal [initial_section_name], chapter_v3.sections.map(&:name)
|
646
692
|
paragraphs = chapter_v3.sections.first.paragraphs
|
647
693
|
assert_equal 1, paragraphs.size
|
@@ -652,12 +698,12 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
652
698
|
context "the version before a section is destroyed" do
|
653
699
|
should "have the section and paragraph" do
|
654
700
|
Timecop.travel 1.second.since
|
655
|
-
@chapter.update_attributes(:
|
701
|
+
@chapter.update_attributes(name: CHAPTER_NAMES[3])
|
656
702
|
assert_equal 4, @chapter.versions.size
|
657
703
|
Timecop.travel 1.second.since
|
658
704
|
@section.destroy
|
659
705
|
assert_equal 4, @chapter.versions.size
|
660
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
706
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
661
707
|
assert_equal CHAPTER_NAMES[2], chapter_v3.name
|
662
708
|
assert_equal [@section], chapter_v3.sections
|
663
709
|
assert_equal [@paragraph], chapter_v3.sections[0].paragraphs
|
@@ -669,9 +715,9 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
669
715
|
should "not have any sections or paragraphs" do
|
670
716
|
@section.destroy
|
671
717
|
Timecop.travel 1.second.since
|
672
|
-
@chapter.update_attributes(:
|
718
|
+
@chapter.update_attributes(name: CHAPTER_NAMES[5])
|
673
719
|
assert_equal 4, @chapter.versions.size
|
674
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
720
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
675
721
|
assert_equal 0, chapter_v3.sections.size
|
676
722
|
assert_equal 0, chapter_v3.paragraphs.size
|
677
723
|
end
|
@@ -681,10 +727,10 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
681
727
|
should "have the one paragraph" do
|
682
728
|
initial_paragraph_name = @section.paragraphs.first.name
|
683
729
|
Timecop.travel 1.second.since
|
684
|
-
@chapter.update_attributes(:
|
730
|
+
@chapter.update_attributes(name: CHAPTER_NAMES[5])
|
685
731
|
Timecop.travel 1.second.since
|
686
732
|
@paragraph.destroy
|
687
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
733
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
688
734
|
paragraphs = chapter_v3.sections.first.paragraphs
|
689
735
|
assert_equal 1, paragraphs.size
|
690
736
|
assert_equal initial_paragraph_name, paragraphs.first.name
|
@@ -695,8 +741,8 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
695
741
|
should "have no paragraphs" do
|
696
742
|
@paragraph.destroy
|
697
743
|
Timecop.travel 1.second.since
|
698
|
-
@chapter.update_attributes(:
|
699
|
-
chapter_v3 = @chapter.versions[3].reify(:
|
744
|
+
@chapter.update_attributes(name: CHAPTER_NAMES[5])
|
745
|
+
chapter_v3 = @chapter.versions[3].reify(has_many: true)
|
700
746
|
assert_equal 0, chapter_v3.paragraphs.size
|
701
747
|
assert_equal [], chapter_v3.sections.first.paragraphs
|
702
748
|
end
|
@@ -706,21 +752,241 @@ class AssociationsTest < ActiveSupport::TestCase
|
|
706
752
|
|
707
753
|
context "a chapter with one paragraph and one citation" do
|
708
754
|
should "reify paragraphs and citations" do
|
709
|
-
chapter = Chapter.create(:
|
710
|
-
section = Section.create(:
|
711
|
-
paragraph = Paragraph.create(:
|
712
|
-
quotation = Quotation.create(:
|
713
|
-
citation = Citation.create(:
|
755
|
+
chapter = Chapter.create(name: CHAPTER_NAMES[0])
|
756
|
+
section = Section.create(name: "Section One", chapter: chapter)
|
757
|
+
paragraph = Paragraph.create(name: "Paragraph One", section: section)
|
758
|
+
quotation = Quotation.create(chapter: chapter)
|
759
|
+
citation = Citation.create(quotation: quotation)
|
714
760
|
Timecop.travel 1.second.since
|
715
|
-
chapter.update_attributes(:
|
761
|
+
chapter.update_attributes(name: CHAPTER_NAMES[1])
|
716
762
|
assert_equal 2, chapter.versions.count
|
717
763
|
paragraph.destroy
|
718
764
|
citation.destroy
|
719
|
-
reified = chapter.versions[1].reify(:
|
765
|
+
reified = chapter.versions[1].reify(has_many: true)
|
720
766
|
assert_equal [paragraph], reified.sections.first.paragraphs
|
721
767
|
assert_equal [citation], reified.quotations.first.citations
|
722
768
|
end
|
723
769
|
end
|
724
770
|
end
|
725
771
|
end
|
772
|
+
|
773
|
+
context "belongs_to associations" do
|
774
|
+
context "Wotsit and Widget" do
|
775
|
+
setup { @widget = Widget.create(name: "widget_0") }
|
776
|
+
|
777
|
+
context "where the association is created between model versions" do
|
778
|
+
setup do
|
779
|
+
@wotsit = Wotsit.create(name: "wotsit_0")
|
780
|
+
Timecop.travel 1.second.since
|
781
|
+
@wotsit.update_attributes widget_id: @widget.id, name: "wotsit_1"
|
782
|
+
end
|
783
|
+
|
784
|
+
context "when reified" do
|
785
|
+
setup { @wotsit_0 = @wotsit.versions.last.reify(belongs_to: true) }
|
786
|
+
|
787
|
+
should "see the associated as it was at the time" do
|
788
|
+
assert_equal nil, @wotsit_0.widget
|
789
|
+
end
|
790
|
+
|
791
|
+
should "not persist changes to the live association" do
|
792
|
+
assert_equal @widget, @wotsit.reload.widget
|
793
|
+
end
|
794
|
+
end
|
795
|
+
|
796
|
+
context "and then the associated is updated between model versions" do
|
797
|
+
setup do
|
798
|
+
@widget.update_attributes name: "widget_1"
|
799
|
+
@widget.update_attributes name: "widget_2"
|
800
|
+
Timecop.travel 1.second.since
|
801
|
+
@wotsit.update_attributes name: "wotsit_2"
|
802
|
+
@widget.update_attributes name: "widget_3"
|
803
|
+
end
|
804
|
+
|
805
|
+
context "when reified" do
|
806
|
+
setup { @wotsit_1 = @wotsit.versions.last.reify(belongs_to: true) }
|
807
|
+
|
808
|
+
should "see the associated as it was at the time" do
|
809
|
+
assert_equal "widget_2", @wotsit_1.widget.name
|
810
|
+
end
|
811
|
+
|
812
|
+
should "not persist changes to the live association" do
|
813
|
+
assert_equal "widget_3", @wotsit.reload.widget.name
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
context "when reified opting out of belongs_to reification" do
|
818
|
+
setup { @wotsit_1 = @wotsit.versions.last.reify(belongs_to: false) }
|
819
|
+
|
820
|
+
should "see the associated as it is live" do
|
821
|
+
assert_equal "widget_3", @wotsit_1.widget.name
|
822
|
+
end
|
823
|
+
end
|
824
|
+
end
|
825
|
+
|
826
|
+
context "and then the associated is destroyed" do
|
827
|
+
setup do
|
828
|
+
@wotsit.update_attributes name: "wotsit_2"
|
829
|
+
@widget.destroy
|
830
|
+
end
|
831
|
+
|
832
|
+
context "when reified" do
|
833
|
+
setup { @wotsit_2 = @wotsit.versions.last.reify(belongs_to: true) }
|
834
|
+
|
835
|
+
should "see the associated as it was at the time" do
|
836
|
+
assert_equal @widget, @wotsit_2.widget
|
837
|
+
end
|
838
|
+
|
839
|
+
should "not persist changes to the live association" do
|
840
|
+
assert_nil @wotsit.reload.widget
|
841
|
+
end
|
842
|
+
end
|
843
|
+
|
844
|
+
context "and then the model is updated" do
|
845
|
+
setup do
|
846
|
+
Timecop.travel 1.second.since
|
847
|
+
@wotsit.update_attributes name: "wotsit_3"
|
848
|
+
end
|
849
|
+
|
850
|
+
context "when reified" do
|
851
|
+
setup { @wotsit_2 = @wotsit.versions.last.reify(belongs_to: true) }
|
852
|
+
|
853
|
+
should "see the associated as it was the time" do
|
854
|
+
assert_nil @wotsit_2.widget
|
855
|
+
end
|
856
|
+
end
|
857
|
+
end
|
858
|
+
end
|
859
|
+
end
|
860
|
+
|
861
|
+
context "where the association is changed between model versions" do
|
862
|
+
setup do
|
863
|
+
@wotsit = @widget.create_wotsit(name: "wotsit_0")
|
864
|
+
Timecop.travel 1.second.since
|
865
|
+
@new_widget = Widget.create(name: "new_widget")
|
866
|
+
@wotsit.update_attributes(widget_id: @new_widget.id, name: "wotsit_1")
|
867
|
+
end
|
868
|
+
|
869
|
+
context "when reified" do
|
870
|
+
setup { @wotsit_0 = @wotsit.versions.last.reify(belongs_to: true) }
|
871
|
+
|
872
|
+
should "see the association as it was at the time" do
|
873
|
+
assert_equal "widget_0", @wotsit_0.widget.name
|
874
|
+
end
|
875
|
+
|
876
|
+
should "not persist changes to the live association" do
|
877
|
+
assert_equal @new_widget, @wotsit.reload.widget
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
context "when reified with option mark_for_destruction" do
|
882
|
+
setup do
|
883
|
+
@wotsit_0 = @wotsit.versions.last.
|
884
|
+
reify(belongs_to: true, mark_for_destruction: true)
|
885
|
+
end
|
886
|
+
|
887
|
+
should "should not mark the new associated for destruction" do
|
888
|
+
assert_equal false, @new_widget.marked_for_destruction?
|
889
|
+
end
|
890
|
+
end
|
891
|
+
end
|
892
|
+
end
|
893
|
+
end
|
894
|
+
|
895
|
+
context "has_and_belongs_to_many associations" do
|
896
|
+
context "foo and bar" do
|
897
|
+
setup do
|
898
|
+
@foo = FooHabtm.create(name: "foo")
|
899
|
+
Timecop.travel 1.second.since
|
900
|
+
end
|
901
|
+
|
902
|
+
context "where the association is created between model versions" do
|
903
|
+
setup do
|
904
|
+
@foo.update_attributes(name: "foo1", bar_habtms: [BarHabtm.create(name: "bar")])
|
905
|
+
end
|
906
|
+
|
907
|
+
context "when reified" do
|
908
|
+
setup { @reified = @foo.versions.last.reify(has_and_belongs_to_many: true) }
|
909
|
+
|
910
|
+
should "see the associated as it was at the time" do
|
911
|
+
assert_equal 0, @reified.bar_habtms.length
|
912
|
+
end
|
913
|
+
|
914
|
+
should "not persist changes to the live association" do
|
915
|
+
assert_not_equal @reified.bar_habtms, @foo.reload.bar_habtms
|
916
|
+
end
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
920
|
+
context "where the association is changed between model versions" do
|
921
|
+
setup do
|
922
|
+
@foo.update_attributes(name: "foo2", bar_habtms: [BarHabtm.create(name: "bar2")])
|
923
|
+
Timecop.travel 1.second.since
|
924
|
+
@foo.update_attributes(name: "foo3", bar_habtms: [BarHabtm.create(name: "bar3")])
|
925
|
+
end
|
926
|
+
|
927
|
+
context "when reified" do
|
928
|
+
setup { @reified = @foo.versions.last.reify(has_and_belongs_to_many: true) }
|
929
|
+
|
930
|
+
should "see the association as it was at the time" do
|
931
|
+
assert_equal "bar2", @reified.bar_habtms.first.name
|
932
|
+
end
|
933
|
+
|
934
|
+
should "not persist changes to the live association" do
|
935
|
+
assert_not_equal @reified.bar_habtms.first, @foo.reload.bar_habtms.first
|
936
|
+
end
|
937
|
+
end
|
938
|
+
|
939
|
+
context "when reified with has_and_belongs_to_many: false" do
|
940
|
+
setup { @reified = @foo.versions.last.reify }
|
941
|
+
|
942
|
+
should "see the association as it is now" do
|
943
|
+
assert_equal "bar3", @reified.bar_habtms.first.name
|
944
|
+
end
|
945
|
+
end
|
946
|
+
end
|
947
|
+
|
948
|
+
context "where the association is destroyed between model versions" do
|
949
|
+
setup do
|
950
|
+
@foo.update_attributes(name: "foo2", bar_habtms: [BarHabtm.create(name: "bar2")])
|
951
|
+
Timecop.travel 1.second.since
|
952
|
+
@foo.update_attributes(name: "foo3", bar_habtms: [])
|
953
|
+
end
|
954
|
+
|
955
|
+
context "when reified" do
|
956
|
+
setup { @reified = @foo.versions.last.reify(has_and_belongs_to_many: true) }
|
957
|
+
|
958
|
+
should "see the association as it was at the time" do
|
959
|
+
assert_equal "bar2", @reified.bar_habtms.first.name
|
960
|
+
end
|
961
|
+
|
962
|
+
should "not persist changes to the live association" do
|
963
|
+
assert_not_equal @reified.bar_habtms.first, @foo.reload.bar_habtms.first
|
964
|
+
end
|
965
|
+
end
|
966
|
+
end
|
967
|
+
|
968
|
+
context "where the unassociated model changes" do
|
969
|
+
setup do
|
970
|
+
@bar = BarHabtm.create(name: "bar2")
|
971
|
+
@foo.update_attributes(name: "foo2", bar_habtms: [@bar])
|
972
|
+
Timecop.travel 1.second.since
|
973
|
+
@foo.update_attributes(name: "foo3", bar_habtms: [BarHabtm.create(name: "bar4")])
|
974
|
+
Timecop.travel 1.second.since
|
975
|
+
@bar.update_attributes(name: "bar3")
|
976
|
+
end
|
977
|
+
|
978
|
+
context "when reified" do
|
979
|
+
setup { @reified = @foo.versions.last.reify(has_and_belongs_to_many: true) }
|
980
|
+
|
981
|
+
should "see the association as it was at the time" do
|
982
|
+
assert_equal "bar2", @reified.bar_habtms.first.name
|
983
|
+
end
|
984
|
+
|
985
|
+
should "not persist changes to the live association" do
|
986
|
+
assert_not_equal @reified.bar_habtms.first, @foo.reload.bar_habtms.first
|
987
|
+
end
|
988
|
+
end
|
989
|
+
end
|
990
|
+
end
|
991
|
+
end
|
726
992
|
end
|