FactoryBot关联加载现有的ActiveRecord模型

时间:2018-02-09 15:49:57

标签: factory-bot

鉴于以下Rails模型......

SpreadsheetDocument document = SpreadsheetDocument.newSpreadsheetDocument();
    document.removeSheet(0);

    document.setLocale(Locale.US);

    Table sheet = document.appendSheet("My chart");
    List<Row> rows = sheet.appendRows(10);

    sheet.getColumnByIndex(0).setWidth(27.06);
    Row headerRow = rows.get(0);
    headerRow.getCellByIndex(0).setStringValue("This is a string");

    Row dateRow = rows.get(1);

    Calendar date = GregorianCalendar.getInstance();
    dateRow.getCellByIndex(0).setDateValue(date);
    dateRow.getCellByIndex(0).setFormatString("yyyy-MM-dd");

    Row numRow = rows.get(1);
    numRow.getCellByIndex(0).setDoubleValue(9.12345678);

    //numRow.getCellByIndex(0).setFormatString("0.000"); // works
    //numRow.getCellByIndex(0).setFormatString("0.00E+00"); // crashes
    numRow.getCellByIndex(0).setFormatString("0.00E00"); // does not work, it becomes 0.00"E00"

    document.save(new File("c:\\Users\\enrico\\Desktop\\openoffice.ods"));

class Project < ActiveRecord::Base belongs_to :project_category after_initialize :do_stuff_based_on_category def do_stuff_based_on_category # things that reference `project_category` object project_category.foo_bar end end class ProjectCategory < ActiveRecord::Base has_many :projects def foo_bar # ... end end 记录的数量和内容是固定的:测试设置使用生产中存在的相同记录。因此,我希望我的ProjectCategory工厂使用显式的,持久的Project对象(不是工厂)。

但是我无法让我的ProjectCategory工厂拿起Project记录,即使正常的ProjectCategory通话工作正常:

new

1 个答案:

答案 0 :(得分:2)

问题在于我在after_initialize钩子中使用了一个关联。

factory_bot documentation(强调我的重点):

  

与ActiveRecord(默认初始值设定项)的最大兼容性   通过在构建类上调用new来构建所有实例,而不使用任何实例   参数。然后调用属性编写器方法来分配所有   属性值。

与直接调用Project.new(包括属性)不同,默认情况下,factory_bot不会传递任何内容,并在事后设置属性。

幸运的是,factory_bot公开了初始化程序以解决这些类型的场景。

  

如果要使用factory_bot构造一个对象   属性传递给initialize或者如果你想做某事   除了在构建类上简单地调用new之外,您可以覆盖   通过在工厂中定义initialize_with来实现默认行为。

所以你可以复制这个:

obj = Project.new project_category: ProjectCategory.find(1)

在工厂内这样做:

FactoryGirl.define do
  factory :project do
    project_category { ProjectCategory.find(1) }
    # ...

    initialize_with { new(project_category: project_category) }
  end
end

如果您有很多属性并且只想将它们全部传递到new调用,则factory_bot有一个快捷方式:

initialize_with { new(attributes) }

以上文档链接详细说明。