【问题标题】:Rails: Sorting a query by params?Rails:按参数对查询进行排序?
【发布时间】:2008-10-18 14:43:46
【问题描述】:

我正在使用运行一个简单的查找全部并使用 willpaginate 进行分页,但我还希望用户对查询进行排序。想到的第一个解决方案就是使用 params[:sort]

http://localhost:3000/posts/?sort=created_at+DESC

@posts = Post.paginate :page => params[:page], :order => params[:sort]

但他的方法的问题是查询默认为按 ID 排序,我希望它是 created_at。

这是一种安全的排序方法吗?有没有办法默认为 created_at?

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    我将使用命名范围来提供默认顺序(自 Rails 2.1 起可用)。

    您将在 Post 模型中添加范围:

    named_scope :ordered, lambda {|*args| {:order => (args.first || 'created_at DESC')} }
    

    然后你可以调用:

    @posts = Post.ordered.paginate :page => params[:page]
    

    上面的示例将使用来自named_scope (created_at DESC) 的默认顺序,但您也可以提供不同的顺序:

    @posts = Post.ordered('title ASC').paginate :page => params[:page]
    

    您可以根据 Romulo 的建议使用它:

    sort_params = { "by_date" => "created_at", "by_name" => "name" }
    @posts = Post.ordered(sort_params[params[:sort]]).paginate :page => params[:page]
    

    如果在sort_params 中找不到params[:sort] 并返回nil,则named_scope 将回退到使用默认顺序。

    Railscasts 有一些关于 named_scopes 的重要信息。

    【讨论】:

    • 如果其他人遇到这种情况,更新后的作用域语法如下:scope :ordered, ->(*args) { order(args.first || 'created_at DESC') } 方法本身仍然有用!
    【解决方案2】:

    一般来说,为 Hash 和 Hash-like 对象提供默认值的方法是使用fetch

    params.fetch(:sort){ :created_at }
    

    很多人只是使用||

    params[:sort] || :created_at
    

    我更喜欢 fetch 本人,因为它更明确,而且当 false 是合法值时它不会中断。

    【讨论】:

      【解决方案3】:

      设置默认值的 Ruby 习惯用法是:

      @posts = Post.paginate :page => params[:page], :order => params[:sort] || "created_at"
      

      但这种方法并不安全。 paginate 方法不会使用"created_at; DROP DATABASE mydatabase;" 之类的参数。相反,您可以使用有效排序参数的字典(未经测试):

      sort_params = { "by_date" => "created_at", "by_name" => "name" }
      
      @posts = Post.paginate :page => params[:page], :order => sort_params[params[:sort] || "by_date"]
      

      这样URI就变成了:

      http://localhost:3000/posts/?sort=by_date
      

      【讨论】:

        【解决方案4】:

        我更喜欢这个成语:

        @posts = Post.paginate :page=>page, :order=>order
        ...
        
        def page
          params[:page] || 1
        end
        
        def order
          params[:order] || 'created_at ASC'
        end
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-28
          • 2015-08-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多