thoughtbot-clearance 0.3.9 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +19 -43
- data/Rakefile +1 -1
- data/generators/clearance/templates/README +27 -10
- data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +4 -2
- data/generators/clearance/templates/app/views/clearance_mailer/confirmation.html.erb +1 -1
- data/generators/clearance/templates/app/views/passwords/edit.html.erb +5 -3
- data/generators/clearance/templates/app/views/passwords/new.html.erb +2 -2
- data/generators/clearance/templates/app/views/sessions/new.html.erb +4 -2
- data/generators/clearance/templates/app/views/users/_form.html.erb +1 -1
- data/generators/clearance/templates/app/views/users/edit.html.erb +2 -0
- data/generators/clearance/templates/app/views/users/new.html.erb +2 -0
- data/lib/clearance/app/controllers/application_controller.rb +1 -1
- data/lib/clearance/app/controllers/confirmations_controller.rb +2 -1
- data/lib/clearance/app/controllers/passwords_controller.rb +2 -2
- data/lib/clearance/app/controllers/sessions_controller.rb +5 -13
- data/lib/clearance/test/functional/confirmations_controller_test.rb +2 -0
- data/lib/clearance/test/functional/passwords_controller_test.rb +21 -20
- data/lib/clearance/test/test_helper.rb +1 -1
- data/lib/clearance/test/unit/clearance_mailer_test.rb +4 -4
- data/shoulda_macros/clearance.rb +1 -1
- metadata +1 -1
data/README.textile
CHANGED
@@ -24,7 +24,7 @@ In config/environment.rb:
|
|
24
24
|
config.gem "thoughtbot-clearance",
|
25
25
|
:lib => 'clearance',
|
26
26
|
:source => 'http://gems.github.com',
|
27
|
-
:version => '>= 0.3.
|
27
|
+
:version => '>= 0.3.9'
|
28
28
|
|
29
29
|
Then:
|
30
30
|
|
@@ -33,32 +33,11 @@ Then:
|
|
33
33
|
|
34
34
|
h2. The generator
|
35
35
|
|
36
|
-
|
36
|
+
Make sure the development database exists and run the generator:
|
37
37
|
|
38
38
|
script/generate clearance
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
app/controllers/confirmations_controller.rb
|
43
|
-
app/controllers/passwords_controller.rb
|
44
|
-
app/controllers/sessions_controller.rb
|
45
|
-
app/controllers/users_controller.rb
|
46
|
-
app/models/user.rb
|
47
|
-
app/models/user_mailer.rb
|
48
|
-
app/views/passwords/edit.html.erb
|
49
|
-
app/views/passwords/new.html.erb
|
50
|
-
app/views/sessions/new.html.erb
|
51
|
-
app/views/user_mailer/change_password.html.erb
|
52
|
-
app/views/user_mailer/confirmation.html.erb
|
53
|
-
app/views/users/_form.html.erb
|
54
|
-
app/views/users/edit.html.erb
|
55
|
-
app/views/users/new.html.erb
|
56
|
-
test/functional/confirmations_controller_test.rb
|
57
|
-
test/functional/passwords_controller_test.rb
|
58
|
-
test/functional/sessions_controller_test.rb
|
59
|
-
test/functional/users_controller_test.rb
|
60
|
-
test/unit/clearance_mailer_test.rb
|
61
|
-
test/unit/user_test.rb
|
40
|
+
A number of files will be created and instructions will be printed.
|
62
41
|
|
63
42
|
You may already have some of these files. Don't worry. You'll be asked if you want to overwrite them.
|
64
43
|
|
@@ -93,7 +72,7 @@ h2. Routes
|
|
93
72
|
Clearance will add these routes to your routes.rb:
|
94
73
|
|
95
74
|
map.resources :users, :has_one => [:password, :confirmation]
|
96
|
-
map.resource
|
75
|
+
map.resource :session
|
97
76
|
map.resources :passwords
|
98
77
|
|
99
78
|
Please note that Clearance depends on root_url, so please make sure that it is defined to *something* in your config/routes.rb:
|
@@ -114,7 +93,7 @@ In config/environment.rb:
|
|
114
93
|
|
115
94
|
h2. Tests
|
116
95
|
|
117
|
-
The tests use "Shoulda":http://thoughtbot.com/projects/shoulda >= 2.0.6 and "Factory Girl":http://thoughtbot.com/projects/factory_girl >= 1.1.5.
|
96
|
+
The tests use "Shoulda":http://thoughtbot.com/projects/shoulda >= 2.0.6 and "Factory Girl":http://thoughtbot.com/projects/factory_girl >= 1.1.5. There needs to be a Clearance module in your test/test_helper.rb:
|
118
97
|
|
119
98
|
class Test::Unit::TestCase
|
120
99
|
self.use_transactional_fixtures = true
|
@@ -129,9 +108,9 @@ h2. Usage: basic workflow
|
|
129
108
|
|
130
109
|
Rails authentication with Clearance uses the standard approach thoughtbot and our clients have agreed upon.
|
131
110
|
|
132
|
-
Users register (UsersController) using an email address and a password (User model). They get an email with a confirmation link
|
111
|
+
Users register (UsersController) using an email address and a password (User model). They get an email (ClearanceMailer) with a confirmation link to confirm their registration (ConfirmationController).
|
133
112
|
|
134
|
-
Registered users can sign in and out (SessionsController). If they forget their password, they request an email containing a link to change it (PasswordsController).
|
113
|
+
Registered users can sign in and out (SessionsController). If they forget their password, they request an email (ClearanceMailer) containing a link to change it (PasswordsController).
|
135
114
|
|
136
115
|
h2. Usage: actions which require an authenticated user
|
137
116
|
|
@@ -143,7 +122,7 @@ To protect your controllers with authentication add:
|
|
143
122
|
The filter will ensure that only authenticated users can access the controller. If someone who's not signed in tries to access a protected action:
|
144
123
|
|
145
124
|
* the URL is stored in the session,
|
146
|
-
* the user is redirected to
|
125
|
+
* the user is redirected to sign in page, and
|
147
126
|
* after successful authentication will be be redirected back to that URL.
|
148
127
|
|
149
128
|
h2. Usage: signed_in?, current_user
|
@@ -152,13 +131,11 @@ Clearance provides two methods that can be used in controllers, helpers, and vie
|
|
152
131
|
|
153
132
|
* signed_in?
|
154
133
|
* current_user
|
155
|
-
|
156
|
-
This may be familiar to you if you've used "restful_authentication":http://github.com/technoweenie/restful-authentication.
|
157
|
-
|
134
|
+
|
158
135
|
<% if signed_in? -%>
|
159
136
|
Hello, <%= current_user.name %>!
|
160
137
|
<% else -%>
|
161
|
-
Please <%= link_to '
|
138
|
+
Please <%= link_to 'Sign in', new_session_path %>
|
162
139
|
<% end -%>
|
163
140
|
|
164
141
|
h2. Usage: mass assignment
|
@@ -168,14 +145,13 @@ Please note that all User attributes except email, password and password_confirm
|
|
168
145
|
class User < ActiveRecord::Base
|
169
146
|
include Clearance::App::Models::User
|
170
147
|
attr_accessible :first_name, :last_name
|
171
|
-
|
148
|
+
end
|
172
149
|
|
173
150
|
h2. Hooks: return_to parameter
|
174
151
|
|
175
|
-
|
152
|
+
To specify where to redirect a user (say you want to have a sign in form on every page and redirect the user to the same page) after he/she signs in, you can add a "return_to" parameter to the request (thanks to "Phillippe":http://www.sivarg.com/2009/01/clearance-coming-from-where-your-were.html for the tip):
|
176
153
|
|
177
|
-
<% form_for :session, :url => session_path(:return_to => request.request_uri) do |form| %>
|
178
|
-
...
|
154
|
+
<% form_for :session, :url => session_path(:return_to => request.request_uri) do |form| %>
|
179
155
|
|
180
156
|
h2. Hooks: url_after_create, url_after_destroy
|
181
157
|
|
@@ -193,24 +169,24 @@ Actions that redirect (create and destroy) in Clearance controllers are customiz
|
|
193
169
|
|
194
170
|
There are similar methods in other controllers as well:
|
195
171
|
|
196
|
-
UsersController#url_after_create (
|
172
|
+
UsersController#url_after_create (register)
|
197
173
|
SessionsController#url_after_create (sign in)
|
198
174
|
SessionsController#url_after_destroy (sign out)
|
199
|
-
PasswordsController#url_after_create (password
|
175
|
+
PasswordsController#url_after_create (password request)
|
200
176
|
ConfirmationsController#url_after_create (confirmation)
|
201
177
|
|
202
|
-
h2. Hooks:
|
178
|
+
h2. Hooks: sign_user_in
|
203
179
|
|
204
|
-
Say you want to add a last_signed_in_at attribute to your User model. You would want to update it when the User
|
180
|
+
Say you want to add a last_signed_in_at attribute to your User model. You would want to update it when the User signs in.
|
205
181
|
|
206
|
-
Clearance has a method named
|
182
|
+
Clearance has a method named sign_user_in that you can overwrite with that logic. Be sure to call sign_in(user) at the end (and write tests!).
|
207
183
|
|
208
184
|
class ApplicationController < ActionController::Base
|
209
185
|
include Clearance::App::Controllers::ApplicationController
|
210
186
|
|
211
187
|
private
|
212
188
|
|
213
|
-
def
|
189
|
+
def sign_user_in(user)
|
214
190
|
# store current time to display "last signed in at" message
|
215
191
|
user.update_attribute(:last_signed_in_at, Time.now)
|
216
192
|
sign_in(user)
|
data/Rakefile
CHANGED
@@ -36,7 +36,7 @@ task :default => 'test:all'
|
|
36
36
|
|
37
37
|
gem_spec = Gem::Specification.new do |gem_spec|
|
38
38
|
gem_spec.name = "clearance"
|
39
|
-
gem_spec.version = "0.
|
39
|
+
gem_spec.version = "0.4.0"
|
40
40
|
gem_spec.summary = "Simple, complete Rails authentication."
|
41
41
|
gem_spec.email = "support@thoughtbot.com"
|
42
42
|
gem_spec.homepage = "http://github.com/thoughtbot/clearance"
|
@@ -1,30 +1,46 @@
|
|
1
|
+
|
1
2
|
*******************************************************************************
|
3
|
+
|
2
4
|
Ok, enough fancy automatic stuff. Time for some old school monkey copy-pasting.
|
3
5
|
|
4
6
|
1. For any other file(s) that you already had and didn't want to overwrite, add
|
5
7
|
the corresponding Clearance module. They are namespaced exactly like the
|
6
|
-
directory structure of a Rails app
|
8
|
+
directory structure of a Rails app.
|
9
|
+
|
10
|
+
Application controller example:
|
11
|
+
|
12
|
+
class ApplicationController < ActionController::Base
|
13
|
+
include Clearance::App::Controllers::ApplicationController
|
14
|
+
end
|
7
15
|
|
8
|
-
|
16
|
+
User model example:
|
9
17
|
|
10
|
-
class User < ActiveRecord::Base
|
11
|
-
|
12
|
-
|
18
|
+
class User < ActiveRecord::Base
|
19
|
+
include Clearance::App::Models::User
|
20
|
+
end
|
21
|
+
|
22
|
+
User test example:
|
13
23
|
|
14
|
-
|
24
|
+
class UserTest < Test::Unit::TestCase
|
25
|
+
include Clearance::Test::Unit::UserTest
|
26
|
+
end
|
27
|
+
|
28
|
+
2. You need to define HOST constant in your environments files.
|
29
|
+
In config/environments/test.rb and config/environments/development.rb it can be:
|
15
30
|
|
16
31
|
HOST = "localhost"
|
17
32
|
|
18
|
-
|
33
|
+
In production.rb it must be the actual host your application is deployed to.
|
34
|
+
The constant is used by mailers to generate URLs in emails.
|
19
35
|
|
20
36
|
In config/environment.rb:
|
21
37
|
|
22
38
|
DO_NOT_REPLY = "donotreply@example.com"
|
23
39
|
|
24
|
-
3. Clearance depends on root_url, so please make sure that it is defined
|
25
|
-
your config/routes.rb:
|
40
|
+
3. Clearance depends on root_url, so please make sure that it is defined to
|
41
|
+
*something* your config/routes.rb:
|
26
42
|
|
27
|
-
map.root :controller => '
|
43
|
+
map.root :controller => 'home'
|
28
44
|
|
29
45
|
4. To run tests you need to add the Clearance module to your
|
30
46
|
test/test_helper.rb:
|
@@ -34,4 +50,5 @@ test/test_helper.rb:
|
|
34
50
|
self.use_instantiated_fixtures = false
|
35
51
|
include Clearance::Test::TestHelper
|
36
52
|
end
|
53
|
+
|
37
54
|
*******************************************************************************
|
@@ -1,8 +1,10 @@
|
|
1
1
|
Someone, hopefully you, has requested that we send you a link to change your password.
|
2
2
|
|
3
3
|
Here's the link:
|
4
|
+
|
4
5
|
<%= edit_user_password_url(@user,
|
5
6
|
:email => @user.email,
|
6
|
-
:password => @user.encrypted_password
|
7
|
+
:password => @user.encrypted_password,
|
8
|
+
:escape => false) %>
|
7
9
|
|
8
|
-
If you didn't request this,
|
10
|
+
If you didn't request this, don't worry: your password hasn't been changed. You can just ignore this email.
|
@@ -1 +1 @@
|
|
1
|
-
<%= new_user_confirmation_url :user_id => @user, :salt => @user.salt %>
|
1
|
+
<%= new_user_confirmation_url :user_id => @user, :salt => @user.salt %>
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<h2>Change your password</h2>
|
2
|
+
|
1
3
|
<p>
|
2
4
|
Your password has been reset. Choose a new password below.
|
3
5
|
</p>
|
@@ -10,14 +12,14 @@
|
|
10
12
|
:password => @user.encrypted_password),
|
11
13
|
:html => { :method => :put }) do |form| %>
|
12
14
|
<div class="password_field">
|
13
|
-
<%= form.label :password,
|
15
|
+
<%= form.label :password, "Choose password" %>
|
14
16
|
<%= form.password_field :password %>
|
15
17
|
</div>
|
16
18
|
<div class="password_field">
|
17
|
-
<%= form.label :password_confirmation,
|
19
|
+
<%= form.label :password_confirmation, "Verify password" %>
|
18
20
|
<%= form.password_field :password_confirmation %>
|
19
21
|
</div>
|
20
22
|
<div class="submit_field">
|
21
|
-
<%= form.submit
|
23
|
+
<%= form.submit "Save this password", :disable_with => "Please wait..." %>
|
22
24
|
</div>
|
23
25
|
<% end %>
|
@@ -6,10 +6,10 @@
|
|
6
6
|
|
7
7
|
<% form_for :password, :url => passwords_path do |form| %>
|
8
8
|
<div class="text_field">
|
9
|
-
<%= form.label :email,
|
9
|
+
<%= form.label :email, "Email address" %>
|
10
10
|
<%= form.text_field :email %>
|
11
11
|
</div>
|
12
12
|
<div class="submit_field">
|
13
|
-
<%= form.submit
|
13
|
+
<%= form.submit "Reset password", :disable_with => "Please wait..." %>
|
14
14
|
</div>
|
15
15
|
<% end %>
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<h2>Sign in</h2>
|
2
|
+
|
1
3
|
<% form_for :session, :url => session_path do |form| %>
|
2
4
|
<div class="text_field">
|
3
5
|
<%= form.label :email %>
|
@@ -12,7 +14,7 @@
|
|
12
14
|
<%= form.label :remember_me %>
|
13
15
|
</div>
|
14
16
|
<div class="submit_field">
|
15
|
-
<%= form.submit
|
17
|
+
<%= form.submit "Sign in", :disable_with => "Please wait..." %>
|
16
18
|
</div>
|
17
19
|
<% end %>
|
18
20
|
|
@@ -21,6 +23,6 @@
|
|
21
23
|
<%= link_to "Register", new_user_path %>
|
22
24
|
</li>
|
23
25
|
<li>
|
24
|
-
<%= link_to "Forgot
|
26
|
+
<%= link_to "Forgot password?", new_password_path %>
|
25
27
|
</li>
|
26
28
|
</ul>
|
@@ -15,7 +15,7 @@ module Clearance
|
|
15
15
|
def create
|
16
16
|
user = User.find_by_email(params[:password][:email])
|
17
17
|
if user.nil?
|
18
|
-
flash.now[:notice] =
|
18
|
+
flash.now[:notice] = "Unknown email"
|
19
19
|
render :action => :new
|
20
20
|
else
|
21
21
|
ClearanceMailer.deliver_change_password user
|
@@ -34,7 +34,7 @@ module Clearance
|
|
34
34
|
@user = User.find_by_email_and_encrypted_password(params[:email],
|
35
35
|
params[:password])
|
36
36
|
if @user.update_attributes params[:user]
|
37
|
-
|
37
|
+
sign_user_in(@user)
|
38
38
|
redirect_to url_after_update
|
39
39
|
else
|
40
40
|
render :action => :edit
|
@@ -13,12 +13,14 @@ module Clearance
|
|
13
13
|
@user = User.authenticate(params[:session][:email],
|
14
14
|
params[:session][:password])
|
15
15
|
if @user.nil?
|
16
|
-
|
16
|
+
flash.now[:notice] = "Bad email or password."
|
17
|
+
render :action => :new
|
17
18
|
else
|
18
19
|
if @user.email_confirmed?
|
19
20
|
remember(@user) if remember?
|
20
|
-
|
21
|
-
|
21
|
+
sign_user_in(@user)
|
22
|
+
flash[:notice] = "Signed in successfully"
|
23
|
+
redirect_back_or url_after_create
|
22
24
|
else
|
23
25
|
deny_access("User has not confirmed email.")
|
24
26
|
end
|
@@ -34,16 +36,6 @@ module Clearance
|
|
34
36
|
|
35
37
|
private
|
36
38
|
|
37
|
-
def sign_in_successful(message = "Signed in successfully")
|
38
|
-
flash[:notice] = message
|
39
|
-
redirect_back_or url_after_create
|
40
|
-
end
|
41
|
-
|
42
|
-
def sign_in_failure(message = "Bad email or password.")
|
43
|
-
flash.now[:notice] = message
|
44
|
-
render :action => :new
|
45
|
-
end
|
46
|
-
|
47
39
|
def remember?
|
48
40
|
params[:session] && params[:session][:remember_me] == "1"
|
49
41
|
end
|
@@ -16,6 +16,8 @@ module Clearance
|
|
16
16
|
get :new, :user_id => @user.to_param, :salt => @user.salt
|
17
17
|
end
|
18
18
|
|
19
|
+
should_set_the_flash_to /confirmed email/i
|
20
|
+
should_set_the_flash_to /signed in/i
|
19
21
|
should_be_signed_in_and_email_confirmed_as { @user }
|
20
22
|
should_redirect_to_url_after_create
|
21
23
|
end
|
@@ -16,43 +16,44 @@ module Clearance
|
|
16
16
|
setup { get :new, :user_id => @user.to_param }
|
17
17
|
|
18
18
|
should_respond_with :success
|
19
|
-
should_render_template
|
19
|
+
should_render_template "new"
|
20
20
|
end
|
21
21
|
|
22
|
-
context
|
22
|
+
context "A POST to #create" do
|
23
23
|
context "with an existing user's email address" do
|
24
24
|
setup do
|
25
25
|
ActionMailer::Base.deliveries.clear
|
26
26
|
|
27
27
|
post :create, :password => { :email => @user.email }
|
28
|
-
@email = ActionMailer::Base.deliveries[0]
|
29
28
|
end
|
30
|
-
|
31
|
-
should
|
32
|
-
|
29
|
+
|
30
|
+
should "send the change your password email" do
|
31
|
+
assert_sent_email do |email|
|
32
|
+
email.subject =~ /change your password/i
|
33
|
+
end
|
33
34
|
end
|
34
35
|
|
35
|
-
should
|
36
|
+
should "set a :notice flash with the user email address" do
|
36
37
|
assert_match /#{@user.email}/, flash[:notice]
|
37
38
|
end
|
38
39
|
|
39
40
|
should_redirect_to_url_after_create
|
40
41
|
end
|
41
42
|
|
42
|
-
context
|
43
|
+
context "with a non-existent email address" do
|
43
44
|
setup do
|
44
|
-
email =
|
45
|
+
email = "user1@example.com"
|
45
46
|
assert ! User.exists?(['email = ?', email])
|
46
47
|
ActionMailer::Base.deliveries.clear
|
47
48
|
|
48
49
|
post :create, :password => { :email => email }
|
49
50
|
end
|
50
51
|
|
51
|
-
should
|
52
|
+
should "not send a password reminder email" do
|
52
53
|
assert ActionMailer::Base.deliveries.empty?
|
53
54
|
end
|
54
55
|
|
55
|
-
should
|
56
|
+
should "set a :notice flash" do
|
56
57
|
assert_not_nil flash.now[:notice]
|
57
58
|
end
|
58
59
|
|
@@ -60,7 +61,7 @@ module Clearance
|
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
63
|
-
context
|
64
|
+
context "A GET to #edit" do
|
64
65
|
context "with an existing user's id and password" do
|
65
66
|
setup do
|
66
67
|
get :edit,
|
@@ -69,7 +70,7 @@ module Clearance
|
|
69
70
|
:email => @user.email
|
70
71
|
end
|
71
72
|
|
72
|
-
should
|
73
|
+
should "find the user with the given id and password" do
|
73
74
|
assert_equal @user, assigns(:user)
|
74
75
|
end
|
75
76
|
|
@@ -91,7 +92,7 @@ module Clearance
|
|
91
92
|
|
92
93
|
context "with an existing user's id but not password" do
|
93
94
|
setup do
|
94
|
-
get :edit, :user_id => @user.to_param, :password =>
|
95
|
+
get :edit, :user_id => @user.to_param, :password => ""
|
95
96
|
end
|
96
97
|
|
97
98
|
should_respond_with :not_found
|
@@ -99,10 +100,10 @@ module Clearance
|
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
102
|
-
context
|
103
|
+
context "A PUT to #update" do
|
103
104
|
context "with an existing user's id but not password" do
|
104
105
|
setup do
|
105
|
-
put :update, :user_id => @user.to_param, :password =>
|
106
|
+
put :update, :user_id => @user.to_param, :password => ""
|
106
107
|
end
|
107
108
|
|
108
109
|
should "not update the user's password" do
|
@@ -114,9 +115,9 @@ module Clearance
|
|
114
115
|
should_render_nothing
|
115
116
|
end
|
116
117
|
|
117
|
-
context
|
118
|
+
context "with a matching password and password confirmation" do
|
118
119
|
setup do
|
119
|
-
new_password =
|
120
|
+
new_password = "new_password"
|
120
121
|
@encrypted_new_password = @user.encrypt(new_password)
|
121
122
|
assert_not_equal @encrypted_new_password, @user.encrypted_password
|
122
123
|
|
@@ -139,9 +140,9 @@ module Clearance
|
|
139
140
|
should_redirect_to_url_after_update
|
140
141
|
end
|
141
142
|
|
142
|
-
context
|
143
|
+
context "with password but blank password confirmation" do
|
143
144
|
setup do
|
144
|
-
new_password =
|
145
|
+
new_password = "new_password"
|
145
146
|
@encrypted_new_password = @user.encrypt(new_password)
|
146
147
|
|
147
148
|
put(:update,
|
@@ -18,7 +18,7 @@ module Clearance
|
|
18
18
|
|
19
19
|
should "contain a link to edit the user's password" do
|
20
20
|
host = ActionMailer::Base.default_url_options[:host]
|
21
|
-
regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?email=#{@user.email.gsub("@", "%40")}&
|
21
|
+
regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?email=#{@user.email.gsub("@", "%40")}&password=#{@user.encrypted_password}}
|
22
22
|
assert_match regexp, @email.body
|
23
23
|
end
|
24
24
|
|
@@ -37,15 +37,15 @@ module Clearance
|
|
37
37
|
@email = ClearanceMailer.create_confirmation @user
|
38
38
|
end
|
39
39
|
|
40
|
-
should
|
40
|
+
should "set its recipient to the given user" do
|
41
41
|
assert_equal @user.email, @email.to[0]
|
42
42
|
end
|
43
43
|
|
44
|
-
should
|
44
|
+
should "set its subject" do
|
45
45
|
assert_match /Account confirmation/, @email.subject
|
46
46
|
end
|
47
47
|
|
48
|
-
should
|
48
|
+
should "set its from address to DO_NOT_REPLY" do
|
49
49
|
assert_equal DO_NOT_REPLY, @email.from[0]
|
50
50
|
end
|
51
51
|
|
data/shoulda_macros/clearance.rb
CHANGED