developmentだと問題なく動いていたがproductionで動かしてみたら掲題の通りの例外が発生。
このメッセージを表示している構文はこうなっている。掲示されているsecret_keyはランダム生成されているものだとわかる。
def raise_no_secret_key
raise <<-ERROR
Devise.secret_key was not set. Please add the following to your Devise initializer:
config.secret_key = '#{SecureRandom.hex(64)}'
Please ensure you restarted your application after installing Devise or setting the key.
ERROR
end
https://github.com/plataformatec/devise/blob/master/lib/devise/rails/routes.rb
じゃあ、なぜdevelopmentだと問題ないのにproductionだと例外が発生するのかというと。
Devise 3.2.3からRails4以降を使用している場合且つ、config/initializers/devise.rbに独自のsecret_keyが設定されていない場合secret_key_baseをベースとしてtokenを生成するようになった。
3.2.3 - 2014-02-20
- enhancements
- Devise will use the secret_key_base on Rails 4+ applications as its secret_key. You can change this and use your own secret by changing the devise.rb initializer.
該当する処理はこんな感じ。
initializer "devise.secret_key" do |app|
if app.respond_to?(:secrets)
Devise.secret_key ||= app.secrets.secret_key_base
elsif app.config.respond_to?(:secret_key_base)
Devise.secret_key ||= app.config.secret_key_base
end
Devise.token_generator ||=
if secret_key = Devise.secret_key
Devise::TokenGenerator.new(
Devise::CachingKeyGenerator.new(Devise::KeyGenerator.new(secret_key))
)
end
end
https://github.com/plataformatec/devise/blob/master/lib/devise/rails.rb
devise.rbをgenerateした段階ではconfig.secret_keyはコメントアウトされていたのでsecret_key_baseを使用している状態。
肝心のsecret_key_baseはどこで設定されているかというとconfig/secrets.ymlで設定されている。
これはRails4.1から導入された管理方法で、productionの項を見れば原因がわかると思う。
production:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
productionの場合環境変数で設定するんだけど怠ったのでsecret_keyが設定されず、devise.rbでも設定していないので未設定の例外が発生していたという訳であった。