Sprockets v3.7.0 deprecation warning
kamen-hursev opened this issue · comments
I use haml in some asset templates. After I updated Sprockets to v3.7. I got a deprecation warning:
DEPRECATION WARNING: You are using the a deprecated processor interface Tilt::HamlTemplate.
Please update your processor interface:
https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors
It seems to me this is not limited to Haml, but all template engines supported by Tilt. Is Tilt::Template
supposed to implement self.call
in order to support Sprockets v4?
The code that triggers the warning is a Rails initializer:
Rails.application.config.assets.configure do |config|
config.register_mime_type 'text/html', extensions: ['.haml', '.html.haml']
config.register_preprocessor 'text/html', Tilt::HamlTemplate
end
Sprockets was initially based on Tilt, but in the later versions they've decided to not make its interface compatible with Tilt. That is a completely fair decision as Tilt templates and Sprocket processors have different use cases.
There are no plans to change Tilt to be compatible with Sprockets v4. I think you can solve the problem by writing a class which implements call
in redirects it to Tilt:
class TiltProcessor
def initialize(template_class)
@template_class = template_class
end
def call(input)
# not sure if I've implemented this correctly
result = @template_class.new(input[:filename]) { input[:data] }.render
{ data: result }
end
end
config.register_preprocessor 'text/html', TiltProcessor.new(Tilt::HamlTemplate)
Thanks, @judofyr , for the code snippet. It (almost) works, just had to change the call
method to:
def call(input)
result = @template_class.new(input[:filename]) { input[:data] }.render
{ data: String.new(result) }
end
Because for some reason Sprockets insists the data is instance_of?(String)
and in some cases I get ActiveSupport::SafeBuffer
.
I encountered another problem. In the haml templates I use some view helpers and used to include them like:
Rails.application.config.assets.configure do |config|
...
include ActionView::Helpers
include Rails.application.routes.url_helpers
end
For some reason after using
config.register_preprocessor 'text/html', TiltProcessor.new(Tilt::HamlTemplate)
they are not included in the Haml processor and get errors like:
NoMethodError: undefined method 'image_tag'
. Do you have any idea how this can be solved?
You could maybe do something like this:
class TiltProcessor
def initialize(template_class)
@template_class = template_class
end
def context
@context ||= Object.new
end
def call(input)
result = @template_class.new(input[:filename]) { input[:data] }.render(context)
{ data: result }
end
end
And then you can extend
it into the context:
processor = TiltProcessor.new(Tilt::HamlTemplate)
processor.context.extend Rails.application.routes.url_helpers
config.register_preprocessor 'text/html', processor
@judofyr, thank you very much for helping me with this!
Just a note that extend
won't work with modules like ActionView::Helpers. So the final solution that works for me is:
class TiltProcessor
def initialize(template_class, context = nil)
@template_class = template_class
@context = context || Object.new
end
def call(input)
result = @template_class.new(input[:filename]) { input[:data] }.render(@context)
{ data: String.new(result) }
end
end
class HamlAssetsContext
include SimpleForm::Helpers
include SimpleForm::ActionViewExtensions::FormHelper
include ActionView::Helpers
include Rails.application.routes.url_helpers
# Include any other view helper module that you need. eg:
# include ApplicationHelper
end
Rails.application.config.assets.configure do |config|
config.register_mime_type 'text/html', extensions: ['.haml', '.html.haml']
processor = TiltProcessor.new(Tilt::HamlTemplate, HamlAssetsContext.new)
config.register_preprocessor 'text/html', processor
end
Very happy you found a solution :) I'm closing this issue now. Feel free to reopen or comment if you have any other issues/questions.
(One tiny suggestion: Change the initializer to def initialize(template_class, context = Object.new)
)
The above solution has some issues related with the context. For example image_tag
, would not render correct URL-s with the hashed tail.
After some more research I managed to find my way around to sprockets legacy_tilt_processor.rb. Adding the final version here, just in case this issue attracts more people with the same/similar problem.
# For Rails add to a file in config/initializers
class TiltProcessor
def initialize(klass)
@klass = klass
end
def call(input)
filename = input[:filename]
data = input[:data]
context = input[:environment].context_class.new(input)
data = @klass.new(filename) { data }.render(context, {})
context.metadata.merge(data: data.to_str)
end
end
Rails.application.config.assets.configure do |env|
env.context_class.class_eval do
include SimpleForm::Helpers
include SimpleForm::ActionViewExtensions::FormHelper
include ActionView::Helpers
include Rails.application.routes.url_helpers
# Include any other view helper module that you need. eg:
# include ApplicationHelper
end
env.register_mime_type 'text/html', extensions: ['.haml', '.html.haml']
env.register_preprocessor 'text/html', TiltProcessor.new(Tilt::HamlTemplate)
end
Just don't understand why the Sprockets' processor class needs to inherit Delegator
.