我第一次使用自定义中间件来标准化错误处理。我在
app/middleware/error_handler.rb
中定义了中间件并在我的主应用程序中使用。rb
...
require_relative "../app/middleware/error_handler"
module AppName
class Application < Rails::Application
...
config.middleware.use Middleware::ErrorHandler
...
end
end
当路由到本地主机时,这在测试和开发中都运行良好。但是当我推送到 github 并且操作接管时,我在执行迁移后得到了这个
An error occurred while loading spec_helper.
Failure/Error: require_relative "../config/environment"
NameError:
uninitialized constant ErrorHandler
# ./config/environment.rb:5:in `<top (required)>'
# ./spec/rails_helper.rb:6:in `require_relative'
# ./spec/rails_helper.rb:6:in `<top (required)>'
# ./spec/spec_helper.rb:3:in `<top (required)>'
No examples found.
这是我的行动/工作流程
name: Run RSpec
on:
push:
branches:
- "*" # Trigger on push to any branch
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16.1
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${{ secrets.ROUTE_RATER_DATABASE_PASSWORD }}
POSTGRES_DB: postgres
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
redis:
image: redis
ports:
- 6379:6379
options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.3.0"
- name: Install dependencies
run: |
gem install bundler
bundle install --jobs 4 --retry 3
- name: Setup DB, Run tests
env:
PGHOST: localhost
PGUSER: postgres
PGPORT: ${{ job.services.postgres.ports[5432] }}
PGPASSWORD: ${{ secrets.DATABASE_PASSWORD }}
REDIS_URL: redis://localhost:6379/1
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
RAILS_ENV: test
run: |
bin/rails db:create db:migrate db:schema:load
bundle exec rspec
app/middleware/error_handler.rb
预计会定义 ErrorHandler
,但您正在定义命名空间 Middleware::ErrorHandler
。
通常,如果您要请求
ErrorHandler
,它将从任何 根目录中找到的第一个
error_handler.rb
文件加载,在本例中为 app/middleware/
。文件结构必须对应于相对于根目录的模块/类名称:
# app/middleware/error_handler.rb
# ^^^^^^^^^^^^^
# |
class ErrorHandler # >-'
end
Rails 自动将
app/
下的目录配置为根目录。这样你就可以加载ErrorHandler
而不需要它:
>> ErrorHandler
=> ErrorHandler
如果你要命名它:
# app/middleware/error_handler.rb
module Middleware
class ErrorHandler
end
end
您收到错误:
>> ErrorHandler
(irb):1:in `<main>': uninitialized constant ErrorHandler (NameError)
ErrorHandler
^^^^^^^^^^^^
这正是
zeitwerk
通过在生产环境或 ci 测试环境中急切加载应用程序所做的事情:
# config/environments/test.rb
config.eager_load = ENV["CI"].present?
在开发中,您可以仔细检查您的应用程序是否可以立即加载:
$ bin/rails zeitwerk:check
Hold on, I am eager loading the application.
expected file app/middleware/error_handler.rb to define constant ErrorHandler, but didn't
由于无论如何你都无法在启动过程中自动加载,所以你必须
require
并使用Middleware::ErrorHandler
,只是不要将其放在autoload路径中。
autoload_once_paths
或 autoload_lib_once
但您必须将 config.middleware.use
移至初始值设定项中:
# config/application.rb
config.autoload_lib_once(ignore: %w(assets tasks))
# config/initializers/middleware.rb
Rails.application.config.middleware.use Middleware::ErrorHandler
# lib/middleware/error_handler.rb
module Middleware
class ErrorHandler
# ...
end
end