omninonsense
omninonsense

Reputation: 6892

What is the context of methods called by before_save in a Rails 3 model?

I honestly had no idea what to call this any other way (or what to actually look for).

So, In my ActiveRecord (...app/model/s/account.rb/) I have the following:

validates :username, :password, :email, :presence => true
validates :username, :email, :uniqueness => true
validates :username, :length => { :within => 5..30}
validates :password, :length => { :within => 6..128}
validates :password, :confirmation => true
validates :email, :format => { :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i }
before_save :encrypt_password

private

    def encrypt_password
        require "digest"
        @account.password = Digest::SHA1.hexdigest(@account.password)
    end

And I get the error:

undefined method `password' for nil:NilClass

Why does it report @account as nil? Well, might be because @account doesn't exist outside the View/Controller, but I (honest to god) couldn't think of any other way of doing this.

P.S: I tried putting the encrypt_password inside the controller; it still didn't work (different error, though).

Upvotes: 0

Views: 4318

Answers (2)

Daniel
Daniel

Reputation: 3027

You should try

 def self.hash_password(password = '')
      self.password = Digest::SHA1.hexdigest(password)
 end

Upvotes: 0

Mortice
Mortice

Reputation: 221

Change the method to read:

def encrypt_password
  require 'digest'
  self.password = Digest::SHA1.hexdigest(self.password)
end

The instance variable @account, which you use in the controller and view, refers to an instance of the class Account, which is what you're working on in this file. So, presumably, you're doing something like this in the controller:

@account = Account.new(params)
@account.save!

The instance of class Account receives the 'save!' call and fires its before_save callback, where it needs to refer to itself as 'self', not @account (which is the name your controller has for it).

Side note: you should require 'digest' at the top of your class file rather than inside the method - there's no need to load the digest library every time you want to hash a password.

Upvotes: 4

Related Questions