How do you output JSON from Ruby on Rails? - ruby-on-rails

I'm looking to have a model that gets created / updated via AJAX. How do you do this in Ruby on Rails?
Also, more specifically: how do you output JSON in RoR?
def create
response = {:success => false}
#source = Source.new(params[:source])
if #source.save
response.success = true
end
render :json => response.to_json
end

All you need to do is call render :json with an object, like so:
render :json => my_object
For most objects, this will just work. If it's an ActiveRecord object, make sure to look at as_json to see how that works. For your case illustrated above, your hash will be transformed to json and returned.
However, you do have an error: you cant access the success key via response.success -- you should instead do response[:success]

jimothy's solution is really good butI believe it isn't scalable in the long term. Rails is meant to be a model, view, and controller framework. Right now JSON is cheated out of a view in default rails. However there's a great project called RABL which allows JSON view. I've written up some arguments for why I think it's a good option and how to get up and running with it quickly. See if this is useful for you: http://blog.dcxn.com/2011/06/22/rails-json-templates-through-rabl/

#source = Source.new(params[:source])
respond_to do | f |
f.html {
# do stuff to populate your html view
# maybe nothing at all because #source is set
}
f.any(:xml, :json) {
render request.format.to_sym => #source
}
end

Related

Rails: JSON.pretty_generate(obj) in the controller does not produce pretty output

I need a pretty output of the JSON for an activerecord object in the rails controller. Based on the answer to this question by jpatokal, I tried the following:
respond_to do |format|
format.json { render :json => JSON.pretty_generate(record) }
end
where
record
is an activerecord object. It does not produce a prettified output. However, when I try outputting a hash using the same code, viz,
respond_to do |format|
format.json { render :json => JSON.pretty_generate({"abc" => "1", "def" => "2"}) }
end
it does produce a prettified output (so pretty_generate is working, and so is my browser).
How do I use pretty_generate to produce a pretty output of an activerecord object?
To get pretty output of JSON from an active record object you have to first request the object as JSON.
record.as_json
The above code will do this for you, the short way to render out pretty JSON from the controller is:
render json: JSON.pretty_generate(record.as_json)
This also solves the "only generation of JSON objects or arrays allowed" error you can get trying to convert AR objects to pretty_generate JSON.
EDIT: I forgot to mention this can all be done in rails 4.1.8 and above (possibly even earlier) using the standard json and multi-json gems packaged with rails project.

Rails Controller -- just return the processed data (dont load into a view)

I'm new to Ruby and Rails. I just completed a course in Laravel, so I am aware of the MVC system(not a newbie as far as the basic concepts are concerned).
I have a rather simple question,
I am sending a POST request to my RAILS REST API,the body of the post request contains a json encoded string like this--->
Array ( [method] => POST [timeout] => 45 [redirection] => 5 [httpversion] => 1.0 [blocking] => 1 [headers] => Array ( ) [body] => {"post_content":"here is the post","post_title":"here we are ","post_author":"1"} [cookies] => Array ( ) )
As you can see,its coming from my php based blog.
My rails API is supposed to be taking the post content and automatically adding links to certains words, by comparing the words with some stuff that i have in an SQLite database.
Ok, so my problem is this:
I just want the response from the Rails controller, I dont want anything loaded into a view. The Rails Controller - returns the content, with 'a href' tags around words that are found in my database. This is to be sent back as the response to my post request, and i want to access it directly as the body of the response.
As of now I dont know how this is to be done. Laravel has the ability to 'return' whatever you want to , at the end of the Controller Action, but in Rails, everything seems to want to load into a view.
I have researched some questions here and found one which said 'render :nothing => true',but that renders nothing at all.Here is what my code looks like.
def process
content = params['post_content']
##perform db function and get back the content with the links embedded.
##HOW TO RETURN THIS CONTENT.
end
Personally, I think, i have to use the render_to_string method, but I have no idea how to do this.
Any help is appreciated.
Best Regards,
Richard Madson.
Some options to consider:
Render just the raw string as the http response body:
render :text => content
Render a view without the default surrounding layout:
render :layout => false
In that case your view could just be:
<%= #content %>
Or render the content as json:
render :json => { :content => content }
The question is, what do you want returned? Text? XML? JSON?
I'm going to assume you want JSON back based on the JSON going in.
respond_to do |format|
format.json { render json: #someobject }
end
It might be helpful to see the rest of the controller method.
If I understand correctly believe what you are looking for is
render :text => "response"
there is also - JSON, XML, nothing, js, file, etc - more information here http://guides.rubyonrails.org/layouts_and_rendering.html

What is the best way to return multiple variables and arrays formatted in xml, json etc with respond_with

I'm looking for a good way to return xml or json from a controller including multiple variables. For example:
def index
#ad = Ad.some_annoying_ad
#map = Map.some_map_for_something
#articles = Articles.trending
respond_with #articles
end
How would I best add the #ad and #map var to the #articles array? I have seen people using the merge function, but I am not sure if that's what I'm looking for. Just want to know which way is most standard, flexible, DRY. Thanks!
Note: I am aware that respond with will automatically format the results in xml or json depending on the file extension added to the url. Thanks!
Instead of merging #ad, #map, just create create a new hash then put add the arrays to it, like
respond_with({:ad => #ad, :map => #map, :article => #article})
It just render all the datas with groups.
I would recommend you to take a look at RABL (stands for Ruby API Builder Language) gem (cast, github). It offers you a DSL for defining the structure of your JSON/XML response in templates (like Haml or CoffeeScript does).
In your case it can be like this:
# in *.json.rabl or *.xml.rabl
object false
child(#ad) { attributes :field1, :field2 }
child(#map) { attributes :field3, :field4 }
child(#article) { attributes :body => :content } # remap is easy!
There is even partials support for DRYing your code. Worth trying.

respond_to with custom format aliasing json format, is this possible?

I have a situation where I'm returning json objects to my application which are built from YML files. Because to parse the yml file and return it as json I always have to do something like this:
format.json { render json: YAML.load(render_to_string :file => File.join(Rails.root,'app','views','home','icons.yml.erb'), :layout => false ) }
I would like to make this operation shorter, by creating a custom format that (however) result in a json, so I don't want to create a new mime type.
My idea is to write:
format.myformat
Which will automatically search for myaction.myformat.erb inside views/mycontroller directory, and will automatically parse the yaml file returning it as a json object.
Is this possible? If yes, how can I eventually do this?
Edit 1:
I found an important suggestion in config/mime_types.rb:
Mime::Type.register_alias "text/html", :iphone
So I can alias a mime type, now the biggest problem is: how to define the default render action for a given format, like format.html does?
If I write
format.html
current_action.html.erb will be automatically rendered, how can I choose the correct method to render a custom format?
Edit 2:
I managed to create this code (inside a controller, through some helper methods I built):
def icons
respond_to do |format|
format.extjson { render_to_extjson }
end
end
Is possible to make rails understand that if I write:
def icons
respond_to do |format|
format.extjson
end
end
it has to do:
format.extjson { render_to_extjson }
by default?
You could do something like:
respond_to do |format|
format.html { #foo = Foo.all(:limit => 10) }
format.any(:atom, :rss) { #foo = Foo.all }
end
A longer post going into the guts of the render actions can be found here: http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to/
While Josh's answer is a valid one, I would rather see your parsing code wrapped up into an object. If you put that object into app/models, it'll be testable and you can always verify any change to the logic with a test suite.
Another upside to this is that you can re-use the format.json call and make you controller that much simpler.
This is not doable at the moment, I read a lot of rails sources and there isn't a way to access that method, so isn't possible to customize it.
I'll write a rails plugin to support this and eventually I'll post it here, but for sure the answer actually is: this can't be done.

Filter a model's attributes before outputting as json

I need to output my model as json and everything is going fine. However, some of the attributes need to be 'beautified' by filtering them through some helper methods, such as number_to_human_size. How would I go about doing this?
In other words, say that I have an attribute named bytes and I want to pass it through number_to_human_size and have that result be output to json.
I would also like to 'trim' what gets output as json if that's possible, since I only need some of the attributes. Is this possible? Can someone please give me an example? I would really appreciate it.
Preliminary search results hint at something regarding as_json, but I can't find a tangible example pertaining to my situation. If this is really the solution, I would really appreciate an example.
Research: It seems I can use to_json's options to explicitly state which attributes I want, but I'm still in need of figuring out how to 'beautify' or 'filter' certain attributes by passing them through a helper before they're output as json.
Would I create a partial for a single json model, so _model.json.erb, and then create another one for the action I'm using, and within that simply render the partial with the collection of objects? Seems like a bunch of hoops to jump through. I'm wondering if there's a more direct/raw way of altering the json representation of a model.
Your model can override the as_json method, which Rails uses when rendering json:
# class.rb
include ActionView::Helpers::NumberHelper
class Item < ActiveRecord::Base
def as_json(options={})
{ :state => state, # just use the attribute when no helper is needed
:downloaded => number_to_human_size(downloaded)
}
end
end
Now you can call render :json in the controller:
#items = Item.all
# ... etc ...
format.json { render :json => #items }
Rails will call Item.as_json for each member of #items and return a JSON-encoded array.
I figured out a solution to this problem, but I don't know if it's the best. I would appreciate insight.
#items = Item.all
#response = []
#items.each do |item|
#response << {
:state => item.state,
:lock_status => item.lock_status,
:downloaded => ActionController::Base.helpers.number_to_human_size(item.downloaded),
:uploaded => ActionController::Base.helpers.number_to_human_size(item.uploaded),
:percent_complete => item.percent_complete,
:down_rate => ActionController::Base.helpers.number_to_human_size(item.down_rate),
:up_rate => ActionController::Base.helpers.number_to_human_size(item.up_rate),
:eta => item.eta
}
end
respond_to do |format|
format.json { render :json => #response }
end
Basically I construct a hash on the fly with the values I want and then render that instead. It's working, but like I said, I'm not sure if it's the best way.

Resources