简体   繁体   English

具有许多可选参数的Rails模型查询

[英]Rails model query with many optional params

A user wants to search by an attribute and/or order the results. 用户想要按属性搜索和/或排序结果。 Here are some example requests 这是一些示例请求

/posts?order=DESC&title=cooking
/posts?order=ASC
/posts?title=cooking

How can I conditionally chain such options to form a query? 如何有条件地链接这些选项以形成查询?

So far I have a very ugly method that will quickly become difficult to maintain. 到目前为止,我有一个非常丑陋的方法,它将很快变得难以维护。

  def index
    common = Hash.new
    common["user_id"] = current_user.id

    if params[:order] && params[:title]

      @vacancies = Post.where(common)
                          .where("LOWER(title) LIKE ?", params[:title])
                          .order("title #{params[:order]}")

    elsif params[:order] && !params[:title]

      @vacancies = Post.where(common)
                          .order("title #{params[:order]}")

    elsif params[:title] && !params[:order]

      @vacancies = Post.where(common)
                          .where("LOWER(title) LIKE ?", params[:title])
    end
  end

Remember that query methods like where and order are meant to be chained. 请记住,诸如whereorder类的查询方法是要链接的。 What you want to do is start with a base query (like Post.where(common) , which you use in all cases) and then conditionally chain other methods: 您要做的是从基本查询开始(例如在所有情况下都使用Post.where(common) ),然后有条件地链接其他方法:

def index
  common = Hash.new
  common["user_id"] = current_user.id

  @vacancies = Post.where(common)

  if params[:order]
    @vacancies = @vacancies.order(title: params[:order].to_sym)
  end

  if params[:title]
    @vacancies = @vacancies.where("LOWER(title) LIKE ?", params[:title])
  end
end

PS Your original code had .order("title #{params[:order]}") . PS您的原始代码为.order("title #{params[:order]}") This is very dangerous, since it opens you up to SQL injection attacks. 这非常危险,因为它使您容易遭受SQL注入攻击。 As a rule of thumb never use string concatenation ( #{...} ) with a value you get from the end user when you're going to pass the result to the database. 根据经验,在将结果传递给数据库时, 切勿将字符串连接( #{...} )与最终用户获得的值一起使用。 Accordingly, I've changed it to .order(title: params[:order]) . 因此,我将其更改为.order(title: params[:order]) Rails will use this hash to construct a secure query so you don't have to worry about injection attacks. Rails将使用此哈希值构造一个安全的查询,因此您不必担心注入攻击。

You can read more about SQL injection attacks in Rails in the official Ruby on Rails Security Guide . 您可以在Ruby on Rails官方安全指南中阅读有关Rails中SQL注入攻击的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM