ruby-on-rails-3 - sheet - factorybot create
¿Cómo definir una matriz/hash en Factory Girl? (5)
Estaba interesado en hacer lo mismo, también para probar un modelo mío que funciona utilizando un hash de contenido de una API de terceros. Descubrí que al usar algunas de las funciones integradas de factory_girl, pude construir estas estructuras de datos de forma limpia.
Aquí hay un ejemplo artificial:
factory :chicken, class:Hash do
name "Sebastian"
colors ["white", "orange"]
favorites {{
"PETC" => "http://www.petc.org"
}}
initialize_with { attributes }
end
El truco principal aquí es que cuando declaras initialize_with, factory_girl ya no intentará asignar los atributos al objeto resultante. También parece omitir la tienda de db en este caso. Entonces, en lugar de construir algo complicado, simplemente pasamos el hash de atributo ya preparado como nuestro contenido. Voila.
Parece necesario especificar algún valor para la clase, a pesar de que en realidad no se está utilizando. Esto es para evitar que factory_girl intente crear una instancia basada en el nombre de la fábrica. He elegido usar clases descriptivas en lugar de Object, pero depende de usted.
Todavía puede sobrescribir los campos cuando usa una de estas fábricas de hash:
chick = FactoryGirl.build(:chicken, name:"Charles")
... sin embargo, si ha anidado el contenido y desea anular los campos más profundos, necesitará aumentar la complejidad del bloque de inicialización para hacer una especie de fusión profunda.
En su caso, está usando algunos datos mezclados y hash, y parece que la propiedad Path debería reutilizarse entre partes de la estructura de datos. No hay problema: conoce la estructura del contenido, por lo que puede crear fácilmente una fábrica que construya la matriz resultante correctamente. He aquí cómo podría hacerlo:
factory :dropbox_hash, class:Array do
path "/home"
revision 48
rev "30054214dc"
thumb_exists false
bytes 0
modified { 3.days.ago }
is_dir true
icon "folder_app"
root "app_folder"
size "0 bytes"
initialize_with { [ attributes[:path], attributes ] }
end
FactoryGirl.build(:dropbox_hash, path:"/Chickens", is_dir:false)
También puede omitir valores innecesarios. Imaginemos que solo Path y rev son realmente necesarios:
factory :dropbox_hash, class:Array do
path "/home"
rev "30054214dc"
initialize_with { [ attributes[:path], attributes ] }
end
FactoryGirl.build(:dropbox_hash, path:"/Chickens", revision:99, modified:Time.now)
Estoy intentando escribir una prueba que simule algunos valores de retorno del servicio REST de Dropbox que me devuelve datos en una matriz, con un hash anidado.
Tengo problemas para descifrar cómo codificar mi fábrica, ya que el resultado de la devolución es una matriz con una dentro. ¿Qué iría aquí?
Factory.define :dropbox_hash do
??
end
Los datos de Dropbox se ven así:
["/home", {"revision"=>48, "rev"=>"30054214dc", "thumb_exists"=>false, "bytes"=>0, "modified"=>"Thu, 29 Dec 2011 01:53:26 +0000", "path"=>"/Home", "is_dir"=>true, "icon"=>"folder_app", "root"=>"app_folder", "size"=>"0 bytes"}]
Y me gustaría una llamada de fábrica como esta en mi RSpec:
Factory.create(:dropbox_hash)
Esto funcionó para mí, y puedo pasar atributos según sea necesario en el hash
factory :some_name, class:Hash do
defaults = {
foo: "bar",
baz: "baff"
}
initialize_with{ defaults.merge(attributes) }
end
> build :some_name, foo: "foobar" #will give you
> { foo: "foobar", baz: "baff" }
Puedes hacer esto en las últimas versiones de factory_girl, pero es incómodo porque está diseñado para construir objetos y no estructuras de datos. Aquí hay un ejemplo:
FactoryGirl.define do
factory :dropbox_hash, :class => ''Object'' do
ignore do
url { "/home" }
revision { 48 }
rev { "30054214dc" }
# more attributes
end
initialize_with { [url, { "revision" => revision, "rev" => rev, ... }] }
to_create {}
end
end
Repasando las cosas raras aquí:
- Cada fábrica necesita una clase de compilación válida, incluso si no se utiliza, así que pasé
Object
aquí para evitar que busqueDropboxHash
. -
array.revision = 48
ignorar todos los atributos utilizando un bloque deignore
para que luego no intente asignarlos a la matriz, comoarray.revision = 48
. - Puedes decirle cómo juntar tu resultado usando
initialize_with
. La desventaja aquí es que necesita escribir de nuevo la lista de atributos completa. - ¡
to_create
proporcionar un bloqueto_create
vacío para que no intente llamar aarray.save!
después.
Un seguimiento de la versión actual de RSpec (3.0):
Simplemente defina su fábrica como siempre y use FactoryGirl.attributes_for
para recibir un hash en lugar de una clase instanciada.
Usé OpenStruct:
factory :factory_hash, class:OpenStruct do
foo "bar"
si "flar"
end
Editar: lo siento, no funciona como un hash
Finalmente uso una versión estática, solo para mantener ese hash proveniente del sistema Factory ...
factory :factory_hash, class:Hash do
initialize_with { {
foo "bar"
si "flar"
} }
end
buscando algo mejor