paper_trail 4.2.0 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +4 -4
  2. data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +28 -9
  3. data/.github/ISSUE_TEMPLATE.md +13 -0
  4. data/.gitignore +2 -1
  5. data/.rubocop.yml +100 -0
  6. data/.rubocop_todo.yml +14 -0
  7. data/.travis.yml +8 -9
  8. data/Appraisals +41 -0
  9. data/CHANGELOG.md +49 -9
  10. data/Gemfile +1 -1
  11. data/README.md +130 -109
  12. data/Rakefile +19 -19
  13. data/doc/bug_report_template.rb +20 -14
  14. data/gemfiles/ar3.gemfile +10 -53
  15. data/gemfiles/ar4.gemfile +7 -0
  16. data/gemfiles/ar5.gemfile +13 -0
  17. data/lib/generators/paper_trail/install_generator.rb +26 -18
  18. data/lib/generators/paper_trail/templates/add_object_changes_to_versions.rb +4 -2
  19. data/lib/generators/paper_trail/templates/add_transaction_id_column_to_versions.rb +2 -0
  20. data/lib/generators/paper_trail/templates/create_version_associations.rb +9 -4
  21. data/lib/generators/paper_trail/templates/create_versions.rb +39 -5
  22. data/lib/paper_trail.rb +169 -146
  23. data/lib/paper_trail/attributes_serialization.rb +89 -17
  24. data/lib/paper_trail/cleaner.rb +15 -9
  25. data/lib/paper_trail/config.rb +28 -11
  26. data/lib/paper_trail/frameworks/active_record.rb +4 -0
  27. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version.rb +5 -1
  28. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version_association.rb +6 -2
  29. data/lib/paper_trail/frameworks/cucumber.rb +1 -0
  30. data/lib/paper_trail/frameworks/rails.rb +2 -7
  31. data/lib/paper_trail/frameworks/rails/controller.rb +29 -9
  32. data/lib/paper_trail/frameworks/rails/engine.rb +7 -1
  33. data/lib/paper_trail/frameworks/rspec.rb +5 -5
  34. data/lib/paper_trail/frameworks/rspec/helpers.rb +3 -1
  35. data/lib/paper_trail/frameworks/sinatra.rb +6 -4
  36. data/lib/paper_trail/has_paper_trail.rb +199 -106
  37. data/lib/paper_trail/record_history.rb +1 -3
  38. data/lib/paper_trail/reifier.rb +297 -118
  39. data/lib/paper_trail/serializers/json.rb +3 -3
  40. data/lib/paper_trail/serializers/yaml.rb +27 -8
  41. data/lib/paper_trail/version_association_concern.rb +3 -1
  42. data/lib/paper_trail/version_concern.rb +75 -35
  43. data/lib/paper_trail/version_number.rb +6 -9
  44. data/paper_trail.gemspec +44 -51
  45. data/spec/generators/install_generator_spec.rb +24 -25
  46. data/spec/generators/paper_trail/templates/create_versions_spec.rb +51 -0
  47. data/spec/models/animal_spec.rb +12 -12
  48. data/spec/models/boolit_spec.rb +8 -8
  49. data/spec/models/callback_modifier_spec.rb +47 -47
  50. data/spec/models/car_spec.rb +13 -0
  51. data/spec/models/fluxor_spec.rb +3 -3
  52. data/spec/models/gadget_spec.rb +19 -19
  53. data/spec/models/joined_version_spec.rb +3 -3
  54. data/spec/models/json_version_spec.rb +23 -24
  55. data/spec/models/kitchen/banana_spec.rb +3 -3
  56. data/spec/models/not_on_update_spec.rb +7 -4
  57. data/spec/models/post_with_status_spec.rb +13 -3
  58. data/spec/models/skipper_spec.rb +10 -10
  59. data/spec/models/thing_spec.rb +4 -4
  60. data/spec/models/truck_spec.rb +5 -0
  61. data/spec/models/vehicle_spec.rb +5 -0
  62. data/spec/models/version_spec.rb +103 -59
  63. data/spec/models/widget_spec.rb +82 -52
  64. data/spec/modules/paper_trail_spec.rb +2 -2
  65. data/spec/modules/version_concern_spec.rb +11 -12
  66. data/spec/modules/version_number_spec.rb +2 -4
  67. data/spec/paper_trail/config_spec.rb +10 -29
  68. data/spec/paper_trail_spec.rb +16 -14
  69. data/spec/rails_helper.rb +10 -9
  70. data/spec/requests/articles_spec.rb +11 -7
  71. data/spec/spec_helper.rb +41 -22
  72. data/spec/support/alt_db_init.rb +8 -13
  73. data/test/custom_json_serializer.rb +3 -3
  74. data/test/dummy/Rakefile +2 -2
  75. data/test/dummy/app/controllers/application_controller.rb +21 -8
  76. data/test/dummy/app/controllers/articles_controller.rb +11 -8
  77. data/test/dummy/app/controllers/widgets_controller.rb +13 -12
  78. data/test/dummy/app/models/animal.rb +1 -1
  79. data/test/dummy/app/models/article.rb +19 -11
  80. data/test/dummy/app/models/authorship.rb +1 -1
  81. data/test/dummy/app/models/bar_habtm.rb +4 -0
  82. data/test/dummy/app/models/book.rb +4 -4
  83. data/test/dummy/app/models/boolit.rb +1 -1
  84. data/test/dummy/app/models/callback_modifier.rb +6 -6
  85. data/test/dummy/app/models/car.rb +3 -0
  86. data/test/dummy/app/models/chapter.rb +4 -4
  87. data/test/dummy/app/models/customer.rb +1 -1
  88. data/test/dummy/app/models/document.rb +2 -2
  89. data/test/dummy/app/models/editor.rb +1 -1
  90. data/test/dummy/app/models/foo_habtm.rb +4 -0
  91. data/test/dummy/app/models/fruit.rb +2 -2
  92. data/test/dummy/app/models/gadget.rb +1 -1
  93. data/test/dummy/app/models/kitchen/banana.rb +1 -1
  94. data/test/dummy/app/models/legacy_widget.rb +2 -2
  95. data/test/dummy/app/models/line_item.rb +1 -1
  96. data/test/dummy/app/models/not_on_update.rb +1 -1
  97. data/test/dummy/app/models/person.rb +6 -6
  98. data/test/dummy/app/models/post.rb +1 -1
  99. data/test/dummy/app/models/post_with_status.rb +1 -1
  100. data/test/dummy/app/models/quotation.rb +1 -1
  101. data/test/dummy/app/models/section.rb +1 -1
  102. data/test/dummy/app/models/skipper.rb +2 -2
  103. data/test/dummy/app/models/song.rb +13 -4
  104. data/test/dummy/app/models/thing.rb +2 -2
  105. data/test/dummy/app/models/translation.rb +2 -2
  106. data/test/dummy/app/models/truck.rb +4 -0
  107. data/test/dummy/app/models/vehicle.rb +4 -0
  108. data/test/dummy/app/models/whatchamajigger.rb +1 -1
  109. data/test/dummy/app/models/widget.rb +7 -6
  110. data/test/dummy/app/versions/joined_version.rb +4 -3
  111. data/test/dummy/app/versions/json_version.rb +1 -1
  112. data/test/dummy/app/versions/kitchen/banana_version.rb +1 -1
  113. data/test/dummy/app/versions/post_version.rb +2 -2
  114. data/test/dummy/config.ru +1 -1
  115. data/test/dummy/config/application.rb +20 -9
  116. data/test/dummy/config/boot.rb +5 -5
  117. data/test/dummy/config/environment.rb +1 -1
  118. data/test/dummy/config/environments/development.rb +4 -3
  119. data/test/dummy/config/environments/production.rb +3 -2
  120. data/test/dummy/config/environments/test.rb +15 -5
  121. data/test/dummy/config/initializers/backtrace_silencers.rb +4 -2
  122. data/test/dummy/config/initializers/paper_trail.rb +1 -2
  123. data/test/dummy/config/initializers/secret_token.rb +3 -1
  124. data/test/dummy/config/initializers/session_store.rb +1 -1
  125. data/test/dummy/config/routes.rb +2 -2
  126. data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +120 -74
  127. data/test/dummy/db/schema.rb +29 -6
  128. data/test/dummy/script/rails +6 -4
  129. data/test/functional/controller_test.rb +34 -35
  130. data/test/functional/enabled_for_controller_test.rb +6 -7
  131. data/test/functional/modular_sinatra_test.rb +43 -38
  132. data/test/functional/sinatra_test.rb +49 -40
  133. data/test/functional/thread_safety_test.rb +4 -6
  134. data/test/paper_trail_test.rb +15 -14
  135. data/test/test_helper.rb +68 -44
  136. data/test/time_travel_helper.rb +1 -15
  137. data/test/unit/associations_test.rb +517 -251
  138. data/test/unit/cleaner_test.rb +66 -60
  139. data/test/unit/inheritance_column_test.rb +17 -17
  140. data/test/unit/model_test.rb +611 -504
  141. data/test/unit/protected_attrs_test.rb +16 -12
  142. data/test/unit/serializer_test.rb +44 -43
  143. data/test/unit/serializers/json_test.rb +17 -18
  144. data/test/unit/serializers/mixin_json_test.rb +15 -14
  145. data/test/unit/serializers/mixin_yaml_test.rb +20 -16
  146. data/test/unit/serializers/yaml_test.rb +12 -13
  147. data/test/unit/timestamp_test.rb +10 -12
  148. data/test/unit/version_test.rb +7 -7
  149. metadata +92 -40
@@ -1,15 +1 @@
1
- if RUBY_VERSION < "1.9.2"
2
- require 'delorean'
3
-
4
- class Timecop
5
- def self.travel(t)
6
- Delorean.time_travel_to t
7
- end
8
-
9
- def self.return
10
- Delorean.back_to_the_present
11
- end
12
- end
13
- else
14
- require 'timecop'
15
- end
1
+ require "timecop"
@@ -1,5 +1,5 @@
1
- require 'test_helper'
2
- require 'time_travel_helper'
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
- self.use_transactional_fixtures = false
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 :name => 'widget_0' }
37
+ setup { @widget = Widget.create name: "widget_0" }
34
38
 
35
- context 'before the associated was created' do
39
+ context "before the associated was created" do
36
40
  setup do
37
- @widget.update_attributes :name => 'widget_1'
38
- @wotsit = @widget.create_wotsit :name => 'wotsit_0'
41
+ @widget.update_attributes name: "widget_1"
42
+ @wotsit = @widget.create_wotsit name: "wotsit_0"
39
43
  end
40
44
 
41
- context 'when reified' do
42
- setup { @widget_0 = @widget.versions.last.reify(:has_one => true) }
45
+ context "when reified" do
46
+ setup { @widget_0 = @widget.versions.last.reify(has_one: true) }
43
47
 
44
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
49
- assert_equal @wotsit, @widget.wotsit(true)
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 'where the association is created between model versions' do
58
+ context "where the association is created between model versions" do
55
59
  setup do
56
- @wotsit = @widget.create_wotsit :name => 'wotsit_0'
60
+ @wotsit = @widget.create_wotsit name: "wotsit_0"
57
61
  Timecop.travel 1.second.since
58
- @widget.update_attributes :name => 'widget_1'
62
+ @widget.update_attributes name: "widget_1"
59
63
  end
60
64
 
61
- context 'when reified' do
62
- setup { @widget_0 = @widget.versions.last.reify(:has_one => true) }
65
+ context "when reified" do
66
+ setup { @widget_0 = @widget.versions.last.reify(has_one: true) }
63
67
 
64
- should 'see the associated as it was at the time' do
65
- assert_equal 'wotsit_0', @widget_0.wotsit.name
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 'not persist changes to the live association' do
69
- assert_equal @wotsit, @widget.wotsit(true)
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 'and then the associated is updated between model versions' do
77
+ context "and then the associated is updated between model versions" do
74
78
  setup do
75
- @wotsit.update_attributes :name => 'wotsit_1'
76
- @wotsit.update_attributes :name => 'wotsit_2'
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 :name => 'widget_2'
79
- @wotsit.update_attributes :name => 'wotsit_3'
82
+ @widget.update_attributes name: "widget_2"
83
+ @wotsit.update_attributes name: "wotsit_3"
80
84
  end
81
85
 
82
- context 'when reified' do
83
- setup { @widget_1 = @widget.versions.last.reify(:has_one => true) }
86
+ context "when reified" do
87
+ setup { @widget_1 = @widget.versions.last.reify(has_one: true) }
84
88
 
85
- should 'see the associated as it was at the time' do
86
- assert_equal 'wotsit_2', @widget_1.wotsit.name
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 'not persist changes to the live association' do
90
- assert_equal 'wotsit_3', @widget.wotsit(true).name
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 'when reified opting out of has_one reification' do
95
- setup { @widget_1 = @widget.versions.last.reify(:has_one => false) }
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 'see the associated as it is live' do
98
- assert_equal 'wotsit_3', @widget_1.wotsit.name
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 'and then the associated is destroyed' do
107
+ context "and then the associated is destroyed" do
104
108
  setup do
105
109
  @wotsit.destroy
106
110
  end
107
111
 
108
- context 'when reify' do
109
- setup { @widget_1 = @widget.versions.last.reify(:has_one => true) }
112
+ context "when reify" do
113
+ setup { @widget_1 = @widget.versions.last.reify(has_one: true) }
110
114
 
111
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
116
- assert_nil @widget.wotsit(true)
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 'and then the model is updated' do
124
+ context "and then the model is updated" do
121
125
  setup do
122
126
  Timecop.travel 1.second.since
123
- @widget.update_attributes :name => 'widget_3'
127
+ @widget.update_attributes name: "widget_3"
124
128
  end
125
129
 
126
- context 'when reified' do
127
- setup { @widget_2 = @widget.versions.last.reify(:has_one => true) }
130
+ context "when reified" do
131
+ setup { @widget_2 = @widget.versions.last.reify(has_one: true) }
128
132
 
129
- should 'see the associated as it was at the time' do
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 :name => 'customer_0' }
143
+ setup { @customer = Customer.create name: "customer_0" }
140
144
 
141
- context 'updated before the associated was created' do
145
+ context "updated before the associated was created" do
142
146
  setup do
143
- @customer.update_attributes! :name => 'customer_1'
144
- @customer.orders.create! :order_date => Date.today
147
+ @customer.update_attributes! name: "customer_1"
148
+ @customer.orders.create! order_date: Date.today
145
149
  end
146
150
 
147
- context 'when reified' do
148
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true) }
151
+ context "when reified" do
152
+ setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
149
153
 
150
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
155
- assert_not_equal [], @customer.orders(true)
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 'when reified with option mark_for_destruction' do
160
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
161
-
162
- should 'mark the associated for destruction' do
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 'where the association is created between model versions' do
174
+ context "where the association is created between model versions" do
169
175
  setup do
170
- @order = @customer.orders.create! :order_date => 'order_date_0'
176
+ @order = @customer.orders.create! order_date: "order_date_0"
171
177
  Timecop.travel 1.second.since
172
- @customer.update_attributes :name => 'customer_1'
178
+ @customer.update_attributes name: "customer_1"
173
179
  end
174
180
 
175
- context 'when reified' do
176
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true) }
181
+ context "when reified" do
182
+ setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
177
183
 
178
- should 'see the associated as it was at the time' do
179
- assert_equal ['order_date_0'], @customer_0.orders.map(&:order_date)
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 'and then a nested has_many association is created' do
189
+ context "and then a nested has_many association is created" do
184
190
  setup do
185
- @order.line_items.create! :product => 'product_0'
191
+ @order.line_items.create! product: "product_0"
186
192
  end
187
193
 
188
- context 'when reified' do
189
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true) }
194
+ context "when reified" do
195
+ setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
190
196
 
191
- should 'see the live version of the nested association' do
192
- assert_equal ['product_0'], @customer_0.orders.first.line_items.map(&:product)
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 'and then the associated is updated between model versions' do
203
+ context "and then the associated is updated between model versions" do
198
204
  setup do
199
- @order.update_attributes :order_date => 'order_date_1'
200
- @order.update_attributes :order_date => 'order_date_2'
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 :name => 'customer_2'
203
- @order.update_attributes :order_date => 'order_date_3'
208
+ @customer.update_attributes name: "customer_2"
209
+ @order.update_attributes order_date: "order_date_3"
204
210
  end
205
211
 
206
- context 'when reified' do
207
- setup { @customer_1 = @customer.versions.last.reify(:has_many => true) }
212
+ context "when reified" do
213
+ setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
208
214
 
209
- should 'see the associated as it was at the time' do
210
- assert_equal ['order_date_2'], @customer_1.orders.map(&:order_date)
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 'not persist changes to the live association' do
214
- assert_equal ['order_date_3'], @customer.orders(true).map(&:order_date)
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 'when reified opting out of has_many reification' do
219
- setup { @customer_1 = @customer.versions.last.reify(:has_many => false) }
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 'see the associated as it is live' do
222
- assert_equal ['order_date_3'], @customer_1.orders.map(&:order_date)
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 'and then the associated is destroyed' do
232
+ context "and then the associated is destroyed" do
227
233
  setup do
228
234
  @order.destroy
229
235
  end
230
236
 
231
- context 'when reified' do
232
- setup { @customer_1 = @customer.versions.last.reify(:has_many => true) }
237
+ context "when reified" do
238
+ setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
233
239
 
234
- should 'see the associated as it was at the time' do
235
- assert_equal ['order_date_2'], @customer_1.orders.map(&:order_date)
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 'not persist changes to the live association' do
239
- assert_equal [], @customer.orders(true)
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 'and then the associated is destroyed' do
251
+ context "and then the associated is destroyed" do
246
252
  setup do
247
253
  @order.destroy
248
254
  end
249
255
 
250
- context 'when reified' do
251
- setup { @customer_1 = @customer.versions.last.reify(:has_many => true) }
256
+ context "when reified" do
257
+ setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
252
258
 
253
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
258
- assert_equal [], @customer.orders(true)
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 'and then the associated is destroyed between model versions' do
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 :name => 'customer_2'
273
+ @customer.update_attributes name: "customer_2"
268
274
  end
269
275
 
270
- context 'when reified' do
271
- setup { @customer_1 = @customer.versions.last.reify(:has_many => true) }
276
+ context "when reified" do
277
+ setup { @customer_1 = @customer.versions.last.reify(has_many: true) }
272
278
 
273
- should 'see the associated as it was at the time' do
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 'and then another association is added' do
285
+ context "and then another association is added" do
280
286
  setup do
281
- @customer.orders.create! :order_date => 'order_date_1'
287
+ @customer.orders.create! order_date: "order_date_1"
282
288
  end
283
289
 
284
- context 'when reified' do
285
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true) }
290
+ context "when reified" do
291
+ setup { @customer_0 = @customer.versions.last.reify(has_many: true) }
286
292
 
287
- should 'see the associated as it was at the time' do
288
- assert_equal ['order_date_0'], @customer_0.orders.map(&:order_date)
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 'not persist changes to the live association' do
292
- assert_equal ['order_date_0', 'order_date_1'], @customer.orders(true).map(&:order_date).sort
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 'when reified with option mark_for_destruction' do
297
- setup { @customer_0 = @customer.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
298
-
299
- should 'mark the newly associated for destruction' do
300
- assert @customer_0.orders.detect { |o| o.order_date == 'order_date_1'}.marked_for_destruction?
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 :title => 'book_0' }
321
+ setup { @book = Book.create title: "book_0" }
310
322
 
311
- context 'updated before the associated was created' do
323
+ context "updated before the associated was created" do
312
324
  setup do
313
- @book.update_attributes! :title => 'book_1'
314
- @book.authors.create! :name => 'author_0'
325
+ @book.update_attributes! title: "book_1"
326
+ @book.authors.create! name: "author_0"
315
327
  end
316
328
 
317
- context 'when reified' do
318
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
329
+ context "when reified" do
330
+ setup { @book_0 = @book.versions.last.reify(has_many: true) }
319
331
 
320
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
325
- assert_equal ['author_0'], @book.authors(true).map(&:name)
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 'when reified with option mark_for_destruction' do
330
- setup { @book_0 = @book.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
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 'mark the associated for destruction' do
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 'mark the associated-through for destruction' do
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 'updated before it is associated with an existing one' do
359
+ context "updated before it is associated with an existing one" do
343
360
  setup do
344
- person_existing = Person.create(:name => 'person_existing')
361
+ person_existing = Person.create(name: "person_existing")
345
362
  Timecop.travel 1.second.since
346
- @book.update_attributes! :title => 'book_1'
363
+ @book.update_attributes! title: "book_1"
347
364
  @book.authors << person_existing
348
365
  end
349
366
 
350
- context 'when reified' do
351
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
367
+ context "when reified" do
368
+ setup do
369
+ @book_0 = @book.versions.last.reify(has_many: true)
370
+ end
352
371
 
353
- should 'see the associated as it was at the time' do
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 'when reified with option mark_for_destruction' do
359
- setup { @book_0 = @book.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
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 'not mark the associated for destruction' do
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 'mark the associated-through for destruction' do
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 'where the association is created between model versions' do
395
+ context "where the association is created between model versions" do
372
396
  setup do
373
- @author = @book.authors.create! :name => 'author_0'
374
- @person_existing = Person.create(:name => 'person_existing')
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! :title => 'book_1'
400
+ @book.update_attributes! title: "book_1"
377
401
  end
378
402
 
379
- context 'when reified' do
380
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
403
+ context "when reified" do
404
+ setup { @book_0 = @book.versions.last.reify(has_many: true) }
381
405
 
382
- should 'see the associated as it was at the time' do
383
- assert_equal ['author_0'], @book_0.authors.map(&:name)
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 'and then the associated is updated between model versions' do
411
+ context "and then the associated is updated between model versions" do
388
412
  setup do
389
- @author.update_attributes :name => 'author_1'
390
- @author.update_attributes :name => 'author_2'
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 :title => 'book_2'
393
- @author.update_attributes :name => 'author_3'
416
+ @book.update_attributes title: "book_2"
417
+ @author.update_attributes name: "author_3"
394
418
  end
395
419
 
396
- context 'when reified' do
397
- setup { @book_1 = @book.versions.last.reify(:has_many => true) }
420
+ context "when reified" do
421
+ setup { @book_1 = @book.versions.last.reify(has_many: true) }
398
422
 
399
- should 'see the associated as it was at the time' do
400
- assert_equal ['author_2'], @book_1.authors.map(&:name)
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 'not persist changes to the live association' do
404
- assert_equal ['author_3'], @book.authors(true).map(&:name)
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 'when reified opting out of has_many reification' do
409
- setup { @book_1 = @book.versions.last.reify(:has_many => false) }
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 'see the associated as it is live' do
412
- assert_equal ['author_3'], @book_1.authors.map(&:name)
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 'and then the associated is destroyed' do
441
+ context "and then the associated is destroyed" do
418
442
  setup do
419
443
  @author.destroy
420
444
  end
421
445
 
422
- context 'when reified' do
423
- setup { @book_1 = @book.versions.last.reify(:has_many => true) }
446
+ context "when reified" do
447
+ setup { @book_1 = @book.versions.last.reify(has_many: true) }
424
448
 
425
- should 'see the associated as it was at the time' do
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 'not persist changes to the live association' do
430
- assert_equal [], @book.authors(true)
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 'and then the associated is destroyed between model versions' do
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 :title => 'book_2'
463
+ @book.update_attributes title: "book_2"
440
464
  end
441
465
 
442
- context 'when reified' do
443
- setup { @book_1 = @book.versions.last.reify(:has_many => true) }
466
+ context "when reified" do
467
+ setup { @book_1 = @book.versions.last.reify(has_many: true) }
444
468
 
445
- should 'see the associated as it was at the time' do
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 'and then the associated is dissociated between model versions' do
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 :title => 'book_2'
479
+ @book.update_attributes title: "book_2"
456
480
  end
457
481
 
458
- context 'when reified' do
459
- setup { @book_1 = @book.versions.last.reify(:has_many => true) }
482
+ context "when reified" do
483
+ setup { @book_1 = @book.versions.last.reify(has_many: true) }
460
484
 
461
- should 'see the associated as it was at the time' do
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 'and then another associated is created' do
491
+ context "and then another associated is created" do
468
492
  setup do
469
- @book.authors.create! :name => 'author_1'
493
+ @book.authors.create! name: "author_1"
470
494
  end
471
495
 
472
- context 'when reified' do
473
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
496
+ context "when reified" do
497
+ setup { @book_0 = @book.versions.last.reify(has_many: true) }
474
498
 
475
- should 'only see the first associated' do
476
- assert_equal ['author_0'], @book_0.authors.map(&:name)
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 'not persist changes to the live association' do
480
- assert_equal ['author_0', 'author_1'], @book.authors(true).map(&:name)
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 'when reified with option mark_for_destruction' do
485
- setup { @book_0 = @book.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
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 'mark the newly associated for destruction' do
488
- assert @book_0.authors.detect { |a| a.name == 'author_1' }.marked_for_destruction?
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 'mark the newly associated-through for destruction' do
492
- assert @book_0.authorships.detect { |as| as.person.name == 'author_1' }.marked_for_destruction?
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 'and then an existing one is associated' do
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 'when reified' do
503
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
537
+ context "when reified" do
538
+ setup { @book_0 = @book.versions.last.reify(has_many: true) }
504
539
 
505
- should 'only see the first associated' do
506
- assert_equal ['author_0'], @book_0.authors.map(&:name)
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 'not persist changes to the live association' do
510
- assert_equal ['author_0', 'person_existing'], @book.authors(true).map(&:name).sort
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 'when reified with option mark_for_destruction' do
515
- setup { @book_0 = @book.versions.last.reify(:has_many => true, :mark_for_destruction => true) }
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 'not mark the newly associated for destruction' do
518
- assert !@book_0.authors.detect { |a| a.name == 'person_existing' }.marked_for_destruction?
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 'mark the newly associated-through for destruction' do
522
- assert @book_0.authorships.detect { |as| as.person.name == 'person_existing' }.marked_for_destruction?
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 'updated before the associated without paper_trail was created' do
574
+ context "updated before the associated without paper_trail was created" do
529
575
  setup do
530
- @book.update_attributes! :title => 'book_1'
531
- @book.editors.create! :name => 'editor_0'
576
+ @book.update_attributes! title: "book_1"
577
+ @book.editors.create! name: "editor_0"
532
578
  end
533
579
 
534
- context 'when reified' do
535
- setup { @book_0 = @book.versions.last.reify(:has_many => true) }
580
+ context "when reified" do
581
+ setup { @book_0 = @book.versions.last.reify(has_many: true) }
536
582
 
537
- should 'see the live association' do
538
- assert_equal ['editor_0'], @book_0.editors.map(&:name)
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(:name => CHAPTER_NAMES[0]) }
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(:name => CHAPTER_NAMES[1])
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(:has_many => true)
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 :name => CHAPTER_NAMES[1]
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 :name => "section 1"
613
+ @chapter.sections.create name: "section 1"
568
614
  Timecop.travel 1.second.since
569
- @chapter.sections.first.update_attributes :name => "section 2"
615
+ @chapter.sections.first.update_attributes name: "section 2"
570
616
  Timecop.travel 1.second.since
571
- @chapter.update_attributes :name => CHAPTER_NAMES[2]
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 :name => "section 3"
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(:has_many => true)
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(:has_many => true)
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 ['section 2'], chapter_v2.sections.map(&:name)
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 :name => CHAPTER_NAMES[2]
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(:has_many => true)
609
- assert_equal ['section 2'], chapter_v2.sections.map(&:name)
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 :name => CHAPTER_NAMES[3]
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(:has_many => true)
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 :name => 'para1'
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 :name => CHAPTER_NAMES[4]
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 :name => 'para3'
644
- chapter_v3 = @chapter.versions[3].reify(:has_many => true)
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(:name => CHAPTER_NAMES[3])
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(:has_many => true)
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(:name => CHAPTER_NAMES[5])
718
+ @chapter.update_attributes(name: CHAPTER_NAMES[5])
673
719
  assert_equal 4, @chapter.versions.size
674
- chapter_v3 = @chapter.versions[3].reify(:has_many => true)
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(:name => CHAPTER_NAMES[5])
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(:has_many => true)
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(:name => CHAPTER_NAMES[5])
699
- chapter_v3 = @chapter.versions[3].reify(:has_many => true)
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(:name => CHAPTER_NAMES[0])
710
- section = Section.create(:name => 'Section One', :chapter => chapter)
711
- paragraph = Paragraph.create(:name => 'Paragraph One', :section => section)
712
- quotation = Quotation.create(:chapter => chapter)
713
- citation = Citation.create(:quotation => quotation)
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(:name => CHAPTER_NAMES[1])
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(:has_many => true)
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