Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is before_save not getting called for my ActiveRecord model?

Nothing prints out to the console when I use IRB to create a new model instance and save, and I get a "ActiveRecord::StatementInvalid: Mysql::Error: Column 'user_id' cannot be null" error, so I assume before_save is not getting called. I can't figure out why. I've even tried using the before_save filter. Here's my code:

require 'secure_resource/secure_resource_encryption'

class Database < ActiveRecord::Base
  belongs_to :username_encryption, :class_name => "Encryption", :foreign_key => :username_encryption_id
  belongs_to :password_encryption, :class_name => "Encryption", :foreign_key => :password_encryption_id

  # Virtual attribute to retrieve the decrypted username.
  def username
    if self.username_encryption.nil?
      return nil
    end

    begin
      return self.username_encryption.encryption
    rescue SecureResourceError
      raise SecureResourceError
    end
  end

  # Provides a way to reset the username.
  def username=(username)
    if self.username_encryption.nil?
      self.username_encryption = Encryption.new
      self.username_encryption.encryption = username
    end
  end

  # Virtual attribute to retrieve the decrypted password.
  def password
    if password_encryption.nil?
      return nil
    end

    begin
      return password_encryption.encryption
    rescue SecureResourceError
      raise SecureResourceError
    end
  end

  # Provides a way to reset the password.
  def password=(password)
    if self.password_encryption.nil?
      self.password_encryption = Encryption.new
      self.password_encryption.encryption = password
    end
  end

  def before_save
    p 'ZZZZZZZZZZZZZZZ'
    p self.user_id.to_s + ' ZZZZZZ'
    p 'ZZZZZZZZZZZZZZZ'
    self.username_encryption.user_id = self.user_id
    self.username_encryption.save
    self.username_encryption_id = self.username_encryption.id

    self.password_encryption.user_id = self.user_id
    self.password_encryption.save
    self.password_encryption_id = self.password_encryption.id
  end
end
like image 336
Chad Johnson Avatar asked Jun 10 '11 18:06

Chad Johnson


1 Answers

As you can see in the documentation, before_save happens after validation. In your case, validation will fail and before_save will never be invoked.

Since the goal of your callback is to set your object to a valid state before validation happens, try the before_validation callback.

like image 98
meagar Avatar answered Nov 04 '22 23:11

meagar