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!