代码之家  ›  专栏  ›  技术社区  ›  Trip

如何按SQL中没有属性的自定义模型方法排序?

  •  29
  • Trip  · 技术社区  · 14 年前

    以前我是这样安排的:

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

    created_at 我在Post模型中编写了一个自定义方法,它给出一个数字作为结果。

    我猜:

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

    失败了。。

    6 回复  |  直到 8 年前
        1
  •  35
  •   Hardryv    14 年前

    它失败了,因为你要求你的数据库做排序。

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

    .all . 在你做这个之前先考虑一下你的设计。

        2
  •  15
  •   jwarchol    14 年前

    Post.all.sort_by {|post| post.custom_method }.reverse
    
        3
  •  9
  •   Sia    9 年前

    正如第一个答案所指出的,order是一个活动的记录命令,它本质上对数据库执行SQL查询,但该字段实际上并不存在于数据库中。

    正如其他人所评论的,您可以通过使用与号(更多信息 here

    Post.all.sort_by(&:custom_method)

    然而,事情确实会变得复杂,这取决于你想在你的视图中做什么。我将分享一个我最近做的案例,以防帮助你思考你的问题。我需要按另一个名为“categories”的资源对资源进行分组,然后按自定义模型方法“netvots”对原始资源进行排序,然后按名称排序。我是通过:

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

    <% @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部分:

    <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>
    
        4
  •  3
  •   Robbie    14 年前

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

    Enumerable.sort_by

        5
  •  2
  •   MZaragoza Tushar Walzade    8 年前

    这比我喜欢的要复杂一点,但是我喜欢保持我的类型作为一个活动的记录模型,所以它比

    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)
    

    #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
    

    我希望这能帮上忙

        6
  •  -5
  •   Rick Hoving    11 年前

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