Mongoid
Mongoid

Reputation: 97

Ruby hash keys as object methods

Is there an API or how would one go about creating hash keys being accessible by dot(.) methods like if there was Array of objects.

Here is an example :

data = [
  {
    key1: 'value1',
    key2: 'value2'
  },
  {
    key1: 'valuex',
    key2: 'valuey'
  },
  ...
]

If I tried to do this :

data.collect(&:key1)

Would get this error :

NoMethodError: undefined method `key1' for #<Hash:0x007fc2a7159188>

This however works :

data.collect{|hs| hs[:key1]}

Just because its a symbol and not object property. Is there a way I could accomplish same behaviour with symbols as if they were object properties?

Upvotes: 1

Views: 2169

Answers (3)

EJAg
EJAg

Reputation: 3308

This is inspired by @spickerman's comment. It's something one can do but probably shouldn't do.

You can add your custom method to Ruby's Enumerable module:

module Enumerable
  def enum_send(:method, *args)
    send(:method) { |obj| obj.send(*args) }
  end
end

You can then call

data.enum_send(:collect, :"[]", :key1)  ## [value1, valuex..]

or something like

data.enum_send(:each, :delete, :key2)  ## [{key1: value1}, {key1: valuex}..]

Upvotes: 0

P. Boro
P. Boro

Reputation: 776

You can wrap those hashes into OpenStruct. Try using this code:

data.map! { |hsh| OpenStruct.new(hsh) }

data.first.key1 # => "value1"

Upvotes: 1

en1010
en1010

Reputation: 1300

You can wrap your objects with OpenStruct

require 'ostruct'

data.map { |it| OpenStruct.new(it) }.collect(&:key1)

Upvotes: 0

Related Questions