How to cleanly initialize attributes in Ruby with new?
Solution 1
def initialize(params)
params.each do |key, value|
instance_variable_set("@#{key}", value)
end
end
Solution 2
You can just iterate over the keys and invoke the setters. I prefer this, because it will catch if you pass an invalid key.
class Foo
attr_accessor :name, :age, :email, :gender, :height
def initialize params = {}
params.each { |key, value| send "#{key}=", value }
end
end
foo = Foo.new name: 'Josh', age: 456
foo.name # => "Josh"
foo.age # => 456
foo.email # => nil
Solution 3
To capitalize on Joshua Cheek's answer with a bit of generalization
module Initializable
def initialize(params = {})
params.each do |key, value|
setter = "#{key}="
send(setter, value) if respond_to?(setter.to_sym, false)
end
end
end
class Foo
include Initializable
attr_accessor :name, :age, :email, :gender, :height
end
Foo.new name: 'Josh', age: 456
=> #<Foo:0x007fdeac02ecb0 @name="Josh", @age=456>
NB If the initialization mix-in has been used and we need custom initialization, we'd just call super:
class Foo
include Initializable
attr_accessor :name, :age, :email, :gender, :height, :handler
def initialize(*)
super
self.handler = "#{self.name} #{self.age}"
end
end
Foo.new name: 'Josh', age: 45
=> #<Foo:0x007fe94c0446f0 @name="Josh", @age=45, @handler="Josh 45">
Solution 4
Foo = Struct.new(:name, :age, :email, :gender, :height)
This is enough for a fully functioning class. Demo:
p Foo.class # Class
employee = Foo.new("smith", 29, "[email protected]", "m", 1.75) #create an instance
p employee.class # Foo
p employee.methods.sort # huge list which includes name, name=, age, age= etc
Solution 5
Why not just explicitly specify an actual list of arguments?
class Foo
attr_accessor :name, :age, :email, :gender, :height
def initialize(name, age, email, gender, height)
@name = name
@age = age
@email = email
@gender = gender
@height = height
end
end
This version may be more lines of code than others, but it makes it easier to leverage built-in language features (e.g. default values for arguments or raising errors if initialize
is called with incorrect arity).
B Seven
Status: Hood Rails on HTTP/2: Rails HTTP/2 Rack Gems: Rack Crud Rack Routing Capybara Jasmine
Updated on May 19, 2020Comments
-
B Seven almost 4 years
class Foo attr_accessor :name, :age, :email, :gender, :height def initalize params @name = params[:name] @age = params[:age] @email = params[:email] . . . end
This seems like a silly way of doing it. What is a better/more idiomatic way of initalizing objects in Ruby?
Ruby 1.9.3