draftsman 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +13 -2
- data/lib/draftsman/model.rb +22 -14
- data/lib/draftsman/version.rb +1 -1
- data/spec/dummy/app/models/skipper.rb +3 -0
- data/spec/dummy/app/models/whitelister.rb +1 -1
- data/spec/dummy/db/migrate/20110208155312_set_up_test_tables.rb +9 -0
- data/spec/dummy/db/schema.rb +39 -0
- data/spec/models/skipper_spec.rb +167 -0
- data/spec/models/vanilla_spec.rb +2 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c75a20681563bfa82fba2f109838a5fb2688d043
|
4
|
+
data.tar.gz: 7f43cc039a9d07048fbdfc04cfd9f8c5ff764ce1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 032096c7295407be9a2ba40e8ccd51e5e595279fef880d0011145867c32ccf3df60e5a47282afeacc7a5b5022745cf0531d96b03cb34a43931577cdcbeabad85
|
7
|
+
data.tar.gz: 6eb88502e4c4f176cb85660614597eea419425d14a35ff2390ae0f6b9a71718fd7d84adce866f82ab904f605c9c82cd967881d2a037ac932a43376bef539544f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.3.1 - August 14, 2014
|
4
|
+
|
5
|
+
- Commit [aae737fcdf](https://github.com/live-editor/draftsman/commit/aae737fcdf48604bc480b1c9c141bf642c0f581c) - `skip` option not persisting skipped values correctly
|
6
|
+
|
3
7
|
## 0.3.0 - July 29, 2014
|
4
8
|
|
5
9
|
- Commit [1e2a59f678](https://github.com/live-editor/draftsman/commit/1e2a59f678cc4d88222dfc1976d564b5649cd329) - Add support for PostgreSQL JSON data type for `object`, `object_changes`, and `previous_draft` columns.
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Draftsman v0.3.
|
1
|
+
# Draftsman v0.3.1 (alpha)
|
2
2
|
|
3
3
|
Draftsman is a Ruby gem that lets you create draft versions of your database records. If you're developing a system in
|
4
4
|
need of simple drafts or a publishing approval queue, then Draftsman just might be what you need.
|
@@ -50,7 +50,7 @@ Works well with Rails, Sinatra, or any other application that depends on ActiveR
|
|
50
50
|
Add Draftsman to your `Gemfile`.
|
51
51
|
|
52
52
|
```ruby
|
53
|
-
gem 'draftsman', '0.3.
|
53
|
+
gem 'draftsman', '0.3.1'
|
54
54
|
```
|
55
55
|
|
56
56
|
Or if you want to grab the latest from `master`:
|
@@ -474,6 +474,16 @@ However, there are some differences:
|
|
474
474
|
as it was _before_ it was destroyed (in case you want the option of reverting the destroy later and restoring the
|
475
475
|
drafted item back to its original state).
|
476
476
|
|
477
|
+
## Semantic Versioning
|
478
|
+
|
479
|
+
Like many Ruby gems, Draftsman honors the concepts behind [semantic versioning][10]:
|
480
|
+
|
481
|
+
> Given a version number MAJOR.MINOR.PATCH, increment the:
|
482
|
+
>
|
483
|
+
> 1. MAJOR version when you make incompatible API changes,
|
484
|
+
> 2. MINOR version when you add functionality in a backwards-compatible manner, and
|
485
|
+
> 3. PATCH version when you make backwards-compatible bug fixes.
|
486
|
+
|
477
487
|
## Contributing
|
478
488
|
|
479
489
|
If you feel like you can add something useful to Draftsman, then don't hesitate to contribute! To make sure your
|
@@ -521,3 +531,4 @@ Draftsman is released under the [MIT License][9].
|
|
521
531
|
[7]: https://raw.github.com/live-editor/draftsman/master/lib/generators/draftsman/templates/create_drafts.rb
|
522
532
|
[8]: http://www.sinatrarb.com/intro.html#Modular%20vs.%20Classic%20Style
|
523
533
|
[9]: http://www.opensource.org/licenses/MIT
|
534
|
+
[10]: http://semver.org/
|
data/lib/draftsman/model.rb
CHANGED
@@ -191,11 +191,6 @@ module Draftsman
|
|
191
191
|
send(self.class.draft_association_name).present?
|
192
192
|
end
|
193
193
|
|
194
|
-
def draft_at(timestamp, reify_options = {})
|
195
|
-
v = send(self.class.versions_association_name).following(timestamp).first
|
196
|
-
v ? v.reify(reify_options) : self
|
197
|
-
end
|
198
|
-
|
199
194
|
# Creates object and records a draft for the object's creation. Returns `true` or `false` depending on whether or not
|
200
195
|
# the objects passed validation and the save was successful.
|
201
196
|
def draft_creation
|
@@ -292,14 +287,12 @@ module Draftsman
|
|
292
287
|
|
293
288
|
data = merge_metadata_for_draft(data)
|
294
289
|
send(self.class.draft_association_name).update_attributes data
|
295
|
-
|
296
290
|
self.save
|
297
291
|
# Destroy the draft if this record has changed back to the original record
|
298
292
|
elsif changed_to_original_for_draft?
|
299
293
|
send(self.class.draft_association_name).destroy
|
300
294
|
send "#{self.class.draft_association_name}_id=", nil
|
301
|
-
self.
|
302
|
-
true
|
295
|
+
self.save
|
303
296
|
# Save a draft if record is changed notably
|
304
297
|
elsif changed_notably_for_draft?
|
305
298
|
data = {
|
@@ -309,24 +302,24 @@ module Draftsman
|
|
309
302
|
}
|
310
303
|
data = merge_metadata_for_draft(data)
|
311
304
|
|
312
|
-
# If there's already a draft, update it
|
305
|
+
# If there's already a draft, update it.
|
313
306
|
if send(self.class.draft_association_name).present?
|
314
307
|
data[:object_changes] = changes_for_draftsman if track_object_changes_for_draft?
|
315
308
|
send(self.class.draft_association_name).update_attributes data
|
316
|
-
# If there's not draft, create an update draft
|
309
|
+
# If there's not draft, create an update draft.
|
317
310
|
else
|
318
311
|
data[:event] = 'update'
|
319
312
|
data[:object_changes] = changes_for_draftsman if track_object_changes_for_draft?
|
320
313
|
send "build_#{self.class.draft_association_name}", data
|
321
314
|
|
322
315
|
if send(self.class.draft_association_name).save
|
323
|
-
|
324
|
-
|
316
|
+
update_column "#{self.class.draft_association_name}_id", send(self.class.draft_association_name).id
|
317
|
+
update_skipped_attributes
|
325
318
|
else
|
326
319
|
raise ActiveRecord::Rollback and return false
|
327
320
|
end
|
328
321
|
end
|
329
|
-
# If record is a draft and not changed notably, then update the draft
|
322
|
+
# If record is a draft and not changed notably, then update the draft.
|
330
323
|
elsif self.draft?
|
331
324
|
data = {
|
332
325
|
:item => self,
|
@@ -335,8 +328,8 @@ module Draftsman
|
|
335
328
|
}
|
336
329
|
data[:object_changes] = changes_for_draftsman(changed_from: @object.draft.changeset) if track_object_changes_for_draft?
|
337
330
|
data = merge_metadata_for_draft(data)
|
338
|
-
|
339
331
|
send(self.class.draft_association_name).update_attributes data
|
332
|
+
update_skipped_attributes
|
340
333
|
# Otherwise, just save the record
|
341
334
|
else
|
342
335
|
self.save
|
@@ -469,6 +462,21 @@ module Draftsman
|
|
469
462
|
write_attribute self.class.trashed_at_attribute_name, Time.now
|
470
463
|
self.update_column self.class.trashed_at_attribute_name, send(self.class.trashed_at_attribute_name)
|
471
464
|
end
|
465
|
+
|
466
|
+
# Updates skipped attributes' values on this model.
|
467
|
+
def update_skipped_attributes
|
468
|
+
if draftsman_options[:skip].present?
|
469
|
+
changed_and_skipped_keys = self.changed.select { |key| draftsman_options[:skip].include?(key) }
|
470
|
+
changed_and_skipped_attrs = {}
|
471
|
+
changed_and_skipped_keys.each { |key| changed_and_skipped_attrs[key] = self.changes[key].last }
|
472
|
+
|
473
|
+
self.reload
|
474
|
+
self.attributes = changed_and_skipped_attrs
|
475
|
+
self.save
|
476
|
+
else
|
477
|
+
true
|
478
|
+
end
|
479
|
+
end
|
472
480
|
end
|
473
481
|
end
|
474
482
|
end
|
data/lib/draftsman/version.rb
CHANGED
@@ -71,6 +71,15 @@ class SetUpTestTables < ActiveRecord::Migration
|
|
71
71
|
t.references :parent
|
72
72
|
t.timestamps
|
73
73
|
end
|
74
|
+
|
75
|
+
create_table :skippers, :force => true do |t|
|
76
|
+
t.string :name
|
77
|
+
t.string :skip_me
|
78
|
+
t.references :draft
|
79
|
+
t.datetime :trashed_at
|
80
|
+
t.datetime :published_at
|
81
|
+
t.timestamps
|
82
|
+
end
|
74
83
|
end
|
75
84
|
|
76
85
|
def self.down
|
data/spec/dummy/db/schema.rb
CHANGED
@@ -34,6 +34,15 @@ ActiveRecord::Schema.define(version: 20110208155312) do
|
|
34
34
|
t.datetime "updated_at"
|
35
35
|
end
|
36
36
|
|
37
|
+
create_table "clingy_parents", force: true do |t|
|
38
|
+
t.string "name"
|
39
|
+
t.integer "draft_id"
|
40
|
+
t.datetime "trashed_at"
|
41
|
+
t.datetime "published_at"
|
42
|
+
t.datetime "created_at"
|
43
|
+
t.datetime "updated_at"
|
44
|
+
end
|
45
|
+
|
37
46
|
create_table "draft_as_sketches", force: true do |t|
|
38
47
|
t.string "name"
|
39
48
|
t.integer "sketch_id"
|
@@ -67,6 +76,26 @@ ActiveRecord::Schema.define(version: 20110208155312) do
|
|
67
76
|
t.string "user_agent"
|
68
77
|
end
|
69
78
|
|
79
|
+
create_table "hopeless_children", force: true do |t|
|
80
|
+
t.string "name"
|
81
|
+
t.integer "clingy_parent_id"
|
82
|
+
t.integer "draft_id"
|
83
|
+
t.datetime "trashed_at"
|
84
|
+
t.datetime "published_at"
|
85
|
+
t.datetime "created_at"
|
86
|
+
t.datetime "updated_at"
|
87
|
+
end
|
88
|
+
|
89
|
+
create_table "mortgages", force: true do |t|
|
90
|
+
t.float "amount"
|
91
|
+
t.integer "parent_id"
|
92
|
+
t.integer "draft_id"
|
93
|
+
t.datetime "trashed_at"
|
94
|
+
t.datetime "published_at"
|
95
|
+
t.datetime "created_at"
|
96
|
+
t.datetime "updated_at"
|
97
|
+
end
|
98
|
+
|
70
99
|
create_table "parents", force: true do |t|
|
71
100
|
t.string "name"
|
72
101
|
t.integer "draft_id"
|
@@ -76,6 +105,16 @@ ActiveRecord::Schema.define(version: 20110208155312) do
|
|
76
105
|
t.datetime "updated_at"
|
77
106
|
end
|
78
107
|
|
108
|
+
create_table "skippers", force: true do |t|
|
109
|
+
t.string "name"
|
110
|
+
t.string "skip_me"
|
111
|
+
t.integer "draft_id"
|
112
|
+
t.datetime "trashed_at"
|
113
|
+
t.datetime "published_at"
|
114
|
+
t.datetime "created_at"
|
115
|
+
t.datetime "updated_at"
|
116
|
+
end
|
117
|
+
|
79
118
|
create_table "trashables", force: true do |t|
|
80
119
|
t.string "name"
|
81
120
|
t.string "title"
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Skipper do
|
4
|
+
let(:skipper) { Skipper.new :name => 'Bob', :skip_me => 'Skipped 1' }
|
5
|
+
it { should be_draftable }
|
6
|
+
|
7
|
+
describe :draft_creation do
|
8
|
+
subject do
|
9
|
+
skipper.draft_creation
|
10
|
+
skipper.reload
|
11
|
+
end
|
12
|
+
|
13
|
+
it { should be_persisted }
|
14
|
+
it { should be_draft }
|
15
|
+
its(:draft_id) { should be_present }
|
16
|
+
its(:draft) { should be_present }
|
17
|
+
its(:draft) { should be_create }
|
18
|
+
its(:name) { should eql 'Bob' }
|
19
|
+
its(:skip_me) { should eql 'Skipped 1' }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe :draft_update do
|
23
|
+
subject do
|
24
|
+
skipper.draft_update
|
25
|
+
skipper.reload
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'without existing draft' do
|
29
|
+
before do
|
30
|
+
skipper.save!
|
31
|
+
skipper.name = 'Sam'
|
32
|
+
skipper.skip_me = 'Skipped 2'
|
33
|
+
end
|
34
|
+
|
35
|
+
it { should be_persisted }
|
36
|
+
it { should be_draft }
|
37
|
+
its(:draft_id) { should be_present }
|
38
|
+
its(:draft) { should be_present }
|
39
|
+
its(:draft) { should be_update }
|
40
|
+
its(:name) { should eql 'Bob' }
|
41
|
+
its(:skip_me) { should eql 'Skipped 2' }
|
42
|
+
|
43
|
+
it 'creates a new draft' do
|
44
|
+
expect { subject }.to change(Draftsman::Draft, :count).by(1)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'changing back to initial state' do
|
49
|
+
before do
|
50
|
+
skipper.published_at = Time.now
|
51
|
+
skipper.save!
|
52
|
+
skipper.name = 'Sam'
|
53
|
+
skipper.draft_update
|
54
|
+
skipper.reload
|
55
|
+
skipper.name = 'Bob'
|
56
|
+
skipper.skip_me = 'Skipped 2'
|
57
|
+
end
|
58
|
+
|
59
|
+
it { should_not be_draft }
|
60
|
+
its(:draft_id) { should be_nil }
|
61
|
+
its(:draft) { should be_nil }
|
62
|
+
its(:name) { should eql 'Bob' }
|
63
|
+
its(:skip_me) { should eql 'Skipped 2' }
|
64
|
+
|
65
|
+
it 'destroys the draft' do
|
66
|
+
expect { subject }.to change(Draftsman::Draft.where(:id => skipper.draft_id), :count).by(-1)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with existing `create` draft' do
|
71
|
+
before { skipper.draft_creation }
|
72
|
+
|
73
|
+
context 'with changes' do
|
74
|
+
before do
|
75
|
+
skipper.name = 'Sam'
|
76
|
+
skipper.skip_me = 'Skipped 2'
|
77
|
+
end
|
78
|
+
|
79
|
+
it { should be_persisted }
|
80
|
+
it { should be_draft }
|
81
|
+
its(:draft_id) { should be_present }
|
82
|
+
its(:draft) { should be_present }
|
83
|
+
its(:draft) { should be_create }
|
84
|
+
its(:name) { should eql 'Sam' }
|
85
|
+
its(:skip_me) { should eql 'Skipped 2' }
|
86
|
+
|
87
|
+
it 'updates the existing draft' do
|
88
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => skipper.draft_id), :count)
|
89
|
+
end
|
90
|
+
|
91
|
+
its "draft's `name` is updated" do
|
92
|
+
subject.draft.reify.name.should eql 'Sam'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'with no changes' do
|
97
|
+
it { should be_persisted }
|
98
|
+
it { should be_draft }
|
99
|
+
its(:draft_id) { should be_present }
|
100
|
+
its(:draft) { should be_present }
|
101
|
+
its(:draft) { should be_create }
|
102
|
+
its(:name) { should eql 'Bob' }
|
103
|
+
its(:skip_me) { should eql 'Skipped 1' }
|
104
|
+
|
105
|
+
it "doesn't change the number of drafts" do
|
106
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => skipper.draft_id), :count)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'with existing `update` draft' do
|
112
|
+
before do
|
113
|
+
skipper.save!
|
114
|
+
skipper.name = 'Sam'
|
115
|
+
skipper.skip_me = 'Skipped 2'
|
116
|
+
skipper.draft_update
|
117
|
+
skipper.reload
|
118
|
+
skipper.attributes = skipper.draft.reify.attributes
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'with changes' do
|
122
|
+
before { skipper.name = 'Steve' }
|
123
|
+
it { should be_persisted }
|
124
|
+
it { should be_draft }
|
125
|
+
its(:draft_id) { should be_present }
|
126
|
+
its(:draft) { should be_present }
|
127
|
+
its(:draft) { should be_update }
|
128
|
+
its(:name) { should eql 'Bob' }
|
129
|
+
its(:skip_me) { should eql 'Skipped 2' }
|
130
|
+
|
131
|
+
it 'updates the existing draft' do
|
132
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => skipper.draft_id), :count)
|
133
|
+
end
|
134
|
+
|
135
|
+
its "draft's `name` is updated" do
|
136
|
+
subject.draft.reify.name.should eql 'Steve'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'with no changes' do
|
141
|
+
it { should be_persisted }
|
142
|
+
it { should be_draft }
|
143
|
+
its(:draft_id) { should be_present }
|
144
|
+
its(:draft) { should be_present }
|
145
|
+
its(:draft) { should be_update }
|
146
|
+
its(:name) { should eql 'Bob' }
|
147
|
+
its(:skip_me) { should eql 'Skipped 2' }
|
148
|
+
|
149
|
+
it "doesn't change the number of drafts" do
|
150
|
+
expect { subject }.to_not change(Draftsman::Draft.where(:id => skipper.draft_id), :count)
|
151
|
+
end
|
152
|
+
|
153
|
+
its "draft's `name` is not updated" do
|
154
|
+
subject.draft.reify.name.should eql 'Sam'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# Not applicable to this customization
|
161
|
+
describe :draft_destroy do
|
162
|
+
end
|
163
|
+
|
164
|
+
# Not applicable to this customization
|
165
|
+
describe 'scopes' do
|
166
|
+
end
|
167
|
+
end
|
data/spec/models/vanilla_spec.rb
CHANGED
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.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Peters
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -187,6 +187,7 @@ files:
|
|
187
187
|
- spec/dummy/app/models/bastard.rb
|
188
188
|
- spec/dummy/app/models/child.rb
|
189
189
|
- spec/dummy/app/models/parent.rb
|
190
|
+
- spec/dummy/app/models/skipper.rb
|
190
191
|
- spec/dummy/app/models/trashable.rb
|
191
192
|
- spec/dummy/app/models/vanilla.rb
|
192
193
|
- spec/dummy/app/models/whitelister.rb
|
@@ -221,6 +222,7 @@ files:
|
|
221
222
|
- spec/models/child_spec.rb
|
222
223
|
- spec/models/draft_spec.rb
|
223
224
|
- spec/models/parent_spec.rb
|
225
|
+
- spec/models/skipper_spec.rb
|
224
226
|
- spec/models/trashable_spec.rb
|
225
227
|
- spec/models/vanilla_spec.rb
|
226
228
|
- spec/models/whitelister_spec.rb
|
@@ -269,6 +271,7 @@ test_files:
|
|
269
271
|
- spec/dummy/app/models/bastard.rb
|
270
272
|
- spec/dummy/app/models/child.rb
|
271
273
|
- spec/dummy/app/models/parent.rb
|
274
|
+
- spec/dummy/app/models/skipper.rb
|
272
275
|
- spec/dummy/app/models/trashable.rb
|
273
276
|
- spec/dummy/app/models/vanilla.rb
|
274
277
|
- spec/dummy/app/models/whitelister.rb
|
@@ -303,6 +306,7 @@ test_files:
|
|
303
306
|
- spec/models/child_spec.rb
|
304
307
|
- spec/models/draft_spec.rb
|
305
308
|
- spec/models/parent_spec.rb
|
309
|
+
- spec/models/skipper_spec.rb
|
306
310
|
- spec/models/trashable_spec.rb
|
307
311
|
- spec/models/vanilla_spec.rb
|
308
312
|
- spec/models/whitelister_spec.rb
|