我应该在哪里创建共享的FactoryBot关联?

问题描述 投票:0回答:1

我有一个User模型,has_one需要Company。使用FactoryBot,我想创建几个共享同一公司的用户。我看到一些advice,我解释为建议我在我的FactoryBot.define do块中创建Company对象,我可以将其用作我的用户的属性:

# In spec/factories/companies.rb
FactoryBot.define do
  factory :company do
    name { 'MyCompany' }
  end
end


# In spec/factories/users.rb
FactoryBot.define do
  company1 = FactoryBot.create(:company)  # this will be shared by several users

  factory :user1 do
    first_name { 'Joe' } 
    last_name { 'Smith' } 
    company_id { company1.id }
  end

  factory :user2 do
    first_name { 'Sam' } 
    last_name { 'Smith' } 
    company_id { company1.id }
  end
end

这似乎首先起作用,除非我需要在rake db:create的测试容器中从头开始重新创建数据库。当rake运行时,它似乎初始化我的工厂并且FactoryBot.create(:company)步骤尝试运行,并且没有适当的db模式,因此它失败:

$ RAILS_ENV=test  bundle exec rake db:rebuild
rake aborted!
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "companies" does not exist
LINE 8:                WHERE a.attrelid = '"companies"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                     c.collname, col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a
                LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                LEFT JOIN pg_type t ON a.atttypid = t.oid
                LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
               WHERE a.attrelid = '"companies"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

这让我觉得我试图在错误的地方创造这些。

为我的测试数据设置company1等共享关联的最佳位置在哪里,以便在我的应用程序正确初始化之后和执行测试套件之前发生?

FWIW,这是错误堆栈:

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "companies" does not exist
LINE 8:                WHERE a.attrelid = '"companies"'::regclass
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
                     c.collname, col_description(a.attrelid, a.attnum) AS comment
                FROM pg_attribute a
                LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
                LEFT JOIN pg_type t ON a.atttypid = t.oid
                LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
               WHERE a.attrelid = '"companies"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:63:in `async_exec'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:63:in `block (2 levels) in query'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies/interlock.rb:48:in `block in permit_concurrent_loads'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/concurrency/share_lock.rb:187:in `yield_shares'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies/interlock.rb:47:in `permit_concurrent_loads'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:62:in `block in query'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:579:in `block (2 levels) in log'
/usr/local/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:578:in `block in log'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/notifications/instrumenter.rb:23:in `instrument'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/abstract_adapter.rb:569:in `log'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql/database_statements.rb:61:in `query'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/postgresql_adapter.rb:749:in `column_definitions'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/abstract/schema_statements.rb:113:in `columns'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/schema_cache.rb:69:in `columns'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/connection_adapters/schema_cache.rb:75:in `columns_hash'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/model_schema.rb:466:in `load_schema!'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/attributes.rb:234:in `load_schema!'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/attribute_decorators.rb:51:in `load_schema!'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/model_schema.rb:459:in `block in load_schema'
/usr/local/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/model_schema.rb:456:in `load_schema'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/model_schema.rb:346:in `attribute_types'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/attribute_methods.rb:230:in `has_attribute?'
/usr/local/bundle/gems/activerecord-5.2.0/lib/active_record/inheritance.rb:55:in `new'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator/new_constructor.rb:9:in `new'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator.rb:14:in `send'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator.rb:10:in `method_missing'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator/invocation_tracker.rb:11:in `method_missing'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator.rb:14:in `send'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/decorator.rb:10:in `method_missing'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/configuration.rb:19:in `block in initialize'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/attribute_assigner.rb:48:in `instance_exec'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/attribute_assigner.rb:48:in `build_class_instance'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/attribute_assigner.rb:13:in `object'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/evaluation.rb:13:in `object'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/strategy/create.rb:9:in `result'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/factory.rb:43:in `run'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/factory_runner.rb:29:in `block in run'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/notifications.rb:170:in `instrument'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/factory_runner.rb:28:in `run'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
/builds/MyGroup/MyApp/spec/factories/users.rb:4:in `block in <main>'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/syntax/default.rb:49:in `instance_eval'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/syntax/default.rb:49:in `run'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/syntax/default.rb:7:in `define'
/builds/MyGroup/MyApp/spec/factories/users.rb:2:in `<main>'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:50:in `load'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:50:in `load'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:277:in `block in load'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:249:in `load_dependency'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:277:in `load'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/find_definitions.rb:20:in `block (2 levels) in find_definitions'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/find_definitions.rb:19:in `each'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/find_definitions.rb:19:in `block in find_definitions'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/find_definitions.rb:15:in `each'
/usr/local/bundle/gems/factory_bot-4.11.1/lib/factory_bot/find_definitions.rb:15:in `find_definitions'
/usr/local/bundle/gems/factory_bot_rails-4.11.1/lib/factory_bot_rails/railtie.rb:21:in `block in <class:Railtie>'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:69:in `block in execute_hook'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:62:in `with_execution_control'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:67:in `execute_hook'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:52:in `block in run_load_hooks'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:51:in `each'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/lazy_load_hooks.rb:51:in `run_load_hooks'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/application/finisher.rb:75:in `block in <module:Finisher>'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/initializable.rb:32:in `instance_exec'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/initializable.rb:32:in `run'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/initializable.rb:61:in `block in run_initializers'
/usr/local/lib/ruby/2.5.0/tsort.rb:228:in `block in tsort_each'
/usr/local/lib/ruby/2.5.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
/usr/local/lib/ruby/2.5.0/tsort.rb:431:in `each_strongly_connected_component_from'
/usr/local/lib/ruby/2.5.0/tsort.rb:349:in `block in each_strongly_connected_component'
/usr/local/lib/ruby/2.5.0/tsort.rb:347:in `each'
/usr/local/lib/ruby/2.5.0/tsort.rb:347:in `call'
/usr/local/lib/ruby/2.5.0/tsort.rb:347:in `each_strongly_connected_component'
/usr/local/lib/ruby/2.5.0/tsort.rb:226:in `tsort_each'
/usr/local/lib/ruby/2.5.0/tsort.rb:205:in `tsort_each'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/initializable.rb:60:in `run_initializers'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/application.rb:361:in `initialize!'
/builds/MyGroup/MyApp/config/environment.rb:5:in `<main>'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `require'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:21:in `block in require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/loaded_features_index.rb:65:in `register'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:20:in `require_with_bootsnap_lfi'
/usr/local/bundle/gems/bootsnap-1.3.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:29:in `require'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:283:in `block in require'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:249:in `load_dependency'
/usr/local/bundle/gems/activesupport-5.2.0/lib/active_support/dependencies.rb:283:in `require'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/application.rb:337:in `require_environment!'
/usr/local/bundle/gems/railties-5.2.0/lib/rails/application.rb:520:in `block in run_tasks_blocks'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:271:in `block in execute'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:271:in `each'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:271:in `execute'
/usr/local/bundle/gems/bugsnag-6.8.0/lib/bugsnag/integrations/rake.rb:18:in `execute_with_bugsnag'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:213:in `block in invoke_with_call_chain'
/usr/local/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:237:in `block in invoke_prerequisites'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:235:in `each'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:235:in `invoke_prerequisites'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:212:in `block in invoke_with_call_chain'
/usr/local/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:193:in `invoke_with_call_chain'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/task.rb:182:in `invoke'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:160:in `invoke_task'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:116:in `each'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:116:in `block in top_level'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:125:in `run_with_threads'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:110:in `top_level'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:83:in `block in run'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:186:in `standard_exception_handling'
/usr/local/bundle/gems/rake-12.3.1/lib/rake/application.rb:80:in `run'
/usr/local/bundle/gems/rake-12.3.1/exe/rake:27:in `<top (required)>'
/usr/local/bundle/bin/rake:23:in `load'
/usr/local/bundle/bin/rake:23:in `<top (required)>'
ruby-on-rails factory-bot
1个回答
2
投票

以这种方式创建对象时 - 每次初始化工厂时都会创建它们,无论它们是否将在特定的测试运行中使用。

通常情况下,拥有独立工厂并在测试中明确声明您希望来自同一公司的两个用户更好:

 let(:company){ create :company }
 let(:user1){ create :user, company: company }
 let(:user2){ create :user, company: company }

对于你不关心确切关系并且只想重用一些有效值并避免关系级联的情况 - 在create_default gem中有test-prof解决方法(参见更多here

© www.soinside.com 2019 - 2024. All rights reserved.