How do you test frozen_string_literal in Ruby?
Tags: ruby, rails, haml, erb
Published: 2023-12-13 23:11:22

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/](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.

```ruby
# frozen_string_literal: true
puts "--#{__FILE__}"
puts "A".object_id
puts "A".object_id
puts "A".object_id
puts "A".object_id
```

Here goes

```bash
% 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...

```bash
% 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.

```haml
# 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
```