【问题标题】:Rails 5 has_many_through include pivot table in resultRails 5 has_many_through 在结果中包含数据透视表
【发布时间】:2023-03-27 01:34:02
【问题描述】:

我有一个包含餐厅和产品的 Rails 5 应用。一种产品 has_many 餐厅,一种餐厅有多种产品。我创建了一个数据透视表并创建了和 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

由于每个餐厅都可以修改每种产品的价格,因此我在我的 restaurant_products 表中添加了一个 custom_price 列。

现在我可以获取某家餐厅的所有产品:

@restaurant.products

但是这样,当我列出产品时,我无法访问自定义价格。如何以某种方式包含或访问正确的数据透视记录以获取自定义价格?

【问题讨论】:

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


    【解决方案1】:

    您可以使用以下内容:

    @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
    

    希望这些帮助 - 如果您有任何问题,请告诉我。

    【讨论】:

      【解决方案2】:

      只需提供一个包含连接表中的行的自定义选择:

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

      这将返回restaurant_products.custom_price,就好像它在products 上的列的位置一样。如果您想将其命名为 custom_price 以外的其他名称,您可以使用 AS 提供别名。

      所以你可以这样做:

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

      【讨论】:

        【解决方案3】:

        在这种情况下,最好如下查询数据透视表

        @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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-06-07
          • 1970-01-01
          • 2015-09-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多