Private methods are a great way to restrict what methods of a class can be invoked from the outside. These provide a great degree of control when designing classes.
One common pattern we like to follow is to make every other method except perform as private in our service classes.
Example service class:
class UserNotificationService
def initialize(user:)
@user = user
end
def perform
send_text_notification
send_email_notification
end
private
attr_reader :user
def send_text_notification
# Service to send text notification
end
def send_email_notification
# Service to send email notification
end
end
Note, all methods other than perform including the attr_reader are private as we don’t plan to access them outside this class.
Until now there was no convenient way of making methods created using the delegate to syntax as private.
Consider the goal of creating a service with only one public method(perform), you would expect the following code to do the trick but it does not work:
class UserNotificationService
# ...
def perform
# ...
end
# ...
private
delegate :name, :email, :ssn, to: :user
# ...
end
The only option you had was to use the following syntax which is not the most elegant and conventional:
class UserNotificationService
# ...
def perform
# ...
end
# ...
private *delegate(:name, :email, :ssn, to: :user)
# ...
end
Rails 6 adds option to pass private: true
to delegate.
Now,
we can achieve our above goal using the following:
class UserNotificationService
# ...
def perform
# ...
end
# ...
delegate :name, :email, :ssn, to: :user, private: true
# ...
end
This change is backwards compatible and your code with private *delegate...
will still work.
Note: protected option is not supported yet, there is a plan to add that in the future.