如何通过SQL中没有属性的自定义模型方法进行排序?

以前我订购过我的post:

@posts = Post.find(:all, :order => "created_at DESC") 

但是现在我想用我在Post模型中编写的自定义方法替换created_at ,该方法给出了一个数字作为结果。

我猜:

 @posts = Post.find(:all, :order => "custom_method DESC") 

哪个失败..

它失败是因为您要求您的数据库进行排序。

@posts = Post.all.sort {|a,b| a.custom_method <=> b.custom_method}

请注意,当您想要开始分页结果并且不再希望获取.all时,这变得非常简单。 在你使用它之前先考虑一下你的设计。

只是为了扩展@Robbie的答案

 Post.all.sort_by {|post| post.custom_method }.reverse 

正如第一个答案所指出的那样,order是一个Active Record命令,它基本上对您的数据库执行SQL查询,但该字段实际上并不存在于您的数据库中。

正如其他人评论的那样,你可以通过使用&符号来更干净地运行Ruby方法sort_by( 这里有更多信息):

Post.all.sort_by(&:custom_method)

但是,根据您在视图中的操作,事情会变得复杂。 我将分享我最近做的一个案例,以防止你思考你的问题。 我需要通过另一个名为“categories”的资源对我的资源进行分组,然后通过“netvotes”对原始资源进行排序,这是一个自定义模型方法,然后按名称排序。 我做到了:

  • 在控制器中按名称排序: @resources = Resource.order(:name)
  • 在视图的外部循环中按类别分组: <% @resources.group_by(&:category).each do |category, resources| %> <% @resources.group_by(&:category).each do |category, resources| %>
  • 然后通过部分资源中的投票对资源进行排序: <%= render resources.sort_by(&:netvotes).reverse %>

视图有点令人困惑,所以这里是index.html.erb中的完整视图循环:

 <% @resources.group_by(&:category).each do |category, resources| %> 

<%= category.name %>

<%= render resources.sort_by(&:netvotes).reverse %>
<% end %>

这是_resource.html.erb部分:

 
<%= link_to fa_icon('chevron-up lg'), upvote_resource_path(resource), method: :put %>
<%= resource.netvotes %>
<%= link_to fa_icon('chevron-down lg'), downvote_resource_path(resource), method: :put %>
<%= link_to resource.name, resource.link, target: "_blank" %>

<%= resource.notes %>

好吧,只需Post.find(:all)就会返回一个AR对象数组。 因此,您可以使用Array.sort_by并将其传递给一个块,并且由于已经提取了这些记录,因此您可以访问sort_by所采用的块内的虚拟属性。

RDoc: Enumerable.sort_by

这比我喜欢的要复杂一点,但是我喜欢保持我的排序作为一个活跃的记录模型,所以它有点复杂而不仅仅是

 Post.all.sort_by {|post| post.custom_method } 

我所做的是:

 ids = Post.all.sort_by {|post| post.custom_method }.map(&:ids) Post.for_ids_with_order(ids) 

这是Post模型中的自定义范围

 #app/models/post.rb class Post < ApplicationRecord ... scope :for_ids_with_order, ->(ids) { order = sanitize_sql_array( ["position(id::text in ?)", ids.join(',')] ) where(:id => ids).order(order) } ... end 

我希望这有帮助

在rails 3中我们可以这样做: Post.order("custom_method DESC")
将应用程序从rails2升级到rails3时