How does Ruby dispatch methods when super is called? - ruby

I'm doing some research into the internals of how methods are called in some object-oriented languages for a hobby project. I have found information about normal dispatch is fairly easy to come by, but calling the "supermethod" of a class's method is a bit harder to understand.
By disassembling Objective-C I have found that the clang will insert references to a particular class, so that in general the superclass that is called by [super message] is fixed at compile time for typical method implementation. (What is Objective-C's msgSendSuper behavior?)
I was hoping to understand what the Ruby mechanism is, but didn't find anything searching. I had a glance at the source but couldn't find what I was looking for. Could somebody please explain the internals of Ruby method dispatch for super calls in the standard ruby-lang.org implementation?

Related

Understanding ".with" in Ruby

Sorry this is probably a question that has been asked many times but as it regards what is a very common word in English it is pretty much impossible to google or search for it.
I have seen a few examples of Ruby code which looks like this:
EnquiryNotification.with(post: #post)
I'm trying to understand what the ".with" part does. Can anyone shed some light on this please?
with is a class method defined on the EnquiryNotification class (or one of its ancestors). The method is neither a keyword in the Ruby language nor is it a common method on classes shipped with Ruby itself or its standard library. As such, to find what this method does, you would likely have to consult the documentation of your chosen framework or application.
An example of a with method defined in a framework is Sequel::Dataset#with to add a CTE to the current query. The method is also available as a class method in Sequel model classes.
It could also be part of ActionMailer as mentioned by Stefan in a comment above.
In any case though, make sure to consult the documentation of your chosen framework or library for details.

Why do we need 'private' methods in Ruby

Can someone give me a concrete example where a 'private' method would accomplish something that can't be done with a 'protected' method? In other words I am want to know why a language designer would put 'private' methods in Ruby.
It really depends on your development team and how your code is going to be used. In Ruby these tags are often suggestions more than hard and fast rules, there's ways to bypass private and protected methods if necessary, but they can serve as a strong hint to someone using your code that calling them is undesirable.
private is something that should be used sparingly as it can make life very difficult for those trying to subclass something. protected is usually sufficient, and helps steer external code to the methods that should be used.
There are occasions where private is necessary, that is you want to prevent subclasses from knowing too much about how the parent class works. This is more common in libraries where you encourage people to subclass but you also want to wall off some of the internal functions that aren't intended to be used by them. This allows you to refactor these methods later at will without breaking someone else's code.
One of the principles of good object-oriented design is controlling how much method exposure you have. Too much exposure means you're committed to making them behave identically now and in the future unless you're prepared to make breaking changes. Too little exposure means your class might be difficult to use, if not useless. Finding that balance is always tricky.
So private and protected exist for reasons, and it's largely the same reasons that C++, Java, PHP, Python and many others have these. It's to assert control over how and where your methods should be used.

cannot find method getExportedKeys( ) in Magento

I am using PHPStorm which is really a great search tool, and I'm searching from the root Magento folder (not just the app folder). I'm searching for:
function getExportedKeys
and even
function\s+getExportedKeys
using regexp. Where would this be, is this a native method or something?
Without any context, my best guess is that this is just using the inherited Varien_Object getter (i.e. __call()). Look for setExportedKeys() and you will probably find the source of the data.
This is a common pattern in Object Oriented Programming. By having all your objects of a particular type share a common ancestor, you can write methods that are shared across your entire code base.
One of the things Varien_Object provides is Magento’s famous “getter” and “setter” methods. These methods are implemented via PHP’s magic __call method. Since the customer object referenced above doesn’t have a setFirstName function, PHP calls Varien_Object’s __call method...

delegates in ruby explained from a Cocoa developer background

I really hope someone can answer this one. I think I am definitely not the only one confused about this and I wasn't able to find anything that clearly explains this concept.
My understanding of the delegation pattern comes from studying the Cocoa framework. To me, the Cocoa implementation is very clear. But I am having a very hard time understanding it in Ruby (standard library's Delegator, SimpleDelegator vs. ActiveSupport's Delegate). It makes little sense to me. Mostly because one is type safe the other is duck type. You can see my point already, but allow me to expand... Here is my summary of how to use the delegate pattern in Cocoa:
Our "ingredients" are: 2 classes, A and B and a protocol, which is Cocoa for a pre-defined set of methods to use for delegation.
The implementation of the pattern is basically as follows:
A defines the set of methods to delegate to B.
B's delegate is set to be A
=> B can now call delegated methods like so: #delegate.send(a_delegated_method)
What I am not tying together is the fact that Ruby uses duck typing, so you can send any method call to any object, right? So using the pattern I just explained, as long as the 2 objects are in the same domain you can say while in A #b.send(:a_delegated_method) and vice versa while in B #a.send(:another_delegated_method).
Could it be that the point with delegates in Ruby is where the delegated method is defined? Meaning that we send from within class A to property #b (#b(:delegated_method)) a :delegated_method defined within A itself?
Hope this isn't too confusing. I myself am confused about why delegates even exist in a duck typing language and what the differences are between Delegator, SimpleDelegator and ActiveSupport's Delegate.
It isn't clear to me that you have understood how delegation works in Cocoa. It is true that the common variety of the delegation pattern in Cocoa involves a protocol, but that's just a way of quieting the compiler.
So let's talk first about quieting the compiler. You can't send the woohoo message to an object in Objective-C unless one of two things is true:
The compiler has reason to believe that this object might respond to the woohoo message.
The compiler is made to suspend judgment.
Nowadays, the first approach is usually used - that's what a protocol is for. But this was not always the case. It used to be that delegation depended mostly on informal protocols. And there still are informal protocols in Cocoa. The idea is that either the method is injected into NSObject by a category, or else you are careful to type the object as id so that it can be sent any message at all.
Now let's talk about dynamism. The reason informal protocols are no longer used is that a feature was introduced allowing protocols to declare optional members. But dynamism is still needed! We may satisfy the compiler, one way or another, but at runtime we have to make sure that it is safe to send a certain message to a certain object. Your app delegate may adopt UIApplicationDelegate, but Cocoa is not going to send it the applicationDidBecomeActive: message unless your app delegate class implements applicationDidBecomeActive: - if it did, you'd crash, and that wouldn't be very nice.
Moreover, if you can just get past the compiler, you can perform delegation in Objective-C even more dynamically than that, as explained here:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html
The idea is that we go right ahead at runtime and send the object the message anyway! If a message arrives that Object A can't handle, it can see if Object B handles it. If it does, it passes the message along to Object B. So we might not crash after all!! I use that approach in one of my apps:
- (id)forwardingTargetForSelector:(SEL)aSelector {
if ([self.originalDataSource respondsToSelector: aSelector])
return self.originalDataSource;
return [super forwardingTargetForSelector:aSelector];
}
In that code, I'm saying that if a message arrives and I can't handle it, I should try to get it sent on to another object, called self.originalDataSource.
If you think about it, that is almost identical to Ruby delegation. I have a helper object, and messages that I can't handle are passed on to it.
Another common use of this pattern is when wrapping a Cocoa collection. You can't subclass, say, NSArray, because it's a class cluster, so the proper approach is to wrap it. You then just forward everything to the NSArray, and presto, you are duck-typed as an NSArray! You look like an NSArray as far as your methods are concerned. Then you introduce some difference in behavior, and now you are duck-typed as a customized NSArray.

Adopting "Growing Object-Oriented Software" techniques to Ruby on Rails

I read Growing Object-Oriented Software, Guided by Tests by Steve Freeman and Nat Pryce and was impressed very much. I want to adopt the ideas of this book in my Rails projects using RSpec, though its examples are written in Java.
A basic precept of this book is that we should mock interfaces instead of concrete classes. They say we can improve the application design by extracting interfaces and naming them.
But, Ruby doesn't have any syntax equivalent to Java's interface. How can I utilize their techniques for Rails projects?
UPDATE
For example, in the page 126 the authors introduced Auction interface in order to implement the bid method. Firstly, they mocked Auction.class to make the test pass, then they implemented an Auction class as anonymous inner class in the Main class. Finally, they extracted a new concrete class XMPPAuction from Main (page 131-132).
This incremental approach is the crux of this book in my opinion.
How can I adopt or imitate such a series of code transformation in the Ruby development?
Check out this previous Stack Overflow answer for a good explanation of interfaces in ruby.
Also, Practical Object-Oriented Design in Ruby is a book in similar vein as Growing Object Oriented Software book, but with ruby examples. Worth checking it out.
Since in Ruby, all things are duck-typed and the interface is simply the set of fields and methods that are publicly exposed you can do one or more of the following:
Test
Design your tests to test interfaces and name and comment your tests appropriately - then you can pass all of your "concrete implementations" of your "interface" through the same test suite. As long as your test suite covers your application's edge cases anything in your application that takes an instance of any of these concrete classes will be able to handle an instance of any of the other concrete classes.
Use base classes
Define a base class that all of your concrete classes will inherit from where all of the methods throw a NotImplemented error. This gives you a hierarchy that you can visualize - however, it does require extra classes and may encourage numerous is a tests in your production code rather than that code relying on has a.
You're right that Ruby does not have formal interfaces. Instead, interfaces are implicit in the messages that an object handles (see duck typing).
If you are still looking for a more formal way to "enforce" an interface in Ruby, consider writing a suite of automated unit tests that are green if an object conforms to the interface properly, and are red otherwise.
For examples, see ActiveModel::Lint::Tests and rspec's shared examples.

Resources