Good afternoon,
I'm trying to render as XML the complete ActiveRecord error list, problem is when you do something like:
respond_to do |format|
format.xml { render :xml => #object }
end
It does not render nested attributes if you don't say so, so either: you should create a template or calling explicity to_xml method and using ":include". This last option seems to work fine with nested attributes on model associations. But what if we got errors? This code does not work:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => :errors }
end
I know I could do #client.errors and even hide .to_xml, but now i want to do something like:
respond_to do |format|
format.xml { render :xml => #client.to_xml(:include => {
:errors,
:client_contact => {:include => :errors } } )}
end
And supposedly I could obtain only in 1 xml, the errors from the client, and the errors from the client.client_contact! Let me know if i'm doing something wrong, or this :include is not supposed to work with errors
Regards
Have a look at the documentation for XML builder in the API docs. You can generate XML based on any number of conditions and output it however you like.
There's also a Railscasts episode showing you how to do a similar thing for RSS feeds.
Related
I am curious if this is even possible. I am looking to render data based on the results of an action in ruby on rails. Here is the code:
def convert
render :text => Item.convert(params[:file], params[:output])
end
As you can see currently it just renders text. The item model takes in two parameters: a file and output. The output could be xml, json, plain text, etc. Some type of data. What I was hoping I could do is that I could render the output based on the output parameter. But make it dynamic. I was hoping I could do:
def convert
#items = Item.convert(params[:file], params[:output])
respond_to do |format|
format.json { render :json => #items }
format.xml { render :xml => #items }
end
end
Something that would call the method and based on the data returned it would render the appropriate data. Testing the above code returns an empty page. The body tag is completely empty.
Any ideas?
thanks
Mike Riley
If you are relying on the name of params[:output] to determine what to render, I would write is as below:
def convert
#items = Item.convert(params[:file], params[:output])
if File.extname(params[:output].match("text"))
render :text => Item.convert(params[:file], params[:output])
elsif File.extname(params[:output].match("json"))
render :json => Item.convert(params[:file], params[:output])
elsif File.extname(params[:output].match("xml"))
render :xml => Item.convert(params[:file], params[:output])
else
render :html => "default_html"
end
end
and you should have a default_html.html.erb that you would render if the extension name of the file does not match what is expected
Here is a Rails code:
respond_to do |format|
format.html
format.xml { render :xml => #users }
format.json { render :json => #users }
end
I know what it does. But I don't know the meaning of the commands syntax-wise.
format.xml -- what is xml, is this a method which an object format has, correct? Where do I find its signature (or description)?
{ } -- a block or a hash? I think this is a block.
render -- a method? where do I find its signature (where in api docs)?
:xml => #users -- a hash, where :xml => is a key, correct?
So it could be reprented as, right?:
respond_to do |format|
format.html
format.xml do
render(:xml => #users)
end
format.json do
render(:json => #users)
end
end
format.*
Using the debugger, I learnt that format is an instance of ActionController::MimeResponds::Collector. It includes AbstractController::Collector, which uses method_missing to respond to various format calls.
if Mime::SET.include?(mime_constant)
AbstractController::Collector.generate_method_for_mime(mime_constant)
send(symbol, &block)
else
# ...
{ render xml: ... }
Looking at method_missing, it's clear that it expects a block.
render
Yes, render is a method. Documentation.
:xml => #user
Yes, it's a hash. The key is the symbol :xml. It can also be written as
render xml: #user
render(xml: #user)
render({xml: #user})
render({:xml => #user})
format comes from the request made to the method, http://app.com/controller/method.format where format could be .html or .csv etc. The meaning of format.xml is simply to check if the user requested an xml page (http://app.com/controller/method.xml.
Block, just like you describe.
At the apidock! http://apidock.com/rails/ActionController/Base/render
Correct, render will act depending on the key that exists. In your case, as the existing key is :xml the render method will output #users formatted as XML.
I have seen some people using code like this
respond_to do |format|
format.html
format.js
end
What is the purpose of this if we have template.html and template.js. Either can be rendered without specifying respond_to
Your snippet doesn't do anything special, but the formatting options allow you to provide additional custom behavior if it is necessary.
For example, if you want to render your #products as a JSON:
respond_to do |format|
format.html
format.js { render :json => #products }
end
This is just one of the many things you can do with the format blocks. For more information, see Ruby on Rails Guides: Layouts and Rendering
The format options can take a block so that you can do some custom rendering such as rendering a file or :head response. Have a look at some of the examples here
If you don't specify different behavior for the different formats there is no reason to use respond_to. If you have templates they will automatically be picked up by rails. The respond_to method is useful if you need different behavior per format:
respond_to do |format|
format.html { render :edit }
format.json { render :json => '{}' }
end
Is that just means different file type?
I'm trying do this in ROR:
formatted_book_structures_url(book,"choose_list")
I suppose to deal with:
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #structures }
format.choose_list { render :partial => "choose_list" }
end
but the error gives me : uninitialized constant Mime::CHOOSE_LIST
Am I misunderstanding something?
The respond_to block expects you to use a MIME type such as html, json, xml, etc. You can add other custom types (see http://weblog.rubyonrails.org/2006/12/19/using-custom-mime-types) however Rails provides most of the more common types. To fix this you need to change choose_list to something else.
I'm a newcomer to Rails, and have been following the tutorial on the rails webpage.
Using the scaffold instruction to create a "post" model, I found that the new action in the controller has a special directive for XML format:
def new
#post = Post.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #post }
end
end
I can't see the reasoning for supporting an XML request when creating a new post. Browsing to /posts/new.xml returns nothing. What is the purpose of this?
The reasoning for it behind the new action is simply to provide a xml client with the default data (or something else if you want).
The format directive is being used by all routes, and you don't need to support a format unless you want to.
The above code could might as well have looked like:
respond_to do |format|
format.html # renders new.html.erb
format.xml { render :xml => {:message => "XML is not supported"} }
format.json { render :text => #post.to_jsonĀ }
format.js # renders new.js.erb
end
Also, this is not limited to the new action, but is available in all your actions. The format to use is either taken from the url (if the route is set up to use it), or from the HTTP-Accept header that the browser sends.