Flo
Flo

Reputation: 540

Cannot load namespaced model when invoking rake task

I got a rake task which invokes other rake tasks, so my development data can be easily reset.

the first rake task (lib/tasks/populate.rake)

# Rake task to populate development database with test data
# Run it with "rake db:populate"
namespace :db do
  desc 'Erase and fill database'
  task populate: :environment do
    ...
    Rake::Task['test_data:create_company_plans'].invoke
    Rake::Task['test_data:create_companies'].invoke
    Rake::Task['test_data:create_users'].invoke
   ...
  end
end

the second rake task (lib/tasks/populate_sub_scripts/create_company_plans.rake)

namespace :test_data do
  desc 'Create Company Plans'
  task create_company_plans: :environment do
    Company::ProfilePlan.create!(name: 'Basic', trial_period_days: 30, price_monthly_cents: 4000)
    Company::ProfilePlan.create!(name: 'Professional', trial_period_days: 30, price_monthly_cents: 27_500)
    Company::ProfilePlan.create!(name: 'Enterprise', trial_period_days: 30, price_monthly_cents: 78_500)
  end
end

when I run bin/rake db:populate then i get this error

rake aborted! LoadError: Unable to autoload constant Company::ProfilePlan, expected /home/.../app/models/company/profile_plan.rb to define it

but when I run the second rake task independently it works well.

The model (path: /home/.../app/models/company/profile_plan.rb)

class Company::ProfilePlan < ActiveRecord::Base
  # == Constants ============================================================

  # == Attributes ===========================================================

  # == Extensions ===========================================================
  monetize :price_monthly_cents

  # == Relationships ========================================================
  has_many :profile_subscriptions

  # == Validations ==========================================================

  # == Scopes ===============================================================

  # == Callbacks ============================================================

  # == Class Methods ========================================================

  # == Instance Methods =====================================================
end

Rails 5.0.1 Ruby 2.4.0

The App was just upgraded from 4.2 to 5

It works when I require the whole path:

require "#{Rails.root}/app/models/company/profile_plan.rb"

But this seems strange to me, because in the error message rails has the correct path to the Model. Does someone know why I have to require the file when invoked from another rake task?

Thank you very much

Upvotes: 4

Views: 1990

Answers (2)

Sony Mathew
Sony Mathew

Reputation: 2971

From what I understand, you can probably overcome the problem by reenable ing and then revoke ing the task as given below. Pardon me if this doesn't work.

['test_data:create_company_plans', 'test_data:create_companies'].each do |task|
  Rake::Task[task].reenable
  Rake::Task[task].invoke
end

There is more info on this stackoverflow question how-to-run-rake-tasks-from-within-rake-tasks .

Upvotes: 1

Rafael Costa
Rafael Costa

Reputation: 1471

Well, it seems that rake doesn't eager load, so when you call the create_company_plans.rake alone it loads the referred objects, however when you invoke it from another rake, it doesn't know you will need them and so they are not loaded.

You can take a look at this other QA which was similar to yours.

I think maybe you don't need to require the whole path, just:

require 'models/company/profile_plan'

Upvotes: 2

Related Questions