简体   繁体   English

我需要一个包含大量字段的搜索表单。 如何在Ruby on Rails中干净地做到这一点?

[英]I need a search form with a large number of fields. How do I do this cleanly in Ruby on Rails?

I'm building a database application that tracks a lot of data for a Person, such as first_name, last_name, DOB, and 20+ more fields. 我正在构建一个数据库应用程序,该应用程序跟踪一个Person的许多数据,例如first_name,last_name,DOB和20多个字段。

Users will need to be able to search for all of these fields. 用户将需要能够搜索所有这些字段。 I'm having trouble writing clean code for this. 我在为此编写干净的代码时遇到了麻烦。 The code below is what I have so far in my people_controller: 到目前为止,我的people_controller中包含以下代码:

The data is submitted from a form_tag 数据是从form_tag提交的

def search
    @people = Person.all
    general_info_string = String.new

    if(params[:first_name] != "") then general_info_string << 'people.first_name = "' + params[:first_name] + '" AND ' end
    if(params[:last_name] != "") then general_info_string << "people.last_name = '" + params[:last_name] + "' AND " end
    ... Lots more of similar clauses

    general_info_string = general_info_string[0, general_info_string.length - 5]
         #   ^This line removes the trailing " AND " from the string 
    @people = @people.where(general_info_string)
end

general_info_string is so called because there are more "where" clauses(not shown) and separate strings that I build to search for them. general_info_string这样称呼general_info_string是因为有更多的“ where”子句(未显示)和我构建的用于搜索它们的单独字符串。

The problem here is that the code looks like a mess and seems like a "hacky" way to do something that should be well supported by Rails. 这里的问题是代码看起来像是一团糟,看起来像是一种“ hacky”的方式来完成应该由Rails很好地支持的事情。 How could I perform this operation in a cleaner way? 我如何以一种更简洁的方式执行此操作?

That's not just hacky - it leaves you open to a string injection attack. 这不仅是hacky-还使您容易受到字符串注入攻击。

You need a :conditions using the ? 您需要使用:conditions ? template, like this example: 模板,例如以下示例:

:conditions => ["key1 = ?", var]

but you need to make the template part into a string that grows once per parameter, and you need to make the var into an array that grows with each parameter's value. 但您需要将模板部分制作成一个字符串,每个参数增加一次,并且需要将var制作成随每个参数值一起增长的数组。 That gives you something like this: 那给你这样的东西:

template = []
values = []

if params[:first_name].present?
    template.push 'people.first_name = ?'
    values.push params[:first_name]
end

if params[:last_name].present?
    template.push 'people.last_name = ?'
    values.push params[:last_name]
end

template = template.join(' AND ')
:conditions => [template, *values]

From there, you should DRY up all those ifs, such as with a table of value keys. 从那里,您应该干燥所有这些if,例如使用值键表。 Then you'd loop through the table, check the key, and push its results into the arrays: 然后,您将遍历表,检查键,并将其结果推入数组:

fields = [:first_name, :last_name, :shoe_size, ...]

fields.each do |field|
    if params[field].present?
        template.push "people.#{field} = ?"
        values.push params[field]
    end
end

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

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