gpt4 book ai didi

ruby-on-rails - validates_presence_of 导致 after_initialize 被一个奇怪的 self 调用

转载 作者:数据小太阳 更新时间:2023-10-29 07:14:03 25 4
gpt4 key购买 nike

我有一个运行良好的模型:

class Weight < ActiveRecord::Base
belongs_to :user
validates_presence_of :weight, :measured_on
attr_accessible :weight, :measured_on

def after_initialize
self.measured_on ||= Date.today
end
end

我添加了这一行

validates_uniqueness_of :measured_on, :scope => :user_id

它开始在验证时抛出错误。不是验证错误而是 Ruby 错误:

>> w.valid?
ActiveRecord::MissingAttributeError: missing attribute: measured_on
from /Users/pupeno/Projects/sano/app/models/weight.rb:8:in `after_initialize'

我在 after_initialize 中放置了一个调试器语句,并且我注意到了一些意想不到的事情。当我创建一个新权重时,它按预期工作,after_initialize 上的 self 对象是预期的权重:

>> w = Weight.new
/Users/pupeno/Projects/sano/app/models/weight.rb:9
self.measured_on ||= Date.today
(rdb:1) p self
#<Weight id: nil, user_id: nil, weight: nil, measured_on: nil, created_at: nil, updated_at: nil>
(rdb:1) c
=> #<Weight id: nil, user_id: nil, weight: nil, measured_on: "2009-11-22", created_at: nil, updated_at: nil>

当我运行 w.valid?它变得奇怪。 after_initialize 再次被调用,我不确定为什么,并且 self 对象不是我所期望的:

>> w.valid?
/Users/pupeno/Projects/sano/app/models/weight.rb:9
self.measured_on ||= Date.today
(rdb:1) p self
#<Weight id: 1>
(rdb:1) p self.inspect
"#<Weight id: 1>"
(rdb:1) p self.class
Weight(id: integer, user_id: integer, weight: float, measured_on: date, created_at: datetime, updated_at: datetime)
(rdb:1) p self.measured_on
ActiveRecord::MissingAttributeError Exception: missing attribute: measured_on
(rdb:1)

似乎创建了另一个没有任何属性但设置了 id 的 Weight 对象。任何想法为什么?这是错误还是预期的行为?我在 after_initialize 上设置 measured_on 是不是做错了什么?

如果有人遇到同样的问题,我目前的解决方法是

class Weight < ActiveRecord::Base
belongs_to :user
validates_presence_of :weight, :measured_on
validates_uniqueness_of :measured_on, :scope => :user_id
attr_accessible :weight, :measured_on

def after_initialize
if self.has_attribute? :measured_on
self.measured_on ||= Date.today
end
end
end

但我想要一个合适的解决方案。

最佳答案

我认为您遇到了我最近遇到的 Rails 错误。参见 This blog entry链接到相关的灯塔错误。

我的理解是,发生的事情是一些先前的 Rails 代码执行“从表名中选择 ID”以查看条目是否存在或匹配。然后该对象缓存表中存在的唯一字段是“id”。然后您的代码运行,然后“属性”值不正确,仅反射(reflect) id 字段。

据我所知,这只发生在这个特定的代码路径被命中时,并且通常不会扰乱事情,除了在进行验证时。

我为解决这个问题所做的是将 after_initialise 代码包装在 begin/rescue ActiveRecord::MissingAttributeError block 中。然后我在应用程序和每个项目上方写了一个大注释,指示何时发布新版本的 Rails,我们可以删除它。

是的,我相信还有更优雅的解决方案。

def after_initialize
begin
# ... updates here
# self.unique_reference = UUIDTools::UUID.random_create.to_s
rescue ActiveRecord::MissingAttributeError
end
end

或者你也可以这样做:

def after_initialize
if self.has_attribute? :measured_on
self.measured_on ||= Date.today
end
end

关于ruby-on-rails - validates_presence_of 导致 after_initialize 被一个奇怪的 self 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1778374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com