【问题标题】:Alternatives to making _id mass assignable使 _id 质量可分配的替代方法
【发布时间】:2012-07-03 02:01:01
【问题描述】:

我有一个 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 可访问?

【问题讨论】:

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


    【解决方案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 =&gt; build_attributes(:bar)

    【讨论】:

    • 这是朝着正确方向迈出的一大步,但看起来这种方法仍然需要 foo_id 可以批量分配?
    • 不,您应该在保存@bar之前添加到控制器的创建操作:@bar.foo = foo
    • 如果我这样做,我需要删除 params['bar'] 中的 foo_id 属性,这是帮助方法首先创建的?
    • 是的,如果你保护它免受批量分配。您需要在build_attributes helper 中删除它,而不是在控制器中。
    • 没想到没有更优雅的解决方案,非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多