Make Delegated Methods Private in Rails

07 Feb 2019

Recently,
I came across some of my old code
that uses Rails’
delegate method.
Take a look at the following example,
where I’m delegating a couple of methods
to an instance variable,
but want to make them private.

As you can see,
we can call both the delegated methods.
They were supposed to be private!
What happened here?

The problem is that
putting delegate under the private scope
has no effect.
Methods in Ruby
have no way of knowing
that the private visibility scope is set
when they are called from within a class.delegate uses module_eval to define
new methods with these names,
but it doesn’t know
that it must make these methods private.

So what do we do
if we wish to delegate a method
without making it a part of the class’ public interface?
Let’s dig into how delegate works.
In cases like this,
I like to use the
pry console
to interactively inspect the behavior of the class.

pry>cdUserDecorator# This pry command puts us within the scope of the UserDecorator class.pry>delegate:first_name,:last_name,to: :@user#=> [:first_name, :last_name]pry>instance_methods#=> [:full_name, :last_name, :first_name]pry>private:first_name,:last_namepry>instance_methods#=> [:full_name]

delegate returns the list of the delegated method names.
We can call private with the method names
to make them private.
This means we can explicitly make the methods private like this:

Links

Hi, I’m Nithin Bekal.
I work at Shopify in Ottawa, Canada.
Previously, co-founder of
CrowdStudio.in and
WowMakers.
Ruby is my preferred programming language,
and the topic of most of my articles here,
but I'm also a big fan of Elixir.
Tweet to me at @nithinbekal.