DEV Community

Jess Lee
Jess Lee Subscriber

Posted on

Explain the 'super' keyword in ruby like I'm five

Latest comments (8)

Collapse
 
imrawal profile image
Mee Lana • Edited

Is it good or bad to chain method in super like in below activerecord(5.1.6) code,

# 'delivery_timings' is a db field attribute
class Country < ApplicationRecord
  # expects array of times and converts to string ie. ['08:00-12:00', '14:00-16:00'] to "08:00-12:00,14:00-16:00"
  def delivery_timings=(val)
    return super(val) if val.blank?

    super(val.reject(&:blank?).join(','))
  end

  # converts string value to array of times ie. "08:00-12:00,14:00-16:00" to ['08:00-12:00', '14:00-16:00']
  def delivery_timings
    return super if super.blank?

    super.split(',')
  end
end

Although the code works, I'm smelling on code(may be wrong).

Collapse
 
cathodion profile image
Dustin King • Edited

When you inherit from a parent class, sometimes you want the child's method to behave slightly differently but still use the parent method's behavior.

Let's say you have a Greeter, and their job is to say hi to everyone they meet. If they have the person's name, they'll greet them by name.

class Greeter
  def greet(name=nil)
    if name
      puts "Hi, #{name}, nice to meet you!"
    else
      puts "Hi, nice to meet you!"
    end
  end
end

Greeter.new.greet
#=> Hi, nice to meet you!

Greeter.new.greet 'Jess'
#=> Hi, Jess, nice to meet you!
Enter fullscreen mode Exit fullscreen mode

Now suppose we hire a new greeter from the planet Marklar, who has a religious belief that everyone's name is Marklar. When their greet method calls super, it calls the greet method from their parent class, Greeter:

class MarklarGreeter < Greeter
  def greet
    super 'Marklar'
  end
end

MarklarGreeter.new.greet
#=> Hi, Marklar, nice to meet you

MarklarGreeter.new.greet 'Jess'
#=> ArgumentError: wrong number of arguments (given 1, expected 0)
Enter fullscreen mode Exit fullscreen mode

Okay, we still need greet to take a name parameter, so that we can use a MarklarGreeter anywhere we use a Greeter. This is called the Liskov Substitution Principle. I can't find a link that explains that like you're five, but it basically says an instance of a child class should be usable anywhere you can use an instance of the parent class.

class MarklarGreeter < Greeter
  def greet(name=nil)
    # We accept a name parameter here, but we ignore it
    # because everyone's name is Marklar
    super 'Marklar'
  end
end

MarklarGreeter.new.greet
#=> Hi, Marklar, nice to meet you!

MarklarGreeter.new.greet 'Jess'
#=> Hi, Marklar, nice to meet you!
Enter fullscreen mode Exit fullscreen mode

More info about Ruby's super here.

Collapse
 
johand profile image
Johan • Edited

With super you can call a method on the parent class with the same name in the child class, for example:

class Foo
  def my_method
    'Hello there'
  end
end

class Bar < Foo
  def my_method
    super
  end
end

b = Bar.new
b.my_method

# => Hello there
Enter fullscreen mode Exit fullscreen mode

Ruby search a method #my_method in the ancestor chain, if the method not exist it will show an error NoMethodError

`my_method': super: no superclass method `my_method' for #<Bar:0x0000564740b32170> (NoMethodError)
Enter fullscreen mode Exit fullscreen mode
Collapse
 
edizle585 profile image
Elijah Logan

So lets say your mom makes super smacking pb &j's using her super smacking pb & j technique (all she does is remove the crust). But today mom had to hurry to work so brother B is making breakfast. Your not sure if b can make pb & j's like mom but he assures you that he's used ( super ) to get moms skill passed down to him so he's qualified. Using super B made you some super smacking pb & j's

class Mom-PB-Technique
def corner-cut(bread)
for corner in bread
corner.cut crust
return bread
end

class B-PB-Technique < Mom-PB-Technique
def corner-cut
super
end

Collapse
 
cathodion profile image
Dustin King • Edited

Doesn't doing B-PB-Technique < Mom-PB-Tecnhnique already give you all of mom's methods?

Collapse
 
zspencer profile image
Zee

Yes, it does. super is most useful when over-riding the behavior from a method provided in the ancestor chain. I would revise the example to the following:

class MomPBTechnique
  def corner_cut(bread)
    for corner in bread
      corner.cut crust
    end
    return bread
  end

class MyPBTechnique < MomPBTechnique
  # I like *one* corner to not be cut!
  def corner_cut
    first_corner = self.bread[0] # Gets the first corner
    self.bread = bread.slice(1, -1) # Sets the bread to only the last 3 corners
    super # Calls the `corner_cut` method defined in `MomPBTechnique`
    return bread.unshift(first_corner) # Places the un-cut first corner back in the bread
  end
end

This more clearly demonstrates how super can be used to re-use-but-still-change behavior in the class hierarchy.

Collapse
 
martin profile image
Martin Beentjes

super is your parent.

Collapse
 
chenge profile image
chenge

IMHO, super is alias of father or mother.