From ab2b082ad14829f4c106804488f791f338611126 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 1/4] 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 | 18 +++++++++++++++--- lib/inline_svg/railtie.rb | 14 ++++++-------- spec/inline_svg_spec.rb | 16 +++++++++++++++- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/lib/inline_svg.rb b/lib/inline_svg.rb index f22d517..4fba526 100644 --- a/lib/inline_svg.rb +++ b/lib/inline_svg.rb @@ -11,6 +11,7 @@ require "inline_svg/railtie" if defined?(Rails) require 'active_support' +require 'active_support/core_ext/object/blank' require 'active_support/core_ext/string' require 'nokogiri' @@ -18,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 = {} @@ -40,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 @@ -51,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) @@ -81,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' From 76a95049042c51e62fa2f00b2111ff5e9508e2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mugnolo?= Date: Tue, 24 Oct 2023 11:40:29 -0400 Subject: [PATCH 2/4] Update lib/inline_svg.rb Co-authored-by: James Martin --- lib/inline_svg.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/inline_svg.rb b/lib/inline_svg.rb index 4fba526..b9fb405 100644 --- a/lib/inline_svg.rb +++ b/lib/inline_svg.rb @@ -47,9 +47,7 @@ def asset_finder end def asset_finder=(finder) - @asset_finder = if finder.respond_to?(:call) - finder - elsif finder.respond_to?(:find_asset) + @asset_finder = if finder.respond_to?(:call) || finder.respond_to?(:find_asset) finder elsif finder.class.name == "Propshaft::Assembly" InlineSvg::PropshaftAssetFinder From c84c9d6ef63290e7c88616e5067209b62fbfd892 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mugnolo?= Date: Tue, 24 Oct 2023 12:03:49 -0400 Subject: [PATCH 3/4] Call method instead --- lib/inline_svg/railtie.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/inline_svg/railtie.rb b/lib/inline_svg/railtie.rb index c57c71d..6921fcc 100644 --- a/lib/inline_svg/railtie.rb +++ b/lib/inline_svg/railtie.rb @@ -13,9 +13,7 @@ class Railtie < ::Rails::Railtie # 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) - } + config.asset_finder = proc { app.assets } end end end From cb2b387a5d2a534c0544a698e7edf53b24763b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20Mugnolo?= Date: Tue, 24 Oct 2023 12:13:37 -0400 Subject: [PATCH 4/4] Add spec example --- spec/inline_svg_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/spec/inline_svg_spec.rb b/spec/inline_svg_spec.rb index 408f04f..b822779 100644 --- a/spec/inline_svg_spec.rb +++ b/spec/inline_svg_spec.rb @@ -51,6 +51,16 @@ def self.named(filename); end expect(InlineSvg.configuration.asset_finder).to eq InlineSvg::PropshaftAssetFinder end + it "allows giving a callable object that returns a callable" do + finder = double("A custom asset finder", find_asset: "some asset") + callable = -> { -> { finder } } + InlineSvg.configure do |config| + config.asset_finder = callable + end + + expect(InlineSvg.configuration.asset_finder).to eq finder + 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'