Esta es una de esas entradas para recordarme la solución a cosas que me han dado problemas.
En este caso es relativo al comportamiento que tiene ActiveRecord al asignar valores a las relaciones.
post = Post.new(:comments => [ Comment.new, Comment.new])
post.count # => 0
post.size # => 2
Parece razonable. Como todavía no se ha guardado el post
ni sus comments
el count
devuelve cero (lo que devolvería la base de datos). Sin embargo @size@devuelve la longitud correcta del array.
Sin embargo, esto es muy molesto durante las pruebas, dónde intentamos evitar los accesos a la base de datos.
let(:post) { mock_model(Post) }
before(:each) do
post.comments = [mock_model(Comment), mock_model(Comment)]
end
Si el código que probamos usa size
, el test es el que queremos. Si usa count
, entonces no. Y sería muy malo hacer que el test dependiese de la implementación elegida.
La solución (o una de ellas) es mockear la asociación para evitar la lógica de active record
:
let(:post) { mock_model(Post) }
before(:each) do
post.stub(:comments).
and_return [mock_model(Comment), mock_model(Comment)]
end
Porque, sí… los arrays devuelven el mismo valor para count
que para size
(y, ya puestos, para length
).
¿Qué te parece? ¿Hay una solución mejor?