How to implement Pagination Rails Rest - ruby-on-rails

I want to implement on Angular 2 pagination but I do not know how to write in controller and in routes on rails. Who can explain how to write controller and routes correctly?
Here is part of my code controller and routes:
Controller:
...
def index
#spr_bit_types = SprBitType.all
render json: #spr_bit_types
end
def show
render json: #spr_bit_type
end
def page
#page = params [: page]
#pre_page = params [: pre_page]
end
...
Routes.rb:
Rails.application.routes.draw do
resources :spr_bit_types, only: [:index, :create, :update, :destroy]
map.connect 'spr_bit_types / page /: page',: controller => 'spr_bit_types',: action =>' page '
...
end
This part of the code does not work at all: map.connect 'spr_bit_types / page /: page',: controller => 'spr_bit_types',: action =>' page '

Use api-pagination gem
and then you can simply write following code
def index
#spr_bit_types = SprBitType.all
paginate json: #spr_bit_types
end
def show
paginate json: #spr_bit_type
end

Related

Rails: How to automatically add a method before the end of each action

I have actions that are supposed to render an index view with different contents. I tried after_action but it still looks for a specific view before running render_index:
after_action :render_index, except: [:index]
def index
#items = Item.all
end
def fruits
#items = Item.where(category: 'fruits')
# render 'index'
end
def cars
#items = Item.where(category: 'cars')
# render 'index'
end
...a lot more
def render_index
render 'index'
end
How can I add render_index just before each end statement so I don't have to write render 'index' over and over?

Controller method #show getting called

I have a link on my #index view:
<%= link_to 'Export Calendar (ICS)', { controller: :tickets, action: :ics_export, format: :ics }, class: "class-needed right" %>
routes.rb that pertains to this:
resources :tickets
get 'tickets/calendar' => 'tickets#ics_export'
post 'tickets' => 'tickets#index'
patch 'tickets/:id/close' => 'tickets#close', as: 'close_ticket'
post 'tickets/:id' => 'ticket_comments#create'
My TicketsController that pertains:
before_action :set_ticket, only: [:show, :edit, :destroy, :update, :close]
def show
#ticket_comment = TicketComment.new
end
def ics_export
tickets = Ticket.all
respond_to do |format|
format.html
format.ics do
cal = Icalendar::Calendar.new
tickets.each do |ticket|
event = Icalendar::Event.new
event.dtstart = ticket.start
event.description = ticket.summary
cal.add_event(event)
end
cal.publish
render :text => cal.to_ical
end
end
end
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
And when I click the link, it takes me to /tickets/calendar.ics which is correct but I get the following error:
ActiveRecord::RecordNotFound in TicketsController#show
Couldn't find Ticket with 'id'=calendar
Extracted source (around line #83):
private
def set_ticket
#ticket = Ticket.find(params[:id])
end
The #ticket = Ticket.find(params[:id]) is highlighted. Which make sense that it is failing to call a ticket with an id of calendar.
Request has parameters:
{"id"=>"calendar",
"format"=>"ics"}
How do I fix this error? Why is it calling the show action?
There is a footnote in the canonical Rails Routing from the Outside In to the effect:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action's route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
As commented, the fix is to specify get 'tickets/calendar' => ... ahead of resources :tickets. If the order of routes is in question, you can run rake routes, which, to the best of my knowledge, should render your routes in the order they are checked.

Rails way to define parameter for filter

There is the following routes:
namespace :api do
namespace :v1 do
resources :places, only: [:index]
end
end
The code of the controller:
class API::V1::PlacesController < API::V1::ApplicationController
def index
#places = (!params[:id]) ? Place.all : Place.find_all_by_type_id(params[:id])
respond_to do |format|
format.json { render json: #places }
format.html
end
end
end
'Place' has 'type_id' field, and I want to filter places by its filter_id. As you can see, now I send the parameter through URL as "places?id=1". But may be I must send parameter as "places/1"? I need also to set up paths; now they doesn't work with "?id=1" form. Please, tell me, how should I do? Thanks.
Rails convention would be to have the list of the places in the "index" action mapped to the relative path /places (GET method).
And then /places/1 (GET) would be mapped to "show", which is intended for presenting a member of the collection. For "show", the route would assign the ID segment of the path ("1") to params[:id].
The guides have a table of default route mappings. The :type_id attribute in the model vs. the :id attribute in the route probably confused you.
A simple solution would be to use /places?type_id=1 instead. In your controller, you can have something like:
def index
collection = Place.all
collection = collection.where(:type_id => params[:type_id].to_s) unless params[:type_id].to_s.blank?
respond_to do |format|
# ...
end
end
Setting :type_id as a query parameter instead of integrating into the relative path seems especially reasonable to me since you are building an API and might add support for more filters in the future.
My recommendation is to rewrite it like this:
# Your routes
namespace :api do
namespace :v1 do
resources :places, only: [:index]
get "/places/by_type/:type_id" => "places#by_type", as: :places_by_type
end
end
# Your controller
class API::V1::PlacesController < API::V1::ApplicationController
def index
respond_to do |format|
format.json { render json: #places }
format.html
end
end
def by_type
#places = Place.where(type_id: params[:type_id])
respond_to do |format|
format.js { render json: #places }
format.html do
render action: "index"
end
end
end
end
I could be slightly wrong about the routes, but I'm pretty sure it should work.

How to nest collection routes?

I use the following routes configuration in a Rails 3 application.
# config/routes.rb
MyApp::Application.routes.draw do
resources :products do
get 'statistics', on: :collection, controller: "statistics", action: "index"
end
end
The StatisticController has two simple methods:
# app/controllers/statistics_controller.rb
class StatisticsController < ApplicationController
def index
#statistics = Statistic.chronologic
render json: #statistics
end
def latest
#statistic = Statistic.latest
render json: #statistic
end
end
This generates the URL /products/statistics which is successfully handled by the StatisticsController.
How can I define a route which leads to the following URL: /products/statistics/latest?
Optional: I tried to put the working definition into a concern but it fails with the error message:
undefined method 'concern' for #<ActionDispatch::Routing::Mapper ...
I think you can do it by two ways.
method 1:
resources :products do
get 'statistics', on: :collection, controller: "statistics", action: "index"
get 'statistics/latest', on: :collection, controller: "statistics", action: "latest"
end
method 2, if you have many routes in products, you should use it for better organized routes:
# config/routes.rb
MyApp::Application.routes.draw do
namespace :products do
resources 'statistics', only: ['index'] do
collection do
get 'latest'
end
end
end
end
and put your StatisticsController in a namespace:
# app/controllers/products/statistics_controller.rb
class Products::StatisticsController < ApplicationController
def index
#statistics = Statistic.chronologic
render json: #statistics
end
def latest
#statistic = Statistic.latest
render json: #statistic
end
end

Rails 3.1/Mongoid - How to find model by name rather than id in routes

Edit: i am using Mongoid/MongoDB for my database, meaning I don't get the normal Active Record tools I think.
I have a simple Rails 3.1 app with a model Page. I would like to match '/:customURL' to the Page#show action for the Page with the relevant :customURL. How should I change the controller and routes? Keep in mind that there are a few routes from '/SOMETHING' that I want to keep. For instance '/pages' should still go to my Page#index action not try to find a page with customURL of 'pages'.
current controller:
def show
#page = Page.find(params[:id])
#title = #page.title
respond_to do |format|
format.html # show.html.erb
format.json { render json: #page }
end
end
routes:
resources :pages do
resources :feeds
end
get "pages/index"
get "pages/show"
get "pages/new"
root :to => "pages#index"
Thanks a million.
Assuming that your Page has a customURL attribute from its database table. In your controller:
def show
#page = Page.first(:conditions => {:customURL => params[:customURL]})
#title = #page.title
respond_to do |format|
format.html # show.html.erb
format.json { render json: #page }
end
end
In your routes
resources :pages, :except => :show do
resources :feeds
end
# Anything you want to match before the custom URLs needs to go above the next route definition
get "/:customURL" => "pages#show"
root :to => "pages#index"

Resources