2012-01-13 16 views
6

estoy spec'ing un ámbito en una aplicación Rails 3.0 de la siguiente manera:Timecop joya para los alcances

class DrawingList < ActiveRecord::Base 
    scope :active_drawings, where('start_date <= ? AND end_date >= ?', Date.today, Date.today) 
end 

En mi especificación, quiero hacer:

before do 
    @list = DrawingList.create #things that include begin and end dates 
end 

it "doesn't find an active drawing if they are out of range" do 
    pending "really need to figure out how to work timecop in the presence of scopes" 
    Timecop.travel(2.days) 
    puts Date.today.to_s 
    DrawingList.active_drawings.first.should be_nil 
end 

como se podría imagínense, los puts realmente muestran que Date.today es dentro de dos días. Sin embargo, el alcance se evalúa en un contexto diferente, por lo que utiliza el viejo "hoy". ¿Cómo se evalúa hoy en un contexto que Timecop puede afectar?

Gracias!

Respuesta

18

Este es un error muy común. Como ha escrito en la fecha utilizada por el alcance es la fecha tal como estaba cuando se cargó el código. Si ejecutas esto en producción, donde el código solo se recarga si reinicias la aplicación (a diferencia del desarrollo en el que se recarga en cada solicitud), obtendrás los resultados correctos el día que reinicies la aplicación, pero al día siguiente los resultados estaría fuera por un día, el día después de 2 días etc.

la forma correcta de definir un alcance como que es

scope :active_drawings, lambda { where('start_date <= ? AND end_date >= ?', Date.today, Date.today)} 

la lambda asegura que esas fechas son evaluados cada vez que se usa el alcance .

+0

Buena respuesta a una buena pregunta. –

+0

¡Es un tema tan difícil de atrapar! Gracias. Estoy tan contento que ahora estoy consciente de este comportamiento. –

Cuestiones relacionadas