Reputation: 34798
in Ruby can I automatically populate instance variables somehow in the initialize method?
For example if I had:
class Weekend
attr_accessor :start_date, :end_date, :title, :description, :location
def initialize(params)
# SOMETHING HERE TO AUTO POPULATE INSTANCE VARIABLES WITH APPROPRIATE PARAMS
end
end
Upvotes: 21
Views: 5557
Reputation: 20857
Ruby can be scary simple sometimes. No looping in sight!
class Weekend < Struct.new(:start_date, :end_date, :title, :description, :location)
# params: Hash with symbols as keys
def initialize(params)
# arg splatting to the rescue
super( * params.values_at( * self.class.members ) )
end
end
Note that you don't even need to use inheritance - a new Struct
can be customized during creation:
Weekend = Struct.new(:start_date, :end_date, :title, :description, :location) do
def initialize(params)
# same as above
end
end
Test:
weekend = Weekend.new(
:start_date => 'start_date value',
:end_date => 'end_date value',
:title => 'title value',
:description => 'description value',
:location => 'location value'
)
p [:start_date , weekend.start_date ]
p [:end_date , weekend.end_date ]
p [:title , weekend.title ]
p [:description, weekend.description ]
p [:location , weekend.location ]
Note that this doesn't actually set instance variables. You class will have opaque getters and setters. If you'd rather not expose them, you can wrap another class around it. Here's an example:
# this gives you more control over readers/writers
require 'forwardable'
class Weekend
MyStruct = ::Struct.new(:start_date, :end_date, :title, :description, :location)
extend Forwardable
# only set up readers
def_delegators :@struct, *MyStruct.members
# params: Hash with symbols as keys
def initialize(params)
# arg splatting to the rescue
@struct = MyStruct.new( * params.values_at( * MyStruct.members ) )
end
end
Upvotes: 5
Reputation: 318
I think you could simply put:
Weekend < Struct.new(:start_date, :end_date, :title, :description, :location)
And then add anything else to the weekend class with:
class Weekend
#whatever you need to add here
end
Upvotes: 2
Reputation: 177
I suggest
class Weekend
@@available_attributes = [:start_date, :end_date, :title, :description, :location]
attr_accessor *@@available_attributes
def initialize(params)
params.each do |key,value|
self.send(:"#{key}=",value) if @@available_attributes.include?(key.to_sym)
end
end
end
Upvotes: 2
Reputation: 115511
To keep things simple:
class Weekend
attr_accessor :start_date, :end_date, :title, :description, :location
def initialize(params)
@start_date = params[:start_date] # I don't really know the structure of params but you have the idea
@end_date = params[:end_date]
end
end
You could do something smarter with a twist of metaprogramming but is this really necessary?
Upvotes: 7
Reputation: 43298
You can use instance_variable_set
like this:
params.each do |key, value|
self.instance_variable_set("@#{key}".to_sym, value)
end
Upvotes: 17