首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >has_many,同时尊重factory_girl中的构建策略

has_many,同时尊重factory_girl中的构建策略
EN

Stack Overflow用户
提问于 2009-10-01 21:17:32
回答 3查看 7.4K关注 0票数 20

情况

代码语言:javascript
复制
# Models
class User < ActiveRecord::Base
  has_many :items 
end 

class Items < ActiveRecord::Base
  belongs_to :user 
  validates_presence_of :user_id 
end 

# Factories
Factory.define(:user) do |u| 
  u.name "foo" 
end 

Factory.define(:user_with_items, :parent => :user) do |u| 
  u.items {|items| [items.association(:item), items.association(:item)]} 
end

Factory.define(:item) do |i| 
  i.color "red" 
end 

Factory.define(:item_with_user, :parent => :user) do |i| 
  i.association(:user) 
end

问题

如果运行@user = Factory(:user_with_items),则@user.items包含这两项。问题是这些项目与数据库中的用户没有关联。如果重新加载关联@user.items(true),则会返回一个空数组。我知道您可以手动构建它们,也可以自己创建辅助方法来构建对象图,但我希望避免这种情况。

问题

所以,我的问题是,如何在尊重构建策略的同时,在factory_girl中建立has_many关系?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-10-16 23:04:58

我用继承之类的东西把它写得很好。My commits在herehere中合并。

它现在在FactoryGirl 1.2.3中,哇!

票数 18
EN

Stack Overflow用户

发布于 2009-10-01 23:10:30

我最终修补了factory girl以允许after_buildafter_create回调。

实现

代码语言:javascript
复制
Factory.class_eval do
  def run (proxy_class, overrides) #:nodoc:
    proxy = proxy_class.new(build_class)
    proxy.callbacks = @callbacks
    overrides = symbolize_keys(overrides)
    overrides.each {|attr, val| proxy.set(attr, val) }
    passed_keys = overrides.keys.collect {|k| Factory.aliases_for(k) }.flatten
    @attributes.each do |attribute|
      unless passed_keys.include?(attribute.name)
        attribute.add_to(proxy)
      end
    end
    proxy.result
  end

  def after_create(&block)
    @callbacks ||= {}
    @callbacks[:after_create] = block
  end

  def after_build(&block)
    @callbacks ||= {}
    @callbacks[:after_build] = block
  end
end

Factory::Proxy.class_eval do
  attr_accessor :callbacks

  def run_callback(name)
    callbacks && callbacks[name] && callbacks[name].call(@instance)
  end
end

Factory::Proxy::Build.class_eval do
  def result
    run_callback(:after_build)
    @instance
  end
end

Factory::Proxy::Create.class_eval do
  def result
    run_callback(:after_build)
    @instance.save!
    run_callback(:after_create)
    @instance
  end
end

这可能是一个邪恶的双胞胎,或者只是你需要的一个扩展。

示例用法

代码语言:javascript
复制
# Models
class User < ActiveRecord::Base
  has_many :items
end

class Items < ActiveRecord::Base
  belongs_to :user
  validates_presence_of :user_id
end

# Factories
Factory.define(:user) do |u|
  u.name "foo"
end

Factory.define(:user_with_items, :parent => :user) do |u|
  u.after_build do |o|
    o.items = [Factory.build(:item, :user => o), Factory.build(:item, :user => o)]
  end
end

Factory.define(:item) do |i|
  i.color "red"
end

Factory.define(:item_with_user, :parent => :user) do |i|
  i.association(:user)
end

# Run
user = Factory(:user_with_items)
user.items(true) # Shows the two saved items

希望这对将来的人有所帮助。我可能会尝试把这个提交给thoughtbot的人,但在他们的bug追踪器中已经有几张关于这个主题的过期罚单。

票数 11
EN

Stack Overflow用户

发布于 2011-03-02 12:50:39

我通常喜欢将构建和创建分开,这样我仍然可以在不访问数据库的情况下构建对象。

代码语言:javascript
复制
Factory.define(:user_with_items, :parent => :user) do |u|
  u.after_build do |u|
    u.items = (1..2).map {Factory.build(:item, :user => u)}
  end
  u.after_create do |u|
    u.items.each {|i| i.save!}
  end
end
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1506556

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档