From 3a214b8af44d5fcacd242c1b3280db5084424df2 Mon Sep 17 00:00:00 2001 From: Michal Cichra Date: Fri, 17 Oct 2025 11:41:32 +0200 Subject: [PATCH] Remove dependency on the Rails module Some parts of the code guard against undefined Rails module, but some parts do that in unsafe manner. Good example: `defined?(Rails.env) && Rails.env` Bad example: `defined?(Rails) && Rails.env` There are gems, that define `module Rails` to extend it, but then it is incomplete and causes failures. This change unifies accessing Rails module with proper `defines?` guarding against incomplete definition of the Rails module. --- docs/CHANGELOG.md | 3 +++ lib/view_component.rb | 2 +- lib/view_component/base.rb | 6 +++--- lib/view_component/collection.rb | 2 +- lib/view_component/config.rb | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index f63af3faf..9c7715760 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -13,6 +13,9 @@ nav_order: 6 * Add Carwow to list of companies using ViewComponent. *Tom Lord* +* ViewComponent now works without `rails` and `railties` gems loaded. + + *Michal Cichra* ## 4.0.2 diff --git a/lib/view_component.rb b/lib/view_component.rb index 3db9728ba..a67288011 100644 --- a/lib/view_component.rb +++ b/lib/view_component.rb @@ -16,7 +16,7 @@ module ViewComponent autoload :Preview autoload :Translatable - if Rails.env.test? + if defined?(Rails.env) && Rails.env.test? autoload :TestHelpers autoload :SystemSpecHelpers autoload :SystemTestHelpers diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb index 97ba41815..854eea910 100644 --- a/lib/view_component/base.rb +++ b/lib/view_component/base.rb @@ -47,7 +47,7 @@ def config end include ActionView::Helpers - include Rails.application.routes.url_helpers if defined?(Rails) && Rails.application + include Rails.application.routes.url_helpers if defined?(Rails.application.routes) include ERB::Escape include ActiveSupport::CoreExt::ERBUtil @@ -302,7 +302,7 @@ def helpers @__vc_helpers ||= __vc_original_view_context || controller.view_context end - if ::Rails.env.development? || ::Rails.env.test? + if defined?(Rails.env) && (::Rails.env.development? || ::Rails.env.test?) # @private def method_missing(method_name, *args) # rubocop:disable Style/MissingRespondToMissing super @@ -331,7 +331,7 @@ def view_cache_dependencies [] end - if Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR == 1 + if defined?(Rails::VERSION) && (Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR == 1) # Rails expects us to define `format` on all renderables, # but we do not know the `format` of a ViewComponent until runtime. def format diff --git a/lib/view_component/collection.rb b/lib/view_component/collection.rb index c53f1f1af..7a3f8d42e 100644 --- a/lib/view_component/collection.rb +++ b/lib/view_component/collection.rb @@ -20,7 +20,7 @@ def each(&block) components.each(&block) end - if Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR == 1 + if defined?(Rails::VERSION) && (Rails::VERSION::MAJOR == 7 && Rails::VERSION::MINOR == 1) # Rails expects us to define `format` on all renderables, # but we do not know the `format` of a ViewComponent until runtime. def format diff --git a/lib/view_component/config.rb b/lib/view_component/config.rb index d3c26f57e..204791b88 100644 --- a/lib/view_component/config.rb +++ b/lib/view_component/config.rb @@ -163,7 +163,7 @@ def default_previews_options options = ActiveSupport::OrderedOptions.new options.controller = "ViewComponentsController" options.route = "/rails/view_components" - options.enabled = Rails.env.development? || Rails.env.test? + options.enabled = defined?(Rails.env) && (Rails.env.development? || Rails.env.test?) options.default_layout = nil options.paths = default_preview_paths options