When to declare a callback method Private or Protected in ROR? - ruby-on-rails

I was taking a look at some best practices in ROR, and I noticed that callback methods are declared in the protected section instead of the private. I've always used private when declaring callback methods, so I was wondering if it is better to use protected and why. Is there any substantial difference in this implementation?

private - only available to be accessed within the class that defines them.
protected - accessible in the class that defines them and in other classes which inherit from that class.

Related

The concept of private

Private is a access specifier. It means that anything say a instance private declared private cannot be accessed by methods of another class.
What is the point of being private if it can be changed by public methods.
Maybe it is because either because my book's poor explanation or my understanding problem that I just don't get what private is.
The book says that being private is a process of hiding the data and providing methods for data access. (Encapsulation)
Also, here is a example where a error would occur. But I have no idea what is it:
public class BankRobber
{
BandAccount momSavings =
new BankAccount (1000);
...
momSaving.balance = -1000;
}}
A
The point of "private" is not to make it impossible for other classes to access the member, but to make it impossible for other classes to access the member except in ways that are allowed by the public (or protected) methods.

Calling private method in ApplicationController?

I am confused on how this library works:
The ApplicationController has a private method called selected_account() as you can see here: ApplicationController
Then, from another Controller which is a child from ApplicationController, we do an action that does this:
def index()
#selected_account = selected_account
graph = get_accounts_graph()
#accounts = Account.get_accounts_map(graph)
end
How can we do that? Isn't it out of scope?
This will be confusing for those who come from java or c# world. But here is a decent explanation
In Ruby, the inheritance hierarchy or the package/module don't really
enter into the equation, it is rather all about which object is the
receiver of a particular method call. When a method is declared
private in Ruby, it means this method can never be called with an
explicit receiver. Any time we're able to call a private method with
an implicit receiver it will always succeed. This means we can call a
private method from within a class it is declared in as well as all
subclasses of this class
It might be confusing at first, but in Ruby private does not mean what it means in Java/C++. Ancestors can call private methods just fine.
What private actually means is that you cannot call the method with an explicit target. That is, if foo is private, you can call it with foo(), but not with self.foo() or obj.foo(). That way you can call private methods only on yourself.
Furthermore, Ruby has protected. The semantics are again different from Java/C++ – protected methods can only be called from instances of the same class. It is rarely used.
The child controller inherits from ApplicationController so it can call internal private methods on itself without issue. There is no scoping problem. The subclass inherits all the public/private/protected methods of its super class.

Why can private helper methods still be accessed in views?

Just another "why is it that way" question: I noticed that private helper methods still can be accessed within views. Why's that? And is there a way to prevent this (e.g. when having helper methods that should only be called from within another helper)?
Helpers are modules that get mixed in to the views. This means that public, protected and private methods in the helper become public, protected and private methods on the views.
I don't think that you can actually hide the helper methods from the view. You'd need to do something like have a helper class which you instantiate in the helper and then delegate calls to that - sounds like it could get messy fast though. :)

access control tripping me up

ok, i'm about at that point in my ruby career where this should be tripping me up.
I have a model called distribution.rb where I have the follwoing protected method:
def update_email_sent_on_date
if self.send_to_changed?
self.date_email_delivered = DateTime.now
end
end
I then call this method from my controller:
distribution.update_email_sent_on_date
however, I'm getting this error:
NoMethodError (protected method `update_email_sent_on_date' called for #<EmailDistribution:0x131a1be90>):
the distribution object is indeed an EmailDistribution (a subclass of distribution where the method is defined). I thought this would work. In any case, I also tried moving the method to the subclass EmailDistribution but no luck. Same error message.
I'd also like to step back and say that what I'm trying to do overall is store the timestamp of when another field in the distribution model is updated. If there's a simpler way, please enlighten me.
I think you're getting tripped up because you are using the protected declaration when you actually want the private declaration.
The protected term in ruby acts differently in other conventional languages.
In Ruby, private visibility is what protected was in Java. Private methods in Ruby are accessible from children. This is a sensible design, since in Java, when method was private, it rendered it useless for children classes: making it a rule, that all methods should be "protected" by default, and never private. However, you can't have truly private methods in Ruby; you can't completely hide a method.
The difference between protected and private is subtle. If a method is protected, it may be called by any instance of the defining class or its subclasses. If a method is private, it may be called only within the context of the calling object---it is never possible to access another object instance's private methods directly, even if the object is of the same class as the caller. For protected methods, they are accessible from objects of the same class (or children).
This is a slightly clearer explanation IMHO, from the book Eloquent Ruby by Russ Olsen:
Note that in Ruby, private methods are callable from subclasses. Think about it: You don't need an explicit object reference to call a superclass method from a subclass.
The rules for protected methods are looser and a bit more complex: Any instance of a class can call a protected method on any other instance of the class.
Lastly, it's good to note that in ruby you can always call private or protected methods regardless of whether they are accessible by using the send method. So if you were in a pinch and just needed to work you could just call it like this and then worry about the private/protected declarations later:
distribution.send(:update_email_sent_on_date)
Read this for more a better explanation..

Long method and testing private methods - design problem

I have a quite long method. It copy an ActiveRecord object with all relations, and changes relations in some cases. To make code more readable, I use private methods. I would like to test them. Technicaly, in Ruby it is no problem, but I suspect, I have bad design. Do you have any advices how to deal with such case?
One school of thought is that each and every private method that matters should be tested implicitly by testing a class's public interface. If a private method didn't get called through the public interface, it is redundant. If your private method is that complex to require its own tests, you should consider putting it in a class of its own and test that class.
In short, it shouldn't be necesary to explicitly test your private methods.
as the saying go's: "Don't touch your privates."

Resources