FactoryBot能在您创建模型后生成工厂吗?

62

如果在Gemfile的dev和test blocks中包含factory_bot_rails gem,则当rails生成模型时,它会自动生成工厂。

是否有一种方法可以在生成模型后生成工厂?


注意:FactoryBot以前叫做FactoryGirl。


你所说的“生成”是什么意思?你必须明确定义并显式调用它们。 - iltempo
@iltempo - 我的意思是,当您使用“factory_girl_rails”宝石时,通过命令生成模型(如“rails g model User first_name:string”...等),此模型的工厂将自动生成,就像测试用例一样。我想知道是否有一种方法在模型创建后使用生成器挂钩。 - GuiDoody
9个回答

177

首先,查看源代码以了解它是如何实现的:

https://github.com/thoughtbot/factory_bot_rails/blob/master/lib/generators/factory_bot/model/model_generator.rb

然后,尝试猜测它是如何工作的:

rails g factory_bot:model Car name speed:integer

结果是:

create  test/factories/cars.rb

并且内容为:

# Read about factories at https://github.com/thoughtbot/factory_girl

FactoryBot.define do
   factory :car do
     name "MyString"
     speed 1
   end
end

记住,在使用 "rails g" 命令时,您始终可以使用 "rails d" 命令撤消它。

rails d factory_bot:model Car name speed:integer

注意:FactoryBot以前的名称是FactoryGirl


12
这应该是正确的答案,因为它回答了关于如何为已创建的模型生成工厂的具体问题。常见的情况是将现有的Rails应用程序从默认固定装置切换到使用FactoryGirl。 - Shyam Habarakada
2
你甚至不需要猜测它是如何工作的,rails g factory_girl:model --help 命令会告诉你如何操作。 - Les Nightingill
6
有没有办法在 spec 目录下创建它? - juliangonzalez
@juliangonzalez 你可以使用 --dir 选项指定目录。rails g factory_girl:model User --dir spec/factories - marman
还有一种方法可以使用schema_to_scaffold gem来实现。它会打印出包含表中所有字段/列的factory_bot:model脚本。 请看下面我的回答。 - frenesim

21

22
这个回答如何回答问题?在模型创建后它如何生成工厂? - Emil
1
请参见下面用户2040729的答案。 - Shyam Habarakada
为了让这个在Rails 4.1中与rspec一起工作,我需要编写以下代码:g.fixture_replacement :factory_girl, dir: "spec/factories" - ClaytonC
4
谁是user2040729?这怎么回答问题?如何使用--fixture-replacement - Arnold Roa
1
这里有一个很大的误解。@GuiDoody 是在询问 rails g model 命令之后调用的生成器命令,而不是使用模式描述在模式中创建魔法工厂。该选项在此处进行了讨论:https://github.com/thoughtbot/factory_girl_rails/issues/63。@edouardo-santana 和 @cjhveal 的答案都是可以接受的。 - fro_oo
显示剩余3条评论

10

谢谢这个宝石,非常不错。 - Tyrel Richey

7

我使用rails g factory_bot:model User命令,可以实现这个功能,无论是运行该命令还是直接输出puts'ing该命令都可以。但您仍然需要填写值。

@run_command        = true
@force              = true
@columns_to_ignore  = %w[id created_at update_at]
@tables_to_ignore = %w[schema_migrations ar_internal_metadata]
tables = ActiveRecord::Base.connection.tables.reject{|t| (@tables_to_ignore || []).include?(t)}

tables.each do |table|
  klass = table.singularize.camelcase.constantize
    command = "rails g factory_bot:model #{klass.to_s} #{klass.columns.reject do |c|
      (@columns_to_ignore || []).include?(c.name)
    end.map do |d|
      "#{d.name}:#{d.sql_type == 'jsonb' ? 'json' : d.type}"
  end.join(' ')}"
  command << ' --force' if @force
  puts command
  puts %x{#{command}} if @run_command
  puts (1..200).to_a.map{}.join('-')
end

这个答案一定是正确的,它可以从数据库中生成工厂。太棒了! 赞! - TheVinspro
小心使用这个脚本,默认情况下 @force = true。 - jrhicks

4

3

这不是答案,但由于我还不能评论:

我认为你可以使用一个叫做schema_to_scaffold的gem来解决部分问题。它能够从你的schema.rb或重命名后的schema.rb生成factory_girl:model命令字符串。输出结果如下:

rails generate factory_girl:model users fname:string lname:string bdate:date email:string encrypted_password:string

请查看这里这里


0

并不完全相关。

我也创建了一个宝石, 用于从现有数据构建工厂。

希望可以帮助您加快流程速度......

puts FactoryBotFactory.build(User.new, file_path: 'spec/factories/user.rb')
puts FactoryBotFactory.build(User.last, file_path: 'spec/factories/user.rb')

# example output from User.new
FactoryBot.define do
  factory :user, class: User do
    id { nil }
    name { nil }
    created_at { nil }
    updated_at { nil }
    display_name { nil }
    image_url { nil }
    is_active { true }
  end
end

如果您需要构建虚假数据,您还可以配置自定义转换器。


0
另一个选择是通过gem install schema_to_scaffold安装并运行scaffold -f命令。
它会打印出用于创建包含表中所有字段的工厂的Rails生成器脚本。然后,您可以复制粘贴该脚本并运行它。

-1

这里有一些不错的答案,但另一个选择是使用stepford。对于一些使用具有外键约束的模式的项目,deep_*方法等可能会有所帮助,而且通过命令行生成工厂的方法也很简单。


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