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.
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