2

I am creating a metrics hash using the following:

@metrics = Hash.new

...

@metrics[:users][:year][:male] = ...
@metrics[:users][:today][:male] = ...

...

Metrics.new(:metrics => @metrics).save

and I have the following class:

class Metrics
  include Mongoid::Document
  include Mongoid::Timestamps

  field :metrics, :type => Hash

  attr_accessible :metrics

  ...

end

To fetch this document, I have:

@metrics = Metrics.find(params[:id])
@metrics = @metrics[:metrics]

In order to access these elements, I need to do:

@metrics['users']['year']['male']

Is there a way I can be consistent in how I access hash values but still storing data in mongo?

w2bro
  • 1,016
  • 1
  • 11
  • 36

1 Answers1

1

What version of Ruby and Mongoid are you using? Accessing hashes in Mongoid objects via symbols works fine in Mongoid 3.0.4 and Ruby 1.9.3. So I can do something like:

@metrics = Metrics.find(params[:id])[:metrics]
@metrics[:users][:year][:male]

or even:

Metrics.find(params[:id])[:metrics][:users][:year][:male]

Also, why not just leave the metrics field out, then treat instances of the Metrics class like instances of Hash? With Mongoid you can dynamically set and get attributes using the standard Ruby Hash symbol syntax without ever "declaring" the fields. With the metrics field removed:

m = Metric.new
m[:users] = {}
m[:users][:year] = {}
m[:users][:year][:male] = "data"

Additionally, if you need methods to auto-initialize nested hashes, so you can do things like:

m = Metric.new
m[:users][:year][:male] = "data"

you can put all of that logic into the Metrics class. To get started on that you could try adapting something like the [] and []= methods from the AutoHash class explained here. That would give you the cleanest interface I think.

Community
  • 1
  • 1
Vickash
  • 1,076
  • 8
  • 8