Rails 5 has_many_through включает сводную таблицу в результат - PullRequest
0 голосов
/ 23 января 2019

У меня есть приложение Rails 5 с ресторанами и продуктами. Один продукт имеет множество ресторанов, а один ресторан имеет много продуктов. Я создал сводную таблицу и создал отношение has_many_through, поскольку хочу работать с сводной таблицей.

Продукт:

has_many :restaurant_products, dependent: :destroy
has_many :restaurants, through: :restaurant_products

Ресторан

has_many :restaurant_products, dependent: :destroy
has_many :products, through: :restaurant_products

Поскольку каждый ресторан может изменять цену для каждого продукта, я добавил столбец custom_price в свою таблицу restaurant_products.

Теперь я могу получить все продукты для определенного ресторана:

@restaurant.products

Но таким образом, когда я перечисляю продукты, у меня нет доступа к пользовательской цене. Как я могу как-то включить или получить доступ к правильной сводной записи, чтобы получить пользовательскую цену?

Ответы [ 3 ]

0 голосов
/ 23 января 2019

Просто предоставьте пользовательский выбор, включающий строку из таблицы объединения:

@products = @restaurant.products
           .select('products.*, restaurant_products.custom_price')

Возвращает restaurant_products.custom_price, как если бы оно находилось в столбце products. Вы можете AS предоставить псевдоним, если хотите назвать его как-то иначе, чем custom_price.

Так что вы можете сделать:

<table>
  # ...
  <% @products.each do |product| %>
  <tr>
    <td><%= product.name %></td>
    <td><%= product.custom_price %></td>
  </tr>
  <% end %>
</table>
0 голосов
/ 23 января 2019

В таких случаях всегда лучше запрашивать сводную таблицу, как показано ниже

@restaurant_products = RestaurantProduct.includes(:product)
                                        .where(restaurant_id: @restaurant.id)

Вы можете отобразить его в виде просто следующим образом.

<table>
  <% @restaurant_products.each do |resta_product| %>
  <tr>
    <td><%= resta_product.product.name %></td>
    <td><%= resta_product.custom_price %></td>
  </tr>
  <% end %>
</table>

Вы можете даже делегировать все методы продукта для работы непосредственно на restaurant_product.

0 голосов
/ 23 января 2019

Вы можете использовать следующее:

@restaurant.restaurant_products.joins(:products).select('restaurant_products.custom_price, products.*')

Это даст вам доступ к экземплярам, ​​включая все столбцы продукта, а также к пользовательской цене таблицы объединения.

Сгенерированный SQLбудет выглядеть примерно так:

SELECT restaurant_products.custom_price, products.* 
FROM `restaurant_products` 
INNER JOIN `products` ON `products`.`id` = `restaurant_products`.`product_id` 
WHERE `restaurant_products`.`restaurant_id` = 1

Быстрый совет: то, что возвращается, может выглядеть немного странно, что-то вроде:

[#<RestaurantProduct id: 1, custom_price: 10>]

... хотя, если вы позвоните attributes, илиАтрибут продукта для экземпляра здесь, у вас будет доступ ко всему, что вы захотите.


Выше приведен быстрый и эффективный доступ к данным записей, хотя, если вам нужен доступ к методам самого продукта, вы могли бы предпочесть следующее:

@product_details = @restaurant.restaurant_products.includes(:products)

А затем циклически перебирать данные:

@product_details.each do |product_detail|
  product_detail.custom_price

  product_detail.product.column_data
  product_detail.product.a_method
end

Надеюсь, что это поможет - дайте мне знать, как у вас обстоят дела или если у вас есть какие-либо вопросы.

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