Simple Pagination in json reponse using Rails Rest routes - ruby-on-rails

I am building a simple service(API) that will return json reponse of users objects using Ruby on Rails. Since it returns an array of objects i want to add pagination functionality (:next_page , :prev) as follows.
"nextpage":www.domain.com/users?page=2&per_page=5
Currently i have a restful route that return url www.domain.com/users.How do i reconstruct the url in my index action and how do i make use of limit and offset in this case to make the pagination to work? I want to return 5 items in every page.Sorry i know it is a newbie question, it is my first time creating a service, if somebody could show me how to do the nextpage i would appreciate and i will implement prev by myself. I have tried looking for tutorials to do this but all of them they don't show the logic in the action/method.Thank you
Note: I dont want to use will_paginate, i just need to build simple paginate

Just append your page and page_per to your links to whatever action. Assume you have standard restful resource based routing, i.e.
config/routes.rb:
resources :users
so you'd have the following route generated
GET '/users' => 'users#index'
if you send this url to your rails app:
'/users?page=2&per_page=5'
You will still get the index action, but you'll have two extra parameters , you can do this:
controllers/users_controller.rb
def index
if params[:page]
# do your custom pagination
else
#users = User.all
end
end

Related

Handle non-REST logic in Rails API

For example, let's say I have a Post resource.
With GET /posts I retrieve all posts (index action). What if I want to retrieve trending posts (posts with a lot of likes in the last 24 hours)? Should I implement the logic in the index action (through a parameter), or should I implement a new action trending that responds to a new endpoint GET /trending, making the API non-REST?
Note: I read this article and I understand the parameter way, but I can't figure out how adding an extra endpoint works...
you can do both. I would opt for the new action. But you can pass an extra param as well in a link:
link_to posts_path(trending: true)
In your controller you can then check if params[:trending].present? and then only pass to the posts variable #posts the trending posts.
You can also assign the trending indicator to a variable that will be passed to the index view so that you can adapt the layout (change header from "posts" to "trending posts") with if params[:trending].present? then #trending = true end
Creating a new action makes controllers and views less cluttered with conditions (if ...)
By the way, creating a new action is still a REST logic if you make it a GET query. If your new action was about updating a post it would need be a PATCHquery
Problably you have the resource :posts inside your routes.rb. This is the place you have to add the new endpoint. In rails the route to the new action.
You have
resources :posts
You should have
resources :posts do
get 'trending', on: :collection
end
Now you can see all routes that rails generate to you line, index, show, create, update... and more one trending
/posts/trending
You can have a look here: Rails guides add restful

Custom URLs in rails app

I'm trying to write a simple CMS in rails that will allow text urls rather than the standard /posts/show/<id>.
I have a model that has a title and body, I would like to replace spaces in the title and use it as the url.
I also want to have the url at the root level, not past /pages/show.
Take a look at this gem friendly_id, is used for create url from fields of the model storing it on database. Otherwise, you can create the route that you want example get 'pages/show', home#index and pointing wherever you want.
While the friendly_id gem is really nice, it's quite heavy for such a simple need. You might consider a lighter alternative approach : https://github.com/johnotander/urls_for_humans
You can override your rails urls by setting them like this:
get 'posts' => 'posts#index'
In your routes.
But since you want to format the url for the show action (which depends on a specific id for each item in posts) your best bet is to use the awesome friendly_id gem.
See: https://github.com/norman/friendly_id
Some resources:
http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
http://blog.teamtreehouse.com/creating-vanity-urls-in-rails
I have figured out how to do what I wanted to do.
I am setting a route to the root url with a parameter like this (config/routes.rb):
get ':title', to: 'pages#show', as: :page
Now I have a pages controller that was generated by rails generate scaffold Page title:string body:text
which has a function set_page which I changed to do this (app/controllers/pages_controller.rb):
def set_page
#page = Page.find_by("title" => params[:title])
end

Rails 3: Using a POST form on the index page?

In my Rails 3.0 app I have a series of very large search forms on my resource:index page, requiring the use of POST instead of GET.
Currently, the app is routing the POST request to resource#create, when I want it to route to resource#index. I realize this is the RESTful route, but need to override it. How can I do that, while also preserving the ability to create a new record of that resource?
Thanks much.
You're better off having a "search" action that is post-only - and then renders the index template eg:
class MyController < ...
def search
#my_things = MyThing.find_with_search_params(params[:search])
render :action => :index
end
end
You can use index, just add this in Rails 3 routes:
resources :my_things do
post :index
end
So you want your "create" action end-point in the controller to do 2 things - Respond to search and do the create also? Bad idea, but the solution might be as simple as using an "if" condition in the create action to do one or the other. If its not a satisfactory answer, feel free to clarify your question a bit more.

How to pass a param from one view to another in Ruby on Rails, using POST

I feel like this should be an easy thing to figure out, but I'm stumped.
I have a value in a Project's instance variable called ID. I want to pass that value to a new Photos page to associate each photo that is created with that specific project, but I don't want the Project's ID to show up in the visible query string.
I've tried using link_to and button_to, but (I suspect) since I'm using "resources :photos" in my routes, all of the requests that come to photo#new are being interpreted as GET instead of POST.
Helllllllllllllllp!
Thanks to anyone that can give me some insight, I'v been killing myself over this for the past hour or two already.
--Mark
The usual way to do this in Rails is to create a route that matches urls like this: /projects/4/photos/new. Doing something else is up to you, but Rails makes it really easy to do stuff like this. See more on routes in Rails 3.
Your entry in routes.rb should look something like this:
resources :projects do
resources :photos
end
Then in app/controllers/photos_controller.rb you'd have this for the "New Photo" form page:
def new
#project = Project.find_by_id(params[:project_id])
end
and this for the action that the form in app/views/photos/new.html.erb submits to:
def create
#project = Project.find_by_id(params[:project_id])
#photo = #project.photos.create(params[:photo])
end
Of course you'll want to have error handling and validation in here, but this is the gist of it. And remember, use GET for idempotent (non state-changing) actions (e.g. GET /projects/4/photos), POST for creating a new thing (e.g. POST /projects/4/photos), and PUT for updating an existing thing (e.g. PUT /projects/4/photos/8).

Ruby on Rails Actions help

I have my index page which posts a single entry instead of the usual scaffold default of all of the entries. I told it to link to an action and it just responds to "Couldn't find Post with ID=all". It is the same as the default index method and index view. I assume this has something to do with routing but being no I have no clue. Any ideas?
The "all" name is misleading. If you want a page to display all the posts then the index page is perfect for that. If you want to show a subset of the posts then I recommend adding another action to your controller with a better name and then this to the routes.rb file:
map.resources :posts, :collection => { :some => :get }
Which you then can reference by using some_posts_path or some_posts_url.
For more information read the Official Ruby on Rails Routing guide.

Resources