使_id可分配的替代方案

时间:2012-07-03 02:01:02

标签: ruby-on-rails activerecord rspec factory-bot

我有一个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可访问的情况下运行?

1 个答案:

答案 0 :(得分:1)

FactoryGirl .attributes_for忽略关联。你可以做到

FactoryGirl.build(:bar).attributes

然而,您需要删除不需要的参数,例如idcreated_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)