首页 > 解决方案 > 必须在 db:seeds 之前启动 rails 控制台才能使种子工作

问题描述

在我正在从事的项目中,rake db:drop db:create db:migrate db:seed将无法工作。undefined method 'my_attribute=' for #<MyObject:0x00007fd1af863908>运行 db:seed 任务时会引发错误。似乎没有什么可以阻止 MyObject 调用 my_attribute - 这是一个非常标准的枚举字段。如果您删除该字段,则会在其他标准字段(例如日期时间字段)上发生类似的未定义方法错误。

但是,运行rake db:drop db:create db:migrate,然后rails console,退出控制台,然后运行rake db:seed工作正常。

有没有人经历过这个?

编辑:

整个错误是:

rake aborted!
NoMethodError: undefined method `my_attribute=' for #<MyObject:0x00007fa53bae34d0>
/Users/Will/.gems/ruby/2.5.0/gems/activemodel-5.2.2/lib/active_model/attribute_methods.rb:430:in `method_missing'
/Users/Will/.gems/ruby/2.5.0/gems/pg_search-2.1.6/lib/pg_search.rb:81:in `method_missing'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:16:in `public_send'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:16:in `block (2 levels) in object'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:15:in `each'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:15:in `block in object'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:14:in `tap'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/attribute_assigner.rb:14:in `object'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/evaluation.rb:13:in `object'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/strategy/create.rb:9:in `result'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/factory.rb:43:in `run'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/factory_runner.rb:29:in `block in run'
/Users/Will/.gems/ruby/2.5.0/gems/activesupport-5.2.2/lib/active_support/notifications.rb:170:in `instrument'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/factory_runner.rb:28:in `run'
/Users/Will/.gems/ruby/2.5.0/gems/factory_bot-5.0.2/lib/factory_bot/strategy_syntax_method_registrar.rb:20:in `block in define_singular_strategy_method'
/my-project/db/seeds.rb:449:in `<top (required)>'

其中 seed.rb 499 是 factorybot.create 任务:

valid_opportunity = FactoryBot.create(:opportunity,
  slug: 'french-sardines-required',
  title: 'French sardines required',
  response_due_on: 9.months.from_now,
  author: editor,
  service_provider: paris,
  countries: [france],
  sectors: [agriculture],
  types: [private_sector],
  values: [hundred_thousand],
  created_at: 2.weeks.ago,
  first_published_at: Time.zone.today,
  source: :post,
  status: :publish)

在模型中,我们有:

class MyModel < ApplicationRecord

  enum my_attribute: { pending: 1, publish: 2, draft: 3, trash: 4 }

end

请注意,my_attribute 是数据库中的一个真实字段,并且如果 my_attribute 周围的行被删除,则该模型的数据库中的另一个字段会标记出类似的错误。

标签: ruby-on-railsrubypostgresql

解决方案


如果您打算一次性完成这一切,那么db:seed您将需要调用ModelName.reset_column_information您打算与之交互的每个模型。

原因是在加载代码时,该类ModelName没有表。动态属性方法是从表列加载的,但由于没有表,因此没有列,因此没有方法。此结果与模型一起缓存,以避免每次引用模型时都必须进行此往返。

调用reset_column_information原因ModelName来重置此缓存。这样,下次引用此模型时,它将返回表(现在存在),重新加载所有列(现在存在),并动态生成与这些列相关的方法。

您必须在您计划以下任何时候执行此操作:

  • 创建表或向表中添加列;
  • 在同一任务运行期间更改该表或新列中的数据

请注意,相同的任务运行并不一定意味着相同的迁移甚至相同的任务本身。它可以是任何迁移或播种,以完成给定任务的完整运行,例如db:migrate或在您的情况下db:migrate db:seed


推荐阅读