worth_saving 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +90 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/javascripts/worth_saving/application.js +15 -0
  6. data/app/assets/stylesheets/worth_saving/application.css +13 -0
  7. data/app/controllers/worth_saving/application_controller.rb +4 -0
  8. data/app/controllers/worth_saving/drafts_controller.rb +51 -0
  9. data/app/helpers/worth_saving/application_helper.rb +4 -0
  10. data/app/models/worth_saving/draft.rb +47 -0
  11. data/app/views/layouts/worth_saving/application.html.erb +14 -0
  12. data/config/routes.rb +3 -0
  13. data/db/migrate/20130911055236_create_worth_saving_drafts.rb +16 -0
  14. data/lib/tasks/worth_saving_tasks.rake +4 -0
  15. data/lib/worth_saving.rb +12 -0
  16. data/lib/worth_saving/action_view_ext.rb +11 -0
  17. data/lib/worth_saving/active_record_ext.rb +39 -0
  18. data/lib/worth_saving/engine.rb +15 -0
  19. data/lib/worth_saving/form.rb +15 -0
  20. data/lib/worth_saving/form/base.rb +21 -0
  21. data/lib/worth_saving/form/record.rb +53 -0
  22. data/lib/worth_saving/form/rendering.rb +100 -0
  23. data/lib/worth_saving/form_builder.rb +57 -0
  24. data/lib/worth_saving/info.rb +102 -0
  25. data/lib/worth_saving/version.rb +3 -0
  26. data/spec/app/controllers/drafts_controller_spec.rb +13 -0
  27. data/spec/app/models/worth_saving/draft_spec.rb +156 -0
  28. data/spec/dummy/README.rdoc +261 -0
  29. data/spec/dummy/Rakefile +7 -0
  30. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  31. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  32. data/spec/dummy/app/controllers/application_controller.rb +24 -0
  33. data/spec/dummy/app/controllers/login_controller.rb +11 -0
  34. data/spec/dummy/app/controllers/pages_controller.rb +48 -0
  35. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  36. data/spec/dummy/app/models/page.rb +12 -0
  37. data/spec/dummy/app/models/subpage.rb +7 -0
  38. data/spec/dummy/app/models/user.rb +4 -0
  39. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  40. data/spec/dummy/app/views/pages/form.html.slim +53 -0
  41. data/spec/dummy/config.ru +4 -0
  42. data/spec/dummy/config/application.rb +66 -0
  43. data/spec/dummy/config/boot.rb +10 -0
  44. data/spec/dummy/config/database.yml +25 -0
  45. data/spec/dummy/config/environment.rb +5 -0
  46. data/spec/dummy/config/environments/development.rb +37 -0
  47. data/spec/dummy/config/environments/production.rb +67 -0
  48. data/spec/dummy/config/environments/test.rb +37 -0
  49. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  50. data/spec/dummy/config/initializers/inflections.rb +15 -0
  51. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  52. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  53. data/spec/dummy/config/initializers/session_store.rb +8 -0
  54. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  55. data/spec/dummy/config/locales/en.yml +5 -0
  56. data/spec/dummy/config/routes.rb +8 -0
  57. data/spec/dummy/db/development.sqlite3 +0 -0
  58. data/spec/dummy/db/migrate/20130911060226_create_worth_saving_drafts.worth_saving.rb +17 -0
  59. data/spec/dummy/db/migrate/20130912071319_create_users.rb +9 -0
  60. data/spec/dummy/db/migrate/20130912071446_create_pages.rb +9 -0
  61. data/spec/dummy/db/migrate/20130912145831_create_subpages.rb +10 -0
  62. data/spec/dummy/db/migrate/20130913060709_add_columns_to_subpages.rb +5 -0
  63. data/spec/dummy/db/migrate/20130913060847_add_columns_to_pages.rb +7 -0
  64. data/spec/dummy/db/schema.rb +52 -0
  65. data/spec/dummy/db/test.sqlite3 +0 -0
  66. data/spec/dummy/log/development.log +17536 -0
  67. data/spec/dummy/log/test.log +76256 -0
  68. data/spec/dummy/public/404.html +26 -0
  69. data/spec/dummy/public/422.html +26 -0
  70. data/spec/dummy/public/500.html +25 -0
  71. data/spec/dummy/public/favicon.ico +0 -0
  72. data/spec/dummy/script/rails +6 -0
  73. data/spec/dummy/tmp/cache/assets/CA6/7A0/sprockets%2Ff6723fb0918cb134f62480f155a0b364 +0 -0
  74. data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  75. data/spec/dummy/tmp/cache/assets/CF8/AF0/sprockets%2F228f63c526665cc53d670799eece3b98 +0 -0
  76. data/spec/dummy/tmp/cache/assets/D09/190/sprockets%2F993fae97313ed7d42322c85e60b02bb1 +0 -0
  77. data/spec/dummy/tmp/cache/assets/D1C/CE0/sprockets%2F9a5f4484900982bd33f792ca06e7f5ea +0 -0
  78. data/spec/dummy/tmp/cache/assets/D31/620/sprockets%2F01f101ae68348ed1bb4e46d7f452a73a +0 -0
  79. data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  80. data/spec/dummy/tmp/cache/assets/D3C/300/sprockets%2Ffb893496ed88af814fa985858f60ee66 +0 -0
  81. data/spec/dummy/tmp/cache/assets/D43/EB0/sprockets%2F43d74a38cb4f14de5087ea7f871ac166 +0 -0
  82. data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  83. data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  84. data/spec/dummy/tmp/cache/assets/D97/C50/sprockets%2F74b5c193fc06fb3cb3c4ac12ac7589a7 +0 -0
  85. data/spec/dummy/tmp/cache/assets/D9E/470/sprockets%2F36bde6f05aa955c51ab2cd97b59e742a +0 -0
  86. data/spec/dummy/tmp/cache/assets/DCF/000/sprockets%2Fcfbeb9f4e8b3b7d1ac752d93c64017d3 +0 -0
  87. data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  88. data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  89. data/spec/dummy/tmp/cache/assets/test/sprockets/01f101ae68348ed1bb4e46d7f452a73a +0 -0
  90. data/spec/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  91. data/spec/dummy/tmp/cache/assets/test/sprockets/228f63c526665cc53d670799eece3b98 +0 -0
  92. data/spec/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  93. data/spec/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  94. data/spec/dummy/tmp/cache/assets/test/sprockets/36bde6f05aa955c51ab2cd97b59e742a +0 -0
  95. data/spec/dummy/tmp/cache/assets/test/sprockets/43d74a38cb4f14de5087ea7f871ac166 +0 -0
  96. data/spec/dummy/tmp/cache/assets/test/sprockets/74b5c193fc06fb3cb3c4ac12ac7589a7 +0 -0
  97. data/spec/dummy/tmp/cache/assets/test/sprockets/993fae97313ed7d42322c85e60b02bb1 +0 -0
  98. data/spec/dummy/tmp/cache/assets/test/sprockets/9a5f4484900982bd33f792ca06e7f5ea +0 -0
  99. data/spec/dummy/tmp/cache/assets/test/sprockets/cfbeb9f4e8b3b7d1ac752d93c64017d3 +0 -0
  100. data/spec/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  101. data/spec/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  102. data/spec/dummy/tmp/cache/assets/test/sprockets/f6723fb0918cb134f62480f155a0b364 +0 -0
  103. data/spec/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  104. data/spec/dummy/tmp/cache/assets/test/sprockets/fb893496ed88af814fa985858f60ee66 +0 -0
  105. data/spec/factories.rb +28 -0
  106. data/spec/features/worth_saving_features_spec.rb +60 -0
  107. data/spec/lib/active_record_ext_spec.rb +291 -0
  108. data/spec/lib/info_spec.rb +29 -0
  109. data/spec/spec_helper.rb +37 -0
  110. data/spec/support/features.rb +8 -0
  111. data/spec/support/features/helpers.rb +96 -0
  112. data/vendor/assets/javascripts/worth_saving.js +10 -0
  113. data/vendor/assets/javascripts/worth_saving/form.js +64 -0
  114. data/vendor/assets/stylesheets/worth_saving.css +18 -0
  115. metadata +424 -0
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The page you were looking for doesn't exist (404)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/404.html -->
21
+ <div class="dialog">
22
+ <h1>The page you were looking for doesn't exist.</h1>
23
+ <p>You may have mistyped the address or the page may have moved.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,26 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>The change you wanted was rejected (422)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/422.html -->
21
+ <div class="dialog">
22
+ <h1>The change you wanted was rejected.</h1>
23
+ <p>Maybe you tried to change something you didn't have access to.</p>
24
+ </div>
25
+ </body>
26
+ </html>
@@ -0,0 +1,25 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>We're sorry, but something went wrong (500)</title>
5
+ <style type="text/css">
6
+ body { background-color: #fff; color: #666; text-align: center; font-family: arial, sans-serif; }
7
+ div.dialog {
8
+ width: 25em;
9
+ padding: 0 4em;
10
+ margin: 4em auto 0 auto;
11
+ border: 1px solid #ccc;
12
+ border-right-color: #999;
13
+ border-bottom-color: #999;
14
+ }
15
+ h1 { font-size: 100%; color: #f00; line-height: 1.5em; }
16
+ </style>
17
+ </head>
18
+
19
+ <body>
20
+ <!-- This file lives in public/500.html -->
21
+ <div class="dialog">
22
+ <h1>We're sorry, but something went wrong.</h1>
23
+ </div>
24
+ </body>
25
+ </html>
File without changes
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
5
+ require File.expand_path('../../config/boot', __FILE__)
6
+ require 'rails/commands'
data/spec/factories.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ FactoryGirl.define do
4
+ factory :user do
5
+ name 'John Doe'
6
+ end
7
+
8
+ factory :page do
9
+ user
10
+ title 'My Big Fat Greek Page'
11
+ content <<-EOS
12
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt
13
+ ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
14
+ laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in
15
+ voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
16
+ cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
17
+ EOS
18
+ approved false
19
+ page_type 'Front'
20
+ position 'Left'
21
+ end
22
+
23
+ factory :subpage do
24
+ page
25
+ subtitle 'My Not-so-big Subtitle'
26
+ content 'This is some content that goes in here. Not a lot.'
27
+ end
28
+ end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ feature 'WorthSaving' do
4
+ let(:fred) { given_user 'Fred Flintstone' }
5
+ let(:barney) { given_user 'Barney Rubble' }
6
+
7
+ scenario "A user begins work on a new page and sees recovery option when refreshing the page", js: true do
8
+ login fred
9
+ visit new_page_path
10
+ within '.worth-saving-standard-form-container .worth-saving-form-container' do
11
+ fill_in_form
12
+ end
13
+ chill_out_long_enough_to_draft
14
+ visit current_path
15
+ within '.worth-saving-header-message' do
16
+ expect(page).to have_content "It appears you were working on a draft that didn't get saved"
17
+ end
18
+ within '.worth-saving-recovery-form-container #new_page' do
19
+ verify_blank_form
20
+ end
21
+ within '.worth-saving-recovery-form-container #recovered_new_page' do
22
+ verify_form({}, true)
23
+ end
24
+ end
25
+
26
+ scenario "As a user I start work on a new page, refresh and see draft, but another user can't see it", js: true do
27
+ login fred
28
+ visit new_page_path
29
+ within '.worth-saving-standard-form-container .worth-saving-form-container' do
30
+ fill_in_form
31
+ end
32
+ chill_out_long_enough_to_draft
33
+ visit current_path
34
+ within '.worth-saving-header-message' do
35
+ expect(page).to have_content "It appears you were working on a draft that didn't get saved"
36
+ end
37
+ login barney
38
+ visit new_page_path
39
+ page.should_not have_css '.worth-saving-header-message'
40
+ end
41
+
42
+ scenario "One user creates a page. Another edits that page, and drafts do not get saved because of methods in ApplicationController", js: true do
43
+ login fred
44
+ visit new_page_path
45
+ within '.worth-saving-standard-form-container .worth-saving-form-container' do
46
+ fill_in_form
47
+ end
48
+ click_on 'Create Page'
49
+ path = current_path
50
+ login barney
51
+ visit path
52
+ within '.worth-saving-standard-form-container .worth-saving-form-container' do
53
+ fill_in 'Content', with: "Here is some new content that I will not expect to see"
54
+ end
55
+ chill_out_long_enough_to_draft
56
+ within '.worth-saving-form-message.error' do
57
+ page.should have_content "Not authorized to draft this Page"
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,291 @@
1
+ require 'spec_helper'
2
+
3
+ describe WorthSaving::ActiveRecordExt do
4
+ before do
5
+ Rails.application.config.stub(:filter_parameters).and_return [:redacted_field]
6
+ end
7
+
8
+ with_model :WorthSavingDraft do
9
+ table do |t|
10
+ t.integer :recordable_id
11
+ t.string :recordable_type
12
+ t.integer :scopeable_id
13
+ t.string :scopeable_type
14
+ t.text :form_data
15
+ end
16
+
17
+ model do
18
+ belongs_to :recordable, polymorphic: true
19
+ belongs_to :scopeable, polymorphic: true
20
+ end
21
+ end
22
+
23
+ with_model :ImportantThing do
24
+ table do |t|
25
+ t.string :stuff
26
+ end
27
+
28
+ model do
29
+ is_worth_saving
30
+ if Rails.version.match /^3/
31
+ attr_accessible :stuff
32
+ end
33
+ end
34
+ end
35
+
36
+ with_model :AnyThing do
37
+ end
38
+
39
+ before do
40
+ if Rails.version.match /^3/
41
+ class WorthSaving::Draft
42
+ attr_accessible :recordable_id, :recordable_type, :scopeable_id, :scopeable_type, :form_data, :scopeable
43
+ end
44
+ end
45
+ end
46
+
47
+ describe 'subclass that is worth_saving' do
48
+ describe 'associations' do
49
+ let(:record) { ImportantThing.new }
50
+ let(:draft) { record.build_worth_saving_draft }
51
+
52
+ context 'when record is persisted' do
53
+ it 'has a worth_saving draft' do
54
+ record.save
55
+ draft.save
56
+ record.worth_saving_draft.should eq draft
57
+ end
58
+ end
59
+
60
+ context 'when record is not persisted' do
61
+ it 'has a worth_saving draft' do
62
+ draft.save
63
+ record.worth_saving_draft.should eq draft
64
+ end
65
+ end
66
+ end
67
+
68
+ describe 'knowing it is worth_saving' do
69
+ subject { ImportantThing.worth_saving? }
70
+
71
+ it { should be_true }
72
+ end
73
+
74
+ describe 'instance knowing it is worth_saving' do
75
+ subject { ImportantThing.new.worth_saving? }
76
+
77
+ it { should eq true }
78
+ end
79
+ end
80
+
81
+ describe 'normal(not-worth_saving) subclass' do
82
+ describe 'knowing it is NOT worth_saving' do
83
+ subject { AnyThing.worth_saving? }
84
+
85
+ it { should eq false }
86
+ end
87
+
88
+ describe 'instance knowing it is NOT worth_saving' do
89
+ subject { AnyThing.new.worth_saving? }
90
+
91
+ it { should eq false }
92
+ end
93
+ end
94
+
95
+ context 'worth_saving subclass with excepted fields' do
96
+ with_model :ImportantThingButUnimportantAuthor do
97
+ table do |t|
98
+ t.string :title
99
+ t.string :author
100
+ end
101
+
102
+ model do
103
+ is_worth_saving except: :author
104
+ end
105
+ end
106
+
107
+ context 'when field is NOT in the exceptions list' do
108
+ describe 'knowing the field is worth_saving' do
109
+ subject { ImportantThingButUnimportantAuthor.worth_saving? :title }
110
+
111
+ it { should eq true }
112
+ end
113
+
114
+ describe 'having an instance that knows the field is worth_saving' do
115
+ subject { ImportantThingButUnimportantAuthor.new.worth_saving? :title }
116
+
117
+ it { should eq true }
118
+ end
119
+ end
120
+
121
+ context 'when a field IS in the exceptions list' do
122
+ describe 'knowing the field is NOT worth_saving' do
123
+ subject { ImportantThingButUnimportantAuthor.worth_saving? :author }
124
+
125
+ it { should eq false }
126
+ end
127
+
128
+ describe 'having an instance that knows the field is NOT worth_saving' do
129
+ subject { ImportantThingButUnimportantAuthor.new.worth_saving? :author }
130
+
131
+ it { should eq false }
132
+ end
133
+ end
134
+
135
+ context 'when multiple fields are in the exceptions list (array argument)' do
136
+ with_model :ImportantThingWithUnimportantFields do
137
+ table do |t|
138
+ t.string :title
139
+ t.string :author
140
+ t.string :content
141
+ end
142
+
143
+ model do
144
+ is_worth_saving except: [:author, :title]
145
+ end
146
+ end
147
+
148
+ describe 'knowing which fields are and are NOT worth_saving' do
149
+ it 'should be able to tell the difference' do
150
+ ImportantThingWithUnimportantFields.worth_saving?(:author).should eq false
151
+ ImportantThingWithUnimportantFields.worth_saving?(:title).should eq false
152
+ ImportantThingWithUnimportantFields.worth_saving?(:content).should eq true
153
+ end
154
+
155
+ context 'Rails.application.filter_params' do
156
+ it 'should not consider these fields worth_saving' do
157
+ ImportantThingWithUnimportantFields.worth_saving?(:redacted_field).should eq false
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ describe 'scope option' do
165
+ with_model :User do
166
+ end
167
+
168
+ with_model :ScopedThing do
169
+ table do |t|
170
+ t.belongs_to :user
171
+ end
172
+
173
+ model do
174
+ if Rails.version.match /^3/
175
+ attr_accessible :user
176
+ end
177
+ belongs_to :user
178
+ is_worth_saving scope: :user
179
+ end
180
+ end
181
+
182
+ describe '.worth_saving_scope' do
183
+ it 'returns scope given in options' do
184
+ ScopedThing.worth_saving_info.scope.should eq :user
185
+ end
186
+ end
187
+
188
+ describe '.worth_saving_info.scope' do
189
+ it 'returns scope given in options' do
190
+ ScopedThing.worth_saving_info.scope.should eq :user
191
+ end
192
+ end
193
+
194
+ describe '#worth_saving_draft' do
195
+ let(:user) { User.create }
196
+ let(:user2) { User.create }
197
+ let(:thing) { ScopedThing.new user: user }
198
+
199
+ context 'an unsaved ScopedThing' do
200
+ it 'finds the draft by scope' do
201
+ draft = WorthSaving::Draft.create recordable_type: 'ScopedThing', scopeable_id: user.id, scopeable_type: 'User'
202
+ thing.worth_saving_draft.should eq draft
203
+ end
204
+
205
+ it 'does not find the draft belonging to the wrong scoped object' do
206
+ draft = WorthSaving::Draft.create recordable_type: 'ScopedThing', scopeable_id: user.id, scopeable_type: 'User'
207
+ thing = ScopedThing.new user: user2
208
+ thing.worth_saving_draft.should be_nil
209
+ end
210
+
211
+ it 'does not find the draft belonging to the wrong recordable' do
212
+ draft = WorthSaving::Draft.create recordable_type: 'ImportantThing', scopeable_id: user.id, scopeable_type: 'User'
213
+ thing = ScopedThing.new user: user
214
+ thing.worth_saving_draft.should be_nil
215
+ end
216
+ end
217
+
218
+ context 'a saved Scopedthing' do
219
+ it 'finds the draft through the has_one association' do
220
+ thing.save
221
+ draft = WorthSaving::Draft.create recordable_id: thing.id, recordable_type: 'ScopedThing'
222
+ thing.reload
223
+ thing.worth_saving_draft.should eq draft
224
+ end
225
+ end
226
+
227
+ context "an unsaved unscoped thing" do
228
+ subject { ImportantThing.new }
229
+ let(:thing) { ImportantThing.new }
230
+ let(:draft) { thing.build_worth_saving_draft }
231
+
232
+ before do
233
+ draft.save
234
+ end
235
+
236
+ its(:worth_saving_draft) { should eq draft }
237
+ end
238
+ end
239
+
240
+ describe '#build_worth_saving_draft' do
241
+ let(:user) { User.create }
242
+ let(:thing) { ScopedThing.new user: user }
243
+
244
+ context 'an unsaved ScopedThing' do
245
+ subject { thing.build_worth_saving_draft }
246
+
247
+ its(:recordable_type) { should eq 'ScopedThing' }
248
+ its(:recordable_id) { should be_nil }
249
+ its(:scopeable) { should eq user }
250
+
251
+ describe 'disallowed attribute override' do
252
+ subject { thing.build_worth_saving_draft recordable_type: 'WrongClass', scopeable_id: 4444 }
253
+
254
+ its(:recordable_type) { should eq 'ScopedThing' }
255
+ its(:scopeable) { should eq user }
256
+ end
257
+ end
258
+
259
+ context 'an unsaved ScopedThing' do
260
+ let(:thing) { ScopedThing.create user: user }
261
+ subject { thing.build_worth_saving_draft form_data: 'some info' }
262
+
263
+ its(:recordable) { should eq thing }
264
+ its(:form_data) { should eq 'some info' }
265
+ end
266
+ end
267
+
268
+ describe 'destruction of worth_saving_draft during save' do
269
+ let(:thing) { ImportantThing.new stuff: 'Something' }
270
+
271
+ context 'new record' do
272
+ it 'happens after but not before' do
273
+ draft = thing.create_worth_saving_draft
274
+ WorthSaving::Draft.find(draft.id).should eq draft
275
+ thing.save
276
+ -> { WorthSaving::Draft.find(draft.id).should }.should raise_error ActiveRecord::RecordNotFound
277
+ end
278
+ end
279
+
280
+ context 'persisted record' do
281
+ it 'happens after but not before' do
282
+ thing.save
283
+ draft = thing.create_worth_saving_draft
284
+ WorthSaving::Draft.find(draft.id).should eq draft
285
+ thing.update_attributes stuff: 'Changed something'
286
+ -> { WorthSaving::Draft.find(draft.id).should }.should raise_error ActiveRecord::RecordNotFound
287
+ end
288
+ end
289
+ end
290
+ end
291
+ end