hello-world.jp.net
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

[s3][ruby]静的ウェブサイトホスティングしたサイトのTwitter Cardsが表示されない場合の対応

先日、S3の静的ウェブサイトホスティングを使ってサイト公開を行った際に、ページ表示やFacebookのOGP表示は問題なくできるのにTwitter Cardsだけ表示されない、という現象が発生しました。

[rails]bodyにclassを付けて特定のページでのみjsが動作するようにする

Asset Pipelineを使用するとjsやcssを結合してくれます。

[ruby][rails]pryでデバッグする

今更ながらpryを使ったデバッグの便利さに感動したのでメモ

[ruby][rails]sidekiqのnamespaceにハマった

sidekiq3.0.1で確認。