4

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

Flo
  • 540
  • 6
  • 20
  • But you have `/home/.../app/models/company/profile_plan.rb` right? – mikdiet Jan 15 '17 at 19:52
  • @MikDiet, thank you. yes, I added them to my question – Flo Jan 15 '17 at 20:09
  • Try to define company module `module Company class ProfilePlan < ...` – taro Jan 20 '17 at 08:23
  • @taro, thank you for your idea, I also tried this before, but I get: TypeError: Company is not a module I think this is because I also have a model named Company – Flo Jan 20 '17 at 13:37

2 Answers2

2

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'
Community
  • 1
  • 1
Rafael Costa
  • 1,291
  • 2
  • 13
  • 30
  • require 'profile_plan' returns LoadError: cannot load such file -- profile_plan – Flo Jan 20 '17 at 13:34
  • what if you `require 'company'`? – Rafael Costa Jan 20 '17 at 14:05
  • I get rake aborted! LoadError: Unable to autoload constant Company::ProfilePlan, expected /home/.../app/models/company/profile_plan.rb to define it – Flo Jan 20 '17 at 14:19
  • Yes, look at my question, I updated it. require the file with the whole path works. But I am not sure why this error happened at all. – Flo Jan 20 '17 at 14:57
  • Thank you very much for the explanation :) – Flo Jan 20 '17 at 15:27
  • if you require each file you reference, that can get repetitive. probably better would be to refactor the rake stuff into your main codebase, and call those methods from the task. – max pleaner Jan 23 '17 at 10:14
1

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 .

Community
  • 1
  • 1
Sony Mathew
  • 2,929
  • 2
  • 22
  • 29