Как удалить ровно одну ассоциацию has_and_belongs_to_many? - PullRequest
0 голосов
/ 21 сентября 2018

«Имеет и принадлежит многим» позволяет иметь несколько ассоциаций между одними и теми же объектами.Итак, я пытаюсь внедрить корзины покупок, в которых может быть несколько продуктов.

# /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 голосов
/ 21 сентября 2018

Основная проблема с вашим подходом состоит в том, что вы используете непосредственно сам продукт, не заботясь о задействованной ассоциации.

Например:

При указании рельсовудалить (Продукт 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) может отличаться для вашего приложения.

0 голосов
/ 21 сентября 2018

Из документации :

Самое простое практическое правило заключается в том, что вы должны установить отношение 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
0 голосов
/ 21 сентября 2018

Вы можете сделать это так.

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

cart.products.delete(product)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...