Estoy teniendo un pequeño problema con la constante ámbito en el mixin módulos. Digamos que tengo algo como esto
module Auth
USER_KEY = "user" unless defined? USER_KEY
def authorize
user_id = session[USER_KEY]
def
end
La USER_KEY constante, de forma predeterminada, el «usuario», a menos que ya está definido. Ahora puede mezclar esto en un par de lugares, pero en uno de esos lugares de la USER_KEY debe ser diferente, por lo que podría tener algo como esto
class ApplicationController < ActionController::Base
USER_KEY = "my_user"
include Auth
def test_auth
authorize
end
end
Yo esperaría que USER_KEY sería «mi_usuario» cuando se utiliza en autorizar, puesto que ya está definido, pero aún así «usuario», tomado de la definición de módulos de USER_KEY. Alguien tiene alguna idea de cómo conseguir la autorización para utilizar la versión de las clases de USER_KEY?
La
USER_KEY
declarado (incluso condicional) enAuth
es conocida a nivel mundial comoAuth::USER_KEY
. No hay «mixed» a la inclusión de módulos, aunque incluyendo módulos puede referencia la clave en un no-completo de la moda.Si quieres en cada una de ellas módulo (por ejemplo,
ApplicationController
) ser capaz de definir su propioUSER_KEY
, intente esto:Si vas a ir a todo este problema, sin embargo, usted puede ser que también acaba de llegar a un método de clase:
o una clase de nivel descriptor de acceso:
Constantes no tienen alcance global en Ruby. Las constantes pueden ser visibles desde cualquier ámbito, pero debe especificar donde la constante es para ser encontrado. Al comenzar una nueva clase, módulo, o def, de comenzar un nuevo ámbito, y si quieres una constante desde otro ámbito, usted tiene que especificar dónde encontrarlo.
X = 0
fuera de la clase yputs ::X
.class C::M::D; end
, dentro de que usted no será capaz de acceder a laM
alcance directamente, por lo queM::X
sería indefinido, sólo se podía acceder a ella comoC::M::X
.puts ::X
no volver2
(el valor deX
enmodule M
. Entonces, ¿qué hace::
decir? El «nivel superior»?Aquí una solución simple.
Cambios:
USER_KEY
..
Explicación
El comportamiento que estamos viendo no es específico para los rieles, sino que es debido a donde ruby busca constantes si no explícitamente ámbito a través de
::
(lo que yo llamo el «default», más arriba). Las constantes se buscan mediante el «ámbito léxico de el código actualmente en ejecución». Esto significa que ruby busca primero la constante en la ejecución de código del módulo (o de clase), luego se mueve hacia afuera para cada una de las sucesivas adjuntando módulo (o clase) hasta que encuentre la constante definida en ese ámbito.En su controlador, llamada
authorize
. Pero cuandoauthorize
es la ejecución, el código actualmente en ejecución es enAuth
. De modo que es donde las constantes miró hacia arriba. Si Auth no hanUSER_KEY
, pero una que encierra el módulo tiene, entonces, el que encierra uno podría ser utilizado. Ejemplo:Un caso especial de esto es el nivel superior del entorno de ejecución, el cual es tratado como pertenecientes a la clase
Object
.Una de ellas es la definición de un módulo o clase con el operador de ámbito (
::
):Tenga en cuenta que la constante puede ser definido mucho más tarde que el método está definido. La búsqueda sólo ocurre cuando USER_KEY se accede, por lo que esto también funciona:
Si su proyecto está en Rails, o al menos utiliza el
ActiveSupport
módulo, usted puede reducir significativamente la lógica necesaria azúcar:Me sorprende que nadie sugirió este enfoque, viendo cómo el OP del escenario residido dentro de una aplicación Rails…
Hay una solución más simple para el OP pregunta de las otras respuestas aquí revelan que:
Fue @james-un-rosen la respuesta que me dio la inspiración para tratar esto. Yo no quería ir a su ruta, porque he tenido varias constantes que son compartidos entre varias clases, cada una con un valor diferente, y su método se veía como un montón de escribir.