Пользовательское промежуточное программное обеспечение Rails не распознается в GH CI

Я впервые использую специальное промежуточное программное обеспечение, чтобы нормализовать обработку ошибок. У меня есть промежуточное программное обеспечение, определенное в 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

Возможно, проблема с zietwerk, который ожидает, что структура каталогов для Middleware::ErrorHandler будет «app/middleware/middleware/error_handler», поскольку верхняя структура папок не считается частью вложенности модулей. Однако странно, что сама ссылка «неинициализированная константа ErrorHandler» не находится в пространстве имен.

engineersmnky 08.07.2024 20:22

Я просто переместил его в lib/middleware и изменил всю загрузку, которая у меня была, и это сработало :shrug: :laughcry: Zeitwerk и путь загрузки - моя ахиллесова пята банкомата :P Мне определенно есть еще что почитать. Спасибо!

Int'l Man Of Coding Mystery 08.07.2024 20:27

Честно говоря, lib в любом случае там, где ему место. Рад, что вы разобрались.

engineersmnky 08.07.2024 20:29

Я так и думал, но я впервые делаю что-то подобное, и в учебниках, которые я видел, это было в приложении/промежуточном программном обеспечении. :(

Int'l Man Of Coding Mystery 08.07.2024 20:37
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
69
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ожидается, что 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

Этот ответ необычен.

Xavier Noria 09.07.2024 14:26

Другие вопросы по теме