hello-world
webエンジニアのメモ。とりあえずやってみる。

[rails]task実行時にrake aborted! NameError: uninitialized constant

公開日時

発生した問題

./bin/rake でtaskを実行すると問題なく実行できる のに、 bundle exec rake でtaskを実行するとrake aborted!になってしまう 、 という現象が発生してハマりました。

結論

:environmentが指定できていなかった 結論としては非常に初歩的なミスだったのですが、:environment自体は記述していたにも関わらずエラーが起きていたので、気づくのに時間がかかってしまいました。

エラーの再現方法

  • 検証用のtaskを作成
./bin/rails g task test_task
  • 以下を記述
# lib/tasks/test_task.rake

namespace :test_task do
  desc "実験用のタスクです"
  task :run, :environment do
    TestModel.new # 適当なModelを呼び出す
    p 'task finished!'
  end
end
  • taskを実行
./bin/rake test_task:run
"task finished!"

./bin/rakeで実行した場合は問題なく実行できました。 続いて

bundle exec rake test_task:run
rake aborted!
NameError: uninitialized constant TestModel

???

:environment も設定しているので問題ないはず 」と思いながら、色々調べて見つけた方法を試していたのですが解決せず。。。

最終的にものすごくしょうもないミスをしていたことに気づきました。

以下が修正後のtaskです。

# lib/tasks/test_task.rake

namespace :test_task do
  desc "実験用のタスクです"
  task run: :environment do
    TestModel.new
    p 'task finished!'
  end
end

最初のやつとの違いにお気づきでしょうか?

before:
  task :run, :environment do

after:
  task run: :environment do

↑ここです。

「:environment も設定しているので問題ないはず」という思い込みのせいでハマってしまったのですが、最初のやり方だと :environmentは設定できておらず、引数として扱われてしまっていました

以下のようにコードを修正すると

namespace :test_task do
  desc "実験用のタスクです"
  task :run, :environment do |task, args|
    p args
    p 'task finished!'
  end
end

引数のキーとしてenvironmentが設定されていることが確認できます。

./bin/rake "test_task:run[test]"
{:environment=>"test"}
"task finished!"

task run: :environment と記述することで正しくtaskが実行できるようになりました。

ただ、 bin/rakeの場合は:environmentが設定されていなくてもエラーにならなかったのはなぜでしょうか?

これは bin/rake 内で springが読み込まれていたためモデルデータがプリロードされていた のが原因でした。

#!/usr/bin/env ruby
begin
  load File.expand_path("../spring", __FILE__)  # <= ここでspringを読み込み
rescue LoadError
end
require_relative '../config/boot'
require 'rake'
Rake.application.run

これはハマりました。。。 思い込みの力は恐ろしいです。

もう同じことにハマらないようにメモを残しておきます。

task作成時は:environmentの指定方法にご注意 ください。

今回の検証内容はruby 2.2.3, Rails 4.2.1で確認しました。

参考


Related #Rails

[rails]ELB使用時にヘルスチェック用のアクションを作成する

ELBにrailsアプリをぶら下げる場合、railsアプリが落ちたらELBから外れてもらいたいです。

[rails]carrierwaveで保存した画像のurlを取得する

carrierwave 0.10.0 で確認 imageカラムにcarrierwaveで保存した画像を保存している場合、デフォルトのままだとだとurlメソッドを実行してもpublic以下のパスのみで http://~ が設定されていません。

[rails]base64エンコードされた画像をcarrierwaveに保存する

Ruby 2.1.4, Rails 4.1.7 で確認 前回はcarrierwaveを使ってPOSTされた画像ファイルの保存を行うAPIを作ってみました。