Grails gsp pagination not breaks list item - grails

Today when i customize list method of my controller,facing issue in list.gsp page.My problem is that all records are displayed on a single page.
for ex. Suppose i have 15 records then all 15 will show on first page and also there in next link at footer.when clicks on it all pages show same 15 records.
I was customize code because i need to run query and basis of result of query show records on list page.
def query = "from Book where isAvailable = 'true'"
def bookInstanceList = Book.findAll(query)
[bookInstanceList: bookInstanceList , bookInstanceTotal: bookInstanceList.size()]
it shows all records on a single page and records are not paginate on different page.
i want to show maximum 10 records on each page.
please reply me where i am missing.
Thanks in advance

So pagination will not work that way. You are getting your total of the resulting number of rows that were returned, not what would have been returned without pagination.
def bookQuery = Book.where{ isAvailable == 'true' }
[bookInstanceList: bookQuery.list(params), bookInstanceTotal: bookQuery.count()]
params should contain max and offset to implement pagination.

Related

Ruby on Rails blog application posts display

I was wondering if there's a way to display both my last post created and also the latest three post created in the same page.
So this is how it looks now.what I want is to keep the left column like it is,but on the right column I want my last 3 posts to be displayed:
In my welcome_controller.rb I have this index method defined #post =Post.limit(1).order("created_at desc")that limits the posts to one but if I change it to 3 it applies to both left and right column and I get this really ugly thing]:
You can retrieve last 3 posts by this query
#posts = Post.last(3)
You could define your data in the action, like
#created_post = Post.limit(1).order("created_at desc")
#last_three_posts = Post.limit(3).order("created_at desc")
and change your view accordingly but the created post will always be in the last three so you could use just #last_three_posts
#last_three_posts = Post.limit(3).order("created_at desc")
#created_post = #last_three_posts.first

How can I populate a form with results from one table which can be edited and saved to another table

The answers to date have not worked so I have re-written my request for help. I hope it is more clear what I am struggling with
I want to move fields from an array (Array1) returned from a table(Table1) into another array (Array2), allow edit and write each record to Table2.
Desired methodology in /new_multiple in the controller:
1. #tasks = Task.find(params[:task_ids]) # returns multiple records
#:task_ids are checkbox tags
#returned from previous form
Note: This works.
2. Move #tasks each into #event and send to existing new.html.erb form for edit and/or confirmation before creation as follows(??):
#tasks.each do |task|
#event = Event.new
#event.location = task.task_location
#event.description = task.task_description
event.start_date = start_date + task.days_from_from_start_task
..... more calculated fields
***send to form for edit, show, create and return for next record (QUESTION 1 below)
end
Note: a redirect and return in *** goes to the form, but the data does not show in the form. I haven't determined if it actually returns.
Questions:
1. Is there a way call a form from the middle of an iteration in the controller and then return to the loop for other records?
2. If not, how do I (can I?)
a)move the multiple #tasks records into an #events array as above (for display in a table in a form for edit)
b)tell the system that each individual row of the array is a new record to be written on submit
Background:
I am creating an application which allows the scheduling of sets of future events. Related tasks (sets) are saved in one table and specify a sequence and a number of days from the first task in the group for that task to occur.
The user starts the process by setting the criteria - task group and the start date from which the events will begin.
The task records are then displayed with the calculated dates/time in a table on a form using a form_tag. At this point, they look like the events that are going to be created. Each line has a check-box tag for selection of tasks in the group. After the user has "ticked" their selection of events (or all), the application returns to the controller to a method called new_multiple_events
Up to this point everything works fine and I can see the selected records that have been chosen (ticked) within the events controller using debugger.
I now want to display each record individually and allow the user to edit the calculated date and time that the event will occur plus a few other fields such as the location and notes etc. and then submit the record for creation in the events table. But this is where I am just NOT getting it.
Models:
Tasks table model:
task.task_description
task.task_location
task.task_notes
task.days_from_start_task
task.task_group_name
Event table model:
event.title = task.task_group_name
event.location = task.task_location
event.description = task.task_notes
event.start_date = start_date + task.days_from_from_start_task
etc...
I have a form which works fine for entry of individual events into the calendar and I would like to move the data from the returned tasks array (plus calculated fields) into the events array as default values for this form which will then allow the user to save the data.
Thanking you in advance for any help you can give.
I don't know how you are prepopulating the event you are editing / creating in the form, but your code states you are doing that in a model. You should however create that logic in the controller before rendering the form, so do something like this:
events_controller.rb
def new
task = Task.find(params[:task_id])
#event = Event.new
#event.title = task.task_group_name
#event.location = task.task_location
#event.description = task.task_notes
#event.start_date = start_date + task.days_from_from_start_task
end
Then create your form like you normally do with the form declaration you already found yourself: form_for #event do |f|
Please consider that I used params[:task_id], suggesting you set up your routes for events nested under tasks so that your url structure looks like (for instance): /tasks/13/events/new
Goog luck
I am closing this issue because I didn't receive a relevant answer. I wanted to allow editing of selected data from one table prior to writing the data, with additional information, to another table. To get around the issue I have instead saved the selected data to the other table and then immediately read the data for edit/update. To the user it looks the same.

.order("RANDOM()") with will_paginate gem

I am wondering if there is any way to still use the .order("RANDOM()") with will_paginate so that when a page loads and it orders the pages, all the post will stay the same on each page until the home page is reloaded.
so to have all the posts on localhost:3000/posts?page=1 stay the same until localhost:3000(root_path) is visited again.
Problem is it will paginate posts but it current re orders them for each page selected so you will often see posts on page 1 also on page 2.
One way to do this is to set the random seed which your database is ordering by, such that it returns the same sequence of random numbers each time. You can store this seed in your users' session, and reset it only when you want to. However, there's a complication -- even though setting the random seed produces the same ordering of random numbers each time, there's no guarantee your database will execute it on your rows in the same order each time, unless you force it to do so like so:
SELECT items.*
FROM (SELECT setseed(0.2)) t
, (SELECT name, rank() OVER (ORDER BY name DESC)
FROM foos ORDER BY name DESC) items
JOIN generate_series(1, (SELECT COUNT(*) FROM foos))
ON items.rank = generate_series
ORDER BY RANDOM()
LIMIT 10;
As you can tell, that's quite complicated, and it forces your database to materialize your entire table into memory. It'd work for smaller data sets, but if you've got a big data set, it's out of the question!
Instead, I'd suggest you go with a solution more like tadman suggested above: generate a page of results, store the ids into session, and when you need to generate the next page, simply ignore anything you've already shown the user. The code would look like:
class ThingsController < ApplicationController
def index
#page = params[:page].to_i
session[:pages] ||= {}
if ids = session[:pages][#page]
# Grab the items we already showed, and ensure they show up in the same order.
#things = Things.where(id: ids).sort_by { |thing| ids.index(thing.id) }
else
# Generate a new page of things, filtering anything we've already shown.
#things = Things.where(["id NOT IN (?)", shown_thing_ids])
.order("RANDOM()")
.limit(30) # your page size
# Save the IDs into our session so the above case will work.
session[:pages][#page] = #things.map(&:id)
end
end
private
def shown_thing_ids
session[:pages].values.flatten
end
end
This method uses the session to store which IDs were shown on each page, so you can guarantee the same set of items and ordering will be shown if the user goes back. For a new page, it will exclude any items already displayed. You can reset the cache whenever you want with:
session.delete(:pages)
Hope that helps! You could also use Redis or Memcache to store your page data, but the session is a good choice if you want the ordering to be random per-user.

will_paginate on limite records

I have a problem to paginate the record that I request from other web service to get data. When i make a request i get some data(not all because if i get all it will be too big) and the total number of records. will_paginate seem can only display the first page and from the second page it show nothing.
page = params[:page]? params[:page]:1
#fields = ConflictCase.get_fields
sites = ConflictCase.get_paging_sites_from_service(10, (page.to_i - 1)) #this will request data from other webservice that I limit only 10 records
#conflict_cases = ConflictCase.transform(sites["sites"], #fields)
#conflict_cases = #conflict_cases.paginate(:page => page, :per_page => 10, :total_entries => sites["total"].to_i)
The problem is that i always get only 10 records so it can display on the first page but from the second page it show nothing. I though because will paginate will work on it own to ignore the first 10 records when we move to second page or more.
Have anyone can suggest any idea?
Thank for your help
This is a perfect scenario to use the ruby debugger, or spit out to the logger the values during each iteration of your objects.
Firstly I would assume will_paginate isn't the issue, so I would debug to look at the #conflict_cases object and what is being passed into the paginate() function, and the values each time for page and sites['total'].

Rails Pagination - first page items amount

Is there a way to put more items on the first page than the rest of the pages, when using pagination in Rails?
I am using the Kaminari gem to paginate a list of items and have implemented infinite scroll to browse through the pages. I want to limit the number of listings loaded per page when scrolling, but would like the initial page to start with a significant amount. Below is the current call to Kaminari in my listings controller:
#listings = Listing.page(params[:page]).per(25)
Something like this?
#listings = Listing.page(params[:page]).per(params[:page].to_i == 1 ? 100 : 25)
I solved the problem like this (First page items is supposed 2 items and next pages 7 items):
per_page = 7
#comments = #content.comments.page(params[:page]).per(per_page).padding((per_page-2) * -1)

Resources