views:

104

answers:

1

In my Rails application there is a model that has some has_one associations (this is a fabricated example):

class Person::Admin < ActiveRecord::Base
  has_one :person_monthly_revenue
  has_one :dude_monthly_niceness
  accepts_nested_attributes_for :person_monthly_revenue, :dude_monthly_niceness
end

class Person::MonthlyRevenue < ActiveRecord::Base
  belongs_to :person_admin
end

class Dude::MonthlyNiceness < ActiveRecord::Base
  belongs_to :person_admin
end

The application talks to a backend that computes some data and returns a piece of JSON like this:

{
    "dude_monthly_niceness": {
        "february": 1.1153232569518972, 
        "october": 1.1250217200558268, 
        "march": 1.3965786869658541, 
        "august": 1.6293418014601631, 
        "september": 1.4062771500697835, 
        "may": 1.7166279693955291, 
        "january": 1.0086401628086725, 
        "june": 1.5711510228365859, 
        "april": 1.5614525597326563, 
        "december": 0.99894169970474289, 
        "july": 1.7263264324994585, 
        "november": 0.95044938418509506
    }, 
    "person_monthly_revenue": {
        "february": 10.585596551505297, 
        "october": 10.574823016656749, 
        "march": 9.9125274764852787, 
        "august": 9.2111604702328922, 
        "september": 9.7905249446675153, 
        "may": 9.1329712474607962, 
        "january": 10.479614016604238, 
        "june": 9.3710235926961936, 
        "april": 9.5897372624830304, 
        "december": 10.052587677671438, 
        "july": 8.9508877843925561, 
        "november": 10.925339756096172
    }, 
}

To deserialize it, I use ActiveRecord's from_json, but instead of a Person::Admin object with all the associations in place, I get this error:

>> Person::Admin.new.from_json(json)
NameError: uninitialized constant Person::Admin::DudeMonthlyNiceness

Am I doing something wrong?

Is there a better way to deserialize data? (I can modify the backend easily)

UPDATE: the original title was "How to deserialize from json to ActiveRecord objects with associations?" but it ended up being my mistake in specifying associations so I changed the title.

+1  A: 

Your classes are in different namespaces. ActiveRecord transforms dude_monthly_niceness into DudeMonthlyNiceness class inside current namespace, which gives Person::Admin::DudeMonthlyNiceness, which doesn't exist.

So you should specify class names explicitly for associations (Do not know what exactly foreign keys you are using, so change if needed):

class Person::Admin < ActiveRecord::Base
  has_one :person_monthly_revenue, :class_name => "Person::MonthlyRevenue", :foreign_key => "person_admin_id"
  has_one :dude_monthly_niceness, :class_name => "Dude::MonthlyNiceness", :foreign_key => "person_admin_id"
  accepts_nested_attributes_for :person_monthly_revenue, :dude_monthly_niceness
end

Another thing is that to be able to receive associated objects using accepts_nested_attributes_for, you need to end your json objects with _attributes:

{
    "dude_monthly_niceness_attributes": {
        "february": 1.1153232569518972, 
        ...
        "november": 0.95044938418509506
    }, 
    "person_monthly_revenue_attributes": {
        "february": 10.585596551505297, 
        ...
        "november": 10.925339756096172
    }, 
}
Voyta
Thanks! It works now, but I had to use `:class_name` instead of `:class` (it's not valid) and the correct foreign_key is `:person_admin_id` for all the relations.
Carmine Paolino
Oh, yes, haven't tested that. Glad the point was clear anyway.
Voyta