2012-09-28 49 views
19

Aquí hay un poco de código del Tutorial Ruby on Rails de M Hartl. ¿Alguien puede explicar por qué es necesaria una variable de instancia (@user) y por qué no usar una variable local? Además, dado que se supone que las variables de instancia son las variables en la instancia de una clase, ¿a qué clase pertenece @user instance?¿Cómo funcionan las variables de instancia en rspec?

require 'spec_helper' 

describe User do 

    before { @user = User.new(name: "Example User", email: "[email protected]") } 

    subject { @user } 

    it { should respond_to(:name) } 
    it { should respond_to(:email) } 
end 

Respuesta

32

Uso de una variable local en ese caso significaría que su alcance se limita a la before y por lo tanto da como resultado un error. El @user es del tipo Usuario pero es una variable de instancia del bloque describe. Rspec tiene algo de magia que en el tiempo de ejecución forma una clase de cada bloque describe. Cada ejemplo (bloque it) termina siendo una subclase de dicha clase. La herencia de clase permite que los ejemplos vean @user.

Editado 2017-05-14

Vinculado entrada en el blog ya no está disponible. Actualizando con Wayback Machine link + insertando la sección relevante aquí.

Tenga en cuenta que esto se considera un antipatrón como se detalla en este blog post. Use let en su lugar.

let tiene las siguientes ventajas:

  • Se memoized cuando se utiliza múltiples veces en un ejemplo, pero no a través de ejemplos.
  • Tiene una carga lenta, por lo que no perderá el tiempo inicializando la variable para ejemplos que no hacen referencia a ella.
  • Se generará una excepción si tiene un error tipográfico en su nombre de variable.
+1

Oh, creo que lo entiendo ahora.Siempre pensé que describir bloque se usaba para hacer las pruebas más legibles para los humanos y nada más. Gracias :) – TradeRaider

+0

Esa publicación del blog ya no está disponible. Puede valer la pena actualizar la respuesta para incluir razones por las que usar una variable de instancia es un antipatrón y eliminar el enlace roto. – keoghpe

2

subject ad it bloques están bajo diferentes ámbitos, por lo que las variables locales no funcionarán. @user pertenece a la clase generada por RSpec debajo del capó.

12

No puede usar una variable local porque una variable local existe solo en el alcance del método local. before, subject y it genera diferentes ámbitos dentro de la misma clase.

El siguiente código

before { user = User.new(name: "Example User", email: "[email protected]") } 

elevará una variable no definida cuando se llama en

subject { user } 

La instancia @user es una instancia de la clase User (después de todo, se crea con User.new)

Sin embargo, en lugar de variables de instancia, es posible que desee utilizar el comando let. Además, si se define

subject { User.new(name: "Example User", email: "[email protected]") } 

no se requiere el uso de before. También obtendrá el beneficio adicional para obtener un método subject disponible para acceder a la instancia, igual a definir let(:subject).

+4

+1 sobre el uso de 'let':' let (: usuario) {User.create (nombre: "Usuario de ejemplo", correo electrónico: "[email protected]")} ' – Meltemi

+0

+1 sobre el uso de asunto: asunto {Usuario. nuevo (nombre: "Usuario de ejemplo", correo electrónico: "[email protected]")} –

Cuestiones relacionadas