簡體   English   中英

Rails ActiveRecord - 在多個屬性上搜索

[英]Rails ActiveRecord - Search on Multiple Attributes

我正在實現一個簡單的搜索功能,它應檢查username,last_name和first_name中的字符串。 我在舊的RailsCast上看過這個ActiveRecord方法:

http://railscasts.com/episodes/37-simple-search-form

find(:all, :conditions => ['name LIKE ?', "%#{search}%"])

但是我如何設置它以便在name,last_name和first name中搜索關鍵字並返回記錄,如果其中一個字段與該術語匹配?

我也想知道RailsCast上的代碼是否容易進行SQL注入?

非常感謝!

我假設您的模型名稱是Model - 只需在執行實際查詢時將其替換為您的真實模型名稱:

Model.where("name LIKE ? OR last_name LIKE ? OR first_name LIKE ?", "%#{search}%","%#{search}%","%#{search}%")

關於你對SQL注入的擔憂 - 兩個代碼片段都不受SQL注入的影響。 只要你沒有直接將字符串嵌入到WHERE子句中就可以了。 易於注入的代碼的示例是:

Model.where("name LIKE '#{params[:name]}'")

雖然選擇的答案會起作用,但我注意到如果你試圖輸入一個搜索“Raul Riera”就會中斷,因為它會在兩種情況下都失敗,因為Raul Riera不是我的名字或我的姓氏..是我的第一個姓氏......我這樣解決了

Model.where("lower(first_name || ' ' || last_name) LIKE ?", "%#{search.downcase}%")

使用Arel,您可以避免使用以下內容手動編寫SQL:

Model.where(
  %i(name first_name last_name)
    .map { |field| Model.arel_table[field].matches("%#{query}%")}
    .inject(:or)
)

如果要匹配的字段列表是動態的,這將特別有用。

最好的方法是:

Model.where("attr_a ILIKE :query OR attr_b ILIKE :query", query: "%#{query}%")

在模型的所有領域中搜索的更通用的解決方案將是這樣的

def search_in_all_fields model, text
  model.where(
    model.column_names
      .map {|field| "#{field} like '%#{text}%'" }
      .join(" or ")
  )
end

或者更好地作為模型本身的范圍

class Model < ActiveRecord::Base
  scope :search_in_all_fields, ->(text){
    where(
      column_names
        .map {|field| "#{field} like '%#{text}%'" }
        .join(" or ")
    )
  }
end

你只需要像這樣調用它

Model.search_in_all_fields "test"

在你開始..之前,沒有,sql注入可能不會在這里工作,但仍然更好,更短

class Model < ActiveRecord::Base
  scope :search_all_fields, ->(text){
    where("#{column_names.join(' || ')} like ?", "%#{text}%")
  }
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM