it-swarm.com.de

Rails 3-Gerät, current_user ist in einem Modell nicht zugänglich?

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?

46
AnApprentice

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)
73
mdrozdziel

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.

30
Michał Szajbe

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) }
8
Mark Locklear

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
0
sampi