rails/rails — pull request #8408 by revans (2012-12-03 17:44:21+00:00)
Title: ActiveModel SecurePassword cost factor for BCrypt

ActiveModel::SecurePassword currently has a class method #min_cost that is used to set a boolean value to change the cost factor of bcrypt-ruby to either 4 (MIN_COST of bcrypt-ruby) or 10 (DEFAULT in bcrypt-ruby).

If you want to have more fine-grained control over the cost factor you need to override the #password= method of the SecurePassword module with your own model that is using has_secure_password.

This PR removes the #min_cost class method and replaces it with a #cost class method which takes an integer. A developer can then set this class method to a specific value is required by their application by doing:

```ruby
class User < ActiveRecord::Base
has_secure_password
ActiveModel::SecurePassword.cost = 15
end
```

#cost maintains the same behavior of #min_cost where it is set to the MIN_COST during tests and defaults to bcrypt-ruby's DEFAULT value.

I personally like having a bit more control over the hash stretches for when I need it, in a simple class setter method instead of override an instance method.

However, I feel like this is the middle of the road solution. I think a better implementation would be:

```ruby
class User < ActiveRecord::Base
has_secure_password cost: 15
end
```

#has_secure_password class method already has support for hash parameters (validations), so adding another key/value for cost is trivial.

Secondly, I think it would be better to set the min_cost and default_cost using bcrypt-ruby's constants instead of integers as I did in this implementation.

I'm opening this PR to show what I've added and start the conversation on what I think would be the better implementation. I don't want to go too far down the road if the Core/Others feel this isn't the right direction. Thanks!