Ich war daran interessiert, dasselbe zu tun und auch ein Modell von mir zu testen, das mit einem Hash von Inhalten aus einer Drittanbieter-API arbeitet. Ich fand heraus, dass ich mithilfe einiger der integrierten Funktionen von factory_girl diese Art von Datenstrukturen sauber erstellen konnte.
Hier ist ein erfundenes Beispiel:
factory :chicken, class:Hash do
name "Sebastian"
colors ["white", "orange"]
favorites {{
"PETC" => "http://www.petc.org"
}}
initialize_with { attributes }
end
Der Haupttrick hier ist, dass factory_girl beim Deklarieren von initialize_with nicht mehr versucht, die Attribute dem resultierenden Objekt zuzuweisen. In diesem Fall scheint es auch den Datenbankspeicher zu überspringen. Anstatt etwas Kompliziertes zu konstruieren, geben wir einfach den bereits vorbereiteten Attribut-Hash als unseren Inhalt zurück. Voila.
Es scheint notwendig, einen Wert für die Klasse anzugeben, obwohl dieser nicht tatsächlich verwendet wird. Dies soll verhindern, dass factory_girl versucht, eine Klasse basierend auf dem Factory-Namen zu instanziieren. Ich habe mich dafür entschieden, beschreibende Klassen anstelle von Object zu verwenden, aber es liegt an Ihnen.
Sie können weiterhin Felder überschreiben, wenn Sie eine dieser Hash-Fabriken verwenden:
chick = FactoryGirl.build(:chicken, name:"Charles")
Wenn Sie jedoch verschachtelten Inhalt haben und tiefere Felder überschreiben möchten, müssen Sie die Komplexität des Initialisierungsblocks erhöhen, um eine Art Deep Merge durchzuführen.
In Ihrem Fall verwenden Sie gemischte Array- und Hash-Daten, und es scheint, dass die Path-Eigenschaft zwischen Teilen der Datenstruktur wiederverwendet werden sollte. Kein Problem - Sie kennen die Struktur des Inhalts, sodass Sie einfach eine Factory erstellen können, die das resultierende Array ordnungsgemäß erstellt. So könnte ich es machen:
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)
Sie können auch weiterhin unnötige Werte weglassen. Stellen wir uns vor, nur Pfad und Drehzahl sind wirklich notwendig:
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)