draftsman 0.1.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 (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rspec +3 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +97 -0
  9. data/LICENSE +20 -0
  10. data/README.md +506 -0
  11. data/Rakefile +6 -0
  12. data/draftsman.gemspec +33 -0
  13. data/lib/draftsman/config.rb +13 -0
  14. data/lib/draftsman/draft.rb +289 -0
  15. data/lib/draftsman/frameworks/cucumber.rb +7 -0
  16. data/lib/draftsman/frameworks/rails.rb +58 -0
  17. data/lib/draftsman/frameworks/rspec.rb +16 -0
  18. data/lib/draftsman/frameworks/sinatra.rb +31 -0
  19. data/lib/draftsman/model.rb +428 -0
  20. data/lib/draftsman/serializers/json.rb +17 -0
  21. data/lib/draftsman/serializers/yaml.rb +17 -0
  22. data/lib/draftsman/version.rb +3 -0
  23. data/lib/draftsman.rb +101 -0
  24. data/lib/generators/draftsman/install_generator.rb +27 -0
  25. data/lib/generators/draftsman/templates/add_object_changes_column_to_drafts.rb +9 -0
  26. data/lib/generators/draftsman/templates/config/initializers/draftsman.rb +11 -0
  27. data/lib/generators/draftsman/templates/create_drafts.rb +22 -0
  28. data/spec/controllers/informants_controller_spec.rb +27 -0
  29. data/spec/controllers/users_controller_spec.rb +23 -0
  30. data/spec/controllers/whodunnits_controller_spec.rb +24 -0
  31. data/spec/draftsman_spec.rb +19 -0
  32. data/spec/dummy/Rakefile +7 -0
  33. data/spec/dummy/app/assets/images/rails.png +0 -0
  34. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  35. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +20 -0
  37. data/spec/dummy/app/controllers/informants_controller.rb +8 -0
  38. data/spec/dummy/app/controllers/users_controller.rb +8 -0
  39. data/spec/dummy/app/controllers/whodunnits_controller.rb +8 -0
  40. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  41. data/spec/dummy/app/helpers/messages_helper.rb +2 -0
  42. data/spec/dummy/app/mailers/.gitkeep +0 -0
  43. data/spec/dummy/app/models/bastard.rb +3 -0
  44. data/spec/dummy/app/models/child.rb +4 -0
  45. data/spec/dummy/app/models/parent.rb +5 -0
  46. data/spec/dummy/app/models/trashable.rb +3 -0
  47. data/spec/dummy/app/models/vanilla.rb +3 -0
  48. data/spec/dummy/app/models/whitelister.rb +3 -0
  49. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  50. data/spec/dummy/config/application.rb +37 -0
  51. data/spec/dummy/config/boot.rb +6 -0
  52. data/spec/dummy/config/database.yml +25 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +32 -0
  55. data/spec/dummy/config/environments/production.rb +73 -0
  56. data/spec/dummy/config/environments/test.rb +39 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/inflections.rb +15 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/routes.rb +6 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/db/migrate/20110208155312_set_up_test_tables.rb +86 -0
  67. data/spec/dummy/db/schema.rb +106 -0
  68. data/spec/dummy/db/seeds.rb +7 -0
  69. data/spec/dummy/lib/assets/.gitkeep +0 -0
  70. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  71. data/spec/dummy/log/.gitkeep +0 -0
  72. data/spec/dummy/public/404.html +26 -0
  73. data/spec/dummy/public/422.html +26 -0
  74. data/spec/dummy/public/500.html +25 -0
  75. data/spec/dummy/public/favicon.ico +0 -0
  76. data/spec/dummy/script/rails +6 -0
  77. data/spec/models/child_spec.rb +205 -0
  78. data/spec/models/draft_spec.rb +297 -0
  79. data/spec/models/parent_spec.rb +191 -0
  80. data/spec/models/trashable_spec.rb +164 -0
  81. data/spec/models/vanilla_spec.rb +201 -0
  82. data/spec/models/whitelister_spec.rb +262 -0
  83. data/spec/spec_helper.rb +52 -0
  84. metadata +304 -0
@@ -0,0 +1,201 @@
1
+ require 'spec_helper'
2
+
3
+ # A Vanilla has a simple call to `has_drafts` without any options specified.
4
+ describe Vanilla do
5
+ let(:vanilla) { Vanilla.new :name => 'Bob' }
6
+ it { should be_draftable }
7
+
8
+ describe :draft_creation do
9
+ subject do
10
+ vanilla.draft_creation
11
+ vanilla.reload
12
+ end
13
+
14
+ it { should be_persisted }
15
+ it { should be_draft }
16
+ its(:draft_id) { should be_present }
17
+ its(:draft) { should be_present }
18
+ its(:draft) { should be_create }
19
+ its(:name) { should eql 'Bob' }
20
+ end
21
+
22
+ describe :draft_update do
23
+ subject do
24
+ vanilla.draft_update
25
+ vanilla.reload
26
+ end
27
+
28
+ context 'without existing draft' do
29
+ before do
30
+ vanilla.save!
31
+ vanilla.name = 'Sam'
32
+ end
33
+
34
+ it { should be_persisted }
35
+ it { should be_draft }
36
+ its(:draft_id) { should be_present }
37
+ its(:draft) { should be_present }
38
+ its(:draft) { should be_update }
39
+ its(:name) { should eql 'Bob' }
40
+
41
+ it 'creates a new draft' do
42
+ expect { subject }.to change(Draftsman::Draft, :count).by(1)
43
+ end
44
+ end
45
+
46
+ describe 'changing back to initial state' do
47
+ before do
48
+ vanilla.published_at = Time.now
49
+ vanilla.save!
50
+ vanilla.name = 'Sam'
51
+ vanilla.draft_update
52
+ vanilla.reload
53
+ vanilla.name = 'Bob'
54
+ end
55
+
56
+ it { should_not be_draft }
57
+ its(:name) { should eql 'Bob' }
58
+ its(:draft_id) { should be_nil }
59
+ its(:draft) { should be_nil }
60
+
61
+ it 'destroys the draft' do
62
+ expect { subject }.to change(Draftsman::Draft.where(:id => vanilla.draft_id), :count).by(-1)
63
+ end
64
+ end
65
+
66
+ context 'with existing `create` draft' do
67
+ before { vanilla.draft_creation }
68
+
69
+ context 'with changes' do
70
+ before { vanilla.name = 'Sam' }
71
+ it { should be_persisted }
72
+ it { should be_draft }
73
+ its(:draft_id) { should be_present }
74
+ its(:draft) { should be_present }
75
+ its(:name) { should eql 'Sam' }
76
+
77
+ it 'updates the existing draft' do
78
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => vanilla.draft_id), :count)
79
+ end
80
+
81
+ its "draft's `name` is updated" do
82
+ subject.draft.reify.name.should eql 'Sam'
83
+ end
84
+
85
+ it 'has a `create` draft' do
86
+ subject.draft.should be_create
87
+ end
88
+ end
89
+
90
+ context 'with no changes' do
91
+ it { should be_persisted }
92
+ it { should be_draft }
93
+ its(:draft_id) { should be_present }
94
+ its(:draft) { should be_present }
95
+ its(:draft) { should be_create }
96
+ its(:name) { should eql 'Bob' }
97
+
98
+ it "doesn't change the number of drafts" do
99
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => vanilla.draft_id), :count)
100
+ end
101
+ end
102
+ end
103
+
104
+ context 'with existing `update` draft' do
105
+ before do
106
+ vanilla.save!
107
+ vanilla.name = 'Sam'
108
+ vanilla.draft_update
109
+ end
110
+
111
+ context 'with changes' do
112
+ before { vanilla.name = 'Steve' }
113
+ it { should be_persisted }
114
+ it { should be_draft }
115
+ its(:draft_id) { should be_present }
116
+ its(:draft) { should be_present }
117
+ its(:name) { should eql 'Bob' }
118
+
119
+ it 'updates the existing draft' do
120
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => vanilla.draft_id), :count)
121
+ end
122
+
123
+ its "draft's `name` is updated" do
124
+ subject.draft.reify.name.should eql 'Steve'
125
+ end
126
+
127
+ it 'has a `create` draft' do
128
+ subject.draft.update?.should be_true
129
+ end
130
+ end
131
+
132
+ context 'with no changes' do
133
+ it { should be_persisted }
134
+ it { should be_draft }
135
+ its(:draft_id) { should be_present }
136
+ its(:draft) { should be_present }
137
+ its(:draft) { should be_update }
138
+ its(:name) { should eql 'Bob' }
139
+
140
+ it "doesn't change the number of drafts" do
141
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => vanilla.draft_id), :count)
142
+ end
143
+
144
+ its "draft's `name` is not updated" do
145
+ subject.draft.reify.name.should eql 'Sam'
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ # Not applicable to this customization
152
+ describe :draft_destroy do
153
+ end
154
+
155
+ describe 'scopes' do
156
+ let!(:drafted_vanilla) { vanilla.draft_creation; return vanilla }
157
+ let!(:published_vanilla) { Vanilla.create :name => 'Jane', :published_at => Time.now }
158
+
159
+ describe :drafted do
160
+ subject { Vanilla.drafted }
161
+ its(:count) { should eql 1 }
162
+
163
+ it 'includes the unpublished item' do
164
+ subject.should include drafted_vanilla
165
+ end
166
+
167
+ it 'does not include the published item' do
168
+ subject.should_not include published_vanilla
169
+ end
170
+ end
171
+
172
+ describe :live do
173
+ subject { Vanilla.live }
174
+
175
+ it 'raises an exception' do
176
+ expect { subject.load }.to raise_exception
177
+ end
178
+ end
179
+
180
+ describe :published do
181
+ subject { Vanilla.published }
182
+ its(:count) { should eql 1 }
183
+
184
+ it 'does not include the unpublished item' do
185
+ subject.should_not include drafted_vanilla
186
+ end
187
+
188
+ it 'includes the published item' do
189
+ subject.should include published_vanilla
190
+ end
191
+ end
192
+
193
+ describe :trashed do
194
+ subject { Vanilla.trashed }
195
+
196
+ it 'raises an exception' do
197
+ expect { subject.load }.to raise_exception
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,262 @@
1
+ require 'spec_helper'
2
+
3
+ describe Whitelister do
4
+ let(:whitelister) { Whitelister.new :name => 'Bob' }
5
+ it { should be_draftable }
6
+
7
+ # Not affected by this customization
8
+ describe :draft_creation do
9
+ end
10
+
11
+ describe :draft_update do
12
+ subject do
13
+ whitelister.draft_update
14
+ whitelister.reload
15
+ end
16
+
17
+ context 'with whitelisted change' do
18
+ context 'without draft' do
19
+ before do
20
+ whitelister.save!
21
+ whitelister.attributes = { :name => 'Sam', :ignored => 'Meh.' }
22
+ end
23
+
24
+ it { should be_persisted }
25
+ it { should be_draft }
26
+ its(:draft_id) { should be_present }
27
+ its(:draft) { should be_present }
28
+ its(:draft) { should be_update }
29
+ its(:name) { should eql 'Bob' }
30
+ its(:ignored) { should eql 'Meh.' }
31
+
32
+ it 'creates a new draft' do
33
+ expect { subject }.to change(Draftsman::Draft, :count).by(1)
34
+ end
35
+
36
+ it 'has an `update` draft' do
37
+ subject.draft.update?.should be_true
38
+ end
39
+
40
+ its "draft's name should be `Sam`" do
41
+ subject.draft.reify.name.should eql 'Sam'
42
+ end
43
+
44
+ context 'changing back to initial state' do
45
+ before do
46
+ whitelister.draft_update
47
+ whitelister.attributes = { :name => 'Bob', :ignored => 'Huzzah!' }
48
+ end
49
+
50
+ it { should_not be_draft }
51
+ its(:name) { should eql 'Bob' }
52
+ its(:ignored) { should eql 'Huzzah!' }
53
+ its(:draft_id) { should be_nil }
54
+ its(:draft) { should be_nil }
55
+
56
+ it 'destroys the draft' do
57
+ expect { subject }.to change(Draftsman::Draft.where(:id => whitelister.draft_id), :count).by(-1)
58
+ end
59
+ end
60
+ end
61
+
62
+ context 'with existing `create` draft' do
63
+ before { whitelister.draft_creation }
64
+
65
+ context 'with changes' do
66
+ before { whitelister.attributes = { :name => 'Sam', :ignored => 'Meh.' } }
67
+ it { should be_persisted }
68
+ it { should be_draft }
69
+ its(:draft_id) { should be_present }
70
+ its(:draft) { should be_present }
71
+ its(:draft) { should be_create }
72
+ its(:name) { should eql 'Sam' }
73
+
74
+ it 'updates the existing draft' do
75
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
76
+ end
77
+
78
+ its "draft's `name` is updated" do
79
+ subject.draft.reify.name.should eql 'Sam'
80
+ end
81
+
82
+ its "draft's `ignored` is updated" do
83
+ subject.draft.reify.ignored.should eql 'Meh.'
84
+ end
85
+ end
86
+
87
+ context 'with no changes' do
88
+ it { should be_persisted }
89
+ it { should be_draft }
90
+ its(:draft_id) { should be_present }
91
+ its(:draft) { should be_present }
92
+ its(:draft) { should be_create }
93
+ its(:name) { should eql 'Bob' }
94
+
95
+ it "doesn't change the number of drafts" do
96
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'with existing `update` draft' do
102
+ before do
103
+ whitelister.save!
104
+ whitelister.attributes = { :name => 'Sam', :ignored => 'Meh.' }
105
+ end
106
+
107
+ context 'with changes' do
108
+ before { whitelister.attributes = { :name => 'Steve', :ignored => 'Huzzah!' } }
109
+ it { should be_persisted }
110
+ it { should be_draft }
111
+ its(:draft_id) { should be_present }
112
+ its(:draft) { should be_present }
113
+ its(:draft) { should be_update }
114
+ its(:name) { should eql 'Bob' }
115
+ its(:ignored) { should eql 'Huzzah!' }
116
+
117
+ it 'updates the existing draft' do
118
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
119
+ end
120
+
121
+ its "draft's `name` is updated" do
122
+ subject.draft.reify.name.should eql 'Steve'
123
+ end
124
+
125
+ its "draft's `ignored` is 'Huzzah!'" do
126
+ subject.draft.reify.ignored.should eql 'Huzzah!'
127
+ end
128
+ end
129
+
130
+ context 'with no changes' do
131
+ it { should be_persisted }
132
+ it { should be_draft }
133
+ its(:draft_id) { should be_present }
134
+ its(:draft) { should be_present }
135
+ its(:name) { should eql 'Bob' }
136
+
137
+ it "doesn't change the number of drafts" do
138
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
139
+ end
140
+
141
+ its "draft's `name` is not updated" do
142
+ subject.draft.reify.name.should eql 'Sam'
143
+ end
144
+
145
+ it 'still has an `update` draft' do
146
+ subject.draft.update?.should be_true
147
+ end
148
+ end
149
+ end
150
+ end
151
+
152
+ context 'without whitelisted change' do
153
+ context 'without existing draft' do
154
+ before do
155
+ whitelister.save!
156
+ whitelister.ignored = 'Huzzah!'
157
+ end
158
+
159
+ it { should be_persisted }
160
+ it { should_not be_draft }
161
+ its(:draft_id) { should be_nil }
162
+ its(:draft) { should be_nil }
163
+ its(:name) { should eql 'Bob' }
164
+ its(:ignored) { should eql 'Huzzah!' }
165
+
166
+ it 'does not create a draft' do
167
+ expect { subject }.to_not change(Draftsman::Draft, :count)
168
+ end
169
+
170
+ # Not affected by this customization
171
+ context 'changing back to initial state' do
172
+ end
173
+ end
174
+
175
+ context 'with existing `create` draft' do
176
+ before do
177
+ whitelister.draft_creation
178
+ whitelister.ignored = 'Huzzah!'
179
+ end
180
+
181
+ it { should be_persisted }
182
+ it { should be_draft }
183
+ its(:draft_id) { should be_present }
184
+ its(:draft) { should be_present }
185
+ its(:name) { should eql 'Bob' }
186
+ its(:ignored) { should eql 'Huzzah!' }
187
+
188
+ it 'updates the existing draft' do
189
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
190
+ end
191
+
192
+ its "draft's `ignored` is updated" do
193
+ subject.draft.reify.ignored.should eql 'Huzzah!'
194
+ end
195
+
196
+ it 'has a `create` draft' do
197
+ subject.draft.should be_create
198
+ end
199
+ end
200
+
201
+ context 'with existing `update` draft' do
202
+ before do
203
+ whitelister.save!
204
+ whitelister.attributes = { :name => 'Sam', :ignored => 'Meh.' }
205
+ end
206
+
207
+ context 'with changes' do
208
+ before { whitelister.ignored = 'Huzzah!' }
209
+ it { should be_persisted }
210
+ it { should be_draft }
211
+ its(:draft_id) { should be_present }
212
+ its(:draft) { should be_present }
213
+ its(:draft) { should be_update }
214
+ its(:name) { should eql 'Bob' }
215
+ its(:ignored) { should eql 'Huzzah!' }
216
+
217
+ it 'updates the existing draft' do
218
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
219
+ end
220
+
221
+ its "draft's `name` is not changed" do
222
+ subject.draft.reify.name.should eql 'Sam'
223
+ end
224
+
225
+ its "draft's `ignored` is updated" do
226
+ subject.draft.reify.ignored.should eql 'Huzzah!'
227
+ end
228
+ end
229
+
230
+ context 'with no changes' do
231
+ it { should be_persisted }
232
+ it { should be_draft }
233
+ its(:draft_id) { should be_present }
234
+ its(:draft) { should be_present }
235
+ its(:draft) { should be_update }
236
+ its(:name) { should eql 'Bob' }
237
+ its(:ignored) { should eql 'Meh.' }
238
+
239
+ it "doesn't change the number of drafts" do
240
+ expect { subject }.to_not change(Draftsman::Draft.where(:id => whitelister.draft_id), :count)
241
+ end
242
+
243
+ its "draft's `name` is not updated" do
244
+ subject.draft.reify.name.should eql 'Sam'
245
+ end
246
+
247
+ its "draft's `ignored` is not updated" do
248
+ subject.draft.reify.ignored.should eql 'Meh.'
249
+ end
250
+ end
251
+ end
252
+ end
253
+ end
254
+
255
+ # Not affected by this customization
256
+ describe :draft_destroy do
257
+ end
258
+
259
+ # Not affected by this customization
260
+ describe 'scopes' do
261
+ end
262
+ end
@@ -0,0 +1,52 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
3
+
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+ require 'shoulda/matchers/integrations/rspec'
7
+ require 'capybara/rspec'
8
+
9
+ Rails.backtrace_cleaner.remove_silencers!
10
+
11
+ # Requires supporting ruby files with custom matchers and macros, etc,
12
+ # in spec/support/ and its subdirectories.
13
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
14
+
15
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
16
+ RSpec.configure do |config|
17
+ config.treat_symbols_as_metadata_keys_with_true_values = true
18
+
19
+ # ## Mock Framework
20
+ #
21
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
22
+ #
23
+ # config.mock_with :mocha
24
+ # config.mock_with :flexmock
25
+ # config.mock_with :rr
26
+
27
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
28
+ # config.fixture_path = "#{::Rails.root}/spec/fixtures"
29
+
30
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
31
+ # examples within a transaction, remove the following line or assign false
32
+ # instead of true.
33
+ config.use_transactional_fixtures = true
34
+
35
+ # If true, the base class of anonymous controllers will be inferred
36
+ # automatically. This will be the default behavior in future versions of
37
+ # rspec-rails.
38
+ config.infer_base_class_for_anonymous_controllers = false
39
+
40
+ # Run specs in random order to surface order dependencies. If you find an
41
+ # order dependency and want to debug it, you can fix the order by providing
42
+ # the seed, which is printed after each run.
43
+ # --seed 1234
44
+ # config.order = 'random'
45
+
46
+ config.mock_with :rspec
47
+ end
48
+
49
+ #require 'rails/railtie'
50
+ #require 'active_record'
51
+ #
52
+ #require 'draftsman'