draftsman 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54041224c0ef580764ae1570192ce7f81a93c44c
4
- data.tar.gz: de68aa15f34f6ec56b6b6cbd087bc2bce726cf73
3
+ metadata.gz: 8b81db1f80bb1d8742793931418a05f425f4574d
4
+ data.tar.gz: 40e32fd2383a15cc1e8e96552e63220faf0c4784
5
5
  SHA512:
6
- metadata.gz: 282c2be7d66bfef55acc7ac61f9c3109b9e9e36fee1329723067a695e98b591aa8bf531776af0578762329f9c158f5f4ca1430bb0c27ce192517eb909590afa1
7
- data.tar.gz: f28d6437916d060b4dbef7285bef2f60483585a8c8e354b1303f0062850add28b1f70dc6f6ca348c5d6872ed2996287709442c6e630e98cbe6bf77fe1cd4bec0
6
+ metadata.gz: 6b3e3e7a21e4078e32d66726366674d1bc0af4eb68fdb7aeec02d82dcb8d0c96f09be4366d3239dbee20b3363758507fbb608b5e5b2c3b04da510a0a003c4a2c
7
+ data.tar.gz: c97dd6e0a81c69d5c5d83ba034b8fceb6db7fee0fa54da1c8b62bc73ee5550c9812e74754910796172d338bdc0549e1cd1afa8708d696c74900136dfe0278bf9
data/.travis.yml CHANGED
@@ -4,9 +4,14 @@ cache: bundler
4
4
  sudo: false
5
5
 
6
6
  rvm:
7
- - 2.4.0-preview3
8
- - 2.3.1
9
- - 2.2.5
7
+ - 2.4.1
8
+ - 2.3.4
9
+ - 2.2.7
10
+
11
+ gemfile:
12
+ - gemfiles/ar_5_1.gemfile
13
+ - gemfiles/ar_5_0.gemfile
14
+ - gemfiles/ar_4_2.gemfile
10
15
 
11
16
  before_script:
12
17
  - bundle exec rake -f spec/dummy/Rakefile db:schema:load
data/CHANGELOG.md CHANGED
@@ -1,6 +1,37 @@
1
1
  # CHANGELOG
2
2
 
3
- ## 0.6.0 - November 16, 2015
3
+ ## 0.7.0 - June 12, 2017
4
+
5
+ ### Enhancements
6
+
7
+ - [@jmfederico](https://github.com/jmfederico)
8
+ [implemented](https://github.com/liveeditor/draftsman/commit/87f242374ad9fd97f7dba2e485d68da407c46fed)
9
+ [#67](https://github.com/liveeditor/draftsman/pull/67)
10
+ 5.1 compatibility
11
+ - [@chrisdpeters](https://github.com/chrisdpeters)
12
+ [implemented](https://github.com/liveeditor/draftsman/commit/e2c8e497899a453daf4c60d6ce02cacbf15a0f12)
13
+ Change Draft.object_col_is_json? to skip over itself if not stashing drafted changes
14
+ - [@npezza93](https://github.com/npezza93)
15
+ [implemented](https://github.com/liveeditor/draftsman/commit/936d5a37c044c5ca0a5699a553d9bc111f2d91d2)
16
+ [#58](https://github.com/liveeditor/draftsman/pull/58)
17
+ Only update attributes that get changed instead of all of them
18
+ - [@jmfederico](https://github.com/jmfederico)
19
+ [implemented](https://github.com/liveeditor/draftsman/commit/e8ba201db6bb88ea0ebc47c1262eb24e892e9a0b)
20
+ [#65](https://github.com/liveeditor/draftsman/pull/65)
21
+ Do not "touch" models when not updating the base table content
22
+
23
+ ### Bug Fixes
24
+
25
+ - [@jokius](https://github.com/jokius)
26
+ [fixed](https://github.com/liveeditor/draftsman/commit/5ca7d6717109d753959a5d56c0fe81c3cd7b75f1)
27
+ [#57](https://github.com/liveeditor/draftsman/pull/57)
28
+ Fix if self.changeset is nil
29
+ - [@jmfederico](https://github.com/jmfederico)
30
+ [fixed](https://github.com/liveeditor/draftsman/commit/207d158d054ed13ca6dc0a15ae2c499b0aac5f5f)
31
+ [#64](https://github.com/liveeditor/draftsman/pull/64)
32
+ Fix error when saving a draft when one already existed
33
+
34
+ ## 0.6.0 - November 16, 2016
4
35
 
5
36
  ### Enhancements
6
37
 
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Draftsman v0.6.0
1
+ # Draftsman v0.7.0
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/liveeditor/draftsman.svg?branch=master)](http://travis-ci.org/liveeditor/draftsman)
4
4
 
@@ -64,7 +64,7 @@ ActiveRecord.
64
64
  Add Draftsman to your `Gemfile`.
65
65
 
66
66
  ```ruby
67
- gem 'draftsman', '~> 0.6.0'
67
+ gem 'draftsman', '~> 0.7.0'
68
68
  ```
69
69
 
70
70
  Or if you want to grab the latest from `master`:
@@ -611,8 +611,8 @@ included, please do the following:
611
611
 
612
612
  2. Run `bundle install`.
613
613
 
614
- 3. `cd spec/dummy` and run `RAILS_ENV=test rake db:migrate` to apply test
615
- database migrations.
614
+ 3. Run `RAILS_ENV=test bundle exec rake -f spec/dummy/
615
+ Rakefile db:schema:load` to load test database schema.
616
616
 
617
617
  4. Add at least one test for your change. Only refactoring and documentation
618
618
  changes require no new tests. If you are adding functionality or fixing a
data/draftsman.gemspec CHANGED
@@ -16,10 +16,10 @@ Gem::Specification.new do |s|
16
16
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
17
  s.require_paths = ['lib']
18
18
 
19
- s.add_dependency 'activerecord', ['>= 3.0', '< 5.1']
19
+ s.add_dependency 'activerecord', ['>= 4.0', '< 5.2']
20
20
 
21
21
  s.add_development_dependency 'rake'
22
- s.add_development_dependency 'railties', ['>= 3.0', '< 5.1']
22
+ s.add_development_dependency 'railties', ['>= 4.0', '< 5.2']
23
23
  s.add_development_dependency 'sinatra', '~> 1.0'
24
24
  s.add_development_dependency 'rspec-rails', '~> 3.5'
25
25
 
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'activerecord', '~> 4.2.8'
6
+ gem 'railties', '~> 4.2.8'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'activerecord', '~> 5.0.0'
6
+ gem 'railties', '~> 5.0.0'
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'activerecord', '~> 5.1.0'
6
+ gem 'railties', '~> 5.1.0'
data/lib/draftsman.rb CHANGED
@@ -30,6 +30,11 @@ module Draftsman
30
30
  !!draftsman_store[:request_enabled_for_controller]
31
31
  end
32
32
 
33
+ # Returns whether or not ActiveRecord is configured to assume that `belongs_to` associations are required.
34
+ def self.active_record_belongs_to_required?
35
+ @active_record_belongs_to_required ||= ActiveRecord::VERSION::STRING.to_f >= 5.0
36
+ end
37
+
33
38
  # Returns whether or not ActiveRecord is configured to require mass assignment whitelisting via `attr_accessible`.
34
39
  def self.active_record_protected_attributes?
35
40
  @active_record_protected_attributes ||= ActiveRecord::VERSION::STRING.to_f < 4.0 || defined?(ProtectedAttributes)
@@ -20,7 +20,7 @@ class Draftsman::Draft < ActiveRecord::Base
20
20
  # Returns whether the `object` column is using the `json` type supported by
21
21
  # PostgreSQL.
22
22
  def self.object_col_is_json?
23
- @object_col_is_json ||= columns_hash['object'].type == :json
23
+ @object_col_is_json ||= Draftsman.stash_drafted_changes? && columns_hash['object'].type == :json
24
24
  end
25
25
 
26
26
  # Returns whether or not this class has an `object_changes` column.
@@ -175,23 +175,11 @@ class Draftsman::Draft < ActiveRecord::Base
175
175
  self.item.attributes = self.reify.attributes if Draftsman.stash_drafted_changes? && self.update?
176
176
 
177
177
  # Write `published_at` attribute
178
- self.item.send("#{self.item.class.published_at_attribute_name}=", Time.now)
178
+ self.item.send("#{self.item.class.published_at_attribute_name}=", current_time_from_proper_timezone)
179
179
 
180
180
  # Clear out draft
181
181
  self.item.send("#{self.item.class.draft_association_name}_id=", nil)
182
182
 
183
- # Determine which columns should be updated
184
- only = self.item.class.draftsman_options[:only]
185
- ignore = self.item.class.draftsman_options[:ignore]
186
- skip = self.item.class.draftsman_options[:skip]
187
- attributes_to_change = only.any? ? only : self.item.attribute_names
188
- attributes_to_change = attributes_to_change - ignore + ['published_at', "#{self.item.class.draft_association_name}_id"] - skip
189
-
190
- # Save without validations or callbacks
191
- self.item.attributes.slice(*attributes_to_change).each do |key, value|
192
- self.item.send("#{key}=", value)
193
- end
194
-
195
183
  self.item.save(validate: false)
196
184
  self.item.reload
197
185
 
@@ -223,7 +211,7 @@ class Draftsman::Draft < ActiveRecord::Base
223
211
  elsif self.previous_draft.present?
224
212
  reify_previous_draft.reify
225
213
  # Prefer changeset for refication if it's present.
226
- elsif !self.changeset.empty?
214
+ elsif self.changeset.present? && self.changeset.any?
227
215
  self.changeset.each do |key, value|
228
216
  # Skip counter_cache columns
229
217
  if self.item.respond_to?("#{key}=") && !key.end_with?('_count')
@@ -277,7 +265,7 @@ class Draftsman::Draft < ActiveRecord::Base
277
265
  end
278
266
  # Then clear out the draft ID.
279
267
  self.item.send("#{self.item.class.draft_association_name}_id=", nil)
280
- self.item.save!(validate: false)
268
+ self.item.save!(validate: false, touch: false)
281
269
  # Then destroy draft.
282
270
  self.destroy
283
271
  when :destroy
@@ -90,7 +90,11 @@ module Draftsman
90
90
  self.trashed_at_attribute_name = options[:trashed_at] || :trashed_at
91
91
 
92
92
  # `belongs_to :draft` association
93
- belongs_to(self.draft_association_name, class_name: self.draft_class_name, dependent: :destroy)
93
+ if ::Draftsman.active_record_belongs_to_required?
94
+ belongs_to(self.draft_association_name, class_name: self.draft_class_name, dependent: :destroy, optional: true)
95
+ else
96
+ belongs_to(self.draft_association_name, class_name: self.draft_class_name, dependent: :destroy)
97
+ end
94
98
 
95
99
  # Scopes
96
100
  scope :drafted, -> (referenced_table_name = nil) {
@@ -169,7 +173,7 @@ module Draftsman
169
173
  object ||= self
170
174
 
171
175
  attrs = object.attributes.except(*self.class.draftsman_options[:skip]).tap do |attributes|
172
- self.class.serialize_attributes_for_draftsman attributes
176
+ self.class.serialize_attributes_for_draftsman(attributes)
173
177
  end
174
178
 
175
179
  if self.class.draft_class.object_col_is_json?
@@ -326,17 +330,18 @@ module Draftsman
326
330
 
327
331
  data = merge_metadata_for_draft(data)
328
332
  send(self.class.draft_association_name).update(data)
329
- self.save
333
+ save
330
334
  else
331
335
  the_changes = changes_for_draftsman(:update)
332
336
  save_only_columns_for_draft if Draftsman.stash_drafted_changes?
333
337
 
334
- # Destroy the draft if this record has changed back to the original
335
- # record.
338
+ # Destroy the draft if this record has changed back to the
339
+ # original values.
336
340
  if self.draft? && the_changes.empty?
337
341
  nilified_draft = send(self.class.draft_association_name)
342
+ touch = changed?
338
343
  send("#{self.class.draft_association_name}_id=", nil)
339
- self.save
344
+ save(touch: touch)
340
345
  nilified_draft.destroy
341
346
  # Save an update draft if record is changed notably.
342
347
  elsif !the_changes.empty?
@@ -397,7 +402,7 @@ module Draftsman
397
402
  if event == :update
398
403
  # Collect all attributes' previous and new values.
399
404
  draftable_attrs.each do |attr|
400
- if self.draft? && self.draft.changeset.key?(attr)
405
+ if self.draft? && self.draft.changeset && self.draft.changeset.key?(attr)
401
406
  the_changes[attr] = [self.draft.changeset[attr].first, send(attr)]
402
407
  else
403
408
  the_changes[attr] = [self.send("#{attr}_was"), send(attr)]
@@ -443,7 +448,7 @@ module Draftsman
443
448
  only_changed_attributes = self.attributes.keys - self.class.draftsman_options[:only]
444
449
 
445
450
  only_changed_attributes.each do |key|
446
- only_changes[key] = send(key)
451
+ only_changes[key] = send(key) if changed.include?(key)
447
452
  end
448
453
 
449
454
  self.update_columns(only_changes) if only_changes.any?
@@ -469,7 +474,8 @@ module Draftsman
469
474
  # Updates skipped attributes' values on this model.
470
475
  def update_skipped_attributes
471
476
  # Skip over this if nothing's being skipped.
472
- return true unless draftsman_options[:skip].present?
477
+ skipped_changed = changed_attributes.keys & draftsman_options[:skip]
478
+ return true unless skipped_changed.present?
473
479
 
474
480
  keys = self.attributes.keys.select { |key| draftsman_options[:skip].include?(key) }
475
481
  attrs = {}
@@ -1,3 +1,3 @@
1
1
  module Draftsman
2
- VERSION = '0.6.0'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -1,45 +1,63 @@
1
1
  require 'spec_helper'
2
+ require 'support/feature_detection'
2
3
 
3
4
  # Tests controller `info_for_draftsman` method
4
5
  describe InformantsController, type: :controller do
5
6
  let(:trashable) { Trashable.create!(name: 'Bob') }
6
7
 
7
8
  describe 'create' do
8
- before { post :create }
9
- subject { Draftsman::Draft.last }
10
-
11
9
  it 'records `ip` from custom `info_for_draftsman`' do
12
- expect(subject.ip).to eql '123.45.67.89'
10
+ post :create
11
+ expect(Draftsman::Draft.last.ip).to eql '123.45.67.89'
13
12
  end
14
13
 
15
14
  it 'records `user_agent` from custom `info_for_draftsman`' do
16
- expect(subject.user_agent).to eql '007'
15
+ post :create
16
+ expect(Draftsman::Draft.last.user_agent).to eql '007'
17
17
  end
18
18
  end
19
19
 
20
20
  describe 'update' do
21
- before { put :update, id: trashable.id }
22
- subject { Draftsman::Draft.last }
23
-
24
21
  it 'records `ip` from custom `info_for_draftsman`' do
25
- expect(subject.ip).to eql '123.45.67.89'
22
+ if request_test_helpers_require_keyword_args?
23
+ put :update, params: { id: trashable.id }
24
+ else
25
+ put :update, id: trashable.id
26
+ end
27
+
28
+ expect(Draftsman::Draft.last.ip).to eql '123.45.67.89'
26
29
  end
27
30
 
28
31
  it 'records `user_agent` from custom `info_for_draftsman`' do
29
- expect(subject.user_agent).to eql '007'
32
+ if request_test_helpers_require_keyword_args?
33
+ put :update, params: { id: trashable.id }
34
+ else
35
+ put :update, id: trashable.id
36
+ end
37
+
38
+ expect(Draftsman::Draft.last.user_agent).to eql '007'
30
39
  end
31
40
  end
32
41
 
33
42
  describe 'destroy' do
34
- before { delete :destroy, id: trashable.id }
35
- subject { Draftsman::Draft.last }
36
-
37
43
  it 'records `ip` from custom `info_for_draftsman`' do
38
- expect(subject.ip).to eql '123.45.67.89'
44
+ if request_test_helpers_require_keyword_args?
45
+ delete :destroy, params: { id: trashable.id }
46
+ else
47
+ delete :destroy, id: trashable.id
48
+ end
49
+
50
+ expect(Draftsman::Draft.last.ip).to eql '123.45.67.89'
39
51
  end
40
52
 
41
53
  it 'records `user_agent` from custom `info_for_draftsman`' do
42
- expect(subject.user_agent).to eql '007'
54
+ if request_test_helpers_require_keyword_args?
55
+ delete :destroy, params: { id: trashable.id }
56
+ else
57
+ delete :destroy, id: trashable.id
58
+ end
59
+
60
+ expect(Draftsman::Draft.last.user_agent).to eql '007'
43
61
  end
44
62
  end
45
63
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'support/feature_detection'
2
3
 
3
4
  describe UsersController, type: :controller do
4
5
  let(:trashable) { Trashable.create!(name: 'Bob') }
@@ -13,20 +14,26 @@ describe UsersController, type: :controller do
13
14
  end
14
15
 
15
16
  describe 'update' do
16
- before { put :update, id: trashable.id }
17
- subject { return Draftsman::Draft.last }
18
-
19
17
  it 'records user name via `user_for_draftsman`' do
20
- expect(subject.whodunnit).to eql 'A User'
18
+ if request_test_helpers_require_keyword_args?
19
+ put :update, params: { id: trashable.id }
20
+ else
21
+ put :update, id: trashable.id
22
+ end
23
+
24
+ expect(Draftsman::Draft.last.whodunnit).to eql 'A User'
21
25
  end
22
26
  end
23
27
 
24
28
  describe 'destroy' do
25
- before { delete :destroy, id: trashable.id }
26
- subject { return Draftsman::Draft.last }
27
-
28
29
  it 'records user name via `user_for_draftsman`' do
29
- expect(subject.whodunnit).to eql 'A User'
30
+ if request_test_helpers_require_keyword_args?
31
+ delete :destroy, params: { id: trashable.id }
32
+ else
33
+ delete :destroy, id: trashable.id
34
+ end
35
+
36
+ expect(Draftsman::Draft.last.whodunnit).to eql 'A User'
30
37
  end
31
38
  end
32
39
  end
@@ -1,33 +1,38 @@
1
1
  require 'spec_helper'
2
+ require 'support/feature_detection'
2
3
 
3
4
  # Tests the automatic usage of `current_user` as the `whodunnit` attribute on the draft object
4
5
  describe WhodunnitsController, type: :controller do
5
6
  let(:trashable) { Trashable.create!(name: 'Bob') }
6
7
 
7
8
  describe 'create' do
8
- before { post :create }
9
- subject { Draftsman::Draft.last }
10
-
11
9
  it 'records `current_user` via `user_for_draftsman' do
12
- expect(subject.whodunnit).to eql '153'
10
+ post :create
11
+ expect(Draftsman::Draft.last.whodunnit).to eql '153'
13
12
  end
14
13
  end
15
14
 
16
15
  describe 'update' do
17
- before { put :update, id: trashable.id }
18
- subject { Draftsman::Draft.last }
19
-
20
16
  it 'records `current_user` via `user_for_draftsman' do
21
- expect(subject.whodunnit).to eql '153'
17
+ if request_test_helpers_require_keyword_args?
18
+ put :update, params: { id: trashable.id }
19
+ else
20
+ put :update, id: trashable.id
21
+ end
22
+
23
+ expect(Draftsman::Draft.last.whodunnit).to eql '153'
22
24
  end
23
25
  end
24
26
 
25
27
  describe 'destroy' do
26
- before { delete :destroy, id: trashable.id }
27
- subject { Draftsman::Draft.last }
28
-
29
28
  it 'records `current_user` via `user_for_draftsman' do
30
- expect(subject.whodunnit).to eql '153'
29
+ if request_test_helpers_require_keyword_args?
30
+ delete :destroy, params: { id: trashable.id }
31
+ else
32
+ delete :destroy, id: trashable.id
33
+ end
34
+
35
+ expect(Draftsman::Draft.last.whodunnit).to eql '153'
31
36
  end
32
37
  end
33
38
  end
@@ -4,7 +4,7 @@ RSpec.describe Child, type: :model do
4
4
  let(:parent) { Parent.new(name: 'Marge') }
5
5
  let(:child) { Child.new(name: 'Lisa', parent: parent) }
6
6
 
7
- describe 'publish!' do
7
+ describe '#publish!' do
8
8
  context 'parent `create` draft with child `create` draft' do
9
9
  before do
10
10
  parent.save_draft
@@ -74,7 +74,7 @@ RSpec.describe Child, type: :model do
74
74
  end
75
75
  end
76
76
 
77
- describe 'revert!' do
77
+ describe '#revert!' do
78
78
  context 'parent `create` draft with child `create` draft' do
79
79
  before do
80
80
  parent.save_draft
@@ -150,7 +150,7 @@ RSpec.describe Child, type: :model do
150
150
  end
151
151
  end
152
152
 
153
- describe 'draft_publication_dependencies' do
153
+ describe '#draft_publication_dependencies' do
154
154
  context 'parent `create` draft with child `create` draft' do
155
155
  before do
156
156
  parent.save_draft
@@ -228,7 +228,7 @@ RSpec.describe Child, type: :model do
228
228
  end
229
229
  end
230
230
 
231
- describe 'draft_reversion_dependencies' do
231
+ describe '#draft_reversion_dependencies' do
232
232
  context 'parent `create` draft with child `create` draft' do
233
233
  before do
234
234
  parent.save_draft
@@ -1,10 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Skipper, type: :model do
4
- let(:skipper) { Skipper.new :name => 'Bob', :skip_me => 'Skipped 1' }
4
+ let(:skipper) { Skipper.new(name: 'Bob', skip_me: 'Skipped 1') }
5
5
 
6
- it 'is draftable' do
7
- expect(subject.class.draftable?).to eql true
6
+ describe '.draftable?' do
7
+ it 'is `true`' do
8
+ expect(subject.class.draftable?).to eql true
9
+ end
10
+ end
11
+
12
+ describe '#object_attrs_for_draft_record' do
13
+ it 'contains changed but not skipped column name' do
14
+ expect(skipper.object_attrs_for_draft_record).to include 'name'
15
+ end
16
+
17
+ it 'does not contain the skipped column name' do
18
+ expect(skipper.object_attrs_for_draft_record).to_not include 'skip_me'
19
+ end
8
20
  end
9
21
 
10
22
  describe '#save_draft' do
@@ -41,6 +53,11 @@ RSpec.describe Skipper, type: :model do
41
53
  it 'has a value for `skip_me`' do
42
54
  expect(subject.skip_me).to eql 'Skipped 1'
43
55
  end
56
+
57
+ it 'sets `updated_at`' do
58
+ time = Time.now
59
+ expect(subject.updated_at).to be > time
60
+ end
44
61
  end
45
62
 
46
63
  context 'on update' do
@@ -87,6 +104,11 @@ RSpec.describe Skipper, type: :model do
87
104
  it 'creates a new draft' do
88
105
  expect { subject }.to change(Draftsman::Draft, :count).by(1)
89
106
  end
107
+
108
+ it 'has a newer `updated_at`' do
109
+ time = skipper.updated_at
110
+ expect(subject.updated_at).to be > time
111
+ end
90
112
  end
91
113
 
92
114
  describe 'changing back to initial state' do
@@ -123,10 +145,18 @@ RSpec.describe Skipper, type: :model do
123
145
  it 'destroys the draft' do
124
146
  expect { subject }.to change(Draftsman::Draft.where(:id => skipper.draft_id), :count).by(-1)
125
147
  end
148
+
149
+ it 'has a newer `updated_at`' do
150
+ time = skipper.updated_at
151
+ expect(subject.updated_at).to be > time
152
+ end
126
153
  end
127
154
 
128
155
  context 'with existing `create` draft' do
129
- before { skipper.save_draft }
156
+ before do
157
+ skipper.save_draft
158
+ skipper.reload
159
+ end
130
160
 
131
161
  context 'with changes' do
132
162
  before do
@@ -169,6 +199,33 @@ RSpec.describe Skipper, type: :model do
169
199
  it "updates the draft's `name`" do
170
200
  expect(subject.draft.reify.name).to eql 'Sam'
171
201
  end
202
+
203
+ it 'has a newer `updated_at`' do
204
+ time = skipper.updated_at
205
+ expect(subject.updated_at).to be > time
206
+ end
207
+ end
208
+
209
+ context 'with changes to drafted attribute' do
210
+ before do
211
+ skipper.name = 'Sam'
212
+ end
213
+
214
+ it 'has a newer `updated_at`' do
215
+ time = skipper.updated_at
216
+ expect(subject.updated_at).to be > time
217
+ end
218
+ end
219
+
220
+ context 'with changes to skipped attribute' do
221
+ before do
222
+ skipper.skip_me = 'Skipped 2'
223
+ end
224
+
225
+ it 'has a newer `updated_at`' do
226
+ time = skipper.updated_at
227
+ expect(subject.updated_at).to be > time
228
+ end
172
229
  end
173
230
 
174
231
  context 'with no changes' do
@@ -203,6 +260,11 @@ RSpec.describe Skipper, type: :model do
203
260
  it "doesn't change the number of drafts" do
204
261
  expect { subject }.to_not change(Draftsman::Draft.where(:id => skipper.draft_id), :count)
205
262
  end
263
+
264
+ it 'has the original `updated_at`' do
265
+ time = skipper.updated_at
266
+ expect(subject.updated_at).to eq time
267
+ end
206
268
  end
207
269
  end
208
270
 
@@ -254,14 +316,16 @@ RSpec.describe Skipper, type: :model do
254
316
  it "updates the draft's `name`" do
255
317
  expect(subject.draft.reify.name).to eql 'Steve'
256
318
  end
319
+
320
+ it 'has the original `updated_at`' do
321
+ time = skipper.updated_at
322
+ expect(subject.updated_at).to eq time
323
+ end
257
324
  end
258
325
 
259
326
  context 'with changes to skipped attributes' do
260
327
  before do
261
328
  skipper.skip_me = 'Skip and save'
262
- skipper.save_draft
263
- skipper.reload
264
- skipper.attributes = skipper.draft.reify.attributes
265
329
  end
266
330
 
267
331
  it 'is persisted' do
@@ -303,6 +367,11 @@ RSpec.describe Skipper, type: :model do
303
367
  it 'updates skipped attribute on draft' do
304
368
  expect(subject.draft.reify.skip_me).to eql 'Skip and save'
305
369
  end
370
+
371
+ it 'has a newer `updated_at`' do
372
+ time = skipper.updated_at
373
+ expect(subject.updated_at).to be > time
374
+ end
306
375
  end
307
376
 
308
377
  context 'with no changes' do
@@ -341,6 +410,11 @@ RSpec.describe Skipper, type: :model do
341
410
  it "does not update the draft's `name`" do
342
411
  expect(subject.draft.reify.name).to eql 'Sam'
343
412
  end
413
+
414
+ it 'has the original `updated_at`' do
415
+ time = skipper.updated_at
416
+ expect(subject.updated_at).to eq time
417
+ end
344
418
  end
345
419
  end
346
420
  end
@@ -5,6 +5,20 @@ describe Vanilla do
5
5
  let(:vanilla) { Vanilla.new(name: 'Bob') }
6
6
  it { should be_draftable }
7
7
 
8
+ describe '#object_attrs_for_draft_record' do
9
+ it 'contains column name' do
10
+ expect(vanilla.object_attrs_for_draft_record).to include 'name'
11
+ end
12
+
13
+ it 'contains column updated_at' do
14
+ expect(vanilla.object_attrs_for_draft_record).to include 'updated_at'
15
+ end
16
+
17
+ it 'contains column created_at' do
18
+ expect(vanilla.object_attrs_for_draft_record).to include 'created_at'
19
+ end
20
+ end
21
+
8
22
  describe '#save_draft' do
9
23
  context 'on create' do
10
24
  it 'is persisted' do
@@ -36,6 +50,18 @@ describe Vanilla do
36
50
  vanilla.save_draft
37
51
  expect(vanilla.name).to eql 'Bob'
38
52
  end
53
+
54
+ it 'sets `updated_at`' do
55
+ time = Time.now
56
+ vanilla.save_draft
57
+ expect(vanilla.updated_at).to be > time
58
+ end
59
+
60
+ it 'sets `created_at`' do
61
+ time = Time.now
62
+ vanilla.save_draft
63
+ expect(vanilla.created_at).to be > time
64
+ end
39
65
  end
40
66
 
41
67
  context 'on update' do
@@ -84,6 +110,12 @@ describe Vanilla do
84
110
  it 'creates a new draft' do
85
111
  expect { vanilla.save_draft }.to change(Draftsman::Draft, :count).by(1)
86
112
  end
113
+
114
+ it 'has the original `updated_at`' do
115
+ vanilla.save_draft
116
+ vanilla.reload
117
+ expect(vanilla.updated_at).to eq vanilla.created_at
118
+ end
87
119
  end
88
120
 
89
121
  describe 'changing back to initial state' do
@@ -123,6 +155,14 @@ describe Vanilla do
123
155
  it 'destroys the draft' do
124
156
  expect { vanilla.save_draft }.to change(Draftsman::Draft.where(id: vanilla.draft_id), :count).by(-1)
125
157
  end
158
+
159
+ it 'has the original `updated_at`' do
160
+ if activerecord_save_touch_option?
161
+ vanilla.save_draft
162
+ vanilla.reload
163
+ expect(vanilla.updated_at).to eq vanilla.created_at
164
+ end
165
+ end
126
166
  end
127
167
 
128
168
  context 'with existing `create` draft' do
@@ -176,6 +216,13 @@ describe Vanilla do
176
216
  vanilla.reload
177
217
  expect(vanilla.draft.create?).to eql true
178
218
  end
219
+
220
+ it 'has a new `updated_at`' do
221
+ time = vanilla.updated_at
222
+ vanilla.save_draft
223
+ vanilla.reload
224
+ expect(vanilla.updated_at).to be > time
225
+ end
179
226
  end # with changes
180
227
 
181
228
  context 'with no changes' do
@@ -217,6 +264,12 @@ describe Vanilla do
217
264
  it "doesn't change the number of drafts" do
218
265
  expect { vanilla.save_draft }.to_not change(Draftsman::Draft.where(id: vanilla.draft_id), :count)
219
266
  end
267
+
268
+ it 'has the original `updated_at`' do
269
+ vanilla.save_draft
270
+ vanilla.reload
271
+ expect(vanilla.updated_at).to eq vanilla.created_at
272
+ end
220
273
  end
221
274
  end # with no changes
222
275
 
@@ -275,6 +328,12 @@ describe Vanilla do
275
328
  vanilla.save_draft
276
329
  expect(vanilla.draft.update?).to eql true
277
330
  end
331
+
332
+ it 'has the original `updated_at`' do
333
+ vanilla.save_draft
334
+ vanilla.reload
335
+ expect(vanilla.updated_at).to eq vanilla.created_at
336
+ end
278
337
  end # with changes
279
338
 
280
339
  context 'with no changes' do
@@ -322,6 +381,12 @@ describe Vanilla do
322
381
  vanilla.reload
323
382
  expect(vanilla.draft.reify.name).to eql 'Sam'
324
383
  end
384
+
385
+ it 'has the original `updated_at`' do
386
+ vanilla.save_draft
387
+ vanilla.reload
388
+ expect(vanilla.updated_at).to eq vanilla.created_at
389
+ end
325
390
  end # with no changes
326
391
  end # with existing `update` draft
327
392
  end # with stashed drafted changes
@@ -374,6 +439,13 @@ describe Vanilla do
374
439
  it 'creates a new draft' do
375
440
  expect { vanilla.save_draft }.to change(Draftsman::Draft, :count).by(1)
376
441
  end
442
+
443
+ it 'has a new `updated_at`' do
444
+ time = vanilla.updated_at
445
+ vanilla.save_draft
446
+ vanilla.reload
447
+ expect(vanilla.updated_at).to be > time
448
+ end
377
449
  end
378
450
 
379
451
  describe 'changing back to initial state' do
@@ -413,6 +485,13 @@ describe Vanilla do
413
485
  it 'destroys the draft' do
414
486
  expect { vanilla.save_draft }.to change(Draftsman::Draft.where(id: vanilla.draft_id), :count).by(-1)
415
487
  end
488
+
489
+ it 'has a new `updated_at`' do
490
+ time = vanilla.updated_at
491
+ vanilla.save_draft
492
+ vanilla.reload
493
+ expect(vanilla.updated_at).to be > time
494
+ end
416
495
  end
417
496
 
418
497
  context 'with existing `create` draft' do
@@ -459,6 +538,13 @@ describe Vanilla do
459
538
  vanilla.save_draft
460
539
  expect(vanilla.draft.create?).to eql true
461
540
  end
541
+
542
+ it 'has a new `updated_at`' do
543
+ time = vanilla.updated_at
544
+ vanilla.save_draft
545
+ vanilla.reload
546
+ expect(vanilla.updated_at).to be > time
547
+ end
462
548
  end
463
549
 
464
550
  context 'with no changes' do
@@ -494,6 +580,11 @@ describe Vanilla do
494
580
  it "doesn't change the number of drafts" do
495
581
  expect { vanilla.save_draft }.to_not change(Draftsman::Draft.where(id: vanilla.draft_id), :count)
496
582
  end
583
+
584
+ it 'has the original `updated_at`' do
585
+ vanilla.save_draft
586
+ expect(vanilla.reload.updated_at).to eq vanilla.created_at
587
+ end
497
588
  end
498
589
  end
499
590
 
@@ -553,6 +644,13 @@ describe Vanilla do
553
644
  vanilla.reload
554
645
  expect(vanilla.draft.update?).to eql true
555
646
  end
647
+
648
+ it 'has a new `updated_at`' do
649
+ time = vanilla.updated_at
650
+ vanilla.save_draft
651
+ vanilla.reload
652
+ expect(vanilla.updated_at).to be > time
653
+ end
556
654
  end # with changes
557
655
 
558
656
  context 'with no changes' do
@@ -594,6 +692,13 @@ describe Vanilla do
594
692
  vanilla.save_draft
595
693
  expect(vanilla.draft.reify.name).to eql 'Sam'
596
694
  end
695
+
696
+ it 'does not update `updated_at`' do
697
+ time = vanilla.updated_at
698
+ vanilla.save_draft
699
+ vanilla.reload
700
+ expect(vanilla.updated_at).to eq time
701
+ end
597
702
  end # with no changes
598
703
  end # with existing `update` draft
599
704
  end # without stashed drafted changes
@@ -4,6 +4,18 @@ describe Whitelister do
4
4
  let(:whitelister) { Whitelister.new(name: 'Bob') }
5
5
  it { should be_draftable }
6
6
 
7
+ describe '#object_attrs_for_draft_record' do
8
+ before { whitelister.ignored = 'Meh.' }
9
+
10
+ it 'contains included column name' do
11
+ expect(whitelister.object_attrs_for_draft_record).to include 'name'
12
+ end
13
+
14
+ it 'does not include non-included column name' do
15
+ expect(whitelister.object_attrs_for_draft_record).to include 'name'
16
+ end
17
+ end
18
+
7
19
  describe '#save_draft' do
8
20
  # Not affected by this customization.
9
21
  context 'on create' do
data/spec/spec_helper.rb CHANGED
@@ -40,8 +40,3 @@ RSpec.configure do |config|
40
40
 
41
41
  config.mock_with :rspec
42
42
  end
43
-
44
- #require 'rails/railtie'
45
- #require 'active_record'
46
- #
47
- #require 'draftsman'
@@ -0,0 +1,11 @@
1
+ # Returns whether or not Rails test helpers recommend or require keyword
2
+ # arguments for controller/request helpers.
3
+ def request_test_helpers_require_keyword_args?
4
+ ActiveRecord::VERSION::STRING.to_f >= 5.0
5
+ end
6
+
7
+ # Returns whether or not the current version of ActiveRecord supports the
8
+ # `touch` option for `#save`.
9
+ def activerecord_save_touch_option?
10
+ ActiveRecord::VERSION::STRING.to_f >= 5.0
11
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: draftsman
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Peters
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-17 00:00:00.000000000 Z
11
+ date: 2017-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '4.0'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '5.1'
22
+ version: '5.2'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '3.0'
29
+ version: '4.0'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '5.1'
32
+ version: '5.2'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rake
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -50,20 +50,20 @@ dependencies:
50
50
  requirements:
51
51
  - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: '3.0'
53
+ version: '4.0'
54
54
  - - "<"
55
55
  - !ruby/object:Gem::Version
56
- version: '5.1'
56
+ version: '5.2'
57
57
  type: :development
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
60
60
  requirements:
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: '3.0'
63
+ version: '4.0'
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
- version: '5.1'
66
+ version: '5.2'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: sinatra
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +122,9 @@ files:
122
122
  - README.md
123
123
  - Rakefile
124
124
  - draftsman.gemspec
125
+ - gemfiles/ar_4_2.gemfile
126
+ - gemfiles/ar_5_0.gemfile
127
+ - gemfiles/ar_5_1.gemfile
125
128
  - lib/draftsman.rb
126
129
  - lib/draftsman/attributes_serialization.rb
127
130
  - lib/draftsman/config.rb
@@ -204,6 +207,7 @@ files:
204
207
  - spec/models/vanilla_spec.rb
205
208
  - spec/models/whitelister_spec.rb
206
209
  - spec/spec_helper.rb
210
+ - spec/support/feature_detection.rb
207
211
  homepage: https://github.com/liveeditor/draftsman
208
212
  licenses:
209
213
  - MIT
@@ -224,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
228
  version: '0'
225
229
  requirements: []
226
230
  rubyforge_project:
227
- rubygems_version: 2.5.1
231
+ rubygems_version: 2.6.11
228
232
  signing_key:
229
233
  specification_version: 4
230
234
  summary: Create draft versions of your database records.
@@ -293,3 +297,4 @@ test_files:
293
297
  - spec/models/vanilla_spec.rb
294
298
  - spec/models/whitelister_spec.rb
295
299
  - spec/spec_helper.rb
300
+ - spec/support/feature_detection.rb