Rails custom inflection support
nicolas-brousse opened this issue · 7 comments
What did you do?
I've a config file in Rails application that follow an inflection acronym.
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections do |inflect|
inflect.acronym "API"
end
# config/configs/payzen_api_config.rb
class PayzenAPIConfig < ApplicationConfig
env_prefix :payzen_api
attr_config :username, :password, :public_key, :sha256key
end
What did you expect to happen?
Code works and load correctly.
What actually happened?
I've got the following error.
expected file /home/user/Projects/rails_app/config/configs/payzen_api_config.rb to define constant PayzenApiConfig, but didn't
Additional context
I suspect eager load not to use rails loader or not the rails inflector.
https://github.com/palkan/anyway_config/blob/master/lib/anyway/railtie.rb#L16
Environment
Ruby Version: ruby 2.7.3p183 (2021-04-05 revision 6847ee089d) [x86_64-linux]
Framework Version (Rails, whatever): Rails 6.0.3.7
Anyway Config Version: 2.1.0
We do use Rails inflector:
Can you show me the full backtrace? I guess, that could happen when you try to load the config class before the inflector initializer is loaded.
@palkan thanks for your answer. I'll have a look on it an may try to create a sample application that have the same issue.
I try to reproduce it on a rails template but I can't reproduce the issue.
In my application, I've the following full backtrace on page loading:
Backtrace
zeitwerk (2.4.2) lib/zeitwerk/loader/callbacks.rb:18:in `on_file_autoloaded'
zeitwerk (2.4.2) lib/zeitwerk/kernel.rb:27:in `block in require'
zeitwerk (2.4.2) lib/zeitwerk/kernel.rb:26:in `tap'
zeitwerk (2.4.2) lib/zeitwerk/kernel.rb:26:in `require'
lib/pay_zen.rb:22:in `public_key'
app/helpers/payment_helper.rb:8:in `block in payzen_headers'
actionview (6.0.3.7) lib/action_view/helpers/capture_helper.rb:45:in `block in capture'
actionview (6.0.3.7) lib/action_view/helpers/capture_helper.rb:209:in `with_output_buffer'
actionview (6.0.3.7) lib/action_view/helpers/capture_helper.rb:45:in `capture'
actionview (6.0.3.7) lib/action_view/helpers/capture_helper.rb:176:in `provide'
app/helpers/payment_helper.rb:7:in `payzen_headers'
app/views/carts/payments/new.html.slim:1
actionview (6.0.3.7) lib/action_view/base.rb:274:in `_run'
actionview (6.0.3.7) lib/action_view/template.rb:185:in `block in render'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `block in instrument'
activesupport (6.0.3.7) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
sentry-rails (4.3.4) lib/sentry/rails/tracing.rb:41:in `instrument'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `instrument'
actionview (6.0.3.7) lib/action_view/template.rb:385:in `instrument_render_template'
actionview (6.0.3.7) lib/action_view/template.rb:183:in `render'
actionview (6.0.3.7) lib/action_view/renderer/template_renderer.rb:58:in `block (2 levels) in render_template'
actionview (6.0.3.7) lib/action_view/renderer/abstract_renderer.rb:88:in `block in instrument'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `block in instrument'
activesupport (6.0.3.7) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
sentry-rails (4.3.4) lib/sentry/rails/tracing.rb:41:in `instrument'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `instrument'
actionview (6.0.3.7) lib/action_view/renderer/abstract_renderer.rb:87:in `instrument'
actionview (6.0.3.7) lib/action_view/renderer/template_renderer.rb:57:in `block in render_template'
actionview (6.0.3.7) lib/action_view/renderer/template_renderer.rb:65:in `render_with_layout'
actionview (6.0.3.7) lib/action_view/renderer/template_renderer.rb:56:in `render_template'
actionview (6.0.3.7) lib/action_view/renderer/template_renderer.rb:13:in `render'
actionview (6.0.3.7) lib/action_view/renderer/renderer.rb:61:in `render_template_to_object'
actionview (6.0.3.7) lib/action_view/renderer/renderer.rb:29:in `render_to_object'
actionview (6.0.3.7) lib/action_view/rendering.rb:117:in `block in _render_template'
actionview (6.0.3.7) lib/action_view/base.rb:304:in `in_rendering_context'
actionview (6.0.3.7) lib/action_view/rendering.rb:116:in `_render_template'
actionpack (6.0.3.7) lib/action_controller/metal/streaming.rb:218:in `_render_template'
actionview (6.0.3.7) lib/action_view/rendering.rb:103:in `render_to_body'
actionpack (6.0.3.7) lib/action_controller/metal/rendering.rb:52:in `render_to_body'
actionpack (6.0.3.7) lib/action_controller/metal/renderers.rb:142:in `render_to_body'
actionpack (6.0.3.7) lib/abstract_controller/rendering.rb:25:in `render'
actionpack (6.0.3.7) lib/action_controller/metal/rendering.rb:36:in `render'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render'
activesupport (6.0.3.7) lib/active_support/core_ext/benchmark.rb:14:in `block in ms'
/home/n.brousse/.rbenv/versions/2.7.3/lib/ruby/2.7.0/benchmark.rb:308:in `realtime'
activesupport (6.0.3.7) lib/active_support/core_ext/benchmark.rb:14:in `ms'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:44:in `block in render'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:84:in `cleanup_view_runtime'
activerecord (6.0.3.7) lib/active_record/railties/controller_runtime.rb:34:in `cleanup_view_runtime'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:43:in `render'
view_component (2.31.1) lib/view_component/rendering_monkey_patch.rb:9:in `render'
actionpack (6.0.3.7) lib/action_controller/metal/implicit_render.rb:35:in `default_render'
actionpack (6.0.3.7) lib/action_controller/metal/basic_implicit_render.rb:6:in `block in send_action'
actionpack (6.0.3.7) lib/action_controller/metal/basic_implicit_render.rb:6:in `tap'
actionpack (6.0.3.7) lib/action_controller/metal/basic_implicit_render.rb:6:in `send_action'
actionpack (6.0.3.7) lib/abstract_controller/base.rb:195:in `process_action'
actionpack (6.0.3.7) lib/action_controller/metal/rendering.rb:30:in `process_action'
actionpack (6.0.3.7) lib/abstract_controller/callbacks.rb:42:in `block in process_action'
activesupport (6.0.3.7) lib/active_support/callbacks.rb:112:in `block in run_callbacks'
app/controllers/concerns/localization.rb:36:in `block in set_locale'
i18n (1.8.10) lib/i18n.rb:314:in `with_locale'
app/controllers/concerns/localization.rb:33:in `set_locale'
activesupport (6.0.3.7) lib/active_support/callbacks.rb:121:in `block in run_callbacks'
activesupport (6.0.3.7) lib/active_support/callbacks.rb:139:in `run_callbacks'
actionpack (6.0.3.7) lib/abstract_controller/callbacks.rb:41:in `process_action'
actionpack (6.0.3.7) lib/action_controller/metal/rescue.rb:22:in `process_action'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:33:in `block in process_action'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `block in instrument'
activesupport (6.0.3.7) lib/active_support/notifications/instrumenter.rb:24:in `instrument'
sentry-rails (4.3.4) lib/sentry/rails/tracing.rb:41:in `instrument'
activesupport (6.0.3.7) lib/active_support/notifications.rb:180:in `instrument'
actionpack (6.0.3.7) lib/action_controller/metal/instrumentation.rb:32:in `process_action'
actionpack (6.0.3.7) lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
activerecord (6.0.3.7) lib/active_record/railties/controller_runtime.rb:27:in `process_action'
actionpack (6.0.3.7) lib/abstract_controller/base.rb:136:in `process'
actionview (6.0.3.7) lib/action_view/rendering.rb:39:in `process'
actionpack (6.0.3.7) lib/action_controller/metal.rb:190:in `dispatch'
actionpack (6.0.3.7) lib/action_controller/metal.rb:254:in `dispatch'
actionpack (6.0.3.7) lib/action_dispatch/routing/route_set.rb:50:in `dispatch'
actionpack (6.0.3.7) lib/action_dispatch/routing/route_set.rb:33:in `serve'
actionpack (6.0.3.7) lib/action_dispatch/journey/router.rb:49:in `block in serve'
actionpack (6.0.3.7) lib/action_dispatch/journey/router.rb:32:in `each'
actionpack (6.0.3.7) lib/action_dispatch/journey/router.rb:32:in `serve'
actionpack (6.0.3.7) lib/action_dispatch/routing/route_set.rb:834:in `call'
sentry-rails (4.3.4) lib/sentry/rails/rescued_exception_interceptor.rb:12:in `call'
http_accept_language (2.1.1) lib/http_accept_language/middleware.rb:14:in `call'
bullet (6.1.0) lib/bullet/rack.rb:15:in `call'
rack (2.2.3) lib/rack/tempfile_reaper.rb:15:in `call'
rack (2.2.3) lib/rack/etag.rb:27:in `call'
rack (2.2.3) lib/rack/conditional_get.rb:27:in `call'
rack (2.2.3) lib/rack/head.rb:12:in `call'
actionpack (6.0.3.7) lib/action_dispatch/http/content_security_policy.rb:18:in `call'
rack (2.2.3) lib/rack/session/abstract/id.rb:266:in `context'
rack (2.2.3) lib/rack/session/abstract/id.rb:260:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/cookies.rb:648:in `call'
activerecord (6.0.3.7) lib/active_record/migration.rb:567:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/callbacks.rb:27:in `block in call'
activesupport (6.0.3.7) lib/active_support/callbacks.rb:101:in `run_callbacks'
actionpack (6.0.3.7) lib/action_dispatch/middleware/callbacks.rb:26:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/actionable_exceptions.rb:18:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/debug_exceptions.rb:32:in `call'
web-console (4.1.0) lib/web_console/middleware.rb:132:in `call_app'
web-console (4.1.0) lib/web_console/middleware.rb:28:in `block in call'
web-console (4.1.0) lib/web_console/middleware.rb:17:in `catch'
web-console (4.1.0) lib/web_console/middleware.rb:17:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (6.0.3.7) lib/rails/rack/logger.rb:37:in `call_app'
railties (6.0.3.7) lib/rails/rack/logger.rb:26:in `block in call'
activesupport (6.0.3.7) lib/active_support/tagged_logging.rb:80:in `block in tagged'
activesupport (6.0.3.7) lib/active_support/tagged_logging.rb:28:in `tagged'
activesupport (6.0.3.7) lib/active_support/tagged_logging.rb:80:in `tagged'
railties (6.0.3.7) lib/rails/rack/logger.rb:26:in `call'
sprockets-rails (3.2.2) lib/sprockets/rails/quiet_assets.rb:13:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/remote_ip.rb:81:in `call'
request_store (1.5.0) lib/request_store/middleware.rb:19:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/request_id.rb:27:in `call'
rack (2.2.3) lib/rack/method_override.rb:24:in `call'
rack (2.2.3) lib/rack/runtime.rb:22:in `call'
activesupport (6.0.3.7) lib/active_support/cache/strategy/local_cache_middleware.rb:29:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/executor.rb:14:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/static.rb:126:in `call'
rack (2.2.3) lib/rack/sendfile.rb:110:in `call'
actionpack (6.0.3.7) lib/action_dispatch/middleware/host_authorization.rb:82:in `call'
sentry-ruby-core (4.3.2) lib/sentry/rack/capture_exceptions.rb:23:in `block in call'
sentry-ruby-core (4.3.2) lib/sentry/hub.rb:52:in `with_scope'
sentry-ruby-core (4.3.2) lib/sentry-ruby.rb:147:in `with_scope'
sentry-ruby-core (4.3.2) lib/sentry/rack/capture_exceptions.rb:14:in `call'
rack-mini-profiler (2.3.2) lib/mini_profiler/profiler.rb:384:in `call'
webpacker (5.4.0) lib/webpacker/dev_server_proxy.rb:25:in `perform_request'
rack-proxy (0.6.5) lib/rack/proxy.rb:57:in `call'
railties (6.0.3.7) lib/rails/engine.rb:527:in `call'
puma (5.3.1) lib/puma/configuration.rb:249:in `call'
puma (5.3.1) lib/puma/request.rb:76:in `block in handle_request'
puma (5.3.1) lib/puma/thread_pool.rb:338:in `with_force_shutdown'
puma (5.3.1) lib/puma/request.rb:75:in `handle_request'
puma (5.3.1) lib/puma/server.rb:437:in `process_client'
puma (5.3.1) lib/puma/thread_pool.rb:145:in `block in spawn_thread'
I've the issue on both webpage and console. On webpage it's on a specific page that call Payzen API, and so call config file to get credentials.
I've inspect the code a bit more.
anyway_config/lib/anyway/railtie.rb
Lines 10 to 13 in 068fdf1
If I'm not wrong, before_configuration
execute code before initializers are loaded. I guess this is done to have access to config file in initializers.
But because of this, config/initializers/inflections.rb
is not loaded yet.
What I've done to try to understand what the code doing is to put a binding.pry
at the end of the following method:
anyway_config/lib/anyway/rails/settings.rb
Lines 21 to 37 in 068fdf1
And I notice the following:
[4] pry(Anyway::Settings)> @autoloader.autoloads
=> {"/home/user/Projects/rails/config/configs/application_config.rb"=>[Object, :ApplicationConfig],
"/home/user/Projects/rails/config/configs/payzen_api_config.rb"=>[Object, :PayzenApiConfig]
Seems the class name already defined, before inflection initializers loaded.
Thanks for the investigation!
Seems the class name already defined, before inflection initializers loaded.
Yeah, we call loader.setup
before initialization. Since the point of this loader is to configure autoload before initialization, we cannot have an access to initializers here.
I suggest configuring inflections in the very beginning of the application boot process, e.g., in your config/application.rb
:
require_relative "initializers/inflections"
module MyApp
class Application < Rails::Application
# ...
end
end
@palkan thank you for the support!