worth_saving 0.0.9

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 (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