How can I add and retrieve elements in a Ruby Hash using readers and setters

60 Views Asked by At

I want to be able to add and retrieve elements to a hash via getters and setters. Here is my class

class Config

  attr_reader :p1, :p2, :p4

  def initialize(options={})
    options.each do |k,v|
      instance_variable_set("@#{k}", v)
    end
  end

end

Currently I am only able to add and retrieve elements with keys as p1, p2 and p3

If I try adding new elements e.g

> a = Config.new({name: "kevin"})
return value is
=> #<Config:0x000000000a4422a8 @name="kevin">

on trying to access the name

> a.name
NoMethodError: undefined method `name' for #<Config:0x000000000a4422a8 @name="kevin">

How can I access the name value with a.name to get "Kevin"

2

There are 2 best solutions below

0
Oscar On

If you only want a data struct storing like hash, maybe you can try OpenStruct

For example:

require 'ostruct'

class Config < OpenStruct
  # some other methods
end

Than you can do this

hash_input = { name: "kevin", gender: "male" }
config = Config.new(hash_input)
config.name
#=> "kevin"

For more detail about OpenStruct, you can checkout here

3
MikeWu On

You can do:

class Config    
  def initialize(options={})
    options.each do |k,v|
      singleton_class.send(:attr_reader, k)
      instance_variable_set("@#{k}", v)
    end
  end
end

This will allow you to define different set of readers for each instance of Config class (if this is your intention). For example:

c1 = Config.new(test1: "test1")
#=> #<Config:0x0000000c3a82c8 @test1="test1">
c2 = Config.new(test2: "test2")
#=> #<Config:0x0000000b7013d0 @test2="test2">
c1.test1
#=> "test1"
c1.test2
# NoMethodError: undefined method `test2' for #<Config:0x0000000c3a82c8 @test1="test1">
# from (pry):59:in `<main>'
c2.test2
#=> "test2"
c2.test1
# NoMethodError: undefined method `test1' for #<Config:0x0000000b7013d0 @test2="test2">
# from (pry):61:in `<main>'