rails pagy multiple tables on one page - ruby-on-rails

I have two different tables on one page and I want to use pagy on each of them.
For sorting/searching I changed names of each pagy object so I did it like
#pagy_inv, #invoices = pagy #invoices.reorder(sort_column_show_city_invoices => sort_direction_show_city_invoices), items: params.fetch(:count, 10)
and
#pagy_ord, #orders = pagy #orders.reorder(sort_column_show_city_orders => sort_direction_show_city_orders), items: params.fetch(:count, 10)
which works fine for sorting and searching, but when I try to change page, it sends page parameter and tries to change page for every table and therefore if one table has like 5 pages and another 10 and I try to move to page 10 it fails because one of the table cannot move to not existing table.
I was thinking to change page param (for example page_inv and page_ord) but how to do that? Or is there some easy way how to change page only for table from selected pagy object?

As you already understood, pagy use a default :page_param (which is :page): if you use more than one instance in the same page you should differentiate the :page_param of different instances or they will use all the same.
You can pass that in the pagy method (as you did with :items).

Related

Using combined models with pagy, getting undefined method 'offset' error

I am using pagy. I combined two models into one, and I used pagy on that combined model. I am getting this error:
undefined method `offset' for #<Array:0x00007f886f88b3b0>
With the last line of the code below highlighted.
My code:
#problems = Problem.me_and_friends(current_user)
#activities = Activity.me_and_friends(current_user)
#combine = (#problems + #activities).sort{|a,b| a.created_at <=> b.created_at }
#pagy, #combined = pagy_countless(#combine, items:100, link_extra: 'class="" style="color:black; margin:3px;"')
It worked fine with using pagination on #problems alone.
I'd appreciate any help.
As soon as you call the (#problems + #activities), you transform the ActiveRecord::Relation into an array (which is also not good because you are loading all the database rows into memory, sorting and then paginating them). Pagy expects an ActiveRecord::Relation to work, hence the error.
You can consider multiple solutions,
Change your UI to show problems and activities in separate UIs, then you can paginate them separately
Update your models to store both problems and activities in the same table (maybe just a reference table which points to either a Problem or an Activity)
If either of these is not feasible, you can consider rolling out a custom solution for the pagination, but it will be tricky.
Update: June 21, 2021
If you are using Rails 6, it introduces the concept of Delegated Types which fits well into this scenario. The example given in the link mentions the issue of pagination across different tables.

Ordering with awesome_nested_set

As I have find out awesome_nested_set is the most popular Rails gem for making categories tree. Unfortunately, it hasn't categories ordering function or it isn't docummented.
Maybe anyone knows how to change these categories order?
Menu
- about
- first page
- second page
- contacts
I don't know how to to add some new categories in the middle of the tree.
Say that the node called first page is an instance of the model Page and has the ID 3. You can do the following:
first_page = Page.find(3)
new_page = Page.create(:name => 'new page')
new_page.move_to first_page, :right
This will create a new page called new page and put it between first page and second page.
EDIT: after looking at the code, it appears that there is now also a method move_to_right_of, which might be more convenient.

How can I set default page to the last page when using pagination?

Assuming there are 115 communities.
Then it show 10 communities per page with pagination.
When I'm going to example.com/communities, it shows 10 oldest records.
However, I want it to link to example.com/communities?page=12 as default.
It should be linked to the last page of communities.
Is it possible?
Now my link is just like this
<%= link_to "Communities", communities_path %>
This is possible but you have to add some logic
communities = Community.page(params[:page])
communities.total_pages # 12
communities_path(page: communities.total_pages)
or you can just reverse the ordering of your query.
Another way of thinking about it. Change your order by so it shows the newest.
So on your arel query, do something like this:
Blog.all.order("id desc")
I left the pagination call out as i do not know what pagination library you are using :).

Creating Table Filters

I have a simple table with 3 columns like so
table
thead
th Element
th Owner
th Progress
tbody
== render :partial => "element_row" :collection => #elements :as => table_element
Each element is unique, and one owner may have several elements. There are a few different types of "progress" e.g. "started", "not started", and "completed".
I want to create a few links that filter the table. For example, I want to create an started link where when the user clicks on the link, the table is filtered down to only show rows where "started" is displayed. Another example of a filter is by owner.
Does anyone have any suggestions for how to do this?
If you're looking for a gem to help you, Ransack is a great, popular, and active project for searching (and by extension, filtering) ActiveRecord data.
If you check out Ernie's demo site you can see how the search parameters modify the URL through GET queries. You could easily create links like your desired started link to mock these GET form requests.
If you want to do this on the server side, add a filter method to the controller that uses link parameters to filter the #elements.
If you selecting #elements from the database using ActiveRecord, you could do:
#elements = Element.where(progress: params[:progress])
If you just want to filter the #elements in memory, you could do:
#elements = #elements.select{ |element| element.progress == params[:progress] }

break down a complex search query in Rails 3

I have a controller which has a lot of options being sent to it via a form and I'm wondering how best to separate them out as they are not all being used simultaneously. Ie sometimes no, tags, sometimes no price specified. For prices I have a default price set so I can work around with it always being there, but the tags either need to be there, or not. etc.
#locations = Location.find(params[:id])
#location = #locations.places.active.where("cache_price BETWEEN ? AND ?",price_low,price_high).tagged_with([params[:tags]).order(params[:sort]).paginate :page => params[:page]
I haven't seen any good examples of this, but I'm sure it must happen often... any suggestions? Also, even will_paginate which gets tacked on last should be optional as the results either go to a list or to a google map, and the map needs no pagination.
the first thing to do when refactoring a complex search action is to use an anonymous scope.
Ie :
fruits = Fruit.scoped
fruits = fruits.where(:colour => 'red') if options[:red_only]
fruits = fruits.where(:size => 'big') if options[:big_only]
fruits = fruits.limit(10) if options[:only_first]
...
If the action controller still remains too big, you may use a class to handle the search. Moreover, by using a class with Rails 3 and ActiveModel you'll also be able to use validations if you want...
Take a look at one of my plugins : http://github.com/novagile/basic_active_model that allows you to easily create classes that may be used in forms.
Also take a look at http://github.com/novagile/scoped-search another plugin more specialized in creating search objects by using the scopes of a model.

Resources