2010-12-08 11 views
1

Ich schreibe eine Rails 3-Anwendung, und ich habe eine Datenbanktabelle von Benutzern. Die Benutzer haben Spalten first_name und last_name. Auf meiner Seite, die die Benutzer auflistet, möchte ich ein einzelnes Textsuchfeld haben, mit dem der Benutzer die Liste filtern kann. Sie müssen in der Lage sein, einen der folgenden Einträge in das Suchfeld einzugeben: - Ein Vorname eines Benutzers - Ein Nachname eines Benutzers - Der vollständige Name eines Benutzers (z. B. "Smith, John")"Where" -Klausel mit verketteten Feldern in Rails 3

Ich weiß nicht, wie die WHERE-Klausel geschrieben wird, die diese Ergebnisse zurückgibt. Der nächste, den ich bekommen habe, ist unten, aber der verkettete Teil der Felder funktioniert nicht.

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

Ich bin auch zu wissen, interessiert, wenn es eine bessere Art und Weise ist meine OR Aussagen zu handhaben, da diese Klausel recht klobig bekommen wird.

Danke für Ihre Hilfe!

Antwort

2

Falls es jemand anderem hilft, ist dies die Lösung, mit der ich gegangen bin:

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 

Danke an Ryan Bates von Railscasts für diese Lösung.

+0

Könnten Sie mir bitte mitteilen, in welchen Railscasts Sie diese Lösung gefunden haben? Danke im Voraus. –

+0

Es war nicht von einem Railscast. –

+0

Ok danke! Ich fand es sehr nützlich :) –

2

Sie müssen sich daran erinnern, dass die where in SQL umgewandelt wird, und wenn Sie verkettete Spalten mit einer Suchzeichenfolge vergleichen möchten, müssen Sie dies auf der Datenbank/SQL-Ebene tun.

Jetzt wird es hier knifflig, weil die Verkettung in SQL abhängig von Ihrer Datenbank ist.

In Postgresql und Oracle Sie so etwas wie schreiben würde:

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

Leider Mysql unterstützt nicht die Standard-Verkettungsoperator ||, mit mysql haben Sie concat stattdessen verwenden:

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

Gibt es einen besseren Weg als eine where-Klausel? Ich würde eher nichts hinzufügen, was für eine Datenbank spezifisch ist. –

+0

Die andere Option ist es im Speicher zu tun, aber ich würde dringend davon abraten. Ich denke, die Verwendung des 'where' hier ist die beste Option: Ihre Datenbank ist am besten für diese Aufgabe geeignet. In diesen Fällen befürchte ich, dass Sie nicht vermeiden können, einen datenbankspezifischen Code hinzuzufügen. – nathanvda