factory_botで配列/ハッシュを定義する方法は?


80

ネストされたハッシュを使用して、配列内のデータを返すDropboxのRESTサービスからのいくつかの戻り値をシミュレートするテストを作成しようとしています。

返される結果は内部にhasがある配列であるため、ファクトリのコーディング方法を理解するのに問題があります。ここに何が行きますか?

Factory.define :dropbox_hash do
 ??
end

Dropboxのデータは次のようになります。

 ["/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"}] 

そして、RSpecでこのようなファクトリコールが欲しいのですが:

Factory.create(:dropbox_hash)

あなたは本当にこれのための工場が必要ですか?シミュレートされた応答を返すメソッドを定義しないのはなぜですか?
ゼテティック2012

それが私がやったことです。しかし、ファクトリーのポイントは、このようなものを分離することだと思いました。私はまだ興味があります-ハッシュと配列はクラスのようです。正しい構文を取得できれば、これは機能するはずです。
ダグ

ActiveRecordモデルインスタンスの生成にのみ使用しました。FactoryGirlは、器具を置き換えることを目的としています。あなたはRSpecのヘルパーメソッドを見るかもしれません:relishapp.com/rspec/rspec-core/v/2-9/docs/helper-methods
zetetic

回答:


155

サードパーティのAPIからのコンテンツのハッシュを使用して動作する私のモデルをテストするためにも、同じことを行うことに興味がありました。factory_girlの組み込み機能のいくつかを使用することで、この種のデータ構造をきれいに構築できることがわかりました。

不自然な例を次に示します。

  factory :chicken, class:Hash do
    name "Sebastian"
    colors ["white", "orange"]

    favorites {{
      "PETC" => "http://www.petc.org"
    }}

    initialize_with { attributes } 
  end

ここでの主なトリックは、initialize_withを宣言すると、factory_girlが結果のオブジェクトに属性を割り当てようとしないことです。この場合、dbストアをスキップするようにも見えます。したがって、複雑なものを作成する代わりに、準備済みの属性ハッシュをコンテンツとして返すだけです。出来上がり。

実際には使用されていませんが、クラスに何らかの値を指定する必要があるようです。これは、factory_girlがファクトリ名に基づいてクラスをインスタンス化しようとするのを防ぐためです。Objectではなく記述クラスを使用することを選択しましたが、それはあなた次第です。

これらのハッシュファクトリのいずれかを使用する場合でも、フィールドをオーバーライドできます。

chick = FactoryGirl.build(:chicken, name:"Charles")

ただし、ネストされたコンテンツがあり、より深いフィールドをオーバーライドする場合は、初期化ブロックの複雑さを増して、ある種の深いマージを実行する必要があります。

あなたの場合、配列とハッシュの混合データを使用しており、Pathプロパティはデータ構造の一部間で再利用する必要があるようです。問題ありません。コンテンツの構造を知っているので、結果の配列を適切に構築するファクトリを簡単に作成できます。これが私がそれをするかもしれない方法です:

  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)

また、不要な値を自由に省略できます。Pathとrevだけが本当に必要だと想像してみましょう。

  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)

これは素晴らしい解決策です。工場の継承でも機能します。
David Pelaez 2014年

このレコード生成/ビルドに私のために動作しますが、それは糸くずが失敗します。FacoryGirl.lint
pixelearth

これありがとう。favorites複数行のブロックでRubocopリンターを渡すには、のdo..end代わりにを使用します{{..}}
scarver2 2018

skip_create代わりに「create」を呼び出したい場合は、ファクトリに追加できますbuild
Sairam

すごい。任意のカスタムクラスを初期化できinitialize_with、クラスコンテキストで評価できることがわかりました。つまり、ある場合はinitialize_with { new(attributes) }、次のbuild :my_factory結果が返されますMyClass.new(attributes)
MikDiet 2010年

10

これが機能するようになり、必要に応じて属性をハッシュに渡すことができます

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" }

3
これには、キーを文字列にすることができるという追加の利点もあります。
crftr 2016

ここでの欠点は、作成されるたびに新しいオブジェクトではなく、単一のオブジェクトを変更することです。ハッシュののOBJECT_IDを見てみましょう
アンソニー・


6

これは最新バージョンのfactory_girlで実行できますが、データ構造ではなくオブジェクトを構築するように設計されているため、扱いにくいです。次に例を示します。

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

ここで奇妙なことを調べます:

  • すべてのファクトリは、使用されていない場合でも有効なビルドクラスを必要とするため、を検索しないようにObjectここに渡しましたDropboxHash
  • ignoreブロックを使用してすべての属性を無視して、後でそれらを配列に割り当てようとしないようにする必要がありますarray.revision = 48
  • を使用して、結果をまとめる方法を説明できますinitialize_with。ここでの欠点は、完全な属性リストを再度書き出す必要があることです。
  • 後でto_create呼び出そうとしないように、空のブロックを指定する必要がありますarray.save!

0

私はOpenStructを使用しました:

factory :factory_hash, class:OpenStruct do
  foo "bar"
  si "flar"
end

編集:申し訳ありませんが、ハッシュとして機能しません

ファクトリーシステムからのハッシュを維持するために、最終的に静的バージョンを使用します...

factory :factory_hash, class:Hash do
  initialize_with { {
    foo "bar"
    si "flar"
  } }
end

より良いものを探しています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.