我有一个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
Controller代码非常简单:
def create
@bar = Bar.new(params[:bar])
if @bar.save
redirect_to @bar
else
render action: 'new'
end
end
有没有办法让规范在不使foo_id
可访问的情况下运行?
答案 0 :(得分:1)
FactoryGirl .attributes_for
忽略关联。你可以做到
FactoryGirl.build(:bar).attributes
然而,您需要删除不需要的参数,例如id
,created_at
,updated_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)
。