paper_trail 3.0.9 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.rspec +1 -2
  4. data/.travis.yml +5 -0
  5. data/CHANGELOG.md +37 -23
  6. data/README.md +170 -63
  7. data/gemfiles/3.0.gemfile +10 -4
  8. data/lib/generators/paper_trail/install_generator.rb +19 -3
  9. data/lib/generators/paper_trail/templates/add_transaction_id_column_to_versions.rb +11 -0
  10. data/lib/generators/paper_trail/templates/create_version_associations.rb +17 -0
  11. data/lib/paper_trail.rb +24 -4
  12. data/lib/paper_trail/cleaner.rb +3 -3
  13. data/lib/paper_trail/config.rb +17 -0
  14. data/lib/paper_trail/frameworks/active_record/models/paper_trail/version_association.rb +7 -0
  15. data/lib/paper_trail/frameworks/rails.rb +1 -0
  16. data/lib/paper_trail/frameworks/rspec.rb +5 -0
  17. data/lib/paper_trail/has_paper_trail.rb +112 -38
  18. data/lib/paper_trail/version_association_concern.rb +13 -0
  19. data/lib/paper_trail/version_concern.rb +145 -38
  20. data/lib/paper_trail/version_number.rb +3 -3
  21. data/paper_trail.gemspec +11 -4
  22. data/spec/generators/install_generator_spec.rb +4 -4
  23. data/spec/models/fluxor_spec.rb +19 -0
  24. data/spec/models/gadget_spec.rb +10 -10
  25. data/spec/models/joined_version_spec.rb +9 -9
  26. data/spec/models/post_with_status_spec.rb +3 -3
  27. data/spec/models/version_spec.rb +49 -71
  28. data/spec/models/widget_spec.rb +124 -71
  29. data/spec/modules/version_concern_spec.rb +8 -8
  30. data/spec/modules/version_number_spec.rb +16 -16
  31. data/spec/paper_trail_spec.rb +17 -17
  32. data/spec/rails_helper.rb +34 -0
  33. data/spec/requests/articles_spec.rb +11 -11
  34. data/spec/spec_helper.rb +77 -36
  35. data/test/dummy/app/models/animal.rb +0 -2
  36. data/test/dummy/app/models/book.rb +4 -0
  37. data/test/dummy/app/models/customer.rb +4 -0
  38. data/test/dummy/app/models/editor.rb +4 -0
  39. data/test/dummy/app/models/editorship.rb +5 -0
  40. data/test/dummy/app/models/line_item.rb +4 -0
  41. data/test/dummy/app/models/order.rb +5 -0
  42. data/test/dummy/app/models/person.rb +1 -1
  43. data/test/dummy/app/models/post.rb +0 -1
  44. data/test/dummy/app/models/song.rb +0 -20
  45. data/test/dummy/app/models/widget.rb +4 -0
  46. data/test/dummy/config/application.rb +3 -0
  47. data/test/dummy/config/initializers/paper_trail.rb +1 -1
  48. data/test/dummy/db/migrate/20110208155312_set_up_test_tables.rb +41 -0
  49. data/test/dummy/db/schema.rb +95 -25
  50. data/test/dummy/public/404.html +26 -0
  51. data/test/dummy/public/422.html +26 -0
  52. data/test/dummy/public/500.html +26 -0
  53. data/test/dummy/public/favicon.ico +0 -0
  54. data/test/dummy/public/javascripts/application.js +2 -0
  55. data/test/dummy/public/javascripts/controls.js +965 -0
  56. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  57. data/test/dummy/public/javascripts/effects.js +1123 -0
  58. data/test/dummy/public/javascripts/rails.js +175 -0
  59. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  60. data/test/test_helper.rb +2 -2
  61. data/test/time_travel_helper.rb +15 -0
  62. data/test/unit/model_test.rb +613 -185
  63. data/test/unit/serializer_test.rb +3 -3
  64. metadata +104 -54
  65. data/spec/models/animal_spec.rb +0 -19
  66. data/test/dummy/public/javascripts/prototype.js +0 -6001
@@ -0,0 +1,13 @@
1
+ require 'active_support/concern'
2
+
3
+ module PaperTrail
4
+ module VersionAssociationConcern
5
+ extend ::ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :version
9
+
10
+ attr_accessible :version_id, :foreign_key_name, :foreign_key_id if PaperTrail.active_record_protected_attributes?
11
+ end
12
+ end
13
+ end
@@ -6,10 +6,15 @@ module PaperTrail
6
6
 
7
7
  included do
8
8
  belongs_to :item, :polymorphic => true
9
+ has_many :version_associations, :dependent => :destroy
10
+
9
11
  validates_presence_of :event
10
- attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes if PaperTrail.active_record_protected_attributes?
12
+
13
+ attr_accessible :item_type, :item_id, :event, :whodunnit, :object, :object_changes, :transaction_id, :created_at if PaperTrail.active_record_protected_attributes?
11
14
 
12
15
  after_create :enforce_version_limit!
16
+
17
+ scope :within_transaction, lambda { |id| where :transaction_id => id }
13
18
  end
14
19
 
15
20
  module ClassMethods
@@ -102,21 +107,28 @@ module PaperTrail
102
107
 
103
108
  # Restore the item from this version.
104
109
  #
105
- # This will automatically restore all :has_one associations as they were "at the time",
106
- # if they are also being versioned by PaperTrail. NOTE: this isn't always guaranteed
107
- # to work so you can either change the lookback period (from the default 3 seconds) or
108
- # opt out.
110
+ # Optionally this can also restore all :has_one and :has_many (including has_many :through) associations as
111
+ # they were "at the time", if they are also being versioned by PaperTrail.
109
112
  #
110
113
  # Options:
111
- # :has_one set to `false` to opt out of has_one reification.
112
- # set to a float to change the lookback time (check whether your db supports
113
- # sub-second datetimes if you want them).
114
+ # :has_one set to `true` to also reify has_one associations. Default is `false`.
115
+ # :has_many set to `true` to also reify has_many and has_many :through associations.
116
+ # Default is `false`.
117
+ # :mark_for_destruction set to `true` to mark the has_one/has_many associations that did not exist in the
118
+ # reified version for destruction, instead of remove them. Default is `false`.
119
+ # This option is handy for people who want to persist the reified version.
120
+ # :dup `false` default behavior
121
+ # `true` it always create a new object instance. It is useful for comparing two versions of the same object
114
122
  def reify(options = {})
115
123
  return nil if object.nil?
116
124
 
117
125
  without_identity_map do
118
- options[:has_one] = 3 if options[:has_one] == true
119
- options.reverse_merge! :has_one => false
126
+ options.reverse_merge!(
127
+ :version_at => created_at,
128
+ :mark_for_destruction => false,
129
+ :has_one => false,
130
+ :has_many => false
131
+ )
120
132
 
121
133
  attrs = self.class.object_col_is_json? ? object : PaperTrail.serializer.load(object)
122
134
 
@@ -133,7 +145,7 @@ module PaperTrail
133
145
  # `item_type` will be the base class, not the actual subclass.
134
146
  # If `type` is present but empty, the class is the base class.
135
147
 
136
- if item
148
+ if item && options[:dup] != true
137
149
  model = item
138
150
  # Look for attributes that exist in the model and not in this version. These attributes should be set to nil.
139
151
  (model.attribute_names - attrs.keys).each { |k| attrs[k] = nil }
@@ -144,14 +156,14 @@ module PaperTrail
144
156
  model = klass.new
145
157
  end
146
158
 
147
- model.class.unserialize_attributes_for_paper_trail attrs
159
+ if PaperTrail.serialized_attributes?
160
+ model.class.unserialize_attributes_for_paper_trail attrs
161
+ end
148
162
 
149
163
  # Set all the attributes in this version on the model
150
164
  attrs.each do |k, v|
151
165
  if model.has_attribute?(k)
152
166
  model[k.to_sym] = v
153
- elsif model.respond_to?("#{k}=")
154
- model.send("#{k}=", v)
155
167
  else
156
168
  logger.warn "Attribute #{k} does not exist on #{item_type} (Version id: #{id})."
157
169
  end
@@ -160,34 +172,35 @@ module PaperTrail
160
172
  model.send "#{model.class.version_association_name}=", self
161
173
 
162
174
  unless options[:has_one] == false
163
- reify_has_ones model, options[:has_one]
175
+ reify_has_ones model, options
176
+ end
177
+
178
+ unless options[:has_many] == false
179
+ reify_has_manys model, options
164
180
  end
165
181
 
166
182
  model
167
183
  end
168
184
  end
169
185
 
170
- # Returns what changed in this version of the item. Cf. `ActiveModel::Dirty#changes`.
171
- # Returns `nil` if your `versions` table does not have an `object_changes` text column.
186
+ # Returns what changed in this version of the item. `ActiveModel::Dirty#changes`.
187
+ # returns `nil` if your `versions` table does not have an `object_changes` text column.
172
188
  def changeset
173
189
  return nil unless self.class.column_names.include? 'object_changes'
174
190
 
175
191
  _changes = self.class.object_changes_col_is_json? ? object_changes : PaperTrail.serializer.load(object_changes)
176
192
  @changeset ||= HashWithIndifferentAccess.new(_changes).tap do |changes|
177
- item_type.constantize.unserialize_attribute_changes(changes)
193
+ if PaperTrail.serialized_attributes?
194
+ item_type.constantize.unserialize_attribute_changes(changes)
195
+ end
178
196
  end
179
197
  rescue
180
198
  {}
181
199
  end
182
200
 
183
201
  # Returns who put the item into the state stored in this version.
184
- def paper_trail_originator
185
- @paper_trail_originator ||= previous.whodunnit rescue nil
186
- end
187
-
188
202
  def originator
189
- warn "DEPRECATED: use `paper_trail_originator` instead of `originator`. Support for `originator` will be removed in PaperTrail 4.0"
190
- self.paper_trail_originator
203
+ @originator ||= previous.whodunnit rescue nil
191
204
  end
192
205
 
193
206
  # Returns who changed the item from the state it had in this version.
@@ -236,25 +249,119 @@ module PaperTrail
236
249
  # Restore the `model`'s has_one associations as they were when this version was
237
250
  # superseded by the next (because that's what the user was looking at when they
238
251
  # made the change).
239
- #
240
- # The `lookback` sets how many seconds before the model's change we go.
241
- def reify_has_ones(model, lookback)
252
+ def reify_has_ones(model, options = {})
253
+ version_table_name = model.class.paper_trail_version_class.table_name
242
254
  model.class.reflect_on_all_associations(:has_one).each do |assoc|
243
- child = model.send assoc.name
244
- if child.respond_to? :version_at
245
- # N.B. we use version of the child as it was `lookback` seconds before the parent was updated.
246
- # Ideally we want the version of the child as it was just before the parent was updated...
247
- # but until PaperTrail knows which updates are "together" (e.g. parent and child being
248
- # updated on the same form), it's impossible to tell when the overall update started;
249
- # and therefore impossible to know when "just before" was.
250
- if (child_as_it_was = child.version_at(send(PaperTrail.timestamp_field) - lookback.seconds))
251
- child_as_it_was.attributes.each do |k,v|
252
- model.send(assoc.name).send :write_attribute, k.to_sym, v rescue nil
255
+ if assoc.klass.paper_trail_enabled_for_model?
256
+ version = model.class.paper_trail_version_class.joins(:version_associations).
257
+ where("version_associations.foreign_key_name = ?", assoc.foreign_key).
258
+ where("version_associations.foreign_key_id = ?", model.id).
259
+ where("#{version_table_name}.item_type = ?", assoc.class_name).
260
+ where("created_at >= ? OR transaction_id = ?", options[:version_at], transaction_id).
261
+ order("#{version_table_name}.id ASC").first
262
+ if version
263
+ if version.event == 'create'
264
+ if options[:mark_for_destruction]
265
+ model.send(assoc.name).mark_for_destruction if model.send(assoc.name, true)
266
+ else
267
+ model.appear_as_new_record do
268
+ model.send "#{assoc.name}=", nil
269
+ end
270
+ end
271
+ else
272
+ child = version.reify(options.merge(:has_many => false, :has_one => false))
273
+ model.appear_as_new_record do
274
+ model.send "#{assoc.name}=", child
275
+ end
253
276
  end
277
+ end
278
+ end
279
+ end
280
+ end
281
+
282
+ # Restore the `model`'s has_many associations as they were at version_at timestamp
283
+ # We lookup the first child versions after version_at timestamp or in same transaction.
284
+ def reify_has_manys(model, options = {})
285
+ assoc_has_many_through, assoc_has_many_directly =
286
+ model.class.reflect_on_all_associations(:has_many).partition { |assoc| assoc.options[:through] }
287
+ reify_has_many_directly(assoc_has_many_directly, model, options)
288
+ reify_has_many_through(assoc_has_many_through, model, options)
289
+ end
290
+
291
+ # Restore the `model`'s has_many associations not associated through another association
292
+ def reify_has_many_directly(associations, model, options = {})
293
+ version_table_name = model.class.paper_trail_version_class.table_name
294
+ associations.each do |assoc|
295
+ next unless assoc.klass.paper_trail_enabled_for_model?
296
+ version_id_subquery = PaperTrail::VersionAssociation.joins(model.class.version_association_name).
297
+ select("MIN(version_id)").
298
+ where("foreign_key_name = ?", assoc.foreign_key).
299
+ where("foreign_key_id = ?", model.id).
300
+ where("#{version_table_name}.item_type = ?", assoc.class_name).
301
+ where("created_at >= ? OR transaction_id = ?", options[:version_at], transaction_id).
302
+ group("item_id").to_sql
303
+ versions = model.class.paper_trail_version_class.where("id IN (#{version_id_subquery})").inject({}) do |acc, v|
304
+ acc.merge!(v.item_id => v)
305
+ end
306
+
307
+ # Pass true to force the model to load
308
+ collection = Array.new model.send(assoc.name, true)
309
+
310
+ # Iterate each child to replace it with the previous value if there is a version after the timestamp
311
+ collection.map! do |c|
312
+ if (version = versions.delete(c.id)).nil?
313
+ c
314
+ elsif version.event == 'create'
315
+ options[:mark_for_destruction] ? c.tap { |r| r.mark_for_destruction } : nil
316
+ else
317
+ version.reify(options.merge(:has_many => false, :has_one => false))
318
+ end
319
+ end
320
+
321
+ # Reify the rest of the versions and add them to the collection, these versions are for those that
322
+ # have been removed from the live associations
323
+ collection += versions.values.map { |version| version.reify(options.merge(:has_many => false, :has_one => false)) }
324
+
325
+ model.send(assoc.name).proxy_association.target = collection.compact
326
+ end
327
+ end
328
+
329
+ # Restore the `model`'s has_many associations through another association
330
+ # This must be called after the direct has_manys have been reified (reify_has_many_directly)
331
+ def reify_has_many_through(associations, model, options = {})
332
+ associations.each do |assoc|
333
+ next unless assoc.klass.paper_trail_enabled_for_model?
334
+ through_collection = model.send(assoc.options[:through])
335
+ collection_keys = through_collection.map { |through_model| through_model.send(assoc.foreign_key) }
336
+
337
+ version_id_subquery = assoc.klass.paper_trail_version_class.
338
+ select("MIN(id)").
339
+ where("item_type = ?", assoc.class_name).
340
+ where("item_id IN (?)", collection_keys).
341
+ where("created_at >= ? OR transaction_id = ?", options[:version_at], transaction_id).
342
+ group("item_id").to_sql
343
+ versions = assoc.klass.paper_trail_version_class.where("id IN (#{version_id_subquery})").inject({}) do |acc, v|
344
+ acc.merge!(v.item_id => v)
345
+ end
346
+
347
+ collection = Array.new assoc.klass.where(assoc.klass.primary_key => collection_keys)
348
+
349
+ # Iterate each child to replace it with the previous value if there is a version after the timestamp
350
+ collection.map! do |c|
351
+ if (version = versions.delete(c.id)).nil?
352
+ c
353
+ elsif version.event == 'create'
354
+ options[:mark_for_destruction] ? c.tap { |r| r.mark_for_destruction } : nil
254
355
  else
255
- model.send "#{assoc.name}=", nil
356
+ version.reify(options.merge(:has_many => false, :has_one => false))
256
357
  end
257
358
  end
359
+
360
+ # Reify the rest of the versions and add them to the collection, these versions are for those that
361
+ # have been removed from the live associations
362
+ collection += versions.values.map { |version| version.reify(options.merge(:has_many => false, :has_one => false)) }
363
+
364
+ model.send(assoc.name).proxy_association.target = collection.compact
258
365
  end
259
366
  end
260
367
 
@@ -1,9 +1,9 @@
1
1
  module PaperTrail
2
2
  module VERSION
3
- MAJOR = 3
3
+ MAJOR = 4
4
4
  MINOR = 0
5
- TINY = 9
6
- PRE = nil
5
+ TINY = 0
6
+ PRE = 'beta1'
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
9
9
 
data/paper_trail.gemspec CHANGED
@@ -19,20 +19,27 @@ Gem::Specification.new do |s|
19
19
 
20
20
  s.required_rubygems_version = '>= 1.3.6'
21
21
 
22
- s.add_dependency 'activerecord', ['>= 3.0', '< 5.0']
23
- s.add_dependency 'activesupport', ['>= 3.0', '< 5.0']
22
+ s.add_dependency 'activerecord', ['>= 3.0', '< 6.0']
23
+ s.add_dependency 'activesupport', ['>= 3.0', '< 6.0']
24
24
 
25
25
  s.add_development_dependency 'rake', '~> 10.1.1'
26
26
  s.add_development_dependency 'shoulda', '~> 3.5'
27
27
  # s.add_development_dependency 'shoulda-matchers', '~> 1.5' # needed for ActiveRecord < 4
28
- s.add_development_dependency 'ffaker', '<= 1.31.0'
28
+ s.add_development_dependency 'ffaker', '>= 1.15'
29
29
  s.add_development_dependency 'railties', ['>= 3.0', '< 5.0']
30
30
  s.add_development_dependency 'sinatra', '~> 1.0'
31
31
  s.add_development_dependency 'rack-test', '>= 0.6'
32
- s.add_development_dependency 'rspec-rails', '~> 2.14'
32
+ s.add_development_dependency 'rspec-rails', '~> 3.1.0'
33
33
  s.add_development_dependency 'generator_spec'
34
34
  s.add_development_dependency 'database_cleaner', '~> 1.2'
35
35
 
36
+ # Allow time travel in testing. timecop is only supported after 1.9.2 but does a better cleanup at 'return'
37
+ if RUBY_VERSION < "1.9.2"
38
+ s.add_development_dependency 'delorean'
39
+ else
40
+ s.add_development_dependency 'timecop'
41
+ end
42
+
36
43
  # JRuby support for the test ENV
37
44
  unless defined?(JRUBY_VERSION)
38
45
  s.add_development_dependency 'sqlite3', '~> 1.2'
@@ -1,4 +1,4 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
2
  require 'generator_spec/test_case'
3
3
  require File.expand_path('../../../lib/generators/paper_trail/install_generator', __FILE__)
4
4
 
@@ -15,7 +15,7 @@ describe PaperTrail::InstallGenerator, :type => :generator do
15
15
  end
16
16
 
17
17
  it "generates a migration for creating the 'versions' table" do
18
- destination_root.should have_structure {
18
+ expect(destination_root).to have_structure {
19
19
  directory 'db' do
20
20
  directory 'migrate' do
21
21
  migration 'create_versions' do
@@ -36,7 +36,7 @@ describe PaperTrail::InstallGenerator, :type => :generator do
36
36
  end
37
37
 
38
38
  it "generates a migration for creating the 'versions' table" do
39
- destination_root.should have_structure {
39
+ expect(destination_root).to have_structure {
40
40
  directory 'db' do
41
41
  directory 'migrate' do
42
42
  migration 'create_versions' do
@@ -50,7 +50,7 @@ describe PaperTrail::InstallGenerator, :type => :generator do
50
50
  end
51
51
 
52
52
  it "generates a migration for adding the 'object_changes' column to the 'versions' table" do
53
- destination_root.should have_structure {
53
+ expect(destination_root).to have_structure {
54
54
  directory 'db' do
55
55
  directory 'migrate' do
56
56
  migration 'add_object_changes_to_versions' do
@@ -0,0 +1,19 @@
1
+ require 'rails_helper'
2
+
3
+ describe Fluxor, :type => :model do
4
+ describe '`be_versioned` matcher' do
5
+ it { is_expected.to_not be_versioned }
6
+ end
7
+
8
+ describe "Methods" do
9
+ describe "Class" do
10
+ subject { Fluxor }
11
+
12
+ describe "#paper_trail_enabled_for_model?" do
13
+ it { is_expected.to respond_to(:paper_trail_enabled_for_model?) }
14
+
15
+ it { expect(subject.paper_trail_enabled_for_model?).to be false }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,7 +1,7 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
2
 
3
- describe Gadget do
4
- it { should be_versioned }
3
+ describe Gadget, :type => :model do
4
+ it { is_expected.to be_versioned }
5
5
 
6
6
  let(:gadget) { Gadget.create!(:name => 'Wrench', :brand => 'Acme') }
7
7
 
@@ -22,16 +22,16 @@ describe Gadget do
22
22
  describe "Methods" do
23
23
  describe "Instance", :versioning => true do
24
24
  describe "private" do
25
- describe :changed_notably? do
25
+ describe '#changed_notably?' do
26
26
  subject { Gadget.new(:created_at => Time.now) }
27
27
 
28
28
  # apparently the private methods list in Ruby18 is different than in Ruby19+
29
29
  if RUBY_VERSION.to_f >= 1.9
30
- its(:private_methods) { should include(:changed_notably?) }
30
+ it { expect(subject.private_methods).to include(:changed_notably?) }
31
31
  end
32
32
 
33
33
  context "create events" do
34
- it { subject.send(:changed_notably?).should == true }
34
+ it { expect(subject.send(:changed_notably?)).to be true }
35
35
  end
36
36
 
37
37
  context "update events" do
@@ -40,24 +40,24 @@ describe Gadget do
40
40
  context "without update timestamps" do
41
41
  it "should only acknowledge non-ignored attrs" do
42
42
  subject.name = 'Wrench'
43
- subject.send(:changed_notably?).should == true
43
+ expect(subject.send(:changed_notably?)).to be true
44
44
  end
45
45
 
46
46
  it "should not acknowledge ignored attrs and timestamps only" do
47
47
  subject.brand = 'Acme'
48
- subject.send(:changed_notably?).should == false
48
+ expect(subject.send(:changed_notably?)).to be false
49
49
  end
50
50
  end
51
51
 
52
52
  context "with update timestamps" do
53
53
  it "should only acknowledge non-ignored attrs" do
54
54
  subject.name, subject.updated_at = 'Wrench', Time.now
55
- subject.send(:changed_notably?).should == true
55
+ expect(subject.send(:changed_notably?)).to be true
56
56
  end
57
57
 
58
58
  it "should not acknowledge ignored attrs and timestamps only" do
59
59
  subject.brand, subject.updated_at = 'Acme', Time.now
60
- subject.send(:changed_notably?).should == false
60
+ expect(subject.send(:changed_notably?)).to be false
61
61
  end
62
62
  end
63
63
  end
@@ -1,32 +1,32 @@
1
- require 'spec_helper'
1
+ require 'rails_helper'
2
2
 
3
- describe JoinedVersion, :versioning => true do
4
- it { JoinedVersion.superclass.should == PaperTrail::Version }
3
+ describe JoinedVersion, :type => :model, :versioning => true do
4
+ it { expect(JoinedVersion.superclass).to be PaperTrail::Version }
5
5
 
6
6
  let(:widget) { Widget.create!(:name => Faker::Name.name) }
7
7
  let(:version) { JoinedVersion.first }
8
8
 
9
9
  describe "Scopes" do
10
10
  describe "default_scope" do
11
- it { JoinedVersion.default_scopes.should_not be_empty }
11
+ it { expect(JoinedVersion.default_scopes).not_to be_empty }
12
12
  end
13
13
 
14
14
  describe "VersionConcern::ClassMethods" do
15
15
  before { widget } # persist a widget
16
16
 
17
- describe :subsequent do
17
+ describe '#subsequent' do
18
18
  it "shouldn't error out when there is a default_scope that joins" do
19
19
  JoinedVersion.subsequent(version).first
20
20
  end
21
21
  end
22
22
 
23
- describe :preceding do
23
+ describe '#preceding' do
24
24
  it "shouldn't error out when there is a default scope that joins" do
25
25
  JoinedVersion.preceding(version).first
26
26
  end
27
27
  end
28
28
 
29
- describe :between do
29
+ describe '#between' do
30
30
  it "shouldn't error out when there is a default scope that joins" do
31
31
  JoinedVersion.between(Time.now, 1.minute.from_now).first
32
32
  end
@@ -35,8 +35,8 @@ describe JoinedVersion, :versioning => true do
35
35
  end
36
36
 
37
37
  describe "Methods" do
38
- describe :index do
39
- it { should respond_to(:index) }
38
+ describe '#index' do
39
+ it { is_expected.to respond_to(:index) }
40
40
 
41
41
  it "shouldn't error out when there is a default scope that joins" do
42
42
  widget # persist a widget