I want to display data from a nested table in my XML output using respond_to. I searched google a bit and it seems :include was the way to go. However I had some problems getting this to work properly.
I have two models (customer and user) that are linked together. When I fetch the data for a single user, I want my xml output to include the customer data.
The Customer model:
class Customer < ActiveRecord::Base has_many :users end
The User model:
class User < ActiveRecord::Base belongs_to :customer end
In my UserController I use the respond_to method to respond to html and xml data.
The show action is as follows:
# Shows the seleted user def show @user = User.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @user) } end end
Calling the show action on the user controller as xml should yield something like:
<user> ... <customer> ... </customer> </user>
But the customer data is not included.
This puzzled me a bit.
Searching a bit on google got me the following answer:
# Shows the seleted user def show @user = User.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @user.to_xml(:include => @user.customer) } end end
source: http://rubydoc.info/docs/rails/3.0.0/ActionController/MimeResponds
(I also tried fetching the customer out separately, that didn’t work either)
This gave me the following error:
undefined method `macro' for nil:NilClass
The solution
After a lot more searching I found out, that you shouldn’t pass an object, but a symbol. The name of the symbol is the data block you want to show, so in my case it was :customer
The code to fix it was:
# Shows the seleted user def show @user = User.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @user.to_xml(:include => :customer) } end end
The data for the customer now returned as well.
Need more data?
If you need data from several tables, just use an array of symbols instead.
# Shows the seleted user def show @user = User.find(params[:id]) respond_to do |format| format.html format.xml { render :xml => @user.to_xml(:include => [:customer, :table2, :table3]) } end end
Hope you can use this tip.