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