plataformatec/devise — pull request #2565 by tenderlove (2013-08-11 05:41:08+00:00)
Title: add a class method so you can encrypt passwords from fixtures

# Don't merge this, I want feedback

Hi,

I want to use devise and fixtures. I can't see a way to store the encrypted password in the fixtures file, so right now I have this hack in my app:

```ruby
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

# hack to generate passwords in fixtures
def self.encrypt password
new.send :password_digest, password
end
end
```

Then in my fixtures file:

```yaml
aaron:
name: Aaron Patterson
email: tenderlove@ruby-lang.org
encrypted_password: <%= User.encrypt "password" %>
```

I'd like to expose a method in Devise so that I don't need to know how Devise encrypts passwords, and I can generate the encrypted string in my fixtures. The patch I've sent here would let me do `Devise.password_digest("whatever", User)`, but I don't think that's a very good API. An alternative would be to add a class method to the class so you could do `User.encrypt("whatever")`. Here is a patch for `User.encrypt`:

```diff
diff --git a/lib/devise/models/database_authenticatable.rb b/lib/devise/models/database_authenticatable.rb
index 3e1da40..84daa50 100644
--- a/lib/devise/models/database_authenticatable.rb
+++ b/lib/devise/models/database_authenticatable.rb
@@ -119,10 +119,8 @@ module Devise
end

protected
-
- # Digests the password using bcrypt.
def password_digest(password)
- ::BCrypt::Password.create("#{password}#{self.class.pepper}", :cost => self.class.stretches).to_s
+ self.class.encrypt password
end

module ClassMethods
@@ -135,6 +133,11 @@ module Devise
def find_for_database_authentication(conditions)
find_for_authentication(conditions)
end
+
+ # Digests the password using bcrypt.
+ def encrypt(password)
+ ::BCrypt::Password.create("#{password}#{self.pepper}", :cost => self.stretches).to_s
+ end
end
end
end
```

I didn't send this patch in the PR because I am worried about adding more class methods to everyone's models. I don't know if we care about that though.

Also, I haven't run the tests with these patches (I have small data capped network and I'm afraid to do `bundle`).