in meinem project.rb-Modell versuche ich, einen Gültigkeitsbereich mit einer dynamischen Variablen zu erstellen:
scope :instanceprojects, lambda {
where("projects.instance_id = ?", current_user.instance_id)
}
Ich erhalte folgende Fehlermeldung:
undefined local variable or method `current_user' for #<Class:0x102fe3af0>
Wo im Controller kann ich auf current_user.instance_id
... zugreifen? Gibt es einen Grund, warum das Modell nicht darauf zugreifen kann, und eine Möglichkeit, um Zugriff zu erhalten? Ist dies auch der richtige Ort, um einen Bereich wie oben zu erstellen, oder gehört das zum Controller?
Das macht nicht viel Sinn, wie Sie schon gesagt haben. Der current_user gehört überhaupt nicht zur Modelllogik, er sollte auf Controller-Ebene behandelt werden.
Sie können jedoch weiterhin einen Bereich erstellen, indem Sie ihm einfach den Parameter vom Controller aus übergeben:
scope :instanceprojects, lambda { |user|
where("projects.instance_id = ?", user.instance_id)
}
Nun können Sie es im Controller aufrufen:
Model.instanceprojects(current_user)
Die bereits akzeptierte Antwort bietet einen wirklich richtigen Weg, um dies zu erreichen.
Aber hier ist die Thread-sichere Version von User.current_user
Trick.
class User
class << self
def current_user=(user)
Thread.current[:current_user] = user
end
def current_user
Thread.current[:current_user]
end
end
end
class ApplicationController
before_filter :set_current_user
def set_current_user
User.current_user = current_user
end
end
Dies funktioniert wie erwartet, kann jedoch als schmutzig betrachtet werden, da hier grundsätzlich eine globale Variable definiert wird.
Ryan Bates stellt eine ziemlich sichere Art dar, diese Art von Strategie zu implementieren in diesem Livescast
Dies ist eine bezahlte Episode (wählen Sie mich nicht herunter!), Aber Sie können den Quellcode kostenlos durchsuchen
Hier erstellt er eine current_tenant
-Methode, Sie können stattdessen jedoch current_user
leicht ersetzen.
Hier sind die wichtigsten Bits des Codes ...
#application_controller.rb
around_filter :scope_current_tenant
private
def current_tenant
Tenant.find_by_subdomain! request.subdomain
end
helper_method :current_tenant
def scope_current_tenant
Tenant.current_id = current_tenant.id
yield
ensure
Tenant.current_id = nil
end
#models/tenant.rb
def self.current_id=(id)
Thread.current[:tenant_id] = id
end
def self.current_id
Thread.current[:tenant_id]
end
Dann kannst du im Modell so etwas machen ...
default_scope { where(tenant_id: Tenant.current_id) }
Sie müssen keine Bereiche verwenden. Wenn Sie die entsprechenden Zuordnungen in Modellen festgelegt haben, sollte der folgende Code, der im Controller platziert wurde, den Trick ausführen:
@projects = current_user.instance.projects