devise 1.1.rc1 → 1.1.rc2

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of devise might be problematic. Click here for more details.

Files changed (93) hide show
  1. data/CHANGELOG.rdoc +63 -27
  2. data/Gemfile +15 -13
  3. data/README.rdoc +63 -51
  4. data/Rakefile +3 -2
  5. data/TODO +1 -0
  6. data/app/controllers/devise/registrations_controller.rb +1 -1
  7. data/app/mailers/devise/mailer.rb +43 -43
  8. data/app/views/devise/confirmations/new.html.erb +2 -2
  9. data/app/views/devise/passwords/edit.html.erb +4 -4
  10. data/app/views/devise/passwords/new.html.erb +2 -2
  11. data/app/views/devise/registrations/edit.html.erb +8 -8
  12. data/app/views/devise/registrations/new.html.erb +6 -6
  13. data/app/views/devise/sessions/new.html.erb +4 -4
  14. data/app/views/devise/unlocks/new.html.erb +2 -2
  15. data/config/locales/en.yml +7 -4
  16. data/lib/devise.rb +33 -6
  17. data/lib/devise/controllers/helpers.rb +38 -2
  18. data/lib/devise/encryptors/authlogic_sha512.rb +0 -2
  19. data/lib/devise/encryptors/bcrypt.rb +0 -2
  20. data/lib/devise/encryptors/clearance_sha1.rb +0 -2
  21. data/lib/devise/encryptors/sha1.rb +6 -8
  22. data/lib/devise/encryptors/sha512.rb +6 -8
  23. data/lib/devise/failure_app.rb +3 -2
  24. data/lib/devise/hooks/activatable.rb +4 -1
  25. data/lib/devise/hooks/forgetable.rb +4 -3
  26. data/lib/devise/hooks/rememberable.rb +6 -2
  27. data/lib/devise/hooks/timeoutable.rb +6 -2
  28. data/lib/devise/mapping.rb +7 -8
  29. data/lib/devise/models.rb +0 -34
  30. data/lib/devise/models/authenticatable.rb +29 -3
  31. data/lib/devise/models/confirmable.rb +3 -2
  32. data/lib/devise/models/database_authenticatable.rb +4 -2
  33. data/lib/devise/models/lockable.rb +1 -1
  34. data/lib/devise/models/recoverable.rb +1 -1
  35. data/lib/devise/models/rememberable.rb +9 -1
  36. data/lib/devise/orm/active_record.rb +4 -6
  37. data/lib/devise/orm/data_mapper.rb +5 -7
  38. data/lib/devise/orm/mongoid.rb +2 -13
  39. data/lib/devise/path_checker.rb +13 -0
  40. data/lib/devise/rails.rb +45 -18
  41. data/lib/devise/rails/routes.rb +24 -7
  42. data/lib/devise/schema.rb +23 -19
  43. data/lib/devise/strategies/authenticatable.rb +20 -4
  44. data/lib/devise/strategies/database_authenticatable.rb +1 -1
  45. data/lib/devise/strategies/token_authenticatable.rb +2 -2
  46. data/lib/devise/test_helpers.rb +2 -1
  47. data/lib/devise/version.rb +1 -1
  48. data/lib/generators/devise/devise/devise_generator.rb +86 -0
  49. data/lib/generators/devise/{templates → devise/templates}/migration.rb +2 -2
  50. data/lib/generators/devise/install/install_generator.rb +24 -0
  51. data/lib/generators/{devise_install → devise/install}/templates/README +1 -1
  52. data/lib/generators/{devise_install → devise/install}/templates/devise.rb +37 -18
  53. data/lib/generators/devise/views/views_generator.rb +63 -0
  54. data/lib/generators/devise_generator.rb +2 -0
  55. data/lib/generators/devise_install_generator.rb +4 -0
  56. data/lib/generators/devise_views_generator.rb +4 -0
  57. data/test/controllers/helpers_test.rb +15 -0
  58. data/test/devise_test.rb +1 -0
  59. data/test/failure_app_test.rb +25 -10
  60. data/test/integration/authenticatable_test.rb +279 -0
  61. data/test/integration/database_authenticatable_test.rb +2 -262
  62. data/test/integration/http_authenticatable_test.rb +7 -9
  63. data/test/integration/registerable_test.rb +14 -2
  64. data/test/integration/rememberable_test.rb +15 -3
  65. data/test/integration/timeoutable_test.rb +12 -0
  66. data/test/integration/token_authenticatable_test.rb +2 -3
  67. data/test/mailers/confirmation_instructions_test.rb +2 -2
  68. data/test/mailers/reset_password_instructions_test.rb +2 -2
  69. data/test/mailers/unlock_instructions_test.rb +3 -3
  70. data/test/models/confirmable_test.rb +16 -0
  71. data/test/models/database_authenticatable_test.rb +20 -20
  72. data/test/models/lockable_test.rb +1 -1
  73. data/test/models/rememberable_test.rb +4 -4
  74. data/test/orm/data_mapper.rb +9 -0
  75. data/test/rails_app/app/active_record/shim.rb +2 -0
  76. data/test/rails_app/app/controllers/application_controller.rb +1 -0
  77. data/test/rails_app/app/controllers/home_controller.rb +3 -0
  78. data/test/rails_app/app/controllers/users_controller.rb +2 -0
  79. data/test/rails_app/app/data_mapper/shim.rb +2 -0
  80. data/test/rails_app/app/data_mapper/user.rb +4 -5
  81. data/test/rails_app/app/mongoid/admin.rb +1 -10
  82. data/test/rails_app/app/mongoid/shim.rb +16 -0
  83. data/test/rails_app/app/mongoid/user.rb +1 -12
  84. data/test/rails_app/config/application.rb +2 -0
  85. data/test/rails_app/config/initializers/devise.rb +2 -2
  86. data/test/rails_app/config/routes.rb +6 -1
  87. data/test/routes_test.rb +2 -2
  88. data/test/test_helper.rb +0 -4
  89. data/test/test_helpers_test.rb +1 -0
  90. metadata +113 -12
  91. data/lib/generators/devise/devise_generator.rb +0 -67
  92. data/lib/generators/devise_install/devise_install_generator.rb +0 -25
  93. data/lib/generators/devise_views/devise_views_generator.rb +0 -62
@@ -5,8 +5,7 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
5
5
  test 'sign in should authenticate with http' do
6
6
  sign_in_as_new_user_with_http
7
7
  assert_response :success
8
- assert_template 'users/index'
9
- assert_contain 'Welcome'
8
+ assert_match '<email>user@test.com</email>', response.body
10
9
  assert warden.authenticated?(:user)
11
10
  end
12
11
 
@@ -17,10 +16,10 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
17
16
  end
18
17
 
19
18
  test 'uses the request format as response content type' do
20
- sign_in_as_new_user_with_http("unknown", "123456", :xml)
19
+ sign_in_as_new_user_with_http("unknown")
21
20
  assert_equal 401, status
22
21
  assert_equal "application/xml; charset=utf-8", headers["Content-Type"]
23
- assert response.body.include?("<error>Invalid email or password.</error>")
22
+ assert_match "<error>Invalid email or password.</error>", response.body
24
23
  end
25
24
 
26
25
  test 'returns a custom response with www-authenticate and chosen realm' do
@@ -33,19 +32,18 @@ class HttpAuthenticationTest < ActionController::IntegrationTest
33
32
 
34
33
  test 'sign in should authenticate with http even with specific authentication keys' do
35
34
  swap Devise, :authentication_keys => [:username] do
36
- sign_in_as_new_user_with_http "usertest"
35
+ sign_in_as_new_user_with_http("usertest")
37
36
  assert_response :success
38
- assert_template 'users/index'
39
- assert_contain 'Welcome'
37
+ assert_match '<email>user@test.com</email>', response.body
40
38
  assert warden.authenticated?(:user)
41
39
  end
42
40
  end
43
41
 
44
42
  private
45
43
 
46
- def sign_in_as_new_user_with_http(username="user@test.com", password="123456", format=:html)
44
+ def sign_in_as_new_user_with_http(username="user@test.com", password="123456")
47
45
  user = create_user
48
- get users_path(:format => format), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}"
46
+ get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => "Basic #{ActiveSupport::Base64.encode64("#{username}:#{password}")}"
49
47
  user
50
48
  end
51
49
  end
@@ -113,7 +113,6 @@ class RegistrationTest < ActionController::IntegrationTest
113
113
  assert_equal "user@test.com", User.first.email
114
114
  end
115
115
 
116
-
117
116
  test 'a signed in user should be able to edit his password' do
118
117
  sign_in_as_user
119
118
  get edit_user_registration_path
@@ -129,6 +128,19 @@ class RegistrationTest < ActionController::IntegrationTest
129
128
  assert User.first.valid_password?('pas123')
130
129
  end
131
130
 
131
+ test 'a signed in user should not be able to edit his password with invalid confirmation' do
132
+ sign_in_as_user
133
+ get edit_user_registration_path
134
+
135
+ fill_in 'password', :with => 'pas123'
136
+ fill_in 'password confirmation', :with => ''
137
+ fill_in 'current password', :with => '123456'
138
+ click_button 'Update'
139
+
140
+ assert_contain "Password doesn't match confirmation"
141
+ assert_not User.first.valid_password?('pas123')
142
+ end
143
+
132
144
  test 'a signed in user should be able to cancel his account' do
133
145
  sign_in_as_user
134
146
  get edit_user_registration_path
@@ -138,4 +150,4 @@ class RegistrationTest < ActionController::IntegrationTest
138
150
 
139
151
  assert User.all.empty?
140
152
  end
141
- end
153
+ end
@@ -19,12 +19,24 @@ class RememberMeTest < ActionController::IntegrationTest
19
19
 
20
20
  test 'do not remember the user if he has not checked remember me option' do
21
21
  user = sign_in_as_user
22
+ assert_nil request.cookies["remember_user_cookie"]
22
23
  assert_nil user.reload.remember_token
23
24
  end
24
25
 
25
26
  test 'generate remember token after sign in' do
26
27
  user = sign_in_as_user :remember_me => true
27
- assert_not_nil user.reload.remember_token
28
+ assert request.cookies["remember_user_token"]
29
+ assert user.reload.remember_token
30
+ end
31
+
32
+ test 'generate remember token after sign in setting cookie domain' do
33
+ # We test this by asserting the cookie is not sent after the redirect
34
+ # since we changed the domain. This is the only difference with the
35
+ # previous test.
36
+ swap User, :cookie_domain => "omg.somewhere.com" do
37
+ user = sign_in_as_user :remember_me => true
38
+ assert_nil request.cookies["remember_user_token"]
39
+ end
28
40
  end
29
41
 
30
42
  test 'remember the user before sign in' do
@@ -35,7 +47,7 @@ class RememberMeTest < ActionController::IntegrationTest
35
47
  assert warden.user(:user) == user
36
48
  end
37
49
 
38
- test 'does not remember other scopes' do
50
+ test 'do not remember other scopes' do
39
51
  user = create_user_and_remember
40
52
  get root_path
41
53
  assert_response :success
@@ -50,7 +62,7 @@ class RememberMeTest < ActionController::IntegrationTest
50
62
  assert_redirected_to new_user_session_path
51
63
  end
52
64
 
53
- test 'do not remember with token expired' do
65
+ test 'do not remember with expired token' do
54
66
  user = create_user_and_remember
55
67
  swap Devise, :remember_for => 0 do
56
68
  get users_path
@@ -36,6 +36,18 @@ class SessionTimeoutTest < ActionController::IntegrationTest
36
36
  assert_not warden.authenticated?(:user)
37
37
  end
38
38
 
39
+ test 'time out is not triggered on sign out' do
40
+ user = sign_in_as_user
41
+ get expire_user_path(user)
42
+
43
+ get destroy_user_session_path
44
+ assert_response :redirect
45
+ assert_redirected_to root_path
46
+
47
+ follow_redirect!
48
+ assert_contain 'Signed out successfully'
49
+ end
50
+
39
51
  test 'user configured timeout limit' do
40
52
  swap Devise, :timeout_in => 8.minutes do
41
53
  user = sign_in_as_user
@@ -18,8 +18,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
18
18
  sign_in_as_new_user_with_token(:http_auth => true)
19
19
 
20
20
  assert_response :success
21
- assert_template 'users/index'
22
- assert_contain 'Welcome'
21
+ assert_match '<email>user@test.com</email>', response.body
23
22
  assert warden.authenticated?(:user)
24
23
  end
25
24
  end
@@ -78,7 +77,7 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
78
77
 
79
78
  if options[:http_auth]
80
79
  header = "Basic #{ActiveSupport::Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
81
- get users_path, {}, "HTTP_AUTHORIZATION" => header
80
+ get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
82
81
  else
83
82
  visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
84
83
  end
@@ -36,13 +36,13 @@ class ConfirmationInstructionsTest < ActionMailer::TestCase
36
36
  end
37
37
 
38
38
  test 'setup subject from I18n' do
39
- store_translations :en, :devise => { :mailer => { :confirmation_instructions => 'Account Confirmation' } } do
39
+ store_translations :en, :devise => { :mailer => { :confirmation_instructions => { :subject => 'Account Confirmation' } } } do
40
40
  assert_equal 'Account Confirmation', mail.subject
41
41
  end
42
42
  end
43
43
 
44
44
  test 'subject namespaced by model' do
45
- store_translations :en, :devise => { :mailer => { :user => { :confirmation_instructions => 'User Account Confirmation' } } } do
45
+ store_translations :en, :devise => { :mailer => { :confirmation_instructions => { :user_subject => 'User Account Confirmation' } } } do
46
46
  assert_equal 'User Account Confirmation', mail.subject
47
47
  end
48
48
  end
@@ -39,13 +39,13 @@ class ResetPasswordInstructionsTest < ActionMailer::TestCase
39
39
  end
40
40
 
41
41
  test 'setup subject from I18n' do
42
- store_translations :en, :devise => { :mailer => { :reset_password_instructions => 'Reset instructions' } } do
42
+ store_translations :en, :devise => { :mailer => { :reset_password_instructions => { :subject => 'Reset instructions' } } } do
43
43
  assert_equal 'Reset instructions', mail.subject
44
44
  end
45
45
  end
46
46
 
47
47
  test 'subject namespaced by model' do
48
- store_translations :en, :devise => { :mailer => { :user => { :reset_password_instructions => 'User Reset Instructions' } } } do
48
+ store_translations :en, :devise => { :mailer => { :reset_password_instructions => { :user_subject => 'User Reset Instructions' } } } do
49
49
  assert_equal 'User Reset Instructions', mail.subject
50
50
  end
51
51
  end
@@ -39,13 +39,13 @@ class UnlockInstructionsTest < ActionMailer::TestCase
39
39
  end
40
40
 
41
41
  test 'setup subject from I18n' do
42
- store_translations :en, :devise => { :mailer => { :unlock_instructions => 'Unlock instructions' } } do
43
- assert_equal 'Unlock instructions', mail.subject
42
+ store_translations :en, :devise => { :mailer => { :unlock_instructions => { :subject => 'Yo unlock instructions' } } } do
43
+ assert_equal 'Yo unlock instructions', mail.subject
44
44
  end
45
45
  end
46
46
 
47
47
  test 'subject namespaced by model' do
48
- store_translations :en, :devise => { :mailer => { :user => { :unlock_instructions => 'User Unlock Instructions' } } } do
48
+ store_translations :en, :devise => { :mailer => { :unlock_instructions => { :user_subject => 'User Unlock Instructions' } } } do
49
49
  assert_equal 'User Unlock Instructions', mail.subject
50
50
  end
51
51
  end
@@ -127,6 +127,14 @@ class ConfirmableTest < ActiveSupport::TestCase
127
127
  User.send_confirmation_instructions(:email => user.email)
128
128
  end
129
129
  end
130
+
131
+ test 'should always have confirmation token when email is sent' do
132
+ user = new_user
133
+ user.instance_eval { def confirmation_required?; false end }
134
+ user.save
135
+ user.send_confirmation_instructions
136
+ assert_not_nil user.confirmation_token
137
+ end
130
138
 
131
139
  test 'should not resend email instructions if the user change his email' do
132
140
  user = create_user
@@ -202,4 +210,12 @@ class ConfirmableTest < ActiveSupport::TestCase
202
210
  user.save
203
211
  assert_not user.reload.active?
204
212
  end
213
+
214
+ test 'should be active without confirmation when confirmation is not required' do
215
+ user = create_user
216
+ user.instance_eval { def confirmation_required?; false end }
217
+ user.confirmation_sent_at = nil
218
+ user.save
219
+ assert user.reload.active?
220
+ end
205
221
  end
@@ -3,10 +3,22 @@ require 'digest/sha1'
3
3
 
4
4
  class DatabaseAuthenticatableTest < ActiveSupport::TestCase
5
5
 
6
- def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=::Devise::Encryptors::Sha1)
6
+ def encrypt_password(user, pepper=User.pepper, stretches=User.stretches, encryptor=User.encryptor_class)
7
7
  encryptor.digest('123456', stretches, user.password_salt, pepper)
8
8
  end
9
9
 
10
+ def swap_with_encryptor(klass, encryptor, options={})
11
+ klass.instance_variable_set(:@encryptor_class, nil)
12
+
13
+ swap klass, options.merge(:encryptor => encryptor) do
14
+ begin
15
+ yield
16
+ ensure
17
+ klass.instance_variable_set(:@encryptor_class, nil)
18
+ end
19
+ end
20
+ end
21
+
10
22
  test 'should respond to password and password confirmation' do
11
23
  user = new_user
12
24
  assert user.respond_to?(:password)
@@ -28,8 +40,10 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
28
40
  end
29
41
 
30
42
  test 'should generate a base64 hash using SecureRandom for password salt' do
31
- ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
32
- assert_equal 'friendly_token', new_user.password_salt
43
+ swap_with_encryptor User, :sha1 do
44
+ ActiveSupport::SecureRandom.expects(:base64).with(15).returns('friendly_token')
45
+ assert_equal 'friendly_token', new_user.password_salt
46
+ end
33
47
  end
34
48
 
35
49
  test 'should not generate salt if password is blank' do
@@ -71,24 +85,10 @@ class DatabaseAuthenticatableTest < ActiveSupport::TestCase
71
85
  end
72
86
  end
73
87
 
74
- test 'should fallback to devise stretches default configuration' do
75
- swap Devise, :stretches => 1 do
76
- user = new_user
77
- assert_equal encrypt_password(user, nil, 1), user.encrypted_password
78
- assert_not_equal encrypt_password(user, nil, 2), user.encrypted_password
79
- end
80
- end
81
-
82
88
  test 'should respect encryptor configuration' do
83
- User.instance_variable_set(:@encryptor_class, nil)
84
-
85
- swap Devise, :encryptor => :sha512 do
86
- begin
87
- user = create_user
88
- assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512)
89
- ensure
90
- User.instance_variable_set(:@encryptor_class, nil)
91
- end
89
+ swap_with_encryptor User, :sha512 do
90
+ user = create_user
91
+ assert_equal user.encrypted_password, encrypt_password(user, User.pepper, User.stretches, ::Devise::Encryptors::Sha512)
92
92
  end
93
93
  end
94
94
 
@@ -64,7 +64,7 @@ class LockableTest < ActiveSupport::TestCase
64
64
  user.unlock_access!
65
65
  assert_nil user.reload.locked_at
66
66
  assert_nil user.reload.unlock_token
67
- assert 0, user.reload.failed_attempts
67
+ assert_equal 0, user.reload.failed_attempts
68
68
  end
69
69
 
70
70
  test 'should not unlock an unlocked user' do
@@ -18,19 +18,19 @@ class RememberableTest < ActiveSupport::TestCase
18
18
  test 'forget_me should clear remember token and save the record without validating' do
19
19
  user = create_user
20
20
  user.remember_me!
21
- assert user.remember_token?
21
+ assert_not user.remember_token.nil?
22
22
  user.expects(:valid?).never
23
23
  user.forget_me!
24
- assert_not user.remember_token?
24
+ assert user.remember_token.nil?
25
25
  assert_not user.changed?
26
26
  end
27
27
 
28
28
  test 'forget_me should clear remember_created_at' do
29
29
  user = create_user
30
30
  user.remember_me!
31
- assert user.remember_created_at?
31
+ assert_not user.remember_created_at.nil?
32
32
  user.forget_me!
33
- assert_not user.remember_created_at?
33
+ assert user.remember_created_at.nil?
34
34
  end
35
35
 
36
36
  test 'forget should do nothing if no remember token exists' do
@@ -1 +1,10 @@
1
+ require 'rails/test_help'
2
+
1
3
  DataMapper.auto_migrate!
4
+
5
+ class ActiveSupport::TestCase
6
+ setup do
7
+ User.all.destroy!
8
+ Admin.all.destroy!
9
+ end
10
+ end
@@ -0,0 +1,2 @@
1
+ module Shim
2
+ end
@@ -5,4 +5,5 @@ class ApplicationController < ActionController::Base
5
5
  protect_from_forgery
6
6
 
7
7
  before_filter :current_user
8
+ before_filter :authenticate_user!, :if => :devise_controller?
8
9
  end
@@ -1,4 +1,7 @@
1
1
  class HomeController < ApplicationController
2
2
  def index
3
3
  end
4
+
5
+ def private
6
+ end
4
7
  end
@@ -1,8 +1,10 @@
1
1
  class UsersController < ApplicationController
2
2
  before_filter :authenticate_user!
3
+ respond_to :html, :xml
3
4
 
4
5
  def index
5
6
  user_session[:cart] = "Cart"
7
+ respond_with(current_user)
6
8
  end
7
9
 
8
10
  def expire
@@ -0,0 +1,2 @@
1
+ module Shim
2
+ end
@@ -1,6 +1,9 @@
1
1
  class User
2
2
  include DataMapper::Resource
3
-
3
+
4
+ extend Devise::Orm::DataMapper::Schema
5
+ include Devise::Orm::DataMapper::Compatibility
6
+
4
7
  property :id, Serial
5
8
  property :username, String
6
9
 
@@ -10,10 +13,6 @@ class User
10
13
 
11
14
  timestamps :at
12
15
 
13
- def save!(*args)
14
- save
15
- end
16
-
17
16
  def self.create!(*args)
18
17
  create(*args)
19
18
  end
@@ -1,15 +1,6 @@
1
1
  class Admin
2
2
  include Mongoid::Document
3
+ include Shim
3
4
 
4
5
  devise :database_authenticatable, :timeoutable, :registerable, :recoverable
5
-
6
- def self.last(options={})
7
- options.delete(:order) if options[:order] == "id"
8
- super options
9
- end
10
-
11
- # overwrite equality (because some devise tests use this for asserting model equality)
12
- def ==(other)
13
- other.is_a?(self.class) && _id == other._id
14
- end
15
6
  end
@@ -0,0 +1,16 @@
1
+ module Shim
2
+ extend ::ActiveSupport::Concern
3
+ include ::Mongoid::Timestamps
4
+
5
+ module ClassMethods
6
+ def last(options={})
7
+ options.delete(:order) if options[:order] == "id"
8
+ super(options)
9
+ end
10
+ end
11
+
12
+ # overwrite equality (because some devise tests use this for asserting model equality)
13
+ def ==(other)
14
+ other.is_a?(self.class) && _id == other._id
15
+ end
16
+ end
@@ -1,21 +1,10 @@
1
1
  class User
2
2
  include Mongoid::Document
3
+ include Shim
3
4
 
4
5
  field :created_at, :type => DateTime
5
6
 
6
7
  devise :database_authenticatable, :confirmable, :lockable, :recoverable,
7
8
  :registerable, :rememberable, :timeoutable, :token_authenticatable,
8
9
  :trackable, :validatable
9
-
10
- # attr_accessible :username, :email, :password, :password_confirmation
11
-
12
- def self.last(options={})
13
- options.delete(:order) if options[:order] == "id"
14
- super options
15
- end
16
-
17
- # overwrite equality (because some devise tests use this for asserting model equality)
18
- def ==(other)
19
- other.is_a?(self.class) && _id == other._id
20
- end
21
10
  end