Rails 5.2.2 Heroku总是返回app [web.1]:FATAL-NameError(未初始化的常量AuthenticateUser :: JsonWebToken)

时间:2019-01-30 03:56:14

标签: ruby-on-rails ruby heroku jwt

我按照https://www.pluralsight.com/guides/token-based-authentication-with-ruby-on-rails-5-api的教程进行操作,但出现了一些固定错误,并且运行良好。

但是当我部署到heroku之后,当我想访问身份验证路由(登录用户)时,我在insomia中收到状态码500:

{
  "status": 500,
  "error": "Internal Server Error"
}

在终端中,我得到了以下代码:

2019-01-30T03:07:19.567264+00:00 app[web.1]: I, [2019-01-30T03:07:19.567151 #9]  INFO -- : [49a401d5-1f31-4a88-8299-3c14d07ef160] Started POST "/authenticate" for 125.161.110.130 at 2019-01-30 03:07:19 +0000
2019-01-30T03:07:19.568759+00:00 app[web.1]: I, [2019-01-30T03:07:19.568673 #9]  INFO -- : [49a401d5-1f31-4a88-8299-3c14d07ef160] Processing by AuthenticationController#authenticate as JSON
2019-01-30T03:07:19.569025+00:00 app[web.1]: I, [2019-01-30T03:07:19.568946 #9]  INFO -- : [49a401d5-1f31-4a88-8299-3c14d07ef160]   Parameters: {"email"=>"mymail@rocketmail.com", "password"=>"[FILTERED]", "authentication"=>{"email"=>"mymail@rocketmail.com", "password"=>"[FILTERED]"}}
2019-01-30T03:07:19.609086+00:00 app[web.1]: D, [2019-01-30T03:07:19.608939 #9] DEBUG -- : [49a401d5-1f31-4a88-8299-3c14d07ef160]    (3.5ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
2019-01-30T03:07:19.618191+00:00 app[web.1]: D, [2019-01-30T03:07:19.618074 #9] DEBUG -- : [49a401d5-1f31-4a88-8299-3c14d07ef160]   User Load (3.4ms)  SELECT  `users`.* FROM `users` WHERE `users`.`email` = 'mymail@rocketmail.com' LIMIT 1
2019-01-30T03:07:19.742727+00:00 app[web.1]: I, [2019-01-30T03:07:19.742595 #9]  INFO -- : [49a401d5-1f31-4a88-8299-3c14d07ef160] Completed 500 Internal Server Error in 173ms (ActiveRecord: 10.4ms)
2019-01-30T03:07:19.743582+00:00 app[web.1]: F, [2019-01-30T03:07:19.743490 #9] FATAL -- : [49a401d5-1f31-4a88-8299-3c14d07ef160]
2019-01-30T03:07:19.743681+00:00 app[web.1]: F, [2019-01-30T03:07:19.743602 #9] FATAL -- : [49a401d5-1f31-4a88-8299-3c14d07ef160] NameError (uninitialized constant AuthenticateUser::JsonWebToken):
2019-01-30T03:07:19.743757+00:00 app[web.1]: F, [2019-01-30T03:07:19.743677 #9] FATAL -- : [49a401d5-1f31-4a88-8299-3c14d07ef160]
2019-01-30T03:07:19.743841+00:00 app[web.1]: F, [2019-01-30T03:07:19.743763 #9] FATAL -- : [49a401d5-1f31-4a88-8299-3c14d07ef160] app/commands/authenticate_user.rb:10:in `call'
2019-01-30T03:07:19.743859+00:00 app[web.1]: [49a401d5-1f31-4a88-8299-3c14d07ef160] app/controllers/authentication_controller.rb:5:in `authenticate'

这里是我的authentication_controller:

class AuthenticationController < ApplicationController
  skip_before_action :authenticate_request
  
  def authenticate
    command = AuthenticateUser.call(params[:email], params[:password])
  
    if command.success?
      render json: { auth_token: command.result }
    else
      render json: { error: command.errors }, status: :unauthorized
    end
  end
end

这是我的authenticate_user:

class AuthenticateUser
  prepend SimpleCommand

  def initialize(email, password)
    @email = email
    @password = password
  end

  def call
    JsonWebToken.encode(user_id: user.id) if user
  end

  private

  attr_accessor :email, :password

  def user
    user = User.find_by_email(email)
    return user if user && user.authenticate(password)

    errors.add :user_authentication, 'invalid credentials'
    nil
  end
end

此处json_web_token:

class JsonWebToken
  class << self
    def encode(payload, exp = 24.hours.from_now)
      payload[:exp] = exp.to_i
      JWT.encode(payload, RubyChallenge::Application.credentials.secret_key_base)
    end
  
    def decode(token)
      body = JWT.decode(token, RubyChallenge::Application.credentials.secret_key_base)[0]
      HashWithIndifferentAccess.new body
    rescue
      nil
    end
  end
end

我已经将环境变量RAILS_MASTER_KEY设置为与配置/ master.key内容相同的值到我的heroku: my heroku config var

我的Gemfile:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.5.1'

gem 'rails', '~> 5.2.2'
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
gem 'puma', '~> 3.11'
gem 'bcrypt', '~> 3.1.7'
gem 'jwt'
gem 'simple_command'
gem 'figaro'
gem 'bootsnap', '>= 1.1.0', require: false

group :development, :test do
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'listen', '>= 3.0.5', '< 3.2'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

预先感谢

编辑:

这里是我的配置/ application.rb:

require_relative 'boot'

require "rails"
# Pick the frameworks you want:
require "active_model/railtie"
require "active_job/railtie"
require "active_record/railtie"
require "active_storage/engine"
require "action_controller/railtie"
require "action_mailer/railtie"
require "action_view/railtie"
require "action_cable/engine"
# require "sprockets/railtie"
require "rails/test_unit/railtie"


Bundler.require(*Rails.groups)

module RubyChallenge
  class Application < Rails::Application
    config.autoload_paths << Rails.root.join('lib')
    config.api_only = true
  end
end
btw thx加布巴尔先生的建议

3 个答案:

答案 0 :(得分:1)

可能您错过了这个:-

默认情况下,应用程序目录中的任何文件都会自动加载,您可以不包含文件就使用它,但是在此之外,您必须在加载应用程序时加载它。

  

为确保一切正常,lib目录的内容   加载Rails应用程序时必须将其包括在内。

config / application.rb

module ApiApp
  class Application < Rails::Application
    #.....
    config.autoload_paths << Rails.root.join('lib')
    #.....
  end
end

答案 1 :(得分:0)

解决方案:

更改我的config / application.rb

module RubyChallenge
  class Application < Rails::Application
    ...
    config.autoload_paths << Rails.root.join('lib')
    ...
  end
end

module RubyChallenge
  class Application < Rails::Application
    ...
    config.eager_load_paths << Rails.root.join('lib')
    ...
  end
end

使其运行良好,这是因为在生产环境中启动应用程序后,Rails 5会禁用自动加载功能,因此谢利什·卡拉姆卡Article

答案 2 :(得分:0)

我也关注了同一个博客,但是当我将代码放在类标题之后时,它就可以正常工作!!!

module TodoApiApp
  class Application < Rails::Application
    config.eager_load_paths << Rails.root.join('lib')
    config.load_defaults 5.2
    config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', headers: :any, methods: %i[get post delete put patch options]
      end
    end
    config.api_only = true
  end
end