Implementing pagination in a Ruby on Rails 4 API - ruby-on-rails

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

Conditional except, only, include in render json for Rails

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.

locate file loaded on respond_with #jobs

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

Generate HTML using grape API in rails

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.

Exposing data as XML and JSON in Rails

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

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.

Resources