2016-11-29 3 views
1

Ich habe ein Rezept-Portal und diese Rezepte können Tags haben.Rails 4: Zugriff auf Variablen im Inneren vor dem Rückruf

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 

... wenn ich ein Rezept löschen, ich mag den Tag löschen, wenn das Rezept das einzige Rezept mit diesem Tag ist gelöscht.

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 

Diese Funktion würde funktionieren, aber ich kann nicht auf die Tags zugreifen. Wie greife ich auf die Tags für das gelöschte Rezept zu?

Antwort

2

Sie greifen die Tags des Rezepts, aber Sie sehen nichts becase dependant_destroy ausgeführt wird vor die tatsächliche des Objekts Rezept zerstören.

Wenn Sie sorgfältig die gestarteten Abfragen überprüfen, werden Sie sehen, dass direkt vor dem Rückruf die DELETE FROM "taggings" . . . ausgeführt wird. Wenn Sie also versuchen, auf die Tags des Rezepts zuzugreifen, wird ein leeres Array zurückgegeben.

Weil Sie nicht Tags wollen jedes Mal zerstören Sie ein Rezept zerstören, sondern nur dann, wenn die einzige ist, sollten Sie Ihren dependant_destroy und legen Sie die Logik in einem after_destroy entfernen, so würde der resultierende Code sein:

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

Danke für die gründliche Erklärung! –

Verwandte Themen