Photo by Elias Castillo on Unsplash
Luke is a guest author for ZEAL. We were lucky enough to have Luke intern with us when he was graduating from LEARN academy. Luke is now a developer at Bitwerx, a consultancy based out of Kentucky. At the moment, we are working together on a project for our longtime client PetIQ.
A good refactor results in cleaner, more readable, and often less code. Recently I saw an opportunity to refactor a complex api pattern in a Ruby on Rails application. Unsure of the correct solution and after multiple iterations, I landed on using a Ruby fundamental keyword, super.
Way back in my bootcamp days, `super` was taught as a fundamental building block of object oriented coding languages. The use of `super` in ruby directly relates to how object inheritance works.
According to ruby-docs.org, `super`, when “called from a method, searches along the method lookup path (the classes and modules available to the current object) for the next method of the same name as the one being executed.”
Let’s take this simple, overused example:
-- CODE language-ruby --class Animal
def hello
puts 'I am an animal.'
end
end
class Dog < Animal
def hello
super
puts 'woof!'
end
end
-- CODE language-ruby --dog = Dog.new
Dog.hello
→ 'I am an animal.'
In this example, Class Dog is a child of Class Animal and inherits its methods. By overwriting the method `hello` and calling super within it, the Dog class will then look for a method called `hello` in it’s parent class and call it. This code is too simple to see the full power of `super` so let’s extend this example out a bit. We’ll start with the same two classes, Animal and Dog, but add another called Cat. How original! We’ll need to add an API fetch to retrieve the hello string.
Without Super:
-- CODE language-ruby --class Animal
def hello
puts 'I am an animal.'
end
end
-- CODE language-ruby --class Dog < Animal
def hello
puts animals.hello
end
def animals
# api call that returns:
{
"data": {
"animals": {
"dog":
{
"hello": 'woof',
},
"cat":
{
"hello": 'meow',
}
}
}
}.data.animals.dog
end
end
-- CODE language-ruby --class Cat < Animal
def hello
puts animals.hello
end
def animals
# api call that returns:
{
"data": {
"animals": {
"dog":
{
"hello": 'woof',
},
"cat":
{
"hello": 'meow',
}
}
}
}.data.animals.cat
end
end
Here we have a lot of duplicated code that can easily be refactored using the super keyword.
With Super:
-- CODE language-ruby --class Animal
def hello
puts "I am an animal."
end
def animals
# api call that returns:
{
"data": {
"animals": {
"dog":
{
"hello": 'woof',
},
"cat":
{
"hello": 'meow',
}
}
}
}.data.animals
end
end
The first step is to pull the api call into the Animal class. From there, we can access it via super in the child classes.
-- CODE language-ruby --class Dog < Animal
def hello
super
puts animals.hello
end
def animals
super.dog
end
end
-- CODE language-ruby --class Cat < Animal
def hello
super
puts animals.hello
end
def animals
super.cat
end
end
Next we use super to return the data in Animal’s animals method.
-- CODE language-ruby --cat = Cat.new
cat.hello
→ "I am an animal."
→ "meow"
dog = Dog.new
dog.hello
→ "I am an animal."
→ "woof"
There we have it!
In these examples, we used class inheritance to move an api call and response to a shared parent class and dynamically parsed the data using ‘super’.
That’s it! `Super` is a simple yet effective solution to reduce and refactor code.
More info on super can be found here.
Are you ready to build something brilliant? We're ready to help.