如何准确删除一个has_and_belongs_to_many关联?

时间:2018-09-21 08:42:46

标签: ruby-on-rails activerecord

“具有并属于多个”允许在同一对象之间具有多个关联。因此,我正在尝试实现可能包含某些某些产品的购物车。

# /app/models/cart.rb
class Cart < ApplicationRecord
  has_and_belongs_to_many :products
end

# /app/models/product.rb
class Product < ApplicationRecord
  has_and_belongs_to_many :carts
end

但是,当我尝试删除一个多对多关联时,它将全部删除:

@cart = Cart.last
@product = Product.last
3.times { @cart.products << @product }
@cart.products.delete(@product)
puts @cart.products.count
# Returns 0; should be 2

是否可以仅删除一个关联?

3 个答案:

答案 0 :(得分:0)

您可以这样做。

cart = Cart.find(card_id)
product = cart.products.find(product_id)

cart.products.delete(product)

答案 1 :(得分:0)

您的方法的主要问题是您直接使用产品本身而实际上并不关心所涉及的关联。

例如:

告诉Rails删除(产品1)时,这意味着它将在关联表(cart.cart_products.where(product_id: 1))中搜索并将delete_all应用于结果。

相反,您应该做的是:

  1. 正式声明两个对象之间的关系has_many :cart_products
  2. 然后使用它删除单个实例cart.cart_products.where(product_id: 1).first.delete

注意:您的应用程序的联接表(cart_products)的名称可能不同。

答案 2 :(得分:0)

来自documentation

  

最简单的经验法则是,如果需要将关系模型作为独立实体使用,则应设置has_many:through关系。如果您不需要对关系模型做任何事情,则设置has_and_belongs_to_many关系可能会更简单(尽管您需要记住要在数据库中创建联接表)。

     

如果需要在连接模型上进行验证,回调或其他属性,则应使用has_many:through。

无论如何,这是我短期内要做的。所以我最终使用了has_many :through

# cart.rb
class Cart < ApplicationRecord
  has_many :carts_products, class_name: 'CartsProduct'
  has_many :products, through: :carts_products
end

# product.rb
class Product < ApplicationRecord
  has_many :carts_products, class_name: 'CartsProduct'
  has_many :carts, through: :carts_products
end

# carts_product.rb
class CartsProduct < ApplicationRecord
  belongs_to :product
  belongs_to :cart
end