2010-04-20 6 views
53

Ich denke, das sollte sehr einfach sein, aber mein Gehirn ist kurz darauf. Wenn ich ein Objekt habe, das den aktuellen Benutzer darstellt und für alle Benutzer mit Ausnahme des aktuellen Benutzers abfragen möchte, wie kann ich dies tun, unter Berücksichtigung, dass der aktuelle Benutzer manchmal nil sein kann?Rails ActiveRecord: Finden Sie alle Benutzer mit Ausnahme des aktuellen Benutzers

Das ist, was ich jetzt tue:

def index 
    @users = User.all 
    @users.delete current_user 
end 

Was auf dem Abfrageergebnis die ich nicht mag, ist, dass ich tue Nachbearbeitung. Abgesehen davon, dass ich mich ein bisschen falsch fühle, glaube ich nicht, dass dies gut funktionieren wird, wenn ich die Abfrage überführe, um mit will_paginate ausgeführt zu werden. Irgendwelche Vorschläge, wie Sie dies mit einer Abfrage tun können? Vielen Dank.

+1

Meiner Meinung nach, wenn ich nach etwas fragen sollte ich lasse die Teil meiner für die Abfrage optimierten Anwendung handle das: die Datenbank. Die Nachbearbeitung der Ergebnisse einer Abfrage, um sie weiter zu filtern, stellt für mich die Logik an die falsche Stelle. – SingleShot

Antwort

119

Es ist möglich, die folgenden in Rails 4 zu tun:

User.where.not(id: id) 

Sie wickeln kann es in einem schönen Rahmen.

scope :all_except, ->(user) { where.not(id: user) } 
@users = User.all_except(current_user) 

Oder eine Klasse Methode verwenden, wenn Sie bevorzugen:

def self.all_except(user) 
    where.not(id: user) 
end 

Beiden Methoden werden ein AR-Relation-Objekt zurück. Das heißt, Sie können Kette Methode aufruft:

@users = User.all_except(current_user).paginate 

Sie können eine beliebige Anzahl von Benutzern ausschließen können, weil where() akzeptiert auch ein Array.

@users = User.all_except([1,2,3]) 

Zum Beispiel:

@users = User.all_except(User.unverified) 

Und auch durch andere Verbände:

class Post < ActiveRecord::Base 
    has_many :comments 
    has_many :commenters, -> { uniq }, through: :comments 
end 

@commenters = @post.commenters.all_except(@post.author) 

Siehe where.not() im API Docs.

+1

Also überholt eine Upvote-Zahl schließlich eine akzeptierte Antwort? – wurde

+0

@wurde no: D - aber es wird da sein, damit die Leute sehen, welche Antwort die Benutzer am meisten schätzen. – Mohamad

+0

Sollte ein Banner auf akzeptierte Antworten platzieren, mit denen die Community nicht einverstanden ist. Ähnlich wie die Regierung Banner auf Zigarettenschachteln verlangt. – wurde

32
@users = (current_user.blank? ? User.all : User.find(:all, :conditions => ["id != ?", current_user.id])) 
+0

Danke für den named_scope Vorschlag. Es hat den Controller ein bisschen aufgeräumt und es weniger hässlich gemacht, wenn man auf "will_paginate" upgradet. Danke noch einmal. – SingleShot

-5

Was Sie tun, ist das Löschen der aktuellen Benutzer aus dem @ users Array. Dies wird nicht funktionieren, da es keine Löschmethode für Arrays gibt. Was möchten Sie wahrscheinlich zu tun ist, diese

def index 
    @users = User.all 
    @users - [current_user] 
end 

Dieses eine Kopie des @users Array zurück, aber mit dem current_user Objekt entfernt (es wurde in der Anordnung in erster Linie enthalten.

Hinweis : Dies funktioniert möglicherweise nicht, wenn Array-Subtraktion auf genaue Übereinstimmungen von Objekten und nicht den Inhalt basiert. Aber es funktionierte mit Strings, wenn ich es versuchte. Denken Sie daran, current_user in [] zu erzwingen, um es in ein Array zu zwingen.

+0

Danke für Ihre Antwort. Das von mir eingereichte Codebeispiel funktioniert tatsächlich, weil es tatsächlich eine Löschmethode für Array gibt. Leider erreicht dein Vorschlag nicht ganz das, wonach ich suche. Danke noch einmal. – SingleShot

+3

>> Array.new.methods.grep/delete/ => ["delete_at", "delete_if", "löschen"] – user253455

+2

Diese Antwort ist auch falsch, da die Indexansicht partiell die @ users-Instanzvariable verwendet, die unverändert ist durch die '-' Operation. Es spielt keine Rolle, was die Indexmethode zurückgibt. (Sie mussten den Operator - = verwenden, um @users an Ort und Stelle zu ändern) – ndbroadbent

7

Hier ist eine kürzere Version:

User.all :conditions => (current_user ? ["id != ?", current_user.id] : []) 
+0

Ich nahm die Antwort von Benutzer jdl, seinen Kommentar über benannte Bereiche und Ihre Verfeinerung und bin jetzt glücklich. Der Controller ist ziemlich sauber, obwohl das named_scoped ein bisschen hässlich ist. Nach dem Hinzufügen von will_paginate hier ist meine Abfrage: User.all_except (current_user) .paginate (: page => params [: page]) – SingleShot

+0

@SingleShot Ich habe die Antwort bearbeitet. –

+0

Sieht gut aus für mich. –

16

Sie können auch named_scope, z. in Ihrem Modell:

named_scope :without_user, lambda{|user| user ? {:conditions => ["id != ?", user.id]} : {} } 

und in der Steuerung:

def index 
    @users = User.without_user(current_user).paginate 
end 

Dieser Rahmen wird für alle Benutzer zurück, wenn mit Null und alle Benutzer mit Ausnahme gegeben in param in anderen Fällen genannt. Der Vorteil dieser Lösung besteht darin, dass Sie diesen Aufruf mit anderen benannten Bereichen oder der paginate-Methode "will_paginate" ketten können.

+0

Dies ist die beste Antwort. Daten so lange wie möglich in Bereichen aufbewahren Außerdem funktionieren die meisten Abfragen in Rails 3 mit Arel. – Gdeglin

+0

Verwenden Sie Klassenmethoden statt Scopes Lambda mit Params – Hauleth

6

Ein Hinweis auf GhandaL Antwort - zumindest in Rails 3, es ist Modifizieren wert

scope :without_user, lambda{|user| user ? {:conditions => ["users.id != ?", user.id]} : {} } 

(Primär hier Veränderung von zu ‚users.id = 'id = ...!'!. .. '; auch scope anstelle von named_scope für Rails 3)

Die ursprüngliche Version funktioniert gut, wenn man einfach die Tabelle Users definiert. Beim Anwenden des Bereichs auf eine Verknüpfung (z. B. team.members.without_user (current_user) ....) musste diese Änderung klären, welche Tabelle wir für den ID-Vergleich verwenden. Ich sah einen SQL-Fehler (mit SQLite) ohne es.

Entschuldigung für die separate Antwort ... Ich habe noch nicht den Ruf, direkt auf GhandaLs Antwort zu kommentieren.

2

Sehr einfache Lösung, die ich verwendet

@users = User.all.where("id != ?", current_user.id) 
0

Eine weitere einfache Möglichkeit, Sie könnte es tun:

@users = User.all.where("id NOT IN(?)", current_user.id) 
0

User.all.where ("? Id NICHT IN()", current_user.id) werden über undefinierte Ausnahme Verfahren, bei dem für #<Array:0x0000000aef08f8>

User.where("id NOT IN (?)", current_user.id) 
0

ein Array mehr helfen würde, ful

arrayID [0] = 1

arrayID [1] = 3

User.where.not (id: arrayID)

Verwandte Themen