How to Fix Frozen String Literal Error
Since version 2.3 Ruby has ability to freeze string literals. Mike Perham has good explanation about how string in Ruby works. Based on his benchmark frozen_string_literal reduces the generated garbage by ~100MB or ~20%.
# mutable string example
mystring = ""
mystring << "hello!" # => mystring variable is mutated to contain "hello!"
# garbage string example
MYCONSTANT= {
"my_key": 123
}
def get_key
MYCONSTANT["my_key"] # => unnecessary garbage
end
Every get_key is called, it will allocate new copy of “my_key”, which is then immediately thrown away as garbage.
Freeze method
Ruby has freeze method to minimize string allocation and treat it as immutable.
def get_key
MYCONSTANT["my_key".freeze]
end
Using the following comment at the top of file by default will make string freeze by default within that file.
# frozen_string_literal: true
# your code goes here
frozen_string_literal one of easiest way to optimize Ruby application, but sometimes it raises error if your old code is not compatible.
How to Fix frozen_string_literal Error
Use String Interpolation
# frozen_string_literal: true
# error
def my_method(post)
example_regex = /example_regex/
"My Method: " << post.to_s.gsub(example_regex, "\\1.")
end
# frozen_string_literal: true
# ok
def my_method(post)
example_regex = /example_regex/
"My Method: #{post.to_s.gsub(example_regex, '\\1.')}"
end
Use join Method
# frozen_string_literal: true
# error
def post_list(posts)
post_list = ""
posts.each do |post|
post_list << "id: #{post.id}\n"
end
post_list
end
# frozen_string_literal: true
# ok
def post_list(posts)
price_list = []
posts.each do |post|
post_list << "id: #{post.id}"
end
post_list.join "\n"
end