dynamic rendering based on data results - ruby-on-rails

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

Related

rails render page as json

How to render page as json correctly
my chunk of code
respond_to :html, :xml, :json
def getOffersByURL
#my_model= Mymodel.where(attr1: params[:url], :validFrom => {:$lte => Time.now}).all
respond_with #my_model
end
When in trying to do like this nothing happens
http://0.0.0.0:3000/getOffersByURL?url=some_data.xml
or
http://0.0.0.0:3000/getOffersByURL?url=some_data.json
concretely it comes like this
Processing by MyController#getOffersByURL as HTML
Parameters: {"url"=>"some_data.xml"}
Try to change your function:
def getOffersByURL
#my_model= Mymodel.where(attr1: params[:url], :validFrom => {:$lte => Time.now}).all
respond_to do |format|
format.json {
render json: #my_model
}
format.html {
#my_model
}
end
end
What happens if you try to show your json like this in your view:
<%= #my_model.to_json %>
Do you have any data checking the page in the browser? Open the developers tool and try to find if the object brings any data...

Rails' respond_to - syntax analysis

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.

Adding strings to Rails JSON output

I need to output custom JSON in order to be backwards compatible with existing software, which is written in Javascript, so I need to wrap my JSON with "parseDate(" at the beginning of it, and ");" at the end of it.
I tried doing it in controller like this
def index
#data = Data.all
#products = Product.all
respond_to do |format|
format.html
format.json {render :json => { :products => {:product => #data.name}}}
end
end
And then specify it in the view:
app/views/products.json.erb
<%= p "parseData(" %>
<%= render :json %>
<%= p "};" %>
But it outputs pure JSON completely skipping both "parseData(" and ");", why? How do I make JSON to be printed in the middle of the view and then append strings to the top and bottom?
JSON renderer supports a callback option.
format.json { render :json => { :products => {:product => #data.name }}, :callback => 'parseDate' }
You can read the implementation in the renderer.rb source code.

Multiple JSON responses in a single Rails controller action

I have my show method on a controller in my application and in the response block I have
respond_to do |format|
format.html { render :layout =>'placing', :next_days => #next_days}# show.html.erb
format.xml { render :xml => #artist }
format.json { render :partial => "places/show.json", :artist => #artist } }
end
This, generates a json output based in the show.json partial in /places/1.json for example, but what if I want one more json output, like /places/alternative_1.json? How can I do that if there is already a json format block inside respond_to?
Any help is appreciated!
Cheers!
Then you will have to make some logic inside your format.json block changing what you are associating to :partial (currently is "places/show.json"), or create another route...
As format.json { render ... } is normal Ruby code, you could do something like:
format.json do
json_partial = json_for_this_case #example
render :partial => json_partial, :locals => {:artist => #artist}
end

Excluding some ActiveRecord properties from xml rendering in rails

I have an ActiveRecord model that I would like to convert to xml, but I do not want all the properties rendered in xml. Is there a parameter I can pass into the render method to keep a property from being rendered in xml?
Below is an example of what I am talking about.
def show
#person = Person.find(params[:id])
respond_to do |format|
format.xml { render :xml => #person }
end
end
produces the following xml
<person>
<name>Paul</name>
<age>25</age>
<phone>555.555.5555</phone>
</person>
However, I do not want the phone property to be shown. Is there some parameter in the render method that excludes properties from being rendered in xml? Kind of like the following example
def show
#person = Person.find(params[:id])
respond_to do |format|
format.xml { render :xml => #person, :exclude_attribute => :phone }
end
end
which would render the following xml
<person>
<name>Paul</name>
<age>25</age>
</person>
You can pass an array of model attribute names to the :only and :except options, so for your example it would be:
def show
#person = Person.find(params[:id])
respond_to do |format|
format.xml { render :text => #person.to_xml, :except => [:phone] }
end
end
to_xml documentation
I just was wondering this same thing, I made the change at the model level so I wouldn't have to do it in the controller, just another option if you are interested.
model
class Person < ActiveRecord::Base
def to_xml
super(:except => [:phone])
end
def to_json
super(:except => [:phone])
end
end
controller
class PeopleController < ApplicationController
# GET /people
# GET /people.xml
def index
#people = Person.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #people }
format.json { render :json => #people }
end
end
end
I set one of them up for json and xml on every object, kinda convenient when I want to filter things out of every alternative formatted response. The cool thing about this method is that even when you get a collection back, it will call this method and return the filtered results.
The "render :xml" did not work, but the to_xml did work. Below is an example
def show
#person = Person.find(params[:id])
respond_to do |format|
format.xml { render :text => #person.to_xml(:except => [:phone]) }
end
end
The except is good, but you have to remember to put it everywhere. If you're putting this in a controller, every method needs to have an except clause. I overwrite the serializable_hash method in my models to exclude what I don't want to show up. This has the benefits of not having t put it every place you're going to return as well as also applying to JSON responses.

Resources