I've followed Ryan Bates' screencast on using jQuery Tokeninput for an auto-completing list for a many-to-many association. Now I want to pull in a photo for each result. I'm using Paperclip and get the url's passed into a JSON file by doing this in the controller:
format.json { render :json => #users.map(&:photo_url) }
Ryan's code for passing the attributes into a JSON file is this:
format.json { render :json => #users.map(&:attributes) }
But how can I combine the two to display both the :attributes and :photo_url methods in the JSON file?
I've tried different things, including the below code, but nothing seems to work. It seems as if there can only be one method called on .map?
// Doesn't work
format.json { render :json => #users.map(&:attributes, &:photo_url) }
// Doesn't work
format.json { render :json => #users.map(&:attributes).map(&:photo_url) }
Does this help? (Note - I'm just returning from a night out and am not 100%, so I might be misunderstanding your question entirely.)
This creates an array of arrays: The first element in the array contains the user's attributes, and the second contains the photo URL:
#users.map {|u| [u.attributes, u.photo_url]}
This creates a hash - just like the above array. But the first element is named "attributes" and the second is named "photo_url".
#users.map {|u| {:attributes => u.attributes, :photo_url => u.photo_url}}
Try plugging one or both of those in. They should work for you.
(E.g. format.json { render :json => #users.map {|u| [u.attributes, u.photo_url]} }).
Edit:
Just had another thought.
You can merge the two into one collection (so that you'll have it all in one hash instead of separate elements in an array):
#users.map {|u| u.attributes.merge(:photo_url => u.photo_url)}
That'll add photo_url as a key to the attributes hash. It might work more easily for whatever code you've written to read the JSON.
In case of this being helpful to anyone, i find out a nice way to do this:
class MyModel < ActiveRecord::Base
has_attached_file :avatar, :styles => { :large => "500x500#", :medium => "300x300#", :small => "100x100#", :thumb => "50x50#" }
def as_json(options)
json = super
self.avatar.styles.each do | format |
json = json.merge({"avatar_"+format[0].to_s => self.avatar(format[0])})
end
json
end
end
You can then simply call
render :json => #my_model
Also working while rendering collections.
It is then possible to do some conditional rendering with as_json(options), with something like:
model_to_json = #my_model.to_json(:nested => true)
render :json => model_json
Related
I am using TinyMCE and I have rolled my own spellchecker using FFI-Hunspell.
I am just rendering this hardcoded response but when I click the spell check button in the WYSIWYG editor, it says that there aren't any misspelled words.
render :json => {:id => "#{params[:id]}", :result => {"presents" => ["presnts"], "motor" => ["moors"]}}.to_json
So, what is the JSON supposed to look like?
I am using the tinymce_rails gem. I would have thought it was using the newer version. Anyways, I found this link that describes in detail how the request/response should look: https://github.com/spohlenz/tinymce-rails. Effectively, the response for the older version of tinyMCE is this:
render :json => ({:id => nil, :result => ['badk', 'wirds'], :error => nil}).to_json
Also, it actually uses a second request to get the suggestions. And those should look like:
render :json => ({:id => nil, :result => ['bad', 'bed'], :error => nil}).to_json
Contrived example:
ActiveAdmin.register Something do
# stuff
controller_action :sad_trombone, :method => :get do
render :json => ["wah", "wah", "wahhh"]
end
end
I hit /admin/somethings/sad_trombone. The JSON response I get looks like this:
{ somethings: ["wah", "wah", "wahhh"] }
While I appreciate the convenient, automagical somethings namespace, I just need my sad_trombone controller to return a plain array, like so:
["wah", "wah", "wahhh"]
How do I do that?
If useful, I'm using:
activeadmin (0.6.0)
rails (3.2.13)
(This is just a simplified example for illustrative purposes.)
Found a solution:
render :json => ["wah", "wah", "wahhh"], :root => false
The :root => false option instructs Rails not to include a root JSON object -- in other words, just the plain data structure you want to return in the response.
In case it's helpful to posterity:
There are (at least) two other, but much more broad ways of accomplishing this:
ActiveRecord.Base.include_root_in_json = false
And:
my_model.to_json(:root => false)
def list
#rings = Ring.order("RAND()")
#JSON RENDERING
render :json => #rings.to_json(:include => [:variations, :stones]), :callback => params[:callback]
end
def show
#showring = Ring.includes(:stones, :variations).find(params[:id])
#other_rings = Ring.select([:id, :stone_count]).where(:style_number => #showring.style_number).reject{ |ring| ring == #showring}
#JSON RENDERING
render :json => {#showring.to_json(:include =>[:variations, :stones]), :other_rings => #other_rings}, :callback => params[:callback]
end
My list view rendering works fine, but when i want to do a show view, with two objects, and showring with includes won't render proper JSON. It is quoting everything in the object with the includes...
JSON output looks like this:
showring => "{"available":"yes","eng...9","stone_y":"149.4"}]}"
other_rings => properly rendered object
On a seperate note, if i have already added the includes to #rings object, why do i then again have to add the association in the "to_json" method?
When you do
render :json => {:show_ring => #showring.to_json(:include =>[:variations, :stones]), :other_rings => #other_rings}
Rails is converting #showring to json (ie getting back a string representation), i.e. the value is the string literal. Instead do
render :json => {:show_ring => #showring.as_json(:include =>[:variations, :stones]), :other_rings => #other_rings}
as_json does all the work of turning the object into a hash but without the final step of turning into a string
if you are going to invest more time in building more JSON objects, you should look into a gem called rabl. It makes building JSON very simple, good for customization which then is good for building API.
Hi I'm using act_as_api to render my xml and json, all is well until i want to add the will_paginate fields into my outputs.
Has anyone been successful?
Found the solution in one of the feature requests for acts_as_api gem
format.xml { render_for_api :template,
:xml => #posts ,
:root => :posts,
:meta => {:current_page => #posts.current_page,
:total_pages => #posts.total_pages,
:per_page => #posts.per_page }}
So there you have it, with meta support, you can add whatever you want, in this case I wanted my pagination data in there.
Metadata support - Add pagination fields
as of today, there is a wiki entry about this topic on github:
https://github.com/fabrik42/acts_as_api/wiki/Add-meta-data-%28like-pagination-info%29-to-your-response
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.