2010-12-08 45 views
1

我正在寫一個rails 3應用程序,並且我有一個用戶數據庫表。用戶具有first_name和last_name列。在列出用戶的我的頁面上,我希望有一個允許用戶過濾列表的文本搜索框。他們需要能夠在搜索框中鍵入下列內容之一: - 用戶的名字 - 用戶的姓氏 - 用戶的全名(例如「Smith,John」)「Where」子句中的連接字段在Rails 3中

我不知道如何編寫將返回這些結果的where子句。我得到的最接近的是,但是連接字段部分不起作用。

where('(first_name LIKE :search) or (last_name LIKE :search) or ("#{last_name}, #{first_name}" LIKE :search)', :search => "%#{search}%") 

我也很想知道是否有更好的方法來處理我的OR語句,因爲這個子句變得相當笨拙。

感謝您的幫助!

回答

2

如果它幫助其他人,這是我去的解決方案:

def self.search(query) 
    if query.blank? 
     scoped 
    else 
     sql = query.split.map do |word| 
     %w[first_name last_name].map do |column| 
     sanitize_sql ["#{column} LIKE ?", "%#{word}%"] 
     end.join(" or ") 
     end.join(") and (") 
     where("(#{sql})") 
    end 
    end 

感謝Railscasts的Ryan Bates爲此解決方案。

2

您必須記住where將變成SQL,並且如果要將連接列與搜索字符串進行比較,則必須在數據庫/ sql級別執行此操作。

現在這是棘手的地方,因爲sql中的連接因數據庫而異。

在PostgreSQL和Oracle你會寫是這樣的:

where("(first_name LIKE :search) or (last_name LIKE :search) or (last_name || ',' || first_name LIKE :search)", :search => "%#{search}%" 

不幸的是,MySQL不支持標準的連接符||,與MySQL中,你將不得不使用concat代替:

where("(first_name LIKE :search) or (last_name LIKE :search) or (concat(last_name, ',', first_name) LIKE :search)", :search => "%#{search}%" 
+1

有沒有更好的辦法做到這一點比where子句呢?如果可能,我寧願不添加特定於數據庫的任何內容。 – 2010-12-08 09:17:03

+0

另一種選擇是在記憶之後,但我強烈建議反對。我認爲在這裏使用'where'是最好的選擇:你的數據庫最適合執行這個任務。在這些情況下,我擔心你無法避免添加一些特定於數據庫的代碼。 – nathanvda 2010-12-08 10:33:40