web-dev-qa-db-ja.com

ビルド/作成時にモデル定義に引数を渡すファクトリーガール

models/message.rb

class Message

  attr_reader :bundle_id, :order_id, :order_number, :event

  def initialize(message)
    hash = message
    @bundle_id = hash[:payload][:bundle_id]
    @order_id  = hash[:payload][:order_id]
    @order_number = hash[:payload][:order_number]
    @event = hash[:concern]
  end
end

spec/models/message_spec.rb

require 'spec_helper'

describe Message do
  it 'should save the payload' do
    payload = {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"}
    message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"})
    message.event.should == "order_create"
  end
end

エラーログ

失敗:

1)メッセージはペイロードを保存する必要があります

 Failure/Error: message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"})
 ArgumentError:
   wrong number of arguments (0 for 1)
 # ./app/models/message.rb:4:in `initialize'
 # ./spec/models/message_spec.rb:7:in `block (2 levels) in <top (required)>'
15
Furqan Asghar

FactoryGirlでは、最初にファクトリを定義する必要があります。ファイルspec/factorys /messages.rbで次のようにしましょう。

FactoryGirl.define do
  factory :message do
    bundle_id 1
    order_id 2
    ...etc...
  end
end

この後、次のようにファクトリビルド作成を呼び出すことができます。

FactoryGirl.build(:message)  # => bundle_id == 1, order_id == 2
FactoryGirl.build(:message, order_id: 3) # => bundle_id == 1, order_id == 3

ただし、特定のケースには1つの問題があります。 FactoryGirlのデフォルトビルダーは、ActiveRecordに似たインターフェース上で動作します。モデルコンストラクターに渡される属性のハッシュではなく、セッターを介して定義済み属性を設定します。

m = Message.new
m.bundle_id = 1
m.order_id  = 2

そのため、モデルのインターフェイス(ActiveRecordに似たモデルに準拠していない)を操作するカスタムコンストラクターを作成し、それをファクトリ定義に登録する必要があります。詳細については、 factory girl docs を参照してください。

その例をお見せしましょう。申し訳ありませんが、テストはしていませんが、手がかりが得られるはずです。

FactoryGirl.define do
  factory :message do
    ignore do
      # need to make all attributes transient to avoid FactoryGirl calling setters after object initialization
      bundle_id 1
      order_id 2
    end

    initialize_with do
      new(payload: attributes)
    end
  end
end
22
cryo28

これは、必須の引数を持つコンストラクターがあるためです。いくつかのオプションがあります。

1)引数を必須ではありません(ただし、これは、テストに合わせてコードを変更することを意味します-いたずらです!)

def initialize(message = nil)

2)ファクトリで「initialize_with」構文を使用します。

describe Message do
  it 'should save the payload' do
    payload = {:payload=>{:order_id=>138251, :order_number=>"AW116554416"},   :concern=>"order_create"}
    message = FactoryGirl.build(:message, {:payload=>{:order_id=>138251, :order_number=>"AW116554416"}, :concern=>"order_create"})
    message.event.should == "order_create"
  end

  initialize_with { new(message) }
end
0
Mikey Hogarth