Forum: Ruby on Rails Nested serialization with to_json and to_xml with array and hash element

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
34854d418156dfbf8a0103977bbab2e4?d=identicon&s=25 RubyNewbie (Guest)
on 2009-01-21 03:47
(Received via mailing list)
Title: Nested serialization with to_json and to_xml with array and
hash element

class Person < ActiveRecord::Base
  has_one :address
  has_one :job

  def office()
    return "Executive_Suite"
  end
end


class Address < ActiveRecord::Base
  belongs_to :person
end


class Job < ActiveRecord::Base
  belongs_to :person
  has_one :paygrade

  def Title
    return "Engineer"
  end
end


class PayGrade < ActiveRecord::Base
  belongs_to: job

end


Given an instance of a Person, I am able to serialize in XML and JSON
in some simpler nested manners such as this:

@person = Person.find_by_id(1)


# render the results with multiple peer associations with no drill
down
respond_to do |format|
      format.json { render.json(:json=>@person.to_json(:include=>
[:address, :job], :methods=>:office) }
      format.xml { render.json(:json=>@person.to_json(:include=>
[:address, :job], :methods=>:office) }
      }
end


# render the results with 1 association requiring deep drill down
respond_to do |format|
      format.json { render.json(:json=>@person.to_json(:include=>
{:job=>{:include=>:paygrade}}) }
      format.xml { render.json(:json=>@person.to_json(:include=>{:job=>
{:include=>:paygrade}}) }
      }
end


Where I continually run into problems is where I have multiple peer
associations at the same level
with one of them needing further drill down into one of its
association.

For instance I thought I could simply do this to serialize the Person
instance, along with their address, job with Paygrade.
Whenever I try to do this:
respond_to do |format|
      format.json { render.json(:json=>@person.to_json(:include=>
[:address, {:job=>{:include=>:paygrade}}] }
      format.xml { render.json(:json=>@person.to_json(:include=>
[:address, {:job=>{:include=>:paygrade}}] }
      }
end


I always get the following error: You have a nil object when you
didn't expect it.  Error evaluating nil.ma.
Based on my understanding the :include is expecting an array but I'm
adding a hash as an element and Rails
is not expecting it in the way I'm specifying?

Where I also continually run into problems is where I have multiple
peer associations at the same level
with one of them needing requiring a custom method to be serialized.



Question 1: What is the correct way to be able to specify that I need
to serialize the Person with address
and job along with the paygrade for the job?  This is the multiple
peers with deep drill down problem mentioned above.

Question 2: What is the correct way to be able to specify that I need
to serialize the Person with address
and job along with the custom Job Title method with the paygrade?
When I try this, I get error:

respond_to do |format|
      format.json { render.json(:json=>@person.to_json(:include=>
[:address, {:job=>{:methods=>:title, :include=>:paygrade}}] }
      format.xml { render.json(:json=>@person.to_json(:include=>
[:address, {:job=>{:methods=>:title, :include=>:paygrade}}] }
      }
end

Please advise, and thanks in advance.
34854d418156dfbf8a0103977bbab2e4?d=identicon&s=25 RubyNewbie (Guest)
on 2009-01-21 04:48
(Received via mailing list)
The error description above was slightly truncated.
The full error is this: You have a nil object when you didn't expect
it! The error occurred while evaluating nil.macro
67add0b0d58ce1f2f3def95ea338fd30?d=identicon&s=25 scho (Guest)
on 2009-03-17 16:31
(Received via mailing list)
Hi Folks,

I ran into the same problem. Here is my fix, which solved the problem
(I've added it to my environment.rb):

module ActiveRecord
  module Serialization
    class Serializer
      def add_includes_with_nested_include(&block)
        if include_associations = options.delete(:include)
          base_only_or_except = { :except => options[:except],
                                  :only => options[:only] }

          include_has_options = include_associations.is_a?(Hash)
          associations = include_has_options ?
include_associations.keys : Array(include_associations)

          for association in associations
            association_has_options = association.is_a?(Hash)
            if association_has_options
              macro_association = association.keys.first
              additional_association_options = association
[macro_association]
            else
              additional_association_options = {}
              macro_association = association
            end
            macro = @record.class.reflect_on_association
(macro_association).macro
            records = case macro
            when :has_many, :has_and_belongs_to_many
              @record.send(macro_association).to_a
            when :has_one, :belongs_to
              @record.send(macro_association)
            end
            unless records.nil?
              association_options = include_has_options ?
include_associations[macro_association] : base_only_or_except
              opts = options.merge(association_options).merge
(additional_association_options)
              yield(macro_association, records, opts)
            end
          end

          options[:include] = include_associations
        end
      end
      alias_method_chain :add_includes, :nested_include
    end
  end
end


If someone wants to commit this to github, more power to you!

scho
67add0b0d58ce1f2f3def95ea338fd30?d=identicon&s=25 scho (Guest)
on 2009-03-18 12:07
(Received via mailing list)
Hi again,

I found out, that the following works as well:
Instead of
[:address, {:job=>{:include=>:paygrade}}]
try
{:address => {}, {:job=>{:include=>:paygrade}}}

scho
This topic is locked and can not be replied to.