如何在没有有效关联ID的情况下执行自动清除关联的表行

时间:2017-08-22 16:20:44

标签: ruby-on-rails associations rails-activerecord

我正在尝试找到一种方法来清除表中与另一个表相关联的行。

重点是我正在尝试为食谱创建应用程序。 例如,当2个或更多食谱具有相同的成分时,我不想有这种情况(让我们说蛋)。如果我删除一个配方,它将删除自动关联的Active Record但我想删除它,例如鸡蛋不会用于另一种配方。

成分模型:

class Ingredient < ApplicationRecord
  belongs_to :recipe, inverse_of: :ingredients

end

食谱模型:

class Recipe < ApplicationRecord
    has_many :ingredients, inverse_of: :recipe
    has_many :directions, inverse_of: :recipe

    accepts_nested_attributes_for :ingredients,
                                    reject_if: proc { |attributes| attributes['name'].blank? },
                                    allow_destroy: true
    accepts_nested_attributes_for :directions,
                                    reject_if: proc { |attributes| attributes['step'].blank? },
                                    allow_destroy: true

    validates :tittle, :description, :image, presence: true
    has_attached_file :image, styles: { :medium => "400x400#" }
    validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
end

那么有没有办法(不包括sql查询)来执行这样的操作?

1 个答案:

答案 0 :(得分:1)

首先创建一个连接Recipe和Ingredient的连接表。这是设置多对多关联所必需的。

class Recipe < ApplicationRecord
  has_many :recipe_ingredients
  has_many :ingredients, through: :recipe_ingredients

  accepts_nested_attributes_for :ingredients,
     reject_if: proc { |attributes| attributes['name'].blank? },
     allow_destroy: true

  # ...
end

# This model is the master table for ingredients 
# using a normalized table avoids duplication
class Ingredient < ApplicationRecord
  has_many :recipe_ingredients
  has_many :ingredients, through: :recipe_ingredients
end

# This contains the quantity of an ingredient used in a recipe
class RecipeIngredient < ApplicationRecord
  belongs_to :recipe
  belongs_to :ingredients
end

然后,您可以通过创建回调来删除孤立的行:

class RecipeIngredient < ApplicationRecord
  belongs_to :recipe
  belongs_to :ingredients

  after_destroy do |record|
    ingredient = record.ingredient
    unless ingredient.recipe_ingredients.any?
      ingredient.destroy
    end
  end
end