Greg
Greg

Reputation: 34798

in Ruby can I automatically populate instance variables somehow in the initialize method?

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

Answers (5)

Kelvin
Kelvin

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

mjd2
mjd2

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

kalifs
kalifs

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

apneadiving
apneadiving

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

Mischa
Mischa

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

Related Questions