-1

保存後のコールバックで配列の何が変更されたかを確認する方法を理解しようとしています。これが私が使用しているコードの例です:

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy
  has_many :subusers, :through => :user_maps, :dependent => :destroy

  has_many :inverse_user_maps, :class_name => "UserMap", :foreign_key => "subuser_id"
  has_one :parent, :through => :inverse_user_maps, :source => :user

  after_save :remove_subusers

  def remove_subusers
    if self.subuser_ids_were != self.subuser_ids
      leftover = self.subuser_ids_were - self.subuser_ids

      leftover.each do |subuser|
        subuser.destroy
      end
    end
  end
end

class UserMap < ActiveRecord::Base
  belongs_to :user
  belongs_to :subuser, :class_name => "User"
end

依存する破棄機能をuser_mapsで機能させることができなかったため、after_saveコールバックを使用してサブユーザーを削除しています。誰かがこれを行う方法について何かアイデアがありますか?

ありがとう!

4

2 に答える 2

0

厳密にはあなたの質問に対する答えではありませんが、次のことを試してみると、:dependent =>:destroyを機能させることができると思います...

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy
  has_many :subusers, :through => :user_maps # removing the :dependent => :destroy option
end

class UserMap < ActiveRecord::Base
  belongs_to :user
  belongs_to :subuser, :class_name => "User", :dependent => :destroy # add it here
end

:dependent =>:destroyオプションをUserMapモデルのbelongs_toアソシエーションに移動することにより、UserMap#destroyメソッドを介してカスケード削除を設定します。つまり、User#destroyを呼び出すと、UserMapレコードごとにUserMap#destroyが呼び出され、次に、sub_userレコードに対してsub_user.destroyが呼び出されます。

編集

上記の解決策が機能しなかったため、次の提案はuser_mapsアソシエーションにコールバックを追加することですが、これには後に追加する警告が表示されます

class User < ActiveRecord::Base
  has_many :user_maps, :dependent => :destroy, :before_remove => :remove_associated_subuser

  def remove_associated_subuser(user_map)
    user_map.subuser.destroy
  end
end

警告

1)before_removeコールバックを使用すると、コールバックでエラーが発生した場合にuser_map.destroy関数が呼び出されなくなります。

2)たとえば、Userクラスのメソッドを使用してUserMapレコードを破棄する必要があります...

# this will fire the callback
u = User.first
u.user_maps.destroy(u.user_maps.first)

# this WONT fire the callback
UserMap.first.destroy

すべてを考慮すると、これは私を緊張させるでしょう。最初にコードを変更して、関連付けが同じテーブルに少し結合されないようにします。これにより、:dependent =>:destroyオプションが機能します。それができない場合は、データベースにカスケード削除制約を追加します。 、少なくともその場合、Railsアプリのどこで/どのように破棄するかに関係なく、関連付けは常に削除されます。

于 2011-10-02T09:30:15.693 に答える
0

Rails after_save コールバックで変更された属性を特定するで提案されているように、Dirty モジュール アクセサーhttp://ar.rubyonrails.org/classes/ActiveRecord/Dirty.htmlを使用できます。

あなたの場合、ハンドラーは2つの要素の配列にafter_saveアクセスできますsubusers_change。最初は前の値で、2番目は新しい値です。

于 2011-10-02T11:22:01.873 に答える