سؤال

First off, i'm using Rails 3.2.1 and ruby 1.9.3p392

I have two models, ad_user and device

An ad_user has many devices, and a device belongs to an ad_user.

My models are as follow:

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

When i assign devices to a user using

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

I can see the before_validation_call, before_save_call and before_update_call printing to the console, however when I unassign these devices from the user with:

u.device_ids=[]

It results in a simple:

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

None of the callbacks are called and my devices end up with having a nil ad_user_id despite the fact that the model should validate the presence. I planned to use the callbacks to check that ad_user_id is not nil before saving or updating but they are not even called.

Am I doing anything wrong here ?

هل كانت مفيدة؟

المحلول 2

Allright then, in my update method of the ad_user controller, before the update_attributes I added:

old_device_ids = @ad_user.device_ids

the after the update_attributes I added:

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

I had already done that earlier, but I wanted to find a proper "Rails way" of doing it.

نصائح أخرى

Unfortunately, I think this is an expected behavior. You shouldn't rely on callbacks being fired when you update associations, so underlying model is being updated implicitly.

What you can do though, try to access devices field instead. device_ids performs differently, on a lower level.

Also consider using association-callbacks, if it fits.

P.S. just a small note: in Rails you can use self.ad_user.present? instead of self.ad_user_id.nil? || self.ad_user_id.blank?. Also, you can merge validates_presence_of statements.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top