FactoryGirl:attributes_for没有给我关联属性

31
我有一个像这样的Code模型工厂:
Factory.define :code do |f|
    f.value "code"
    f.association :code_type
    f.association(:codeable, :factory => :portfolio)
end

但当我使用像这样的简单测试(test_should_create_code)测试我的控制器时:

  test "should create code" do
    assert_difference('Code.count') do
      post :create, :code => Factory.attributes_for(:code)
    end
    assert_redirected_to code_path(assigns(:code))
  end

测试失败,新记录未被创建。

在控制台中,看起来attributes_for没有像create一样返回所有所需的属性。

rob@compy:~/dev/my_rails_app$ rails console test
Loading test environment (Rails 3.0.3)
irb(main):001:0> Factory.create(:code)
=> #<Code id: 1, code_type_id: 1, value: "code", codeable_id: 1, codeable_type: "Portfolio", created_at: "2011-02-24 10:42:20", updated_at: "2011-02-24 10:42:20">
irb(main):002:0> Factory.attributes_for(:code)
=> {:value=>"code"}

有什么想法吗?

谢谢。

7个回答

23

7
这会带来一些不必要的副作用,如返回时间戳、ID等信息......并不是解决所有问题的理想方案。 - coneybeare
2
@coneybeare:这个问题有一个简单的解决方法。请查看以下链接中的解决方案:https://dev59.com/92kv5IYBdhLWcg3w4kl2 - fearless_fool
对我没用:它显示“MassAssignmentSecurity :: Error:无法批量分配受保护的属性:id,created_at,updated_at..” - Livia Huang

10

这个方法仅返回可进行批量赋值的属性,不包括时间戳等信息:

(FactoryGirl.build :position).attributes.symbolize_keys.reject { |key, value| !Position.attr_accessible[:default].collect { |attribute| attribute.to_sym }.include?(key) }

尽管如此,它仍然相当丑陋。 我认为FactoryGirl应该从一开始就提供这样的功能。

我在这里发起了一个请求:here


9
我建议采用另一种方法,我认为这更清晰:
attr = attributes_for(:code).merge(code_type: create(:code_type))

2
你也可以使用 attributes_for(:code).merge(code_type_attributes: attributes_for(:code_type)) - Matt

2

以下是我的做法...

conf = FactoryGirl.build(:conference)
post :create, {:conference => conf.attributes.slice(*conf.class.accessible_attributes) }

2

我将其他人说的内容综合起来,希望能对其他人有所帮助。为了与相关版本的FactoryGirl保持一致,我使用了Factory.build()而不是FactoryGirl.build()。如有需要,请进行更新。

def build_attributes_for(*args)
  build_object = Factory.build(*args)
  build_object.attributes.slice(*build_object.class.accessible_attributes).symbolize_keys
end

在 Factory.attributes_for 的位置上简单调用此方法:

post :create, :code => build_attributes_for(:code)

完整的代码片段(在一个辅助模块中)在此处:https://gist.github.com/jlberglund/5207078


0
在我的APP/spec/controllers/pages_controllers_spec.rb中,我设置了以下内容:
let(:valid_attributes) { FactoryGirl.attributes_for(:page).merge(subject: FactoryGirl.create(:theme), user: FactoryGirl.create(:user)) } 
因为我有两个相关的模型。这也可以工作:
 FactoryGirl.define do
    factory :page do
       title      { Faker::Lorem.characters 12 }
       body       { Faker::Lorem.characters 38 }
       discution  false
       published  true
       tags       "linux, education, elearning"
       section   { FactoryGirl.create(:section) }
       user      { FactoryGirl.create(:user)    }                                                                                                                            
     end
  end

0

这里有另一种方法。您可能想要省略idcreated_atupdated_at属性。

FactoryGirl.build(:car).attributes.except('id', 'created_at', 'updated_at').symbolize_keys

限制:

  • 它不会为HMT和HABTM关联生成属性(因为这些关联存储在连接表中,而不是实际属性)。
  • 工厂中的关联策略必须是create,例如association :user, strategy: :create。如果不明智地使用此策略,它可能会使您的工厂变得非常缓慢。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接