To_xml Hell


#1

I am trying to create a custom response to a particular action being
called in my controller and I am getting some really weird errors. I
am running the rails 1.2 stable branch.

Here is the action in my controller:

GET /:year/:month/level/1

GET /:year/:month/level/1.xml

def show
@level = Level.find(params[:id])
@assets = @level.assests.find_by_year_month(params[:year],
params[:month])

respond_to do |format|
format.html # show.rhtml
format.xml { @level.to_xml :include => [ @assests ] }
end
end

Here are the models:
class Level < ActiveRecord::Base
has_many :assets
end

class Asset < ActiveRecord::Base
belongs_to :level

def self.find_by_year_month(year, month)
requested_date = Date.new(year.to_i, month.to_i, 1)
from = requested_date - 1
to = requested_date >> 1
find_with_deleted(:all,
:conditions => ["created_at < ? AND ( deleted_at IS NULL " +
“OR deleted_at < ? AND deleted_at > ? )”, to, to, from ])
end
end

I have written the find_by_year_month class method on the Asset model
and it works great. When I run this action I get:

NoMethodError in LevelsController#show

You have a nil object when you didn’t expect it!
The error occurred while evaluating nil.macro

C:/…/vendor/rails/activerecord/lib/active_record/xml_serialization.rb:
185:in add_includes' C:/../vendor/rails/activerecord/lib/active_record/xml_serialization.rb: 180:ineach’
C:/…/vendor/rails/activerecord/lib/active_record/xml_serialization.rb:
180:in add_includes' C:/../vendor/rails/activerecord/lib/active_record/xml_serialization.rb: 232:into_s’
C:/…/vendor/rails/activesupport/lib/active_support/vendor/builder/
xmlbase.rb:140:in call' C:/../vendor/rails/activesupport/lib/active_support/vendor/builder/ xmlbase.rb:140:in_nested_structures’
C:/…/vendor/rails/activesupport/lib/active_support/vendor/builder/
xmlbase.rb:60:in method_missing' C:/../vendor/rails/activesupport/lib/active_support/vendor/builder/ xmlbase.rb:32:insend
C:/…/vendor/rails/activesupport/lib/active_support/vendor/builder/
xmlbase.rb:32:in tag!' C:/../vendor/rails/activerecord/lib/active_record/xml_serialization.rb: 230:into_s’
C:/…/vendor/rails/activerecord/lib/active_record/xml_serialization.rb:
107:in to_xml' C:/../app/controllers/schedules_controller.rb:23:inshow’
C:/…/app/controllers/schedules_controller.rb:21:in show' C:/../app/controllers/application.rb:32:inset_timezone’

Apparently, the error occurs on line 185 of C:/…/vendor/rails/
activerecord/lib/active_record/xml_serialization.rb in `add_includes’

I can’t figure out why this doesn’t work. According to the post Jamis
Buck made (
http://weblog.jamisbuck.org/2006/3/27/web-services-rails-style
) this should work. Shouldn’t it?

Any help would be greatly appreciated.

Nicholas


#2

And of course no variable called @assests was set in the controller
(although I see there is one called @assets). Uninitialized instance
variables are treated as nil.


#3

It’s

format.xml { @level.to_xml :include => [ :assests ] }

Use symbols, not variables. However, given what you are trying to do
takes
parameters, you may be best off defining your own to_xml on Asset as the
to_xml document page suggests:

http://api.rubyonrails.org/classes/ActiveRecord/XmlSerialization.html#M000910

Jason


#4

That was a type-o on my part. I did check to make sure the variables
match in my code, but thanks for pointing that out.

  • Nicholas

#5

I have tried the approach you’ve suggested and it does work. I just
thought you could pass an array in the :include array as Jamis did in
his post.

def add
company = params[:person].delete(:company)
@company = Company.find_or_create_by_name(company[:name])
@person = @company.people.create(params[:person])

respond_to do |wants|
wants.html { redirect_to(person_list_url) }
wants.js
wants.xml { render :xml => @person.to_xml(:include => @company) }
end
end

The post was made on March 27th of 2006, so it easily could be
invalid. Any thoughts?

Nicholas