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

时间:2010-10-29 20:49:27

标签: ruby-on-rails

之前我订购了我的帖子:

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

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

我猜:

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

失败..

6 个答案:

答案 0 :(得分:34)

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

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

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

答案 1 :(得分:15)

只是为了扩展@Robbie的回答

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

答案 2 :(得分:9)

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

正如其他人评论的那样,你可以使用&符号更多地运行Ruby方法sort_by(更多信息here):

Post.all.sort_by(&:custom_method)

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

  • 在控制器中按名称排序:@resources = Resource.order(:name)
  • 在视图的外部循环中按类别分组:<% @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| %>
  <div class="well">
    <h3 class="brand-text"><%= category.name %></h3>
    <%= render resources.sort_by(&:netvotes).reverse %>
  </div>
<% end %>

这是_resource.html.erb partial:

<div class="row resource">
  <div class="col-sm-2 text-center">
    <div class="vote-box">
      <%= link_to fa_icon('chevron-up lg'), upvote_resource_path(resource), method: :put %><br>
      <%= resource.netvotes %><br>
      <%= link_to fa_icon('chevron-down lg'), downvote_resource_path(resource), method: :put %>
    </div>
  </div>
  <div class="col-sm-10">
    <%= link_to resource.name, resource.link, target: "_blank" %>
    <p><%= resource.notes %></p>
  </div>
</div>

答案 3 :(得分:3)

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

RDoc:Enumerable.sort_by

答案 4 :(得分:2)

这比我喜欢的要复杂一些,但是我喜欢保持我的活跃记录模式,所以它比仅仅更复杂

gls

我所做的是:

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

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

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

我希望这个帮助

答案 5 :(得分:-5)

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