I'm building an API on Rails using ActiveRecordSerializer for serialization. When I want to render a list of resources I use:
render json: #resources
This automatically detects that there is a serializer for the resource, and uses it.
Now I want to implement pagination, and my idea is having a class called PaginatedResponse, instantiate it and render it as a json like this:
render json: PaginatedResponse.new(#resources, <more meta information of the page>)
The problem is that when I use this, everything works well but the resources are not rendered using ActiveRecordSerializer, but a default serializer. I suspect that this is happening because PaginatedResponse does not extend ActiveRecord.
Any clue how can I solve this?
Rails 4 has introduced a new concept jbuilder by default. So just create index.json.jbuilder and put the json syntex based code. Just refer the default scaffold index json jbuilder below,
json.array!(#users) do |user|
json.extract! user, :name, :email, :phone, :native_place
json.url user_url(user, format: :json)
end
This is for rendering all users with his name, phone, native_place.
So remove the line
render json: #resources
from your code and implement the the new jbuilder concept.
The solution was including ActiveModel::SerializerSupport in PaginatedResponse to indicate ActiveRecordSerializer that a serializer should be used.
Related
Can one have conditional except, only or include options when rendering? So, like in the example below:
render json: #post,
except: [:author]
Is it possible to have that except option or a similar option be conditional?
Ideally, something along the lines of a conditional way of doing this that allows me to deal with many different conditions and cases.
Like maybe something like:
render json: #post,
except: return_excluded_keys
return_excluded_keys function could return keys that need to be excluded.
I am using Rails 4.2.6 and Active Model Serializers 0.9.3.
Maybe:
render json: #post.as_json(except: [:author])
Conditional attributes in Active Model Serializers
https://github.com/rails-api/active_model_serializers/issues/825
I believe these should point you in the right direction. You can pass a condition to the serialiser and then manually construct the output.
On my project I have
respond_to :json
load_and_authorize_resource
def show
respond_with #job_pattern
end
as per tutorial here http://blog.plataformatec.com.br/2009/08/embracing-rest-with-mind-body-and-soul/
it works like this: when a request comes, for example with format xml, it will first search for a template at users/index.xml
so I checked for job_patterns/index.json but didnt find any file with this name
can anyone guide me where i can find the file or how the output is generated here if it is not with the file.
Because respond_to :json does not render a view, rather it calls render json: #job_pattern.
render json:#job_pattern calls #job_pattern.to_json and sets the JSON string as the response body. You can do the same with XML or YML.
This is an example of the rails convention over configuration philosophy - if there is a show.json.[erb|haml] it takes priority. Otherwise rails will look for an instance variable which corresponds with the name of the controller (#job or #jobs for index) and attempt to serialize it as JSON.
Further reading:
Justin Weiss: respond_to Without All the Pain
Rails Guides: Layouts and Rendering in Rails
In your case, your action is show so the template associated with is show.json in views/[namespace]/show.json.
You should create this template, or if this template is not found Rails will automatically invoke to_json on the object passed to respond_with.
Refer to documentation.
Recents version of Rails with generated scaffold use show.json.jbuilder as template file.
For more info about it:
jbuilder
I have a requirement where I need to generate/spit out HTML markup from one of my APIs. I am using grape API but cannot find a way to throw out HTML markup. I can specify content-type as text/html and create a HTML markup but is there a better way to achieve this like rendering a template similar to below:
render template:'my_template' locals: {:data => data}
and 'my_template' (HTML) can take care of how the page looks like ? render is an undefined method in GrapeAPI so not sure what other stuff I can use ?
I think it's quite a bad idea to use an API only framework to render HTML...
Nevertheless, you should be able to use the :txt content-type to simply render out your string like you described.
You could use ERB for that, as it is part of the standard-library and pretty easy to use:
require "erb"
class Template
attr_reader :name, :data
def initialize(name, data)
#name = name
#data = data
end
def build
raw = File.read("templates/#{name}.erb")
ERB.new(raw).result(binding)
end
end
as far as I read, grape automatically uses the to_s method of an entity to render :txt, so you could implement something like this in your model:
def to_s
Template.new(self.class.to_s.downcase, self)
end
it might also be possible to register a html content type and write some kind of formatter that does this kind of stuff.
I am trying to understand how I can expose my data in XML and JSON. I have made HTML views for the data now, but I don't understand much of the respond_to block and how you can respond with JSON and XML....and at the same time have control on the structure. Can somebody please help me with where I should start reading and learn how to do this? I haven't had much luck searching for it myself.
You can start by reading this guide. It gives a pretty good idea of how rendering works in rails.
This article is also very helpful.
I use the rabl gem to format the JSON I expose.
Your respond_to block for your users_controller#show action could look like:
respond_to do |format|
format.html
format.json
end
Then you can create a rabl template in /app/views/users/show.json.rabl:
object #user
attributes :id, :username, :first_name, :last_name
You can find more about rabl here
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.