From 56f28b94581e4dfce26da887640ecc22e93c0578 Mon Sep 17 00:00:00 2001 From: Simon Fish Date: Sun, 8 Sep 2024 19:34:33 +0100 Subject: [PATCH] Use ActiveSupport::Configurable to cascade config ViewComponent::Base itself will always use the defaults. Any classes inheriting from ViewComponent::Base will cascade config down using InheritableOptions, only specifying any overrides. Generate options being on their own "layer of config is currently unresolved - it might be that config needs to be a new object inheriting from InheritableOptions that has method accessors for everything in that namespace. It seems like this solution is now applicable to everything, not just strict_helper_enabled? --- lib/view_component/base.rb | 30 +++++++++--------------------- lib/view_component/config.rb | 5 +++-- lib/view_component/engine.rb | 2 +- lib/view_component/use_helpers.rb | 4 +++- test/sandbox/test/base_test.rb | 20 ++++++++++---------- 5 files changed, 26 insertions(+), 35 deletions(-) diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb index 65d467522..e51e70645 100644 --- a/lib/view_component/base.rb +++ b/lib/view_component/base.rb @@ -43,16 +43,6 @@ def config class_attribute :__vc_strip_trailing_whitespace, instance_accessor: false, instance_predicate: false self.__vc_strip_trailing_whitespace = false # class_attribute:default doesn't work until Rails 5.2 - # Default for class - class_attribute :__vc_strict_helpers_enabled, instance_accessor: false, instance_predicate: false, default: false - # Changeable for instance - attr_writer :__vc_strict_helpers_enabled - - def __vc_strict_helpers_enabled - @__vc_strict_helpers_enabled.nil? ? self.class.__vc_strict_helpers_enabled : @__vc_strict_helpers_enabled - end - alias_method :strict_helpers_enabled?, :__vc_strict_helpers_enabled - attr_accessor :__vc_original_view_context # Components render in their own view context. Helpers and other functionality @@ -529,9 +519,16 @@ def inherited(child) # `compile` defines compile - # Set strict_helpers_enabled from global config + child.include ActiveSupport::Configurable + if child.superclass == ViewComponent::Base - child.__vc_strict_helpers_enabled = Rails.application.config.view_component.strict_helpers_enabled + child.define_singleton_method(:config) do + @@config ||= Rails.application.config.view_component.inheritable_copy + end + else + child.define_singleton_method(:config) do + @@config ||= superclass.config.inheritable_copy + end end # Give the child its own personal #render_template_for to protect against the case when @@ -655,15 +652,6 @@ def strip_trailing_whitespace? __vc_strip_trailing_whitespace end - # TODO - def strict_helpers_enabled=(value = true) - self.__vc_strict_helpers_enabled = value - end - - def strict_helpers_enabled? - __vc_strict_helpers_enabled - end - # Ensure the component initializer accepts the # collection parameter. By default, we don't # validate that the default parameter name diff --git a/lib/view_component/config.rb b/lib/view_component/config.rb index 5eaca7927..9ece189e6 100644 --- a/lib/view_component/config.rb +++ b/lib/view_component/config.rb @@ -11,7 +11,7 @@ class << self alias_method :default, :new def defaults - ActiveSupport::OrderedOptions.new.merge!({ + ActiveSupport::InheritableOptions.new({ generate: default_generate_options, preview_controller: "ViewComponentsController", preview_route: "/rails/view_components", @@ -26,7 +26,8 @@ def defaults test_controller: "ApplicationController", default_preview_layout: nil, capture_compatibility_patch_enabled: false, - helpers_enabled: true + helpers_enabled: true, + strict_helpers_enabled?: false }) end diff --git a/lib/view_component/engine.rb b/lib/view_component/engine.rb index 8932ad800..2e323e5a3 100644 --- a/lib/view_component/engine.rb +++ b/lib/view_component/engine.rb @@ -6,7 +6,7 @@ module ViewComponent class Engine < Rails::Engine # :nodoc: - config.view_component = ViewComponent::Config.current + config.view_component = ViewComponent::Config.defaults rake_tasks do load "view_component/rails/tasks/view_component.rake" diff --git a/lib/view_component/use_helpers.rb b/lib/view_component/use_helpers.rb index 8d395da26..c0a324de5 100644 --- a/lib/view_component/use_helpers.rb +++ b/lib/view_component/use_helpers.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require "view_component/errors" + module ViewComponent::UseHelpers extend ActiveSupport::Concern @@ -13,7 +15,7 @@ def use_helper(helper_method, from: nil, prefix: false) class_eval(<<-RUBY, __FILE__, __LINE__ + 1) def #{helper_method_name}(*args, &block) - raise HelpersCalledBeforeRenderError if view_context.nil? + raise ::ViewComponent::HelpersCalledBeforeRenderError if view_context.nil? #{define_helper(helper_method: helper_method, source: from)} end diff --git a/test/sandbox/test/base_test.rb b/test/sandbox/test/base_test.rb index 7bba16a23..cf61121ff 100644 --- a/test/sandbox/test/base_test.rb +++ b/test/sandbox/test/base_test.rb @@ -157,18 +157,18 @@ def test_no_method_error_does_not_reference_missing_helper def test_strict_helpers_enabled with_config_option(:strict_helpers_enabled, false) do - refute ViewComponent::Base.strict_helpers_enabled?, ".strict_helpers_enabled? should be false by default" - refute ViewComponent::Base.new.strict_helpers_enabled?, "#strict_helpers_enabled? should be false by default" - Rails.application.config.view_component.strict_helpers_enabled = true - refute ViewComponent::Base.strict_helpers_enabled?, ".strict_helpers_enabled? should not be changed by global config for ViewComponent::Base" - refute ViewComponent::Base.new.strict_helpers_enabled?, "#strict_helpers_enabled? should not be changed by global config for ViewComponent::Base" top_level_component_class = Class.new(ViewComponent::Base) - assert top_level_component_class.strict_helpers_enabled?, ".strict_helpers_enabled? should inherit from global config" - assert top_level_component_class.new.strict_helpers_enabled?, "#strict_helpers_enabled? should inherit from global config" - top_level_component_class.strict_helpers_enabled = false + refute ViewComponent::Base.config.strict_helpers_enabled?, ".strict_helpers_enabled? should be false by default" + # refute ViewComponent::Base.new.config.strict_helpers_enabled?, "#strict_helpers_enabled? should be false by default" + Rails.application.config.view_component[:strict_helpers_enabled?] = true + refute ViewComponent::Base.config.strict_helpers_enabled?, ".strict_helpers_enabled? should not be changed by global config for ViewComponent::Base" + # refute ViewComponent::Base.new.config.strict_helpers_enabled?, "#strict_helpers_enabled? should not be changed by global config for ViewComponent::Base" + assert top_level_component_class.config.strict_helpers_enabled?, ".strict_helpers_enabled? should inherit from global config" + assert top_level_component_class.new.config.strict_helpers_enabled?, "#strict_helpers_enabled? should inherit from global config" inherited_component_class = Class.new(top_level_component_class) - refute inherited_component_class.strict_helpers_enabled?, ".strict_helpers_enabled? should inherit from its parent" - refute inherited_component_class.new.strict_helpers_enabled?, "#strict_helpers_enabled? should inherit from its parent" + top_level_component_class.config[:strict_helpers_enabled?] = false + refute inherited_component_class.config.strict_helpers_enabled?, ".strict_helpers_enabled? should inherit from its parent" + refute inherited_component_class.new.config.strict_helpers_enabled?, "#strict_helpers_enabled? should inherit from its parent" end end end