Our Rails application needs to support both xml and json formats.  In
some cases, we need to return custom XML that spans several objects
and associations.  I've been able to write custom to_xml methods that
use the builder and block functionality.  When trying the same thing
with the to_json method, I failed to get the same result.

Basically to_xml has this signature: to_xml(options = {}, &block).
I've perused around and it appears to_json has this signature:
to_json(options = {}).  Is there a version of to_json that will yield
to a block
and provide the json builder? Can someone please tell me if I've done
something wrong with the code below?  Is there is a plugin or newer
version of Rails that will add the same support for to_json that
to_xml supports?



Here is the relevant code

class Conference < ActiveRecord::Base
        has_many :courses, :dependent => :destroy
end


class Course < ActiveRecord::Base
        belongs_to :conference
        has_many :sessions, :dependent => :destroy
        has_one :manual

            # just a place holder method so we can serialize it
        def pre_requisite
                "An open mind"
        end
end


class Session < ActiveRecord::Base
        belongs_to :courses
        has_one :presentation, :dependent=>:destroy


            # just a place holder method so we can serialize it
        def maximum_capacity_reached?
                false;
        end
end


class Presentation < ActiveRecord::Base
        belongs_to :session
        belongs_to :instructor
end


class Manual < ActiveRecord::Base
        belongs_to :course
end


class Instructor < ActiveRecord::Base
end


Now let's suppose I have a controller that will return the full detail
of a conference and needs all of the related data and will also
serialize some custom methods.
class ConferencesController < ApplicationController
        # GET /conferences/:id
        def show
                conference_id = params[:id]

                respond_to do |format|
                        format.html # unsupported
                        format.json {
                                
render(:json=>Conference.full_json(conference_id))
                        }
                        format.xml {
                                render(:xml=>Conference.full_xml(conference_id))
                        }
                end
        end
end

So I've extended the conference class so that it can build this nested
xml along with the result of selective methods on various classes.
this code uses the fact that to_xml has this signature: to_xml(options
= {}, &block)

class Conference < ActiveRecord::Base
        has_many :courses, :dependent => :destroy


        def slogan
                "#{name}: Be here or be in the dark!"
        end

        def self.full_xml(conference_id)
                # ensure we've loaded the full structure in the most efficient
manner
                conference = Conference.find(conference_id, :include=>{:courses 
=>
[:manual, {:sessions=>:presentation}]})

                # extract detailed hierarchical xml
                conference.to_xml do |xml|
                        xml.slogan conference.slogan # output the banner

                        #iterate courses and any custom methods
                        xml.courses{
                                conference.courses.each do |course|
                                        course.to_xml(:builder=>xml, 
:skip_instruct => true) do |
xml_course|
                                                xml_course.sessions{
                                                        #iterate sessions and 
any custom methods
                                                        course.sessions.each do 
|session|
                                                                
session.to_xml(:builder=>xml_course, :skip_instruct => true)
do |xml_course_session|
                                                                        
xml_course_session.is_at_capacity
session.maximum_capacity_reached?
                                                                end
                                                        end
                                                }
                                        end
                                end
                        }
                end
        end


        def self.full_json(conference_id)
                # ensure we've loaded the full structure in the most efficient
manner
                conference = Conference.find(conference_id, :include=>{:courses 
=>
[:manual, {:sessions=>:presentation}]})

                debugger()

                # extract detailed hierarchical xml
                conference.to_json do |json|
                        json.slogan conference.slogan # output the banner

                        #iterate courses and any custom methods
                        json.courses{
                                conference.courses.each do |course|
                                        course.to_json(:builder=>json, 
:skip_instruct => true) do |
json_course|
                                                json_course.sessions{
                                                        #iterate sessions and 
any custom methods
                                                        course.sessions.each do 
|session|
                                                                
session.to_json(:builder=>json_course, :skip_instruct => true)
do |json_course_session|
                                                                        
json_course_session.is_at_capacity
session.maximum_capacity_reached?
                                                                end
                                                        end
                                                }
                                        end
                                end
                        }
                end
        end
end


When I invoke the method, via http://localhost:3000/conferences/1.xml,
I get the desired generated XML output:
<conference>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">1</id>
<name>Ruby Live</name>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<slogan>Ruby Live: Be here or be in the dark!</slogan>
-
<courses>
-
<course>
<conference-id type="integer">1</conference-id>
<course-name>Action Controller: In Depth</course-name>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">1</id>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
-
<sessions>
-
<session>
<course-id type="integer">1</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-04T15:59:41-08:00</end-time>
<id type="integer">1</id>
<rating type="integer">4</rating>
<room-number>101</room-number>
<start-time type="datetime">2008-12-04T13:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
-
<session>
<course-id type="integer">1</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-05T15:59:41-08:00</end-time>
<id type="integer">2</id>
<rating type="integer">4</rating>
<room-number>101</room-number>
<start-time type="datetime">2008-12-05T13:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
</sessions>
</course>
+
<course>
<conference-id type="integer">1</conference-id>
<course-name>Active Record: In Depth</course-name>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">2</id>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
-
<sessions>
-
<session>
<course-id type="integer">2</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-04T17:59:41-08:00</end-time>
<id type="integer">3</id>
<rating type="integer">5</rating>
<room-number>201</room-number>
<start-time type="datetime">2008-12-04T15:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
-
<session>
<course-id type="integer">2</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-05T17:59:41-08:00</end-time>
<id type="integer">4</id>
<rating type="integer">5</rating>
<room-number>201</room-number>
<start-time type="datetime">2008-12-05T15:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
</sessions>
</course>
</courses>
</conference>

When I invoke the method, via http://localhost:3000/conferences/1.json,
I get the following undesired generated json output.  Basically the
builder and block that acts on to_xml is ignored or defunct.
{"name": "Ruby Live", "updated_at": "2008/11/04 13:59:41 -0800", "id":
1, "created_at": "2008/11/04 13:59:41 -0800"}

I need to support both xml and json formats while returning the same
data.  Can someone please tell me what if there is a plugin or newer
version of Rails that will add this same support for to_json that
to_xml supports?Our application needs to support both xml and json
formats while returning the same data.  In some cases, we need to
return custom XML that spans several objects and associations.  I've
been able to write custom to_xml methods that use the builder and
block functionality.  When trying the same thing with the to_json
method, I failed to get the same result.  Can someone please tell me
if I've done something wrong with the code below?  Is there is a
plugin or newer version of Rails that will add the
same support for to_json that to_xml supports?

Here is the relevant code

class Conference < ActiveRecord::Base
        has_many :courses, :dependent => :destroy
end


class Course < ActiveRecord::Base
        belongs_to :conference
        has_many :sessions, :dependent => :destroy
        has_one :manual

            # just a place holder method so we can serialize it
        def pre_requisite
                "An open mind"
        end
end


class Session < ActiveRecord::Base
        belongs_to :courses
        has_one :presentation, :dependent=>:destroy


            # just a place holder method so we can serialize it
        def maximum_capacity_reached?
                false;
        end
end


class Presentation < ActiveRecord::Base
        belongs_to :session
        belongs_to :instructor
end


class Manual < ActiveRecord::Base
        belongs_to :course
end


class Instructor < ActiveRecord::Base
end


Now let's suppose I have a controller that will return the full detail
of a conference and needs all of the related data and will also
serialize some custom methods.
class ConferencesController < ApplicationController
        # GET /conferences/:id
        def show
                conference_id = params[:id]

                respond_to do |format|
                        format.html # unsupported
                        format.json {
                                
render(:json=>Conference.full_json(conference_id))
                        }
                        format.xml {
                                render(:xml=>Conference.full_xml(conference_id))
                        }
                end
        end
end

So I've extended the conference class so that it can build this nested
xml along with the result of selective methods on various classes.
class Conference < ActiveRecord::Base
        has_many :courses, :dependent => :destroy


        def slogan
                "#{name}: Be here or be in the dark!"
        end

        def self.full_xml(conference_id)
                # ensure we've loaded the full structure in the most efficient
manner
                conference = Conference.find(conference_id, :include=>{:courses 
=>
[:manual, {:sessions=>:presentation}]})

                # extract detailed hierarchical xml
                conference.to_xml do |xml|
                        xml.slogan conference.slogan # output the banner

                        #iterate courses and any custom methods
                        xml.courses{
                                conference.courses.each do |course|
                                        course.to_xml(:builder=>xml, 
:skip_instruct => true) do |
xml_course|
                                                xml_course.sessions{
                                                        #iterate sessions and 
any custom methods
                                                        course.sessions.each do 
|session|
                                                                
session.to_xml(:builder=>xml_course, :skip_instruct => true)
do |xml_course_session|
                                                                        
xml_course_session.is_at_capacity
session.maximum_capacity_reached?
                                                                end
                                                        end
                                                }
                                        end
                                end
                        }
                end
        end


        def self.full_json(conference_id)
                # ensure we've loaded the full structure in the most efficient
manner
                conference = Conference.find(conference_id, :include=>{:courses 
=>
[:manual, {:sessions=>:presentation}]})

                debugger()

                # extract detailed hierarchical xml
                conference.to_json do |json|
                        json.slogan conference.slogan # output the banner

                        #iterate courses and any custom methods
                        json.courses{
                                conference.courses.each do |course|
                                        course.to_json(:builder=>json, 
:skip_instruct => true) do |
json_course|
                                                json_course.sessions{
                                                        #iterate sessions and 
any custom methods
                                                        course.sessions.each do 
|session|
                                                                
session.to_json(:builder=>json_course, :skip_instruct => true)
do |json_course_session|
                                                                        
json_course_session.is_at_capacity
session.maximum_capacity_reached?
                                                                end
                                                        end
                                                }
                                        end
                                end
                        }
                end
        end
end


When I invoke the method, via http://localhost:3000/conferences/1.xml,
I get the desired generated XML output:
<conference>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">1</id>
<name>Ruby Live</name>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<slogan>Ruby Live: Be here or be in the dark!</slogan>
-
<courses>
-
<course>
<conference-id type="integer">1</conference-id>
<course-name>Action Controller: In Depth</course-name>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">1</id>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
-
<sessions>
-
<session>
<course-id type="integer">1</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-04T15:59:41-08:00</end-time>
<id type="integer">1</id>
<rating type="integer">4</rating>
<room-number>101</room-number>
<start-time type="datetime">2008-12-04T13:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
-
<session>
<course-id type="integer">1</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-05T15:59:41-08:00</end-time>
<id type="integer">2</id>
<rating type="integer">4</rating>
<room-number>101</room-number>
<start-time type="datetime">2008-12-05T13:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
</sessions>
</course>
+
<course>
<conference-id type="integer">1</conference-id>
<course-name>Active Record: In Depth</course-name>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<id type="integer">2</id>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
-
<sessions>
-
<session>
<course-id type="integer">2</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-04T17:59:41-08:00</end-time>
<id type="integer">3</id>
<rating type="integer">5</rating>
<room-number>201</room-number>
<start-time type="datetime">2008-12-04T15:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
-
<session>
<course-id type="integer">2</course-id>
<created-at type="datetime">2008-11-04T13:59:41-08:00</created-at>
<end-time type="datetime">2008-12-05T17:59:41-08:00</end-time>
<id type="integer">4</id>
<rating type="integer">5</rating>
<room-number>201</room-number>
<start-time type="datetime">2008-12-05T15:59:41-08:00</start-time>
<updated-at type="datetime">2008-11-04T13:59:41-08:00</updated-at>
<is_at_capacity>false</is_at_capacity>
</session>
</sessions>
</course>
</courses>
</conference>

When I invoke the method, via http://localhost:3000/conferences/1.json,
I get the following undesired generated json output.  Basically the
builder and block that acts on to_xml is ignored or defunct.
{"name": "Ruby Live", "updated_at": "2008/11/04 13:59:41 -0800", "id":
1, "created_at": "2008/11/04 13:59:41 -0800"}

I need to support both xml and json formats while returning the same
data.  Can someone please tell me what if there is a plugin or newer
version of Rails that will add this same support for to_json that
to_xml supports?
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Talk" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-talk?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to