假设我们有这个模型
class Account < ActiveRecord::Base
after_initialize :set_name
def set_name
self.name = ‘My Account’
end
end
现在我想运行一个查询,该查询仅返回模型的某些属性,但不是全部,特别是不返回在 after_initialize 回调中使用的“name”属性
Account.group(:name).select("count(*), id").first
然后此执行会引发以下错误,因为 set_name 回调使用尚未“加载”或选择到查询返回的记录中的属性。
ActiveModel::MissingAttributeError: missing attribute: name
幸运的是,对于某些特定情况,我可以执行相同的 sql 查询,而无需使用帐户模型来获得所需的结果
sql = Account.group(:name).select("count(*), id").to_sql
ActiveRecord::Base.connection.execute(sql).first
=> #<Mysql2::Result:0x00000106eddbc0>
但问题是,如果我想获取 Account 对象而不是 Mysql2::Result 对象怎么办? .select
方法是否应该返回“完整”对象及其所有属性(例如,用 Nil 填充缺失的列)?或者对我们的 ActiveRecord 模型使用 after_initialize 回调是一个非常糟糕的主意?当然,我们也可以在回调中添加一些代码来检查属性是否存在,但在我看来,这在 OO 语言中是不自然的或听起来很奇怪。
最佳答案
after_initialize
的大多数使用可以(并且应该)替换为相应数据库列上的默认值。如果您将该属性设置为常量值,您可能需要将此作为替代方案。
编辑:如果该值不是常量,则调用 has_attribute?(:name)
将防止此错误 - ActiveModel::MissingAttributeError occurs after deploying and then goes away after a while
关于sql - 在 Rails ActiveRecord 模型中,使用 after_initialize 回调是一个非常糟糕的主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21792996/