0

I am new to ruby and wanted to know if this is possible. Suppose I have a file with different blocks like this

fruits[tomato=1,orange=2]
greens[peas=2,potato=3]

I have parsed this file and stored it into a hash like this

{"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato"=>"3", "peas"=>"2"}}

And I also know how to access the different parts of the hash. But suppose if want to make it something like this

fruits.tomato  # 1
fruits.orange  # 2
(Like an object with tomato and orange being its variables)

The catch here is suppose I don't know if the file is going to contain fruits and greens, it could contain a different group called meat. I know this dynamic problem can be solved if I insert everything into a hash with the key as group name and value will be another hash. But can this be done with the example of fruit.tomato or fruits.orange I provided above(Probably by declaring it in a class but I am not sure how to dynamically add class vars in ruby or if that is even possible as I am new to the language).

2 Answers 2

1

I spent quite a bit of time making a program just like this in order to help speed up development with API's. I ended up writing a gem to objectify raw JSON (shameless plug: ClassyJSON).

That said, I think your use case is a good one for OpenStruct. I limited my code to just your example and your desired result but here's what it might look like:

require 'ostruct'

hash = {"fruits"=>{"tomato"=>"1", "orange"=>"2"}, "greens"=>{"potato"=>"3", "peas"=>"2"}}
structs = []

hash.each do |k, v|
  if v.is_a? Hash
    obj = OpenStruct.new({k => OpenStruct.new(v)})
  end
  structs << obj
end

Here we built up a number of OpenStruct objects and can access their values as you outlined:

[1] pry(main)> structs
=> [#<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>, #<OpenStruct greens=#<OpenStruct potato="3", peas="2">>]
[2] pry(main)> structs.first
=> #<OpenStruct fruits=#<OpenStruct tomato="1", orange="2">>
[3] pry(main)> structs.first.fruits
=> #<OpenStruct tomato="1", orange="2">
[4] pry(main)> structs.first.fruits.tomato
=> "1"
Sign up to request clarification or add additional context in comments.

4 Comments

cool. You'll want to add some logic to that loop if you have arrays or simple key values but that should get you going.
Sorry, about that I may not posted my whole question. So do you think OpenStruct is a favorable way to come to this solution as I mean this would be similar to a Struct in c/c++ which I have been told to stay away from.
It's been a really long time since I've done any C so I can't really remember the pros and cons. OpenStruct uses ruby's metaprogramming under the hood so it is unique in that sense.
Anthony I found this solution which I am going to use and can be used directly when I am creating the hashmap. I have added it as an answer.
0
  def add_accessor_method(name, ref)
    define_singleton_method name do
     return ref
    end
  end

I found this solution which will make an accessor method for me during parsing the file itself. So I will not have to use OpenStruct later on to convert my hash to an object with different accessor methods. ( I am sure OpenStruct under the hood is doing that)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.