What is the most efficient way to initialize a Class in Ruby with different parameters and default values?

41,340

Solution 1

The typical way to solve this problem is with a hash that has a default value. Ruby has a nice syntax for passing hash values, if the hash is the last parameter to a method.

class Fruit
  attr_accessor :color, :type

  def initialize(params = {})
    @color = params.fetch(:color, 'green')
    @type = params.fetch(:type, 'pear')
  end

  def to_s
    "#{color} #{type}"
  end
end

puts(Fruit.new)                                    # prints: green pear
puts(Fruit.new(:color => 'red', :type => 'grape')) # prints: red grape
puts(Fruit.new(:type => 'pomegranate')) # prints: green pomegranate

A good overview is here: http://deepfall.blogspot.com/2008/08/named-parameters-in-ruby.html

Solution 2

Since Ruby 2.0 there is support of named or keyword parameters.

You may use:

class Fruit
  attr_reader      :color, :type

  def initialize(color: 'green', type: 'pear')
    @color = color
    @type = type
  end

  def to_s
    "#{color} #{type}"
  end
end

puts(Fruit.new)                                    # prints: green pear
puts(Fruit.new(:color => 'red', :type => 'grape')) # prints: red grape
puts(Fruit.new(:type => 'pomegranate')) # prints: green pomegranate

Some interesting notes on this topic:

Solution 3

I'd do it like this:

class Fruit
  attr_accessor :color, :type

  def initialize(args={})
    options = {:color => 'green', :type => 'pear'}.merge(args)

    self.color = options[:color]
    self.type  = options[:type]
  end
end

apple = Fruit.new(:color => 'red', :type => 'apple')

This way, you never have to worry about missing arguments--or their order--and you'll always have your default values right there. .merge will of course overwrite the default values if they're present.

Solution 4

I like vonconrad's answer but would have a separate defaults method. Maybe it's not efficient in terms of lines of code, but it's more intention-revealing and involves less cognitive overhead, and less cognitive overhead means more efficient dev onboarding.

class Fruit
  attr_accessor :color, :type

  def initialize(args={})
    options = defaults.merge(args)

    @color = options.fetch(:color)
    @type  = options.fetch(:type)
  end

  def defaults
    {
      color: 'green',
      type:  'pear'
    }
  end
end

apple = Fruit.new(:color => 'red', :type => 'apple')

Solution 5

More simple way:

class Fruit
  attr_accessor :color, :type
  def initialize(color = 'green', type = 'pear')
    @color = color
    @type = type
  end
  def to_s
    "#{color} #{type}"
  end
end


puts Fruit.new # prints: green pear
puts Fruit.new('red','apple') # prints: red apple
puts Fruit.new(nil,'pomegranate') # prints: green pomegranate
Share:
41,340
Istvan
Author by

Istvan

Hands On Data & Cloud Architect with Leadership Experience. Things I care about: Systems Engineering Data Engineering Machine Learning Functional Programming

Updated on July 22, 2020

Comments

  • Istvan
    Istvan almost 4 years

    I would like to have a class and some attributes which you can either set during initialization or use its default value.

    class Fruit
      attr_accessor :color, :type
      def initialize(color, type)
        @color=color ||= 'green'
        @type=type ||='pear'
      end
    end
    
    apple=Fruit.new(red, apple)
    
  • Brian Clapper
    Brian Clapper over 13 years
    Yes, except this approach requires that you pass the parameters in order. With the hash approach, you must specify the parameter name (i.e., the hash key), but you can pass those keys in any order.
  • Hoang Le
    Hoang Le almost 9 years
    I like this solution the most among the others. The reason is we won't need to create any further significant objects (imagine a big class instance for example) in case the params already has those options. But I also would like to use even cleaner syntax (just my opinion) like this: @color = params[:color] || 'green'
  • WestCoastProjects
    WestCoastProjects over 4 years
    I'm going to have an opportunity to do a little ruby/jruby! After 7 years!
  • aceofbassgreg
    aceofbassgreg over 3 years
    To be clear, this is by far the best answer here, though as knut said kwargs weren't available until Ruby 2.0.
  • Patrick Barattin
    Patrick Barattin over 2 years
    This doesn’t allow you to set default values.