Conditional JSON output for ActiveRecord Model (Rails 3) - ruby-on-rails

I am using ActiveRecord's as_json integration with ActiveSupport::JSON to render custom output in my controllers. A basic setup I have in my model looks something like this:
def as_json(options = {})
{ :guid => id,
:title => title,
:body => body,
:date => created_at }
end
I want to take this setup a step further and show select information depending upon options passed. My question is, when I call respond_with #model_instance or render :json => #model_instance am I able to pass options that the options argument in as_json receives? If not, should I just create and convert a unique hash in my controller?

Seems like you could just call .as_json and pass in the options, no?
render :json => #mymodel.as_json(:someoption =>" value")

Related

Rails – Display object and a collection in RABL template

I'm using RABL as the foundation for a JSON API. I need to display both an object (#user) and a collection (#posts) in a template. Typically, this is no problem. #posts are a child of #user, so, I just do this:
object #user
attributes :id, :name
child :posts do |post|...
The problem is, I run #posts through a helper method (by_category) in the controller like so:
#user = User.find(params[:id])
#posts = #user.posts.by_category(params[:category])
By just fetching the posts as a child node, I don't apply the helper method – and I can't fetch posts by_category.
I'm wondering how to best approach this, and if there's a way to display both an object and a collection in the same RABL template?
Right from the documentation, you can include locals in partials like this example:
You can also pass in other instance variables to be used in your template as:
Rabl::Renderer.new('posts/show', #post, :locals => { :custom_title => "Hello world!" })
Then, in your template, you can use #custom_title as:
attribute :content
node(:title) { #custom_title }
This allows you to use something like:
Controller:
Rabl::Renderer.new('user/show', #user, :locals => { :posts_category => "examples" })
Partial:
attribute id
node(:posts) { |user| user.posts.by_category(#posts_category) }

Add a single attribute to a model's Json

I have the following code in one of my controllers;
render :json => Article.order("ID Desc").limit(3)
Which outputs an array of articles like:
[{"id":1, "content":"Blah"},{"id":2, "content":"Blah"}, {"id":3, "content":"Blah"}]
All I want to do is add a count attribute to each model. So it would be something like:
[{"id":1, "content":"Blah", "count":3},{"id":2, "content":"Blah", "count":1}, {"id":3, "content":"Blah", "count":6}]
Is there anyway to go about this in my controller without overriding the as_json method?
I saw a merge method called in another question, so I tried this:
render :json => Article.order("ID Desc").limit(3).merge(:count => 2)
with no luck.
It's better for you to handle this json yourself, but not to_json method( of Arrays or active_record)
articles = Article.order("ID Desc").limit(3)
render :json => articles.map { |article|
{
:id => article.id,
:content => article.content,
:count => 3 # or 2 or 1
}
}

Rails: How can I render multiple objects to JSON?

I am trying to render multiple objects as JSON. This is my render call:
render :json => {:widget => #widget.to_json(:include => :foo),
:updated => Time.now.to_i}
I have to use to_json because of the include, and the addition updated so I know when the last call was made. The problem is that the to_json is rendered as a String instead of the object structure of the widget.
How do I get the full object structure of the widget and the updated information?
Move the :include => :foo into your Widget model.
class Widget < ActiveRecord::Base
def as_json(options = {})
super options.merge(:include => :foo)
end
end

How to change values overriding the 'to_json' method?

I am using Ruby on Rails 3 and I would like to override the to_json method.
At this time I use the following code in order to avoid to export important information.
def to_json
super(
:except => [
:password
]
)
end
If I want change a value using that method, how I can do?
For example, I would like to capitalize the user name
:name => name.capitalize
on retrieving this
#user.to_json
If you want to render :json => #user in the controller for Rails 3, you can override as_json in the model:
class User < ActiveRecord::Base
def as_json(options={})
result = super({ :except => :password }.merge(options))
result["user"]["name"] = name.capitalize
result
end
end
Here's a good post about the differences between to_json and as_json.
Use the :methods option to to_json.
http://apidock.com/rails/ActiveRecord/Serialization/to_json

Rails InheritedResources - respond_with JSON, using `find_and_return_for_some_grid` instead of `find(:all)`?

I have a model, say User. I want to call /users (users_controller#index) and pass it basically a scope so it returns data based on:
The format (js, json, html)
The chart/grid/layout it will be rendered in (highcharts, basic html table, jquery flexigrid, etc.)
With inherited_resources and has_scope, you can do something like that but it's not quite it.
I want to return [{:page => 10, :cells => [{:name => "User A"}...]}] if params are something like {:action => "index", :format => "js", :grid => "flexigrid"}, and return [#<User name='User A'>...] rendered in a haml template if it's just html.
How do I do that RESTfully in Rails with inherited resources?
Something like this:
class UsersController < InheritedResources::Base
respond_with :js, :method => :find_and_return_for_grid
end
Does this require me creating my own Responder?
You need to override the index method, something like:
def index
index! do |format|
format.html
format.js do
if(params[:grid] == "flexigrid")
render :json => format_for_grid(collection).to_json
end
end
end
end
With format_for_grid a method that convert an array of Users to the data format you want
Personaly speaking I won't format the js response like this, I mean splitting the response in cells is something I would do on view side with js, beacause has to do with the way you want to display the data, I think it would taste more Restful to just return the non display-oriented collection.to_json

Resources