Rails 3.2.1关联没有回调?

时间:2014-04-24 09:00:38

标签: ruby-on-rails ruby associations

首先,我使用Rails 3.2.1和ruby 1.9.3p392

我有两个模型,ad_user和device

ad_userdevicesdevice,而ad_user属于class AdUser < ActiveRecord::Base has_many :devices class Device < ActiveRecord::Base belongs_to :device_type belongs_to :device_status belongs_to :ad_user validates_presence_of :name validates_uniqueness_of :name validates_presence_of :serial validates_uniqueness_of :serial validates_presence_of :device_type_id validates_presence_of :device_status_id validates_presence_of :ad_user_id before_update :before_update_call before_save :before_save_call before_create :before_create_call before_validation :before_validation_call protected def before_update_call p self.name p self.ad_user_id p "-=-=-=-=-=-=-=-=-" p "before_update_call" self.ad_user_id = 1 if self.ad_user_id.nil? || self.ad_user_id.blank? end def before_save_call p self.name p self.ad_user_id p "-=-=-=-=-=-=-=-=-" p "before_save_call" self.ad_user_id = 1 if self.ad_user_id.nil? || self.ad_user_id.blank? end def before_create_call p self.name p self.ad_user_id p "-=-=-=-=-=-=-=-=-" p "before_create_call" self.ad_user_id = 1 if self.ad_user_id.nil? || self.ad_user_id.blank? end def before_validation_call p self.name p self.ad_user_id p "-=-=-=-=-=-=-=-=-" p "before_validation_call" self.ad_user_id = 1 if self.ad_user_id.nil? || self.ad_user_id.blank? end

我的模型如下:

u = AdUser.first
u.device_ids=[1,2]

当我使用

将设备分配给用户时
before_validation_call

我可以看到before_save_callbefore_update_callu.device_ids=[] 打印到控制台,但是当我从用户取消分配这些设备时:

SQL (2.0ms) UPDATE "devices" SET "ad_user_id" = NULL WHERE "devices"."ad_user_id" = 405 AND "devices"."id" IN (332, 333)

结果很简单:

ad_user_id

尽管模型应该验证存在,但我的设备最终都没有被调用,并且我的设备最终没有ad_user_id。我计划在保存或更新之前使用回调来检查{{1}}是否为零,但它们甚至都没有被调用。

我在这里做错了吗?

2 个答案:

答案 0 :(得分:0)

不幸的是,我认为这是一种预期的行为。您不应该依赖于更新关联时触发的回调,因此隐式更新基础模型。

虽然您可以做什么,但请尝试访问devices字段。 device_ids在不同的级别上表现不同。

如果适合,请考虑使用association-callbacks

P.S。只是一个小注意事项:在Rails中,您可以使用self.ad_user.present?代替self.ad_user_id.nil? || self.ad_user_id.blank?。此外,您可以合并validates_presence_of语句。

答案 1 :(得分:0)

然后,在update控制器的ad_user方法中,在我添加的update_attributes之前:

old_device_ids = @ad_user.device_ids

我添加update_attributes之后:

(old_device_ids - AdUser.find(params[:id]).device_ids).each do |device|
    Device.find(device).update_attributes(:ad_user_id => 1)
end

我之前已经做过,但我想找到一个合适的&#34; Rails方式&#34;这样做。