Arel:加入 table,在加入的字段上排序
Arel: join table, sort on joined field
我有以下 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
它们的 tables 具有与其可访问属性相同的字段。
我希望能够按出版物名称、广告名称或供应商名称进行升序或降序排序。
我还有一个广告控制器,我想在其中显示广告列表。该列表显示广告名称 (aname)、广告内容 (prose)、供应商名称 (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 可以是 "pname"、"aname" 或 "vname" 之一,而 sort_order 可以是 "ASC" 或"DESC",两者都将作为来自 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
索引视图 table 片段(用 SLIM 编写)如下所示:
tr
- @ads.each do |ad|
td = ad.id
td = ad.aname
td = ad.pname
td = ad.vname
我知道我可以使用 AREL 来执行此操作,但我一直在 Rails 控制台中尝试使用 AREL 来生成和执行带有分页的查询,并阅读网络上的教程和我不知道如何在 AREL 中获取此查询,对连接字段进行排序,并能够使用 will_paginate Ruby 查询子句对查询进行分页。
如何使用 AREL,甚至 ActiveRecord 来做到这一点?我感谢我能得到的任何帮助。
您可以使用 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)
您可以使解决方案同时适用于 Arel 和 ActiveRecord。我建议您尽可能多地使用 ActiveRecord,除非您不能使用 AR。
Arel 很棒,但最近我发现在我的代码库中,它降低了整体可读性,尤其是如果您将它与 AR 混合使用或使用过多。
还有一些其他建议:
关于尝试使用 "includes" 而不是 "joins" 的相同查询。您可能认为它比必须添加 select 子句更容易。 outerjoins我用的是includes,不过比较详细,google"includes vs joins",很有意思
与我的第一个建议完全相反,如果您的查询变得复杂,我强烈建议您使用 https://github.com/activerecord-hackery/ransack or https://github.com/activerecord-hackery/squeel 作为您的用例。
特别是如果您不只是为了学习目的而执行上述操作。
我有以下 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
它们的 tables 具有与其可访问属性相同的字段。
我希望能够按出版物名称、广告名称或供应商名称进行升序或降序排序。
我还有一个广告控制器,我想在其中显示广告列表。该列表显示广告名称 (aname)、广告内容 (prose)、供应商名称 (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 可以是 "pname"、"aname" 或 "vname" 之一,而 sort_order 可以是 "ASC" 或"DESC",两者都将作为来自 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
索引视图 table 片段(用 SLIM 编写)如下所示:
tr
- @ads.each do |ad|
td = ad.id
td = ad.aname
td = ad.pname
td = ad.vname
我知道我可以使用 AREL 来执行此操作,但我一直在 Rails 控制台中尝试使用 AREL 来生成和执行带有分页的查询,并阅读网络上的教程和我不知道如何在 AREL 中获取此查询,对连接字段进行排序,并能够使用 will_paginate Ruby 查询子句对查询进行分页。
如何使用 AREL,甚至 ActiveRecord 来做到这一点?我感谢我能得到的任何帮助。
您可以使用 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)
您可以使解决方案同时适用于 Arel 和 ActiveRecord。我建议您尽可能多地使用 ActiveRecord,除非您不能使用 AR。
Arel 很棒,但最近我发现在我的代码库中,它降低了整体可读性,尤其是如果您将它与 AR 混合使用或使用过多。
还有一些其他建议:
关于尝试使用 "includes" 而不是 "joins" 的相同查询。您可能认为它比必须添加 select 子句更容易。 outerjoins我用的是includes,不过比较详细,google"includes vs joins",很有意思
与我的第一个建议完全相反,如果您的查询变得复杂,我强烈建议您使用 https://github.com/activerecord-hackery/ransack or https://github.com/activerecord-hackery/squeel 作为您的用例。 特别是如果您不只是为了学习目的而执行上述操作。