Arel:连接表,对连接字段进行排序

时间:2015-03-26 15:51:02

标签: ruby-on-rails sorting arel jointable

我有以下ActiveRecord模型

class Publication < ActiveRecord::Base
   attr_accessible :id, :pname

   has_many :advertisements
end

class Vendor < ActiveRecord::Base
   attr_accessible :id, :vname
   has_many :advertisements
end

class Advertisement < ActiveRecord::Base
  attr_accessible :id, :vendor_id, :publication_id, :prose, :aname
  belongs_to :vendor
  belongs_to :publication

end

这些表格与其可访问属性具有相同的字段。

我希望能够对发布名称,广告名称或供应商名称进行排序,升序或降序。

我还有广告控制器,我想在其中显示广告列表。该列表显示广告的名称(aname),广告的散文(散文),供应商的名称(vname)以及出版物的名称(pname)。

按发布名称排序的SQL查询类似于:

SELECT ads.aname AS aname, ads.id, ads.prose, ven.vname AS vname, pub.pname AS pname  
    FROM advertisements AS ads
      INNER JOIN publications AS pub ON ads.publication_id = pub.id
      INNER JOIN vendors AS ven ON ads.vendor_id = ven.id
      ORDER BY <sort_column> <sort_order>

其中sort_column可以是&#34; pname&#34;,&#34; aname&#34;或&#34; vname&#34;和sort_order可以是&#34; ASC&#34之一;或者&#34; DESC&#34;,两者都将作为Web表单中的参数以及分页页码。

控制器索引代码与 类似

class AdvertisementsController < ApplicationController
   def index
     sort_column = params[:sort_column]
     sort_order = params[:sort_order]

     @ads = Advertisement.join( somehow join tables)
               .where(some condition).where(some other condition)
               .order("#{sort_column} #{sort_order}")      ### I don't know what to do here
               .paginate(page: params[:page], per_page: 10) #from will_paginate

   end

   #   other controller methods.......
end

索引视图表片段(用SLIM编写)如下所示:

tr
- @ads.each do |ad|
  td = ad.id
  td = ad.aname
  td = ad.pname
  td = ad.vname

我知道我可以使用AREL来做到这一点,但是我一直在使用AREL在Rails控制台中试图用分页生成和执行这个查询,并在网上阅读教程我不能弄清楚如何在AREL中获取此查询,对连接字段进行排序,并能够使用will_paginate Ruby查询子句对查询进行分页。

如何使用AREL,甚至ActiveRecord来执行此操作?我感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

您可以使用vanilla ActiveRecord方法完成您想要的任务,而不使用Arel。你所拥有的非常接近,这可能会帮助你实现目标。

# whitelist incoming params
sort_column = %w(pname aname vname).include?(params[:sort_column]) ? params[:sort_column] : "pname"
sort_order  = %w(asc desc).include?(params[:sort_order])           ? params[:sort_order]  : "desc"

@ads = Advertisement.select("advertisements.*, vendors.vname, publications.pname").
  joins(:publication, :vendor).
  where(some condition).
  where(some other condition).
  order("#{sort_column} #{sort_order}").
  page(params[:page]).per_page(10)

答案 1 :(得分:0)

您可以让解决方案同时适用于Arel和ActiveRecord。我建议你尽可能多地坚持使用ActiveRecord,除非你不能用AR做到这一点。

Arel非常棒,但最近我发现在我的代码库中,它会降低整体可读性,特别是如果你将它与AR混合使用或者使用过多的话。

还有其他一些建议:

  1. 关于尝试使用&#34的相同查询;包括&#34;而不是使用&#34;加入&#34;。您可能比必须添加select子句更容易。我使用include for outerjoins,但是为了更详细的比较,google&#34;包括vs join&#34;,它非常有趣。

  2. 在我的第一个建议完全相反的方向上,如果您的查询变得复杂,我强烈建议您使用https://github.com/activerecord-hackery/ransackhttps://github.com/activerecord-hackery/squeel作为您的用例。 特别是如果你没有为了学习目的而做上述事情。