包括vs Joins Activerecord查询示例。还重构。我究竟做错了什么?

时间:2015-03-09 20:39:59

标签: activerecord

目前我的控制器如下所示:

def index
    if params[:activity]
      @trips = Trip.joins(:categories).where("categories.slug = ?", params[:activity])
    elsif params[:location]
      @trips = Trip.joins(:categories).where("categories.slug = ?", params[:location])
    else
      @trips = Trip.includes(:categories).all
    end
end

因为我想要加载,因为我在索引视图中做了很多trip.categories调用,所以我想使用includes。但我认为我的语法错了。

def index
    if params[:activity]
      @trips = Trip.includes(:categories).where("categories.slug = ?", params[:activity])
    elsif params[:location]
      @trips = Trip.includes(:categories).where("categories.slug = ?", params[:location])
    else
      @trips = Trip.includes(:categories).all
    end
end

这似乎在视图中引发了错误:

ActionView::Template::Error (PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "categories"
LINE 1: SELECT "trips".* FROM "trips" WHERE (categories.slug = 'hiki...
                                             ^
: SELECT "trips".* FROM "trips" WHERE (categories.slug = 'hiking')):
    12:     </tr>
    13:   </thead>
    14:   <tbody>
    15:     <% @trips.each do |trip| %>
    16:       <tr>
    17:         <td><%= trip.upvotes%></td>
    18:         <td><%= link_to "#{trip.title}", trip_path(trip.id) %></td>
  app/views/trips/index.html.erb:15:in `_app_views_trips_index_html_erb__1143926925325362083_70272895749760'

有人知道问题是什么吗?

2 个答案:

答案 0 :(得分:1)

includes默认情况下根本不使用联接。 Active Record用于尝试解析您的条件,以查看您是否正在执行任何需要使用include的连接版本但是相当脆弱且容易出错的内容,因此它已被弃用并最终被删除。

相反,您必须使用references方法告诉Active Record,例如

Trip.includes(:categories).references(:categories).where("categories.slug =?", params[:location])

您还可以使用eager_load代替includes

明确请求基于联接的策略

答案 1 :(得分:0)

我认为您应该同时使用includesjoinsjoins限制您的结果,includes以避免N + 1次查询。我的建议是这样的。

def index
  @trips = Trip.includes(:categories).all
  slug = params[:activity] || params[:location]
  @trips = @trips.joins(:categories).where(categories: { slug: slug }) if slug
end

关于这一点的好处是,如果您想稍后添加额外的搜索条件,那么只需在底部添加新行就很容易。

如果您想在其他任何地方使用此功能,您可能需要考虑将其纳入旅行模型的范围。