Basic solutions
Let's assume that we are using class Foo that has one public method and one private method:
class Foo
def bar
:awesome
end
private
def baz
:something_private
end
end
Everything is great, we see such a solution in virtually every project. Running Foo.new.baz
will cause the error NoMethodError (private method 'baz' called for # <Foo: 0x00007f884b1b3b88>) and that's what we meant to do. What happens if we try to change the save format and add private as a prefix in the class definition?
class Foo
def bar
:awesome
end
private def baz
:something_private
end
end
As you can see after running the code, it actually works! Why can we enter the visibility of the method before doing it? Because when defining a method, def returns the name of the method as a symbol. This expression is not only a part of the syntax, but de facto a method derived from the Module class and treating this symbol as an argument. For more information, please see the documentation in this link. Since it started so easy with private, let's try to change the visibility of the private method.
class Foo
def bar
:awesome
end
private def baz
:something_private
end
public :baz
end
What will happen after running the code?
irb(main):012:0> Foo.new.baz
=> :something_private
Success! Our method of bases became public because we made it visible twice. Of course, the same operation applies to the modules.
Great, but where does it get us?
This functionality gives us a lot because we can freely change the visibility of a method while defining it, or even change the visibility of methods when inheriting them.
Now, let's take a look at what Ruby 2.7 can do in terms of changing the visibility of aliases and accessors.
class Foo
private attr_accessor :awesome_variable
end
Unfortunately, we get an error as the private method expects symbols and attr_accessor. The code returns nil and thus this method is not compatible with the private use in Ruby 2.7. So what are our options?
- We can use attr_accessor under the private keyword to make it work, i.e. we will get an error when we want to refer to the
awesome_variableawesome_variable
method.
class Foo
private
attr_accessor :awesome_variable
end
- The second option is to execute the private method on methods generated by
attr_attribute
; in this case, we also have to remember to enter the setter there.
class Foo
attr_accessor :awesome_variable
private :awesome_variable, :awesome_variable=
end
Problems with the attr_ *
methods are not the only obstacles. We can encounter the same difficulty when we want to create a private alias.
class Foo
private alias :bar, :awesome_bar
end
Ruby 3.0 and our business
Fortunately, Ruby 3.0 introduces a great change as the visibility methods can take array as an argument and methods alias, attr_ *, can reset the array with the names of the methods that have been defined. You can read more here.
Now, let's see some examples in the latest euba and check if the changes have actually been made and how we can use them.
In the first example, let’s use private before attr accessor:
class Foo
private attr_accessor :awesome_variable
end
Such a call will not cause errors in parsing the syntax and, what is important, the awesome_variable
andawesome_variable =
methods become private.
The alias method will do the same as now it also returns a symbol as the name of the new method and makes it visible.
class Foo
private alias :bar, :awesome_bar
end
An interesting fact is that we can also delve into further methods, e.g. the awesome_print module can be called between private and attr_reader; it is important that such a method returns an array with the names of the methods that are on the right side of the expression.
class Module
def awesome_print(names)
puts names
names
end
end
class Foo
private awesome_print attr_reader :awesome_bar
end
Summary
Hope you will find this article useful! In case of more news about Ruby 3.0. read more here.
Happy coding!

Read more:
Shut up and take your money #1: Hidden costs and real agility in product development process
CTO challenges – scale-up and growth of software products