Just posed the question on LinkedIn'
Potentially silly question, I am not ashamed of not knowing this... How do you mark a Haml file with the magic comment # frozen_string_literal: true. Is it even possible?
https://www.linkedin.com/feed/update/urn:li:activity:7140300572573724673/
Alek K came back with a bit of research. I'm a fan of poking something with a stick.
That's a quite interesting question, one I've never thought of myself before. As a response, I wrote a short article on my blog, describing a little experiment. I hope this can shed some light on the issue.
https://torrocus.com/blog/haml-with-frozen-string-literal-wtf/
His theory was Rubocop must know how to solve this. Sadly.
# frozen_string_literal: true SOMETHING
Is not valid Haml. Since it's trying to render a # which would be a div with no id. Simply won't work. I thought I'd take a quick stab at this.
Suppose we have. Silly example. But all I want to prove is that with frozen_string_literal that the object_id is the same for all instances of "A" since it's the same String.
# frozen_string_literal: true puts "--#{__FILE__}" puts "A".object_id puts "A".object_id puts "A".object_id puts "A".object_id
Here goes
% ruby frozen.rb --/Users/roblacey/repos/personal/robl.me/frozen.rb 60 60 60 60
Yep it's the same object_id everytime. So how would we even test this in Erb?
# frozen_string_literal: true <% puts "--#{__FILE__}" %> <% puts "A".object_id %> <% puts "A".object_id %> <% puts "A".object_id %> <% puts "A".object_id %>
I guess we do...
% irb irb(main):001> require 'erb' irb(main):002> ERB.new(File.read('frozen.erb')).result(binding) --(erb) 7980 8000 8020 8040 => "# frozen_string_literal: true\n\n\n\n\n\n"
Nope none of these are the same object_id. There is some more magic going on. Indeed our Haml file is going to fail with what we saw before.
# frozen_string_literal: true - puts "--#{__FILE__}" - puts "A".object_id - puts "A".object_id - puts "A".object_id - puts "A".object_id
Yep fails.
require 'haml' => true irb(main):005> (Haml::Template.new() { File.read('frozen.haml') }).render (__TEMPLATE__):2:in `__tilt_18120': Illegal element: classes and ids must have values. (Haml::SyntaxError) from /Users/roblacey/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/tilt-2.3.0/lib/tilt/template.rb:207:in `bind_call' from /Users/roblacey/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/tilt-2.3.0/lib/tilt/template.rb:207:in `evaluate' from /Users/roblacey/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/tilt-2.3.0/lib/tilt/template.rb:102:in `render' from (irb):5:in `<main>' from /Users/roblacey/.asdf/installs/ruby/3.2.2/lib/ruby/gems/3.2.0/gems/irb-1.9.1/exe/irb:9:in `<top (required)>' from /Users/roblacey/.asdf/installs/ruby/3.2.2/bin/irb:25:in `load' from /Users/roblacey/.asdf/installs/ruby/3.2.2/bin/irb:25:in `<main>'
So honestly, I am not sure how this even works with ERB templates in Rails. I need to take a further dig into the Rails source to find out more.
Anyone, Bueller?
UPDATE: Cheers @castwide seems so obvious now. erb templates aren't Ruby they are just converted/eval'ed into Ruby. So this makes sense if the first line is the comment has the comment delimited.
<%# frozen_string_literal: true %> <% puts "--#{__FILE__}" %> <% puts "A".object_id %> <% puts "A".object_id %> <% puts "A".object_id %> <% puts "A".object_id %>
require 'erb' => true irb(main):003> ERB.new(File.read('frozen.erb')).result(binding) --(erb) 27600 27600 27600 27600
Haml clearly doesn't work in the same way. As we can't just replicate it.
-# frozen_string_literal: true - puts "--#{__FILE__}" - puts "A".object_id - puts "A".object_id - puts "A".object_id - puts "A".object_id
require 'haml' => true irb(main):003> (Haml::Template.new() { File.read('frozen.haml') }).render --(__TEMPLATE__) 48000 48020 48040 48060
Top comments (2)
In ERB, the comment needs the code tags.
When rendered, it raises
FrozenError
:Seems so obvious now. Cheers.