Pagination for API End points usin will_paginate - api

I am trying to create an api end point to show a list.
My snippet is
def index
render json: #business, adapter: :json_api
end
How can I do pagination for this list?. Is it possible by using only will_paginate gem?

Yes it is possible using will_paginate gem aslo, either you can use gem 'api-pagination' click here for more details,
if you dont want to use this gem then you can manually do something like this,
you can create a function for page and limit of records per page like this:
def page
params[:page] || 1
end
def limit
params[:per] || 10
end
And then when you fetch your records you can do something like this:
def index
#business = fetch_business.page(page).per(limit)
render json: #business
end
def fetch_business
#your code to retrive all business
end
And hence you can pass page number on every request which will help you to retrive the data easily.
Since i am begginner into this, comments and suggestions are welcomed.

Related

How do I retrieve a random GET request in Ruby on Rails 5?

I've created my REST API based on Michael Scott from the Office, so far if you go onto the main part of the API it displays all the quotes /api/v1/quotes/ and you can get individual ones if you add an id number such as /api/v1/quotes/5,but I want users to be able to get a random quote when they put in a GET request.
This would preferably be done with an extra part of the URL such as /api/v1/quotes/random.
I've looked at a lot online but I can't figure this out. Do I put my code into the quotes controller and create another function or do I have to put this somewhere else such as routes.db? Also do I put in the SQL function of RANDOM or is there a better and more efficient way to randomise it. My database only has 50 records in it and it's done in mysql2.
Thanks in advance.
It's my first time posting here as usually I hate asking for help as I think I can always figure it out myself but I'm extremely new to Ruby so I'm fairly clueless on how to solve this. If you need me to clarify my question then just let me know.
You can do that in Model as well as controller.
Model:
class Model < ApplicationRecord
def self.random
Model.limit(1).order("RANDOM()").first
end
end
Controller: In method show
def show
render json: Model.find_by(id: params[:id]) || Model.random
end
I hope that helpful.
I would configure a quotes/random collection route:
# in config/routes.rb
resources :quote do
get 'random', on: :collection
end
and use a controller method like this:
# in controllers/quotes_controller.rb
def random
#quote = Quote.order('RAND()').first
render :show
end
Please note: Returning a single random row from a table is database specific – for MySQL
ORDER BY RAND() LIMIT 1
seems to be the way to go.

How to send data to another controller without GET method using link?

I am using Rails 5.2.2. I have users, authors and books tables. Every user can only see the records which saved by themselves.
Books table has user_id and author_id foreign keys. I need to save that data automatically.
In my books_controller.rb file I created a set_defaults method to add this data automatically like,
def set_defaults
params[:book][:user_id] = current_user.id
end
There is no problem with the user_id but I don't know how to access the author id.
I added a link under the authors#show page and want to add book to author using that link.
So how can i get the author_id with the safe way?
Add a Book
This redirects to http://localhost:3000/authors/8/books/new
I don't want to use the id from link and don't want to use get method.
I only want to use the link (Add a book) to save a book.So how can i pass that author object to controller ?
In your html form:
<%= form_for [#author, #book] do |f| %>
# Your Book fields here
<% end %>
In your controller (without an authorization gem)
class AuthorsController < ApplicationController
def show
#author = current_user.authors.find(params[:id])
end
def create
#author = current_user.authors.find(params[:id])
#book = Book.new(book_params)
if #book.save
# handle save
else
# handle error
end
end
private
def book_params
params.require(:book).permit(:title .....)
end
end
Okay i found a solution but i am not sure that it's a good practice. Any better solutions will be appreciated.
I created a global variable in author show.html.erb page :
$current_author = #author
And i used it in books_controller.rb
params[:book][:author_id] = $current_author.id

working on rails 3 tutorial by hartl and stuck on 12.3.4 - New Status Feed

I'm stuck on the last exercise in the Hartlt book 12.3.4 where you define the status feed for yourself and the users you are following. I'm a Rails newbie so just let me know if I need to post additional information.
When I tail the development log I can see will_paginate fire the SQL to gather the initial records, and the initial page looks fine when it is served up. When I click a link to go to any another page, it appears will_paginate doesn't fire the SQL to get retrieve more data from the database as the next page is server up fine, but there is no data.
There are also no new entries in the development log and maybe I'm wrong, but I think this indicates will_paginate didn't hit the database.
I tried to include all the relevant code snippits below. Happy to send anything that's missing.
Here is my pages_controller.rb
def home
#title = "Home"
if signed_in?
#micropost = Micropost.new
#feed_items = current_user.feed.paginate(:page => params[:page])
end
end
Here is my user.rb
def feed
Micropost.from_users_followed_by(self)
end
Here is my microposts.rb
scope :from_users_followed_by, lambda { |user| followed_by(user) }
private
def self.followed_by(user)
following_ids = %(SELECT followed_id FROM relationships
WHERE follower_id = :user_id)
where("user_id IN (#{following_ids}) OR user_id = :user_id",
:user_id => user)
end
NOTE: In the video tutorial (chapter 12, time = 02:06:00) and the book (page 517, listing 12.44) Harlt uses the variable "followed_ids" instead of "following_ids". In the virgin sample code you can download from his site the variable name is "following_ids", and I have tried it both ways - but it fails.
Bottom line - the dev log shows will_paginate retrieving the first batch of data, but it never goes back to the database for additional data.
Can anyone suggest what I can take a look at to resolve my problem?
Many thanks.
do you have more records than will fit on one page?
If not, it may be that will_paginate is doing a count first.
Then deciding not to load any records.
Get into the console and try it out.
$ rails console
user = User.find(23)
# the same user you're logged in as
user.feed.count
# is it more than one page?
user.feed.paginate(:page => 1)
# 20 records?
user.feed.paginate(:page => 2)
# nothing?
Also:
in your example scope :from_users_followed_by, lambda { |user| followed_by(user) } is redundant.
You may as well just say;
def feed
Micropost.followed_by(self)
end

Rails if referrer then do issue

I am trying to figure out the best way to build an if else if statement in the controller around a rails specific referrer. Is there a way to pull the last rails path and use it in the below statement? I think I am close but totally stumped...
This is an update action that will be hit from one form at multiple locations on the site.
I am looking to replace "form_path"
def update
#object = Milestone.find(params[:id])
if #milestone.update_attributes(params[:milestone])
if request.referer == form_path
redirect_to root_path
else
redirect_to object2_path
end
else
....
end
end
Is form_path a variable you're defining somewhere else in the controller? Outside of understanding that, it looks like it should work.
Instead of messing with referer, you could place a hidden_field in the form based on where it's coming from, and pull that out of the params hash.
Something like:
hidden_field_tag :location, controller_name
Then in the controller:
if params[:location] == yadda yadda

making a 'next' link, but (id+1) record might not exist in the database

so i want to make a page the displays a Phrase by select (initially) at random from the database. on that page i want a <%= link_to "next"%> but i was wondering if there was an efficient way to ensure that the next record exists
currently I'm using just
# #phrase is current phrase
<%= link_to "next", phrase_path( Phrase.find( #phrase.id + 1 ) ) %>
yes, i know i should call a #next from the controller, or better yet have a next method in the model to call #phrase.next, but this is for illustrative purposes.
but this often turns up an ActiveRecord::RecordNotFound error because some phrases have been deleted from the db (due to moderation, error, etc...). I could rescue from this and loop that till it works in the controller then pass it or something, but that seems like a bad solution, and not particularly 'railsy'
is there a convenient solution to this anyone has found
figured it out
based on this link which is a little outdated, uses named_scope from back in rails 2. I first rewrote it using the new rails 3 scope style, but then just changed it to a method. just used
def next
Phrase.where("id > ?", self.id).order("id ASC").first
end
def previous
Phrase.where("id < ?", self.id).order("id DESC").first
end
Try creating a next/previous scope on your model, as suggested in http://steve.dynedge.co.uk/2010/01/13/random-previous-and-next-entries-from-active-record-models-using-offset/
This will allow you to do something like:
Phrase.next(5) or Phrase.next(#phrase.id)
Why don't you create a method in the controller called next and pass in the current record id. It would be trivial from there to redirect the user back to the show page for that next resource.
If you are deadset on creating the link in advance, look into creating a helper method to find the next record that exists and make it available in your views. Then you could call that whenever you needed the id of the next available record.
Something like will_paginate might be of help too. I know your page size is just one, but the essence of what you're doing is pagination.