22
class Post < ActiveRecord::Base
  has_many :posts_tags
  has_many :tags, through: :posts_tags
end

class PostsTag < ActiveRecord::Base
  belongs_to :post
  belongs_to :tag
end

class Tag < ActiveRecord::Base
  has_many :posts_tags
  has_many :posts, through: :posts_tags
end

Post が破棄されたら、Tag への関連付けもすべて削除します。PostsTag モデルの検証を実行したくありません。削除したいだけです。

Post モデルから posts タグへの関係に依存するものを追加すると、希望どおりに機能することがわかりました: has_many :posts_tags, dependent: :delete_all

ただし、この件に関するドキュメントは、代わりにこれを行う必要があることを示唆しているようです: has_many :tags, through: :posts_tags, dependent: :delete_all. これを行うと、Tag オブジェクトが破棄され、結合オブジェクトが残ります。

http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many

has_many の場合、destroy は、コールバックが実行されるように、削除されるレコードの destroy メソッドを常に呼び出します。ただし、delete は、:dependent オプションで指定された戦略に従って削除を行うか、:dependent オプションが指定されていない場合は、デフォルトの戦略に従います。デフォルトの戦略は :nullify (外部キーを nil に設定)ですが、デフォルトの戦略が delete_all (コールバックを実行せずに結合レコードを削除する) である has_many :through を除きます。

  1. デフォルト戦略を実際に使用するにはどうすればよいですか? :dependent を完全にオフのままにすると、レコードはまったく削除されません。そして、 has_many 関係に :dependent を示すことはできません。Rails が戻ってきて、「:dependent オプションには、:destroy、:delete_all、:nullify、または :restrict ({}) のいずれかが必要です」と表示されます。
  2. どちらの関係にも :dependent を指定しないと、PostsTag オブジェクトの post_id が無効になることはありません。

おそらく私はこれを間違って読んでおり、私が見つけたアプローチは正しい方法ですか?

4

1 に答える 1

24

Your original idea of:

has_many :posts_tags, dependent: :delete_all

is exactly what you want. You do not want to declare this on the has-many-though association :tags, as that will destroy all associated Tags. What you want to delete is the association itself - which is what the PostTag join model represents.

So why do the docs say what they do? You are misunderstanding the scenario that the documentation is describing:

Post.find(1).destroy
Post.find(1).tags.delete

The first call (your scenario) will simply destroy the Post. That is, unless you specify a :dependent strategy, as I suggest you do. The second call is what the documentation is describing. Calling .tags.delete will not (by default) actually destroy the tags (since they are joined by has-many-through), but the associated join model that joins these tags.

于 2013-06-05T20:51:15.093 に答える