From 738284eb91fa3ab4a0316f8b37d443fc5460d31c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mugnolo?= Date: Thu, 12 Oct 2023 16:39:55 -0400 Subject: [PATCH] Set asset finder from callable It fixes #151 by allowing to set the asset finder to a callable object. This is useful when the asset pipeline is not ready when the initializer is run, for example when using Propshaft. I'm not sure if this is the best way to solve this problem. On one hand, Propshaft could be be ready when its initializer is run, but on the other hand, this gem's railtie assumes the asset pipeline is ready. --- lib/inline_svg.rb | 17 ++++++++++++++--- lib/inline_svg/railtie.rb | 14 ++++++-------- spec/inline_svg_spec.rb | 16 +++++++++++++++- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/inline_svg.rb b/lib/inline_svg.rb index 45aa49e..4fba526 100644 --- a/lib/inline_svg.rb +++ b/lib/inline_svg.rb @@ -19,7 +19,7 @@ module InlineSvg class Configuration class Invalid < ArgumentError; end - attr_reader :asset_file, :asset_finder, :custom_transformations, :svg_not_found_css_class + attr_reader :asset_file, :custom_transformations, :svg_not_found_css_class def initialize @custom_transformations = {} @@ -41,8 +41,15 @@ def asset_file=(custom_asset_file) end end + def asset_finder + set_asset_finder_from_callable + @asset_finder + end + def asset_finder=(finder) - @asset_finder = if finder.respond_to?(:find_asset) + @asset_finder = if finder.respond_to?(:call) + finder + elsif finder.respond_to?(:find_asset) finder elsif finder.class.name == "Propshaft::Assembly" InlineSvg::PropshaftAssetFinder @@ -52,7 +59,6 @@ def asset_finder=(finder) # See: https://github.com/jamesmartin/inline_svg/issues/25 InlineSvg::StaticAssetFinder end - asset_finder end def svg_not_found_css_class=(css_class) @@ -82,6 +88,11 @@ def incompatible_transformation?(klass) !klass.is_a?(Class) || !klass.respond_to?(:create_with_value) || !klass.instance_methods.include?(:transform) end + def set_asset_finder_from_callable + while @asset_finder&.respond_to?(:call) + self.asset_finder = @asset_finder.call + end + end end @configuration = InlineSvg::Configuration.new diff --git a/lib/inline_svg/railtie.rb b/lib/inline_svg/railtie.rb index 6e55db9..c57c71d 100644 --- a/lib/inline_svg/railtie.rb +++ b/lib/inline_svg/railtie.rb @@ -10,14 +10,12 @@ class Railtie < ::Rails::Railtie config.after_initialize do |app| InlineSvg.configure do |config| - # Configure the asset_finder: - # Only set this when a user-configured asset finder has not been - # configured already. - if config.asset_finder.nil? - # In default Rails apps, this will be a fully operational - # Sprockets::Environment instance - config.asset_finder = app.instance_variable_get(:@assets) - end + # Configure an asset finder for Rails. This will be evaluated when the + # first SVG is rendered, giving time to the asset pipeline to be done + # loading. + config.asset_finder = proc { + app.instance_variable_get(:@assets) + } end end end diff --git a/spec/inline_svg_spec.rb b/spec/inline_svg_spec.rb index b4fe73d..408f04f 100644 --- a/spec/inline_svg_spec.rb +++ b/spec/inline_svg_spec.rb @@ -19,6 +19,10 @@ def self.named(filename); end describe InlineSvg do describe "configuration" do + before do + InlineSvg.reset_configuration! + end + context "when a block is not given" do it "complains" do expect do @@ -29,7 +33,7 @@ def self.named(filename); end context "asset finder" do it "allows an asset finder to be assigned" do - sprockets = double('SomethingLikeSprockets', find_asset: 'some asset') + sprockets = double("Something like sprockets", find_asset: "some asset") InlineSvg.configure do |config| config.asset_finder = sprockets end @@ -37,6 +41,16 @@ def self.named(filename); end expect(InlineSvg.configuration.asset_finder).to eq sprockets end + it "allows to give a callable object that returns an asset finder" do + propshaft = double("Something like propshaft", class: double(name: "Propshaft::Assembly")) + callable = -> { propshaft } + InlineSvg.configure do |config| + config.asset_finder = callable + end + + expect(InlineSvg.configuration.asset_finder).to eq InlineSvg::PropshaftAssetFinder + end + it "falls back to StaticAssetFinder when the provided asset finder does not implement #find_asset" do InlineSvg.configure do |config| config.asset_finder = 'Not a real asset finder'