Code Comments

Ruby has two types of comments: inline and block.

Inline comments start with the # character and continue until the end of the line:

# On a separate line
class Foo # or at the end of the line
  # can be indented
  def bar
  end
end

Block comments start with =begin and end with =end. Each should start on a separate line.

=begin
This is
commented out
=end

class Foo
end

=begin some_tag
this works, too
=end

=begin and =end can not be indented, so this is a syntax error:

class Foo
  =begin
  Will not work
  =end
end

Magic Comments

While comments are typically ignored by Ruby, special “magic comments” contain directives that affect how the code is interpreted.

Top-level magic comments must appear in the first comment section of a file.

NOTE: Magic comments affect only the file in which they appear; other files are unaffected.

# frozen_string_literal: true

var = 'hello'
var.frozen? # => true

Alternative syntax

Magic comments may consist of a single directive (as in the example above). Alternatively, multiple directives may appear on the same line if separated by “;” and wrapped between “-*-” (see Emacs’ file variables).

# emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*-

p 'hello'.frozen? # => true
p 'hello'.encoding # => #<Encoding:Big5>

encoding Directive

Indicates which string encoding should be used for string literals, regexp literals and __ENCODING__:

# encoding: big5

''.encoding # => #<Encoding:Big5>

Default encoding is UTF-8.

Top-level magic comments must start on the first line, or on the second line if the first line looks like #! shebang line.

The word “coding” may be used instead of “encoding”.

frozen_string_literal Directive

Indicates that string literals should be allocated once at parse time and frozen.

# frozen_string_literal: true

3.times do
  p 'hello'.object_id # => prints same number
end
p 'world'.frozen? # => true

The default is false; this can be changed with --enable=frozen-string-literal. Without the directive, or with # frozen_string_literal: false, the example above would print 3 different numbers and “false”.

Starting in Ruby 3.0, string literals that are dynamic are not frozen nor reused:

# frozen_string_literal: true

p "Addition: #{2 + 2}".frozen? # => false

It must appear in the first comment section of a file.

warn_indent Directive

This directive can turn on detection of bad indentation for statements that follow it:

def foo
  end # => no warning

# warn_indent: true
def bar
  end # => warning: mismatched indentations at 'end' with 'def' at 6

Another way to get these warnings to show is by running Ruby with warnings (ruby -w). Using a directive to set this false will prevent these warnings to show.

shareable_constant_value Directive

Note: This directive is experimental in Ruby 3.0 and may change in future releases.

This special directive helps to create constants that hold only immutable objects, or Ractor-shareable constants.

The directive can specify special treatment for values assigned to constants:

Mode none (default)

No special treatment in this mode (as in Ruby 2.x): no automatic freezing and no checks.

It has always been a good idea to deep-freeze constants; Ractor makes this an even better idea as only the main ractor can access non-shareable constants:

# shareable_constant_value: none
A = {foo: []}
A.frozen? # => false
Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.

Mode literal

In “literal” mode, constants assigned to literals will be deeply-frozen:

# shareable_constant_value: literal
X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze

Other values must be shareable:

# shareable_constant_value: literal
X = Object.new # => cannot assign unshareable object to X

Note that only literals directly assigned to constants, or recursively held in such literals will be frozen:

# shareable_constant_value: literal
var = [{foo: []}]
var.frozen? # => false (assignment was made to local variable)
X = var # => cannot assign unshareable object to X

X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X
                                # (`Set[...]` is not a literal and
                                # `{foo: []}` is an argument to `Set.[]`)

The method Module#const_set is not affected.

Mode experimental_everything

In this mode, all values assigned to constants are made shareable.

# shareable_constant_value: experimental_everything
FOO = Set[1, 2, {foo: []}]
# same as FOO = Ractor.make_shareable(...)
# OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze`

var = [{foo: []}]
var.frozen? # => false (assignment was made to local variable)
X = var # => calls `Ractor.make_shareable(var)`
var.frozen? # => true

This mode is “experimental”, because it might be error prone, for example by deep-freezing the constants of an external resource which could cause errors:

# shareable_constant_value: experimental_everything
FOO = SomeGem::Something::FOO
# => deep freezes the gem's constant!

This will be revisited before Ruby 3.1 to either allow everything or to instead remove this mode.

The method Module#const_set is not affected.

Mode experimental_copy

In this mode, all values assigned to constants are deeply copied and made shareable. It is safer mode than experimental_everything.

# shareable_constant_value: experimental_copy
var = [{foo: []}]
var.frozen? # => false (assignment was made to local variable)
X = var # => calls `Ractor.make_shareable(var, copy: true)`
var.frozen? # => false
Ractor.shareable?(X) #=> true
var.object_id == X.object_id #=> false

This mode is “experimental” and has not been discussed thoroughly. This will be revisited before Ruby 3.1 to either allow copy or to instead remove this mode.

The method Module#const_set is not affected.

Scope

This directive can be used multiple times in the same file:

# shareable_constant_value: none
A = {foo: []}
A.frozen? # => false
Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.

# shareable_constant_value: literal
B = {foo: []}
B.frozen? # => true
B[:foo].frozen? # => true

C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError)

D = [Object.new.freeze]
D.frozen? # => true

# shareable_constant_value: experimental_everything
E = Set[1, 2, Object.new]
E.frozen? # => true
E.all(&:frozen?) # => true

The directive affects only subsequent constants and only for the current scope:

module Mod
  # shareable_constant_value: literal
  A = [1, 2, 3]
  module Sub
    B = [4, 5]
  end
end

C = [4, 5]

module Mod
  D = [6]
end
p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true
p C.frozen?, Mod::D.frozen? # => false, false