【问题标题】:Why is before_save not getting called for my ActiveRecord model?为什么我的 ActiveRecord 模型没有调用 before_save?
【发布时间】:2011-09-12 17:05:57
【问题描述】:

当我使用 IRB 创建新模型实例并保存时,控制台没有任何内容打印出来,并且我收到“ActiveRecord::StatementInvalid: Mysql::Error: Column 'user_id' cannot be null”错误,所以我假设before_save 没有被调用。我不知道为什么。我什至尝试过使用 before_save 过滤器。这是我的代码:

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

【问题讨论】:

    标签: ruby-on-rails validation activerecord callback


    【解决方案1】:

    如您所见,in the documentationbefore_save 发生在 验证之后。在您的情况下,验证将失败,并且永远不会调用 before_save

    由于您的回调目标是在验证发生之前将您的对象设置为有效状态,因此请尝试 before_validation 回调。

    【讨论】:

    • 啊,所以验证期间发生了 MySQL 错误。出于某种原因,我认为它是在保存期间发生的。我会试一试,看看会发生什么。如何明确判断验证是否通过?
    • 事情是,在 IRB 中,当我创建一个新的数据库实例、设置参数并调用 database.valid? 时,会返回 true。那么这怎么可能是一个验证问题呢?
    • @Chad 啊,我没有仔细阅读。如果 MySQL 引发错误,则您的 before_validation before_save 回调已触发并且 Rails 正在与数据库通信。您的user_id 字段之一为空。尝试使用logger.info 代替puts/p,后者不会写入Rails 中的控制台。
    • 使用 before_validation 有效。验证失败,因为我正在以某种方法在数据库模型内创建加密记录(即,self.username_encryption = Encryption.new in Database.some_method)。然后我试图在数据库类的 before_save 钩子中设置 self.username_encryption 的一些属性,由于某种原因我无法在 self.username_encryption 上设置属性,所以,当我调用 database.save 时,对数据库对象进行验证失败。
    • 我在 Rails 4.2.4 中看到了这种情况,尽管验证通过了!
    猜你喜欢
    • 1970-01-01
    • 2013-03-18
    • 2015-06-09
    • 1970-01-01
    • 2021-03-16
    • 2018-04-14
    • 2014-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多