2016-11-29 16 views
1

私はレシピポータルを持っており、これらのレシピにタグを付けることができます。 Rails 4:before_destroyコールバック内で変数にアクセス

class Recipe < ActiveRecord::Base 
    has_many :taggings, dependent: :destroy 
    has_many :tags, through: :taggings, dependent: :destroy 
end 

class Tag < ActiveRecord::Base 
    has_many :taggings, dependent: :destroy 
    has_many :recipes, through: :taggings 
end 

class Tagging < ActiveRecord::Base 
    belongs_to :tag 
    belongs_to :recipe 
end 

...私はレシピを削除すると、削除されたレシピは、このタグを持つ唯一のレシピであれば、私はタグ を削除したいと思います。

class Recipe < ActiveRecord::Base 
    has_many :taggings, dependent: :destroy 
    has_many :tags, through: :taggings, dependent: :destroy 

    before_destroy :remove_tags 

    private 

    # I need to pass an individual recipe 
    def remove_tags 
     if self.tags.present? 
      self.tags.each do |tag| 
       Recipe.tagged_with(tag).length == 1 ? tag.delete : next 
       # tagged_with() returns recipes with the given tag name 
      end 
     end 
    end 
end 

この機能は動作しますが、タグにアクセスできません。 削除するレシピのタグにアクセスするにはどうすればよいですか?

答えて

2

あなたはレシピのタグにアクセスしているが、あなたは、実際にはレシピオブジェクトの破壊前に実行されるdependant_destroy becase何も表示されません。

起動したクエリを注意深く調べると、コールバック直前にDELETE FROM "taggings" . . .が実行されるので、レシピのタグにアクセスしようとすると空の配列が返されます。

あなたは毎回のタグを破壊したくないので、あなたはレシピを破壊するが、あなたはあなたのdependant_destroyを削除し、after_destroyのロジックを置くべき唯一のものである場合にのみ、その結果のコードは次のようになります。

class Recipe < ApplicationRecord 
    has_many :taggings 
    has_many :tags, through: :taggings 

    after_destroy :remove_tags 

    private 

    # I need to pass an individual recipe 
    def remove_tags 
    if self.tags.present? 
     self.tags.each do |tag| 
     Recipe.tagged_with(tag).length == 1 ? tag.delete : next 
     # tagged_with() returns recipes with the given tag name 
     end 
    end 
    end 
end 
+0

徹底的な説明をありがとう! –

関連する問題