From 7d1fc8c0b4c96448edc9b86c74e97219d66afae3 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 the asset finder to be a callable object. This is useful when the asset pipeline is not ready when the initializer is run, for example, when using Propshaft. I don't know if this is the best way to solve this problem. On the one hand, Propshaft could be done 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'