2010-09-18 11 views
45

en mi modelo project.rb, estoy tratando de crear un instrumento que tiene una variable dinámica:Rails 3 idee, current_user no es accesible en un modelo?

scope :instanceprojects, lambda { 
    where("projects.instance_id = ?", current_user.instance_id) 
} 

me sale el siguiente error:

undefined local variable or method `current_user' for #<Class:0x102fe3af0> 

¿Dónde en el controlador de E puede acceder current_user.instance_id ... ¿Hay alguna razón por la cual el modelo no puede acceder y una forma de obtener acceso? Además, ¿es este el lugar adecuado para crear un ámbito como el anterior, o pertenece al controlador?

Respuesta

71

Esto no tiene mucho sentido, como ya ha señalado. El usuario_actual no pertenece a la lógica del modelo en absoluto, debe manejarse en el nivel del controlador.

Pero todavía se puede crear un espacio así, sólo tiene que pasar el parámetro a ella desde el controlador:

scope :instanceprojects, lambda { |user| 
    where("projects.instance_id = ?", user.instance_id) 
} 

Ahora se le puede llamar en el controlador:

Model.instanceprojects(current_user) 
+1

eso es increíble. probándolo ahora – AnApprentice

+0

Funcionó muy bien. ¡Gracias! – AnApprentice

+7

Llamé al alcance 'de' para que se lea bien. 'Project.of current_user' – romeroabelleira

27

La respuesta ya aceptada proporciona una forma realmente correcta de lograr esto.

Pero aquí está la versión flujos seguros de User.current_user truco.

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 

Esto funciona como se esperaba, sin embargo se puede considerar sucio, porque básicamente definimos una variable global aquí.

+2

Gracias - Tenía una situación específica en la que realmente lo necesitaba y no tenía forma de pasarlo. Por cierto, este código tiene algunos errores: debe usar el usuario.current_user = método de ApplicationController (de lo contrario, por qué lo tiene), y también está configurado en: current_user, pero el lector lee de: user (Me tomó mucho tiempo ver eso!) – Jords

+0

Gracias por señalarlo. Respuesta actualizada –

+0

Lo he intentado y funciona perfecto. Sin embargo, en mi entorno de desarrollo no hay una situación multiusuario. Todavía estoy preocupado por los comentarios en otras respuestas sobre el tema seguro de subprocesos. ¿Alguien más ha probado esto en el entorno de producción? ¡Aclamaciones! –

8

Ryan Bates establece una manera bastante segura para implementar este tipo de estrategia in this railscast

Este episodio pagado (no me votar abajo!) Pero se puede browse the source code for free

Aquí se crea un método current_tenant , pero podría sustituir fácilmente current_user en su lugar.

Éstos son los bits de la clave de código ...

#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 

Luego, en el modelo que se puede hacer algo como ...

default_scope { where(tenant_id: Tenant.current_id) } 
0

No es necesario utilizar alcances. Si ha establecido las asociaciones apropiadas en los modelos, la siguiente pieza de código colocada en el controlador debería hacer el truco:

@projects = current_user.instance.projects 
Cuestiones relacionadas