draftsman 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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'