Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 3 工厂女孩:为什么属性_省略了一些属性?_Ruby On Rails 3_Factory Bot - Fatal编程技术网

Ruby on rails 3 工厂女孩:为什么属性_省略了一些属性?

Ruby on rails 3 工厂女孩:为什么属性_省略了一些属性?,ruby-on-rails-3,factory-bot,Ruby On Rails 3,Factory Bot,我想使用FactoryGirl.attributes_进行控制器内测试,如: it "raise error creating a new PremiseGroup for this user" do expect { post :create, {:premise_group => FactoryGirl.attributes_for(:premise_group)} }.to raise_error(CanCan::AccessDenied) end 。。。但这不起作

我想使用FactoryGirl.attributes_进行控制器内测试,如:

it "raise error creating a new PremiseGroup for this user" do
  expect {
    post :create, {:premise_group => FactoryGirl.attributes_for(:premise_group)}
  }.to raise_error(CanCan::AccessDenied)
end
。。。但这不起作用,因为#attributes_for忽略了:user_id属性。以下是的
#创建
#属性"之间的区别:

>> FactoryGirl.create(:premise_group)
=> #<PremiseGroup id: 3, name: "PremiseGroup_4", user_id: 6, is_visible: false, is_open: false)
>> FactoryGirl.attributes_for(:premise_group)
=> {:name=>"PremiseGroup_5", :is_visible=>false, :is_open=>false}
简短答复: 根据设计,FactoryGirl的
属性为
故意忽略会触发数据库事务的内容,以便测试快速运行。但是如果您愿意花时间,您可以编写一个
build\u attributes
方法(如下)来建模所有属性

原始答案 深入研究FactoryGirl文档,例如,您会发现提到
attributes\u忽略了关联——请参阅下面的更新。作为一种解决方法,我围绕着
FactoryGirl.build(…).attributes
包装了一个helper方法,该方法去除了
id
处创建,以及
处更新:

def build_attributes(*args)
  FactoryGirl.build(*args).attributes.delete_if do |k, v| 
    ["id", "created_at", "updated_at"].member?(k)
  end
end
所以现在:

>> build_attributes(:premise_group)
=> {"name"=>"PremiseGroup_21", "user_id"=>29, "is_visible"=>false, "is_open"=>false}
。。。这正是人们所期望的

更新
吸收了FactoryGirl创建者的意见后,我理解了为什么
attributes\u for
忽略关联:引用关联会生成对db的调用,这在某些情况下会大大降低测试速度。但是,如果您需要关联,上面显示的
构建属性
方法应该会起作用。

我认为这比无所畏惧的傻瓜的答案稍有改进,尽管这取决于您想要的结果

用一个例子最容易解释。假设模型中有lat和long属性。在表单上,没有lat和long字段,而是lat degree、lat minute、latsecond等。这些字段稍后可以转换为十进制lat long格式

假设你的工厂是这样的:

factory :something
  lat_d 12
  lat_m 32
  ..
  long_d 23
  long_m 23.2
end
fearless的
build\u属性将返回
{lat:nil,long:nil}
。而下面的
build\u属性将返回
{lat\u d:12,lat\u m:32…,lat:nil…}

def build_attributes
  ba = FactoryGirl.build(*args).attributes.delete_if do |k, v| 
    ["id", "created_at", "updated_at"].member?(k)
  end
  af = FactoryGirl.attributes_for(*args)
  ba.symbolize_keys.merge(af)
end

为了进一步阐述给定的
build\u属性
解决方案,我对其进行了修改,只添加了可访问的关联:

def build_attributes(*args)
    obj = FactoryGirl.build(*args)
    associations = obj.class.reflect_on_all_associations(:belongs_to).map { |a| "#{a.name}_id" }
    accessible = obj.class.accessible_attributes

    accessible_associations = obj.attributes.delete_if do |k, v| 
        !associations.member?(k) or !accessible.include?(k)
    end

    FactoryGirl.attributes_for(*args).merge(accessible_associations.symbolize_keys)
end
还有一种方法:

FactoryGirl.build(:car).attributes.except('id'、'created\u at'、'updated\u at')。符号化\u键

限制:

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

经过网络挖掘后,我认为公认的答案似乎过时了,因为它对我不起作用&特别是,我向您介绍:

Rails 5最基本功能的干净版本+ 这将创建
:属于
关联,并将其
id
(和
类型
(如果
:多态
)添加到属性中。它还通过
FactoryBot::Syntax::Methods
包含代码

spec/support/factory\u bot\u macros.rb

模块FactoryBot::语法::方法
定义(*args)的嵌套属性
attributes=属性(用于(*args)
klass=args.first.to_.camelize.constantize
klass.反思所有协会(:所属)。每个协会|
关联=FactoryBot.create(r.class\u name.下划线)
属性[“#{r.name}_id”]=association.id
属性[“#{r.name}_type”]=association.class.name如果r.options[:多态性]
结束
属性
结束
结束


这是一个经过改编的版本,对他来说是一种荣誉。看起来有一些这样的问题:我目前将build\u attributes方法放在
spec/spec\u helper.rb
下。或者我应该把它放在其他地方?@MikeHan:把#build_属性放在spec/spec_helper.rb中应该可以。在我的例子中,我把它放在spec/factories.rb文件中。把它放在spec/factory\u girl\u helper.rb中,并在需要时包含它,可能会稍微干净一些。@fearless\u傻瓜酷。谢谢你的提示。这太棒了。谢谢你的帮助!我还没有试过你的代码,但我怀疑你的意思是删除如果!成员?还有!包括对吗?
def build_attributes(*args)
    obj = FactoryGirl.build(*args)
    associations = obj.class.reflect_on_all_associations(:belongs_to).map { |a| "#{a.name}_id" }
    accessible = obj.class.accessible_attributes

    accessible_associations = obj.attributes.delete_if do |k, v| 
        !associations.member?(k) or !accessible.include?(k)
    end

    FactoryGirl.attributes_for(*args).merge(accessible_associations.symbolize_keys)
end