Passing default arguments


Have you ever needed to set a default for an argument when defining a class?

Say we have a Product class that has a Category.

  class Category
    attr_reader :name
    def initialize(name: "General")
      @name = name
    end
  end

  class Product
    attr_reader :name, :category
    def initialize(name: , category: )
      @name     = name
      @category = category
    end
  end
  # => "General"

The category can be passed in as an argument on the initialize method or be set to the default category if it doesn't.

A first approach to this would be to pass nil in and decide what to actually assign inside of the method:

  class Product
    attr_reader :name, :category
    def initialize(name: , category: nil)
      @name     = name
      @category = category || Category.new
    end
  end

  product = Product.new(name: "milk")

  product.category.name
  # => "General"

But there's a more elegant way to achieve the same result. Instead of asking if we got a category and then deciding what to use, we can pass in the default value directly on the arguments list. After that, we know that the category argument will have the right default out of the box

  class Product
    attr_reader :name, :category
    def initialize(name: , category: Category.new)
      @name     = name
      @category = category
    end
  end

  product = Product.new(name: "milk")

  product.category.name
  # => "General"

This makes the code shorter and easier to read (IMO).

It also makes it safer, since we're now relying on Ruby to provide us with the right thing instead of writing the logic ourselves.

The next time you need a default, give it a try!