58

I have a class

class Person
    attr_accessor :name,:age
    def initialize(name,age)
        @name = name
        @age = age
    end
end

I'd like to make the age optional so its 0 if its not passed, or the name to be blank if not passed

Ive researched a bit on it but its a bit confusing as to what i've found (having to pass variables in another variable { }).

Tarang
  • 75,157
  • 39
  • 215
  • 276

4 Answers4

120

It's as simple as this:

class Person
    attr_accessor :name, :age

    def initialize(name = '', age = 0)
        self.name = name
        self.age = age
    end
end


Person.new('Ivan', 20)
Person.new('Ivan')

However, if you want to pass only age, the call would look pretty ugly, because you have to supply blank string for name anyway:

Person.new('', 20)

To avoid this, there's an idiomatic way in Ruby world: options parameter.

class Person
    attr_accessor :name, :age

    def initialize(options = {})
        self.name = options[:name] || ''
        self.age = options[:age] || 0
    end
end

Person.new(name: 'Ivan', age: 20)
Person.new(age: 20)
Person.new(name: 'Ivan')

You can put some required parameters first, and shove all the optional ones into options.

Edit

It seems that Ruby 2.0 will support real named arguments.

def example(foo: 0, bar: 1, grill: "pork chops")
  puts "foo is #{foo}, bar is #{bar}, and grill is #{grill}"
end

# Note that -foo is omitted and -grill precedes -bar
example(grill: "lamb kebab", bar: 3.14)
Sergio Tulentsev
  • 226,338
  • 43
  • 373
  • 367
  • Note that an argument can't be optional if it's followed by a required argument, or to put it another way: all the optional arguments have to be after the required arguments – Gareth Mar 14 '12 at 21:11
  • Ah i see, the latter is what ive been looking it but you explain it perfectly well and its no longer confusing!! – Tarang Mar 14 '12 at 21:17
  • 2
    Named arguments are allowed only with ruby 2.0 and RubyMotion projects !! ;] Not only ruby 2.0 – mArtinko5MB Feb 17 '14 at 08:49
  • ```Person.new(name: 'Ivan', age: 20)``` the argument needs to be an object like => ```Person.new({name: 'Ivan', age: 20})``` – Neha Saggam Feb 26 '19 at 11:14
  • @NehaSaggam: no, it doesn't. Works either way. – Sergio Tulentsev Feb 26 '19 at 14:21
9

If you want both arguments to be optional but also set default values when nil then you could go with:

class Person

def initialize(name = nil, age = 0)
  @name ||= "Default name"
  @age = age
end

end

This gets over the issue of passing nil as the first option but still getting a useable default value.

@person = Person.new nil, 30
@person.name # => "Default name"
@person.age # => 30
bodacious
  • 6,608
  • 9
  • 45
  • 74
4

This is more of a Ruby thing. You can define optional arguments for a method like this:

def initialize(name="", age=0)
  @name = name
  @age = age
end

By doing it this way, you will be able to call Person.new and then have name default to a blank string if it's not passed and age default to 0. If you want age to be something but name to be blank you'll need to pass an empty string anyway:

Person.new("", 24)
Ryan Bigg
  • 106,965
  • 23
  • 235
  • 261
  • 1
    If you want to be able to only specify the right hand argument, you probably want to be passing a Hash into your method as a single parameter – Gareth Mar 14 '12 at 21:13
3

Use hash for ruby 1.8/1.9 as follow:

def myMethod(options={})
  @email = options[:email]
  @phone = options[:phone]
end

# sample usage
myMethod({:email => "example@email.ir", :phone => "0098-511-12345678"})

Also on ruby 2.0/2.1 you can use keyword arguments as follow:

def myMethod(email: 'default@email.ir', phone: '0098-000-00000000')
  @email = email
  @phone = phone
end

# sample usage
myMethod(email: "example@email.ir", phone: "0098-511-12345678")
S.M.Mousavi
  • 5,013
  • 7
  • 44
  • 59