Secondary sorting of a column using will_paginate - ruby-on-rails

Rails 6
will_paginate
In my model, I have the following:
def index
#books = Book.all.paginate page: params[:page], per_page: params[:per_page]
end
which is going to give me an array of objects, each with the following attributes:
name
author_id
So, in my view, I can do the following:
th= sortable "name", "Name"
th= sortable "author_id", "Author ID"
But what I really want to do, is show the Author Name, which I can get from the book object, as follows:
book.author.name
As book belongs to author
How do Have a column in the table, with the author's name, and make that column sortable?

Did you tried something like this?
controllers/books_controller.rb
def index
books_with_author = Book.all.map { |book|
book.attributes.merge(author_name: book.author.name)
}
#books = books_with_author.paginate page: params[:page], per_page: params[:per_page]
end
Also you can define to your model for future use
models/book.rb
def author_name
self.author.name
end

Related

Rails5: filtering with sunspot_solr

I have a search implemented with the gem sunspot_solr. I would like to add links in the search results to be able to filter the search by alphabetical order and other parameters.
my controller is
class SearchController < SuperSiteController
def index
#sunspot_search = Sunspot.search User, Post do |query|
query.keywords #search_query
query.paginate(:page => params[:page], :per_page => 30)
end
#posts = #sunspot_search.results
end
I wish I could filter for older, recent, and alphabetical order within your search has already been completed. I did not find anything in the documentation about this.
Has anyone worked with this type of search before, and if so, do you know the best practice for doing this?
I think you aim to order results based on a property (data field) of documents.
For example, to sort the results of Post model by created_at, you have to add this field to the index definition in app/models/post.rb as below:
class Post < ActiveRecord::Base
searchable do
...
time :created_at
...
end
end
And then in you SearchController sort the result as below:
class SearchController < SuperSiteController
def index
Post.search do
fulltext #search_query
paginate(:page => params[:page], :per_page => 30)
order_by :created_at, :desc #:desc for descending, :asc for ascending
end
#posts = #sunspot_search.results
end
In order to order results alphabetically you just have to add the field to you index definition as what mentioned above with text function instead of time and use order_by in SearchController.

spree only show products in current taxon not current taxon and descendants

When on taxon page like /clothing how can I change it to only show products in clothing not clothing and its subcategories? In the taxons_controller.rb it is calling
#searcher = build_searcher(params.merge(:taxon => #taxon.id))
#products = #searcher.retrieve_products
In retrieve_products https://github.com/spree/spree/blob/85da083faf81a4b0150e183d2f7aec988e674b07/core/lib/spree/core/search/base.rb#L15 it is using
get_base_scope
which in turn is using:
base_scope.in_taxon(taxon) unless taxon.blank?
https://github.com/spree/spree/blob/b66ea0229646062acb7b6f89ac2447f5ffc862fb/core/app/models/spree/product/scopes.rb#L78 even says in the scope that it includes descendants. How do I override this to only show products in current category?
Found I had to override the search scope in the model. For reference if anyone finds this:
module Spree
Product.class_eval do
add_search_scope :in_taxon do |taxon|
Spree::Product.joins(:taxons).where(Taxon.table_name => { :id => taxon.id }).
order("spree_products_taxons.position ASC")
end
end
end

How to paginate an eager loaded association model

I have the following code :
Post.where("user_id IN [1, 2, 3, 4, 5, 6]").includes(:authors, :comments).paginate(page: params[:page], per_page: 30)
what i want here is to eager load just 8 comments per post using will_paginate, is this possible ? and how ?
Not a tested answer
I don't see that possible from there, but:
Comment.joins(:posts).includes(:posts).where(posts: { user_id: [1,2,3,4,5,6] })
I am not sure if joins and includes can be called together.
This would give you a relation for comments you can continue working on, and you will have eager loaded posts:
#comments = Comment.joins(:post).includes(:post).where(posts: { user_id: [1,2,3,4,5,6] })
#comments.paginate(...)
If you want to get the posts from #comments I would do this:
class Comment < ActiveRecord::Base
def self.post_ids
all.map(&:post_id)
end
def self.posts
Post.where(id: post_ids)
end
end
Then use and paginate it:
#posts = #comments.posts.paginate(...)

How can I sort records ordered by datetime?

#comments has 10 records sorted by id ASC now.
I wanted to reverse order simply, so I coded #comments = #comments.reverse
But I get this error message
ActionView::Template::Error (undefined method `total_count'
<%= page_entries_info(#comments, :entry_name => 'comment').html_safe %>
If I take off reverse and leave it as #comments = #comments, there won't be any problem.
Why? and How can I sort it ordered by created_at DESC?
#comments = Comment.where(:user_id => user_ids, :commentable_type => commentable)
if params[:page].blank?
params[:page] = ((#comments.count - 1)/10) + 1
#comments = #comments.page(params[:page]).per(10)
else
#comments = #comments.page(params[:page]).per(10)
end
#comments = #comments.reverse
You're receiving
ActionView::Template::Error (undefined method `total_count'
because #comments.reverse returns a plain array. You need a Relation object that has the pagination functionality. The best way to accomplish your sorting needs is to create a scope in your comments model:
class Comment < ActiveRecord::Base
scope :reversed, -> { order 'created_at DESC' }
end
Then instantiate your comments by calling the scope:
#comments = Comment.reversed
You can call the page method on that #comments collection and the rest should work. You can chain your where like you had it before, so it would look like:
Comment.reversed.where(:user_id => user_ids, :commentable_type => commentable)
#comments = Comment.where(:user_id => user_ids, :commetable_type => commentable).order("created_at DESC").page(params[:page]).per(10)
ALso, your page calculation is bad can can result in float/fractional numbers. If params[:page] is blank, just default to page 1 for the first page.

Why I cannot use 'order' in sunspot search?

I have a column called cached_votes_up in Communities table.
Now I'd like to fetch the records ordered by its number.
#search = Community.search do
fulltext params[:search]
with(:genre_id, params[:genre])
order_by :cached_votes_up, :desc
paginate :page => params[:page], :per_page => 5
end
#communities = #search.results
But this returns the following error:
No field configured for Community with name 'cached_votes_up'
You need to index the cached_votes_up attribute of your object. Add these lines in your Community model:
searchable do
integer :cached_votes_up
end

Resources