I’ve seen so many examples of people being self-centered in their code, always calling their methods on self when they don’t need to!

self is a handy reference to the current object (or class) depending on how the method is defined. In a class that inherits from ActiveRecord for example, calling self before defining a method will define that method on that class, rather than the objects of that class. Once inside of the method, you are free to go about as you will; Ruby will know what you mean when you call other methods inside that method.

A prime example would be this self-centered piece of code:

class Forum < ActiveRecord::Base
  acts_as_tree
  
  def to_s
    self.title
  end
  
  def self.find_all_without_parent
    self.find_all_by_parent_id(nil)
  end
  
  def root
    self.parent.nil? ? self : self.parent
  end
  
end

These are a few methods with both good and bad examples of using self.

We’ll start with #to_s. This method is defined by typing def to_s, which tells ruby we want to define a method called “to_s” on all objects of the Forum class. Inside the method however, we have a bad-case of self-centering, by calling self where it’s not needed. Ruby already knows that we’re operating with an object derived from the forum class, and calling self will only return the same object! So why do we do it here? We can remove the superfluous self call, and the method will still work.

Our next method is self.find_all_without_parent. The self. prefix to the method tells Ruby that we want to define this method on the Forum class itself, rather than a derived object from the class. Inside the method again we have a bad case of self-centering! Ruby already knows we’re operating with the Forum class, and calling self will only return the Forum class once more. Again we can remove the superfluous self call and the method will still work.

In both of these examples, you could’ve called self on self and then the method multiple times: self.self.title or even self.self.self.self.self.title, but that’s just going a bit overboard!

In the last method is two incorrect usages of self, and one correct use of self. The method is #root. The method defines a one-lined if statement by calling a method (self.parent.nil?) which will return either true or false. The next character is a space followed by a ?, which indicates to ruby anything after this is what we want executed when self.parent.nil? returns true. Here we just call self, and this is the good use of self. The #root method is attempting to find the root element for the tree heirachy of the forums, if the forum object we’re calling root does not have a parent, we want it to return itself as it is the highest level of the forum structure. The next character in the code is a colon (:), which tells Ruby what we want to do if self.parent.nil? returns false. Here we’ve called self.parent, which again is a superflous call to the self object. We only need to call parent because Ruby already knows which context we are referring to! The final superfluous self call is the self.parent.nil? from where our one-lined if statement originated.

I hope you’ve enjoyed this little tidbit, and please stop being so self-centered.

UPDATE: RSL has posted an easier way than parent.nil? ? self : parent as the first comment. The code is now simply:

def root
  parent || self
end

UPDATE #2: The root method was still broken as I realised this morning as I tampered with the tests. The method is supposed to get the highest forum in a string of forums. This works perfectly for 2-level-deep forums, but not for 3-level-deep. The third-level element would’ve returned the second-level element rather than the first. The revised code is now:

  def root
    parent.nil? ? self : (parent.root == parent ? parent : parent.root)
  end