diff --git a/.rubocop.yml b/.rubocop.yml index bb580f41..5422099f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,6 +4,12 @@ AllCops: TargetRubyVersion: 3.0 NewCops: enable SuggestExtensions: false + Exclude: + - 'node_modules/**/*' + - 'tmp/**/*' + - 'vendor/**/*' + - '.git/**/*' + - 'docs/**/*' Metrics: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 3055e1ca..01388ec3 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,19 +1,11 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 10000` -# on 2024-11-22 18:44:50 UTC using RuboCop version 1.68.0. +# on 2025-03-01 10:06:34 UTC using RuboCop version 1.73.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: EnforcedStyle, IndentationWidth. -# SupportedStyles: outdent, indent -Layout/AccessModifierIndentation: - Exclude: - - 'lib/inertia_rails/configuration.rb' - # Offense count: 2 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, IndentationWidth. @@ -23,7 +15,7 @@ Layout/ArgumentAlignment: - 'bin/console' - 'spec/inertia/response_spec.rb' -# Offense count: 5 +# Offense count: 9 # This cop supports safe autocorrection (--autocorrect). Layout/BlockEndNewline: Exclude: @@ -37,18 +29,10 @@ Layout/CaseIndentation: Exclude: - 'lib/inertia_rails/renderer.rb' -# Offense count: 2 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowForAlignment. -Layout/CommentIndentation: - Exclude: - - 'lib/inertia_rails/rspec.rb' - -# Offense count: 2 +# Offense count: 1 # This cop supports safe autocorrection (--autocorrect). Layout/EmptyLineAfterGuardClause: Exclude: - - 'lib/inertia_rails/configuration.rb' - 'lib/inertia_rails/controller.rb' # Offense count: 1 @@ -97,14 +81,7 @@ Layout/FirstArgumentIndentation: Layout/FirstHashElementIndentation: EnforcedStyle: consistent -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: Width, AllowedPatterns. -Layout/IndentationWidth: - Exclude: - - 'spec/inertia/configuration_spec.rb' - -# Offense count: 5 +# Offense count: 9 # This cop supports safe autocorrection (--autocorrect). Layout/MultilineBlockLayout: Exclude: @@ -118,7 +95,7 @@ Layout/MultilineMethodCallIndentation: Exclude: - 'spec/inertia/ssr_spec.rb' -# Offense count: 7 +# Offense count: 6 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space @@ -139,19 +116,18 @@ Layout/SpaceInsideArrayLiteralBrackets: - 'spec/dummy/app/controllers/inertia_test_controller.rb' - 'spec/dummy/config/environments/production.rb' -# Offense count: 20 +# Offense count: 13 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters. # SupportedStyles: space, no_space # SupportedStylesForEmptyBraces: space, no_space Layout/SpaceInsideBlockBraces: Exclude: - - 'spec/inertia/configuration_spec.rb' - 'spec/inertia/error_sharing_spec.rb' - 'spec/inertia/rendering_spec.rb' - 'spec/inertia/request_spec.rb' -# Offense count: 128 +# Offense count: 122 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. # SupportedStyles: space, no_space, compact @@ -163,7 +139,6 @@ Layout/SpaceInsideHashLiteralBraces: - 'spec/dummy/app/controllers/inertia_conditional_sharing_controller.rb' - 'spec/dummy/app/controllers/inertia_share_test_controller.rb' - 'spec/inertia/conditional_sharing_spec.rb' - - 'spec/inertia/configuration_spec.rb' - 'spec/inertia/middleware_spec.rb' - 'spec/inertia/rails_mimic_spec.rb' - 'spec/inertia/rendering_spec.rb' @@ -181,7 +156,7 @@ Layout/TrailingEmptyLines: - 'lib/tasks/inertia_rails.rake' - 'spec/inertia/rails_mimic_spec.rb' -# Offense count: 12 +# Offense count: 10 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: AllowInHeredoc. Layout/TrailingWhitespace: @@ -226,7 +201,8 @@ Lint/UnderscorePrefixedVariableName: # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods. +# Configuration parameters: AutoCorrect, AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. +# NotImplementedExceptions: NotImplementedError Lint/UnusedMethodArgument: Exclude: - 'lib/patches/mapper.rb' @@ -254,7 +230,7 @@ Naming/VariableNumber: Exclude: - 'spec/dummy/app/controllers/inertia_test_controller.rb' -# Offense count: 21 +# Offense count: 25 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, AllowedMethods, AllowedPatterns, AllowBracesOnProceduralOneLiners, BracesRequiredMethods. # SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces @@ -263,11 +239,9 @@ Naming/VariableNumber: # AllowedMethods: lambda, proc, it Style/BlockDelimiters: Exclude: - - 'lib/inertia_rails/configuration.rb' - 'lib/inertia_rails/controller.rb' - 'spec/inertia/action_filter_spec.rb' - 'spec/inertia/conditional_sharing_spec.rb' - - 'spec/inertia/configuration_spec.rb' - 'spec/inertia/rendering_spec.rb' - 'spec/inertia/request_spec.rb' - 'spec/inertia/rspec_helper_spec.rb' @@ -331,12 +305,13 @@ Style/ExpandPathArguments: Exclude: - 'spec/rails_helper.rb' -# Offense count: 74 +# Offense count: 71 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. # SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Exclude: + - '**/*.arb' - 'app/controllers/inertia_rails/static_controller.rb' - 'bin/console' - 'lib/inertia_rails.rb' @@ -344,7 +319,6 @@ Style/FrozenStringLiteralComment: - 'lib/inertia_rails/engine.rb' - 'lib/inertia_rails/helper.rb' - 'lib/inertia_rails/inertia_rails.rb' - - 'lib/inertia_rails/middleware.rb' - 'lib/inertia_rails/rspec.rb' - 'lib/inertia_rails/version.rb' - 'lib/patches/better_errors.rb' @@ -396,7 +370,6 @@ Style/FrozenStringLiteralComment: - 'spec/inertia/always_prop_spec.rb' - 'spec/inertia/base_prop_spec.rb' - 'spec/inertia/conditional_sharing_spec.rb' - - 'spec/inertia/configuration_spec.rb' - 'spec/inertia/error_sharing_spec.rb' - 'spec/inertia/lazy_prop_spec.rb' - 'spec/inertia/middleware_spec.rb' @@ -409,7 +382,6 @@ Style/FrozenStringLiteralComment: - 'spec/inertia/ssr_spec.rb' - 'spec/rails_helper.rb' - 'spec/spec_helper.rb' - - 'spec/support/helper_module.rb' - 'spec/support/shared_examples.rb' # Offense count: 1 @@ -424,13 +396,6 @@ Style/GlobalVars: Exclude: - 'spec/inertia/rspec_helper_spec.rb' -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals. -Style/GuardClause: - Exclude: - - 'lib/inertia_rails/configuration.rb' - # Offense count: 1 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols. @@ -440,11 +405,10 @@ Style/HashSyntax: Exclude: - 'lib/tasks/inertia_rails.rake' -# Offense count: 6 +# Offense count: 5 # This cop supports safe autocorrection (--autocorrect). Style/IfUnlessModifier: Exclude: - - 'lib/inertia_rails/configuration.rb' - 'lib/inertia_rails/controller.rb' - 'lib/patches/better_errors.rb' - 'lib/patches/debug_exceptions/patch-5-0.rb' @@ -457,12 +421,6 @@ Style/IfUnlessModifierOfIfUnless: Exclude: - 'lib/inertia_rails/controller.rb' -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/KeywordArgumentsMerging: - Exclude: - - 'lib/inertia_rails/configuration.rb' - # Offense count: 3 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle. @@ -479,12 +437,6 @@ Style/MapToSet: Exclude: - 'lib/inertia_rails/action_filter.rb' -# Offense count: 1 -# This cop supports safe autocorrection (--autocorrect). -Style/MultilineIfModifier: - Exclude: - - 'lib/inertia_rails/configuration.rb' - # Offense count: 1 # This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: EnforcedStyle. @@ -493,7 +445,7 @@ Style/MutableConstant: Exclude: - 'lib/inertia_rails/version.rb' -# Offense count: 1 +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). Style/NegatedIfElseCondition: Exclude: @@ -558,7 +510,7 @@ Style/SoleNestedConditional: Exclude: - 'lib/inertia_rails/controller.rb' -# Offense count: 90 +# Offense count: 82 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline. # SupportedStyles: single_quotes, double_quotes @@ -580,15 +532,12 @@ Style/StringLiterals: - 'spec/dummy/app/controllers/inertia_config_test_controller.rb' - 'spec/dummy/app/controllers/inertia_lambda_shared_props_controller.rb' - 'spec/dummy/app/controllers/inertia_rails_mimic_controller.rb' - - 'spec/dummy/app/controllers/inertia_render_test_controller.rb' - 'spec/dummy/config/application.rb' - 'spec/dummy/config/environments/production.rb' - 'spec/dummy/config/puma.rb' - 'spec/dummy/config/routes.rb' - 'spec/dummy/config/spring.rb' - 'spec/inertia/conditional_sharing_spec.rb' - - 'spec/inertia/configuration_spec.rb' - - 'spec/inertia/rendering_spec.rb' - 'spec/inertia/response_spec.rb' - 'spec/inertia/rspec_helper_spec.rb' - 'spec/rails_helper.rb' @@ -610,23 +559,21 @@ Style/SymbolArray: EnforcedStyle: percent MinSize: 3 -# Offense count: 16 +# Offense count: 14 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. # SupportedStylesForMultiline: comma, consistent_comma, no_comma Style/TrailingCommaInArguments: Exclude: - 'lib/inertia_rails.rb' - - 'lib/inertia_rails/renderer.rb' - 'spec/dummy/app/controllers/inertia_config_test_controller.rb' - 'spec/dummy/app/controllers/inertia_rails_mimic_controller.rb' - - 'spec/inertia/configuration_spec.rb' - 'spec/inertia/rendering_spec.rb' -# Offense count: 21 +# Offense count: 22 # This cop supports safe autocorrection (--autocorrect). # Configuration parameters: EnforcedStyleForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma +# SupportedStylesForMultiline: comma, consistent_comma, diff_comma, no_comma Style/TrailingCommaInHashLiteral: Exclude: - 'lib/inertia_rails/rspec.rb' @@ -639,17 +586,18 @@ Style/TrailingCommaInHashLiteral: - 'spec/inertia/response_spec.rb' - 'spec/inertia/rspec_helper_spec.rb' -# Offense count: 1 +# Offense count: 2 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: WordRegex. +# Configuration parameters: EnforcedStyle, MinSize, WordRegex. # SupportedStyles: percent, brackets Style/WordArray: - EnforcedStyle: percent - MinSize: 4 + Exclude: + - 'lib/inertia_rails/middleware.rb' + - 'spec/inertia/rendering_spec.rb' -# Offense count: 21 +# Offense count: 26 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: - Max: 290 + Max: 276 diff --git a/lib/inertia_rails/configuration.rb b/lib/inertia_rails/configuration.rb index 9e39ed3d..4c258e83 100644 --- a/lib/inertia_rails/configuration.rb +++ b/lib/inertia_rails/configuration.rb @@ -29,6 +29,23 @@ class Configuration OPTION_NAMES = DEFAULTS.keys.freeze + class << self + def default + new(**DEFAULTS, **env_options) + end + + private + + def env_options + DEFAULTS.keys.each_with_object({}) do |key, hash| + value = ENV.fetch("INERTIA_#{key.to_s.upcase}", nil) + next if value.nil? + + hash[key] = %w[true false].include?(value) ? value == 'true' : value + end + end + end + protected attr_reader :controller protected attr_reader :options @@ -36,9 +53,9 @@ def initialize(controller: nil, **attrs) @controller = controller @options = attrs.extract!(*OPTION_NAMES) - unless attrs.empty? - raise ArgumentError, "Unknown options for #{self.class}: #{attrs.keys}" - end + return if attrs.empty? + + raise ArgumentError, "Unknown options for #{self.class}: #{attrs.keys}" end def bind_controller(controller) @@ -56,7 +73,7 @@ def merge!(config) end def merge(config) - Configuration.new(**@options.merge(config.options)) + Configuration.new(**@options, **config.options) end # Internal: Finalizes the configuration for a specific controller. @@ -70,23 +87,22 @@ def component_path_resolver(path:, action:) end OPTION_NAMES.each do |option| - define_method(option) { - evaluate_option @options[option] - } unless method_defined?(option) - define_method("#{option}=") { |value| + unless method_defined?(option) + define_method(option) do + evaluate_option options[option] + end + end + define_method("#{option}=") do |value| @options[option] = value - } - end - - def self.default - new(**DEFAULTS) + end end - private + private def evaluate_option(value) return value unless value.respond_to?(:call) return value.call unless controller + controller.instance_exec(&value) end end diff --git a/lib/inertia_rails/renderer.rb b/lib/inertia_rails/renderer.rb index f556a7b4..9d9f69d7 100644 --- a/lib/inertia_rails/renderer.rb +++ b/lib/inertia_rails/renderer.rb @@ -60,7 +60,7 @@ def render_ssr def layout layout = configuration.layout - layout.nil? ? true : layout + layout.nil? || layout end def shared_data diff --git a/spec/inertia/configuration_spec.rb b/spec/inertia/configuration_spec.rb index 6d0b251c..54628853 100644 --- a/spec/inertia/configuration_spec.rb +++ b/spec/inertia/configuration_spec.rb @@ -1,8 +1,10 @@ +# frozen_string_literal: true + RSpec.describe 'Inertia configuration', type: :request do after { reset_config! } - describe "InertiaRails::Configuration" do - it "does not allow to modify options after frozen" do + describe 'InertiaRails::Configuration' do + it 'does not allow to modify options after frozen' do config = InertiaRails::Configuration.default config.ssr_enabled = true expect(config.ssr_enabled).to eq true @@ -11,26 +13,64 @@ expect { config.ssr_enabled = false }.to raise_error(FrozenError) expect { config.merge!(InertiaRails::Configuration.default) }.to raise_error(FrozenError) - expect { + expect do merged_config = config.merge(InertiaRails::Configuration.default) expect(merged_config.ssr_enabled).to eq false - }.not_to raise_error + end.not_to raise_error + end + + context 'with environment variables' do + it 'always prioritizes initialized variables' do + with_env( + 'INERTIA_SSR_ENABLED' => 'true', + 'INERTIA_SSR_URL' => 'http://env-ssr-url:1234', + 'INERTIA_DEEP_MERGE_SHARED_DATA' => 'true' + ) do + config = InertiaRails::Configuration.default + + config.ssr_enabled = false + + expect(config.ssr_enabled).to eq false + expect(config.ssr_url).to eq 'http://env-ssr-url:1234' + expect(config.deep_merge_shared_data).to eq true + end + end + + it 'respects environment variables when merging defaults' do + with_env( + 'INERTIA_SSR_ENABLED' => 'true' + ) do + config = InertiaRails::Configuration.default + config.deep_merge_shared_data = true + + controller_config = InertiaRails::Configuration.new(ssr_url: 'http://ssr-url:1234') + controller_config.with_defaults(config) + + expect(controller_config.ssr_enabled).to eq true + expect(controller_config.ssr_url).to eq 'http://ssr-url:1234' + expect(controller_config.deep_merge_shared_data).to eq true + end + end end end describe 'inertia_config' do - it 'overrides the global values' do - get configuration_path - - expect(response.parsed_body.symbolize_keys).to include( - deep_merge_shared_data: true, - default_render: false, - layout: "test", - ssr_enabled: true, - ssr_url: "http://localhost:7777", - version: "2.0", - encrypt_history: false, - ) + it 'overrides the global values and ENV' do + with_env( + 'INERTIA_SSR_URL' => 'http://env-ssr-url:1234' + ) do + get configuration_path + + expect(response.parsed_body.symbolize_keys).to include( + deep_merge_shared_data: true, + default_render: false, + layout: 'test', + ssr_enabled: true, + ssr_url: 'http://localhost:7777', + version: '2.0', + encrypt_history: false + ) + end end end @@ -38,15 +78,15 @@ subject { JSON.parse(response.body)['version'] } context 'base case' do - before { get empty_test_path, headers: {'X-Inertia' => true} } + before { get empty_test_path, headers: { 'X-Inertia' => true } } it { is_expected.to be_nil } end context 'version is a string' do before do - InertiaRails.configure {|c| c.version = '1.0'} - get empty_test_path, headers: {'X-Inertia' => true, 'HTTP_X_INERTIA_VERSION' => '1.0'} + InertiaRails.configure { |c| c.version = '1.0' } + get empty_test_path, headers: { 'X-Inertia' => true, 'HTTP_X_INERTIA_VERSION' => '1.0' } end it { is_expected.to eq '1.0' } @@ -54,8 +94,8 @@ context 'version is a callable' do before do - InertiaRails.configure {|c| c.version = -> {'1.0'}} - get empty_test_path, headers: {'X-Inertia' => true, 'X-Inertia-Version' => '1.0'} + InertiaRails.configure { |c| c.version = -> { '1.0' } } + get empty_test_path, headers: { 'X-Inertia' => true, 'X-Inertia-Version' => '1.0' } end it { is_expected.to eq '1.0' } @@ -63,8 +103,8 @@ context 'string vs float mismatches' do before do - InertiaRails.configure {|c| c.version = 1.0} - get empty_test_path, headers: {'X-Inertia' => true, 'X-Inertia-Version' => '1.0'} + InertiaRails.configure { |c| c.version = 1.0 } + get empty_test_path, headers: { 'X-Inertia' => true, 'X-Inertia-Version' => '1.0' } end it { is_expected.to eq 1.0 } @@ -77,7 +117,7 @@ context 'request in same thread' do before do - get empty_test_path, headers: {'X-Inertia' => true, 'X-Inertia-Version' => '1.0'} + get empty_test_path, headers: { 'X-Inertia' => true, 'X-Inertia-Version' => '1.0' } end it { is_expected.to eq '1.0' } @@ -86,7 +126,7 @@ context 'request in other thread' do before do Thread.new do - get empty_test_path, headers: {'X-Inertia' => true, 'X-Inertia-Version' => '1.0'} + get empty_test_path, headers: { 'X-Inertia' => true, 'X-Inertia-Version' => '1.0' } end.join end @@ -107,7 +147,7 @@ context 'with a new layout' do before do - InertiaRails.configure {|c| c.layout = 'testing' } + InertiaRails.configure { |c| c.layout = 'testing' } end context 'request in same thread' do @@ -134,7 +174,7 @@ context 'opting out of a different layout for Inertia' do before do - InertiaRails.configure {|c| c.layout = true } + InertiaRails.configure { |c| c.layout = true } end it 'uses default layout for controller' do diff --git a/spec/support/helper_module.rb b/spec/support/helper_module.rb index 2ea3d6c2..f0521659 100644 --- a/spec/support/helper_module.rb +++ b/spec/support/helper_module.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module HelperModule def with_forgery_protection orig = ActionController::Base.allow_forgery_protection @@ -8,4 +10,14 @@ def with_forgery_protection ActionController::Base.allow_forgery_protection = orig end end + + def with_env(**env) + orig = ENV.to_h + begin + ENV.replace(env) + yield if block_given? + ensure + ENV.replace(orig) + end + end end