2

On the application I am upgrading from Rails 3.2.22.4 to Rails 4.0.13, the following block of code for enhancing the global environment task has become a road-block by not working on the target Rails version:

Rails.application.class.rake_tasks do                                              
  Rake::Task["environment"].enhance do                                             
    ...                                                  
  end                                                                              
end 

This works fine on 3.2, but fails with Don't know how to build task 'environment' error message in 4.0.

In 3.2, Rails.application.class.rake_tasks returns a Proc object ( [#<Proc:0x007f978602a470@.../lib/rails/application.rb:301>] ) pointing to this line in the rails codebase. On 4.0, it returns an empty array.

The line referred to in the above Proc object seems to be removed in this commit.

What would the preferred way to enhance the environment rake task be in Rails 4.x?

The above piece of code is in the lib/subdomain/rake.rb file, and it is include with the following code in lib/subdomain/engine.rb:

module Subdomain
  class Engine < Rails::Engine

    ...
    rake_tasks do |_app|
      require 'subdomain/rake'
    end
    ...
  end
end

Rake tasks can't be executed as the command fails with this error. rails server|console commands work ok.

Prakash Murthy
  • 12,923
  • 3
  • 46
  • 74
  • 1
    In the commit you linked to, the defining of the `:environment` task has been moved from the `initialize` method to the `run_tasks_blocks` method, not simply deleted. This may affect at which point in the bootup sequence it is executed. Where exactly in your project file structure is the above code snippet included? It appears to be executed before `run_tasks_blocks`. Also which command is producing the error message? Is it `rails s`, or is it `rake foo`? – Luke Griffiths Sep 08 '16 at 20:38
  • Thanks. That does help. Let me look at the bootup sequence. Edited the question to include info about the location of the code. Only rake tasks fail; rails server and console can be started. – Prakash Murthy Sep 08 '16 at 21:07

1 Answers1

3

Option 1

If I'm understanding the question properly, something like this should work by placing these tasks in a standard location like lib/tasks/environment.rake. Note: None of this is particularly Rails-specific.

# Re-opening the task gives the ability to extend the task
task :environment do
  puts "One way to prepend behavior on the :environment rake task..."
end

task custom: :environment do
  puts "This is a custom task that depends on :environment..."
end

task :environment_extension do
  puts "This is another way to prepend behavior on the :environment rake task..."
end

# You can "enhance" the rake task directly too
Rake::Task[:environment].enhance [:environment_extension]

The output of this would be:

$ rake custom
This is another way to prepend behavior on the :environment rake task...
One way to prepend behavior on the :environment rake task...
This is a custom task that depends on :environment...

Option 2

However, the question remains as to why :environment needed to be extended. If it's to trigger something before, say, a db:migrate, you might be better off just re-opening the task in question and adding another dependency to that particular task. For example:

task custom: :environment do
  puts "This is a custom task that depends on :environment..."
end

task :custom_extension do
  puts "This is a new dependency..."
end

# Re-opening the task in question allows you to added dependencies
task custom: :custom_extension

The result of this is:

$ rake custom
This is a new dependency on :custom
This is a custom task that depends on :environment...

C-C-C-Combo Breaker!!

Combining everything, the output would look like this:

$  rake custom
This is another way to prepend behavior on the :environment rake task...
One way to prepend behavior on the :environment rake task...
This is a new dependency on :custom
This is a custom task that depends on :environment...
Ryan McGeary
  • 235,892
  • 13
  • 95
  • 104
  • 1
    Thanks. This helped in figuring out that the code block that I was stuck with is not being used!!! The requisite customization for which that code block was in place has already been implemented as a custom version of `db:load_config` task as described in the very first example in this answer. Deleting the code made no impact in the original code base :-) – Prakash Murthy Sep 09 '16 at 22:11