1

関連するモデルの作成をテストする Rails コントローラーの仕様があります。

モデル:

class Foo < ActiveRecord::Base
  has_many :bars
end

class Bar < ActiveRecord::Base
  belongs_to :foo
  attr_accessible :foo, :foo_id
end

コントローラーの仕様:

@foo = FactoryGirl.create(:foo)
expect {
  post :create, { bar: FactoryGirl.attributes_for(:bar, foo_id: @foo.id )}
}.to change(Bar, :count).by(1)

この仕様を一括割り当て可能にする必要のない形式に変更すると、次のfoo_idように壊れActiveRecord::AssociationTypeMismatch expected Foo got Stringます。

@foo = FactoryGirl.create(:foo)
expect {
  post :create, { bar: FactoryGirl.attributes_for(:bar, foo: @foo )}
}.to change(Bar, :count).by(1)

describe Bar do
  it { should_not allow_mass_assignment_of(:foo_id) }
end

コントローラーのコードは非常に単純です。

def create
    @bar = Bar.new(params[:bar])
    if @bar.save
      redirect_to @bar
    else
      render action: 'new'
    end
  end

アクセス可能にせずに仕様を実行する方法はありfoo_idますか?

4

1 に答える 1

1

FactoryGirl.attributes_forは関連付けを無視します。できるよ

FactoryGirl.build(:bar).attributes

ただし、その方法では、、、などidの不要なパラメータを削除する必要があります。created_atupdated_at

で特別なメソッドを作成することをお勧めしますspec_helper

def build_attributes(*args)
  FactoryGirl.build(*args).attributes.delete_if do |k, v|
    ['id', 'created_at', 'updated_at'].member?(k)
  end
end

そしてそれを使用します:post :create, :bar => build_attributes(:bar)

于 2012-07-03T06:05:48.057 に答える