Reputation: 16724
I have a has like this:
reminder_hash = {"bot_client_id"=>"test-client-id", "recurring"=>true, "recurring_natural_language"=>"everyday", "time_string"=>"10AM", "time_zone"=>"America/Los_Angeles", "via"=>"slack", "keyword"=>"test-keyword", "status"=>"active", "created_time"=>1444366166000}
I would like to pass to method like this (from Rspec):
let(:reminder) { Reminder.new( reminder_hash ) }
I would like the instance variables for Reminder to be based on the hash.
expect(reminder.bot_client_id).to eq('test-client-id')
I can't get it to work. I tried the following:
class Reminder
attr_accessor :bot_client_id
def initiate(hash)
# http://stackoverflow.com/questions/1615190/declaring-instance-variables-iterating-over-a-hash
hash.each do |k,v|
instance_variable_set("@#{k}",v)
# if you want accessors:
eigenclass = class<<self; self; end
eigenclass.class_eval do
attr_accessor k
end
end
end
Rspec gives the following error:
Failure/Error: let(:reminder) { Reminder.new( reminder_hash ) }
ArgumentError:
wrong number of arguments (1 for 0)
Question: How do I pass a hash to an instance method for an object, so that the hash values are the instance variables for that newly created object?
Upvotes: 1
Views: 874
Reputation: 80065
Ruby has OpenStruct to do that.
require 'ostruct'
reminder_hash = {"bot_client_id"=>"test-client-id", "recurring"=>true, "recurring_natural_language"=>"everyday", "time_string"=>"10AM", "time_zone"=>"America/Los_Angeles", "via"=>"slack", "keyword"=>"test-keyword", "status"=>"active", "created_time"=>1444366166000}
reminder = OpenStruct.new(reminder_hash)
p reminder.bot_client_id # => "test-client-id"
Use a Struct for a full blown Class:
Reminder = Struct.new(*reminder_hash.keys.map(&:to_sym))
r = Reminder.new(*reminder_hash.values)
p r.bot_client_id # => "test-client-id"
Upvotes: 0
Reputation: 15967
Sure you can do something like this in your initialize method:
hash.each do |k, v|
instance_variable_set("@#{k}", v)
self.class.send(:attr_reader, k)
end
Here's an example using your input hash:
class Reminder
def initialize(hash)
hash.each do |k, v|
instance_variable_set("@#{k}", v)
self.class.send(:attr_reader, k)
end
end
end
reminder_hash = {"bot_client_id"=>"test-client-id", "recurring"=>true, "recurring_natural_language"=>"everyday", "time_string"=>"10AM", "time_zone"=>"America/Los_Angeles", "via"=>"slack", "keyword"=>"test-keyword", "status"=>"active", "created_time"=>1444366166000}
reminder = Reminder.new(reminder_hash)
puts reminder
puts reminder.bot_client_id
Output:
#<Reminder:0x007f8a48831498>
test-client-id
Upvotes: 1