-1

On a project I'm working on, rake db:drop db:create db:migrate db:seed won't work. It raises undefined method 'my_attribute=' for #<MyObject:0x00007fd1af863908> error when running the db:seed task. There is seemingly nothing preventing MyObject calling my_attribute - it's a very standard enum field. If you remove the field a similar undefined method error occurs on other standard fields such a datetime field.

However, running rake db:drop db:create db:migrate, then rails console, exiting the console, then running rake db:seed works fine.

Has anyone experienced this?

EDIT:

The entire error is:

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)>'

Where seeds.rb 499 is a factorybot.create task:

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)

In the model we have:

class MyModel < ApplicationRecord

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

end

Note that my_attribute is a real field in the database, and also that if the line around my_attribute is removed, a different field in the database for this model flags up a similar error.

Will Taylor
  • 1,994
  • 2
  • 23
  • 36

1 Answers1

0

If you plan to do this all in 1 shot then in db:seed you will need to call ModelName.reset_column_information for each model you intend to interact with.

The reason for this is when the code is loaded the class ModelName does not have a table. The dynamic attribute methods are loaded from the table columns but since there is no table, there are no columns, and thus no methods. This result is cached with the model to avoid having to make this round trip every time you reference the model.

Calling reset_column_information causes ModelName to reset this cache. This way the next time this model is referenced it will go back to the table (that now exists), reload all the columns (that now exist), and dynamically generate the methods pertinent to these columns.

You must do this anytime you plan to:

  • create a table or add columns to a table and;
  • change the data in that table or new column during the same task run

Please note same task run does not necessarily mean same migration or even same task itself. It can be any migration or seeding that could occur to complete the full run of a given task(s) like db:migrate or in your case db:migrate db:seed

engineersmnky
  • 25,495
  • 2
  • 36
  • 52