ruby on rails - que - ¿Rails 3 idea, current_user no es accesible en un modelo?
ruby on rails tutorial (4)
Esto no tiene mucho sentido, como ya has señalado. El usuario_actual no pertenece a la lógica del modelo en absoluto, debe manejarse en el nivel del controlador.
Pero aún puedes crear un alcance como ese, solo pasarle el parámetro desde el controlador:
scope :instanceprojects, lambda { |user|
where("projects.instance_id = ?", user.instance_id)
}
Ahora puedes llamarlo en el controlador:
Model.instanceprojects(current_user)
en mi modelo project.rb, intento crear un ámbito con una variable dinámica:
scope :instanceprojects, lambda {
where("projects.instance_id = ?", current_user.instance_id)
}
Obtuve el siguiente error:
undefined local variable or method `current_user'' for #<Class:0x102fe3af0>
Donde en el controlador puedo acceder a 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?
La respuesta ya aceptada proporciona una forma realmente correcta de lograr esto.
Pero aquí está la versión segura para User.current_user
truco User.current_user
.
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í.
No necesita usar ámbitos. 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
Ryan Bates presenta una forma bastante segura de implementar este tipo de estrategia en esta transmisión de rieles
Este es un episodio pago (¡no me votes!) Pero puedes navegar por el código fuente gratis
Aquí crea un método current_tenant
, pero puede sustituir fácilmente a current_user
lugar.
Aquí están los pedazos 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 puedes hacer algo como ...
default_scope { where(tenant_id: Tenant.current_id) }