Solr - undefined method `results' for Ransack - ruby-on-rails

I'm working on a project on Ruby on rails and wanted to added a search feature. I installed the solr gem following the steps from this site:
http://es.asciicasts.com/episodes/278-busquedas-con-sunspot
right now, this is how my controller looks like:
class DealsController < ApplicationController
def index
# #deals = Deal.paginate(page: params[:page])
#search = Deal.search do
fulltext params[:search]
end
#deals = #search.results
end
private
def deal_params
params.require(:deal).permit(:title)
end
end
this is my model:
class Deal < ActiveRecord::Base
searchable do
text :title, :info1, :page
end
end
and this is my view:
<div class='container'>
<div class='row upper_container'>
<div class='search_container'>
<%= form_tag deals_path, :method => :get, :class => 'navbar-form navbar-left' do %>
<div class='form-group'>
<%= text_field_tag :search, params[:search], class: 'form-control' %>
</div>
<%= submit_tag 'Search', :name => nil %>
<% end %>
</div>
</div>
<% #deals.each_with_index do |d, i| %>
<% if i % 3 == 0 %>
<div class='row middle_container'>
<% end %>
<div class='col-md-4'>
<div class='deal_container'>
<%= d.title %>
<img src='<%= d.photo %>'>
</div>
</div>
<% if (i % 3 == 2) || (i == (#deals.length - 1)) %>
</div>
<% end %>
<% end %>
<div class='text-center'>
<%= will_paginate #deals %>
</div>
</div>
But i get the following error:
undefined method `results' for Ransack::Search>:Ransack::Search
on this line: #deals = #search.results
Any help? thanks!

Jude, change your
#deals = #search.results
to
#deals = #search.result

Are you by chance using the sunspot gem?
If you are using Active Admin and the Sunspot gem for Rails, beware:
they conflict on the search method leading to some very confusing
results.
Active Admin has a dependency on meta_search which provides a
.search() method on Active Record classes. Sunspot attempts to provide
the same method, aliased from solr_search, but only if the method does
not already exist.
In short, searching can be done using solr_search() rather than
search():
#search = Profile.solr_search do
keywords params[:q]
paginate page: params[:page], per_page: page_size
end
#results = #search.results
http://mrdanadams.com/2012/beware-using-active_admin-and-sunspot-rails-gems-together/

Related

How make caching work with pagination and search form?

I working with ruby on rails and my products views is cached and I can find products with search form. I want to use pagination as well, but when added, it didn't worked and also search form. Found code line ,but not sure how to use it, code below.
<% cache ["v1-#{params[:page]-#{params[:q]", cache_key_for_products]
> do %>
My code
Index.html.erb
<div class="products">
<div class="container">
<center><h1>All products</h1></center>
<div class="row">
<% cache(cache_key_for_products) do %>
<%= render #products %>
<% end %>
</div>
<%= will_paginate #comments, :container => false %>
</div>
</div>
_product.html.erb
<% cache product do %>
<div class="col-md-3 col-lg-3 col-sm-6 col-xs-12">
<div class="product-block">
<h4 id="product-name"><%= product.name %></h4>
<%= link_to product_path(product), class: 'product_link' do %>
<%= image_tag(product.image_url, class: "img-responsive") %>
<% end %>
<div class="price">
<h4>£ <%= product.price %></h4>
</div>
</div>
</div>
<% end %>
products_helper.rb
module ProductsHelper
def cache_key_for_products
count = Product.count
max_updated_at = Product.maximum(:updated_at).try(:utc).try(:to_s, :number)
"products/#{params[:q] || "all"}-#{count}-#{max_updated_at}#{signed_in? && current_user.admin? ? "-admin" : "normal"}"
end
end
products_controller.rb
def index
if params[:q].present?
search_term = params[:q]
if Rails.env.development?
#products = Product.where("name LIKE ?", "%#{search_term}%")
else
#products = Product.where("name ilike ?", "%#{search_term}%")
end
else
#products = Product.all.paginate(:page => params[:page], :per_page => 30)
end
end
In your controller, looks like you are paginating correctly when not performing a search, but need to add the pagination to your search query also:
def index
if params[:q].present?
search_term = params[:q]
if Rails.env.development?
#products = Product.where("name LIKE ?", "%#{search_term}%").paginate(:page => params[:page], :per_page => 30)
else
#products = Product.where("name ilike ?", "%#{search_term}%").paginate(:page => params[:page], :per_page => 30)
end
else
#products = Product.all.paginate(:page => params[:page], :per_page => 30)
end
end
Also you are caching each search result set, this means that the same products could be potentially cached multiple times in many different searches. This will quickly bloat your cache. It would be better to cache each product once and fetch these products from cache regardless of the search.
I see you are caching each product (in _product.html.erb partial). In index.html.erb change the code to this:
<div class="products">
<div class="container">
<center><h1>All products</h1></center>
<div class="row">
<%= render #products, cache: true %>
</div>
<%= will_paginate #comments, :container => false %>
</div>
</div>
This will take advantage of multi fetch fragment caching which Rails 5 has built in:
1.3.1 Collection caching
The render helper can also cache individual templates rendered for a
collection. It can even one up the previous example with each by
reading all cache templates at once instead of one by one. This is
done by passing cached: true when rendering the collection:
<%= render partial: 'products/product', collection: #products, cached:
true %> All cached templates from previous renders will be fetched at
once with much greater speed. Additionally, the templates that haven't
yet been cached will be written to cache and multi fetched on the next
render.
Otherwise if you are < Rails 5, use the Multi Fetch Fragments gem to enable this functionality.
In index.html.erb you could modify the collection cache rendering to something this to use a custom cache key:
<%= render #products, cache: Proc.new{|item| [item, 'show']} %>

Error with instance variable in Index view

So in my tutors_controller.rb this is my index action
def index
#tutor = Tutor.all
#tutor = #tutor.fees_search(params[:fees_search]) if params[:fees_search].present?
end
and in my index.html.erb this is the view
<div class='container'>
<%= form_tag(tutors_path, method: :get) do %>
<%= label_tag 'fees_search', 'Max Fees' %>
<%= select_tag 'fees_search', options_for_select((10..50).step(10)) %>
<%= submit_tag 'Filter' %>
<% end %>
<% #tutor.each do |tutor| %>
<% unless tutor.admin? %>
<div class='row' id='tutor-listing'>
<div class='col-xs-4'>
<%= image_tag(tutor.profile.avatar.url, :class => "img-rounded" ) if tutor.profile.avatar? %>
</div>
<div class='col-xs-8'>
<h3><%= link_to tutor.full_name, tutor_path(tutor) %></h3>
<% unless tutor.subjects.nil? %>
<% tutor.subjects.each do |subs| %>
<span class='badge'id='tutor-listing-badge'>
<%= link_to subs.name, subject_path(subs) %>
</span>
<% end %>
<% end %>
<% unless current_tutor %>
<%= button_to "Shortlist Tutor", add_to_cart_path(tutor.id), :method => :post %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</div>
So i understand that when the index view first renders, #tutor would simply be Tutor.all so it renders each individual tutor perfectly.
After trying to filter it though, i start receiving errors. The exact error is NoMethodError in Tutors#indexand the highlighted line is <% unless tutor.admin? %>
profile.rb model
class Profile < ActiveRecord::Base
belongs_to :tutor
scope :fees_to, -> (fees_to) { where("fees_to <= ?", "#{fees_to}") }
end
tutor.rb model
class Tutor < ActiveRecord::Base
has_one :profile, dependent: :destroy
def self.fees_search(n)
#profile = Profile.fees_to(n)
if #profile.empty?
return Tutor.none
else
#profile.each do |y|
y.tutor
end
end
end
end
I get that now my #tutor instance variable has obviously changed. But how do i go about resolving this problem? Should i be rendering a partial instead? Obviously my index action in my controller could be "better" also but i'm quite confused now as to what i should be doing.
Would appreciate any advice! Thank you!
#profile.each do |y|
y.tutor
end
Seems to be a problem. All the other outcomes are a Tutor.something scope, whereas this will return the last tutor only. Change each to map to get an array of Tutors instead.

Running into undefined method `total_pages' with will_paginate

My goal is to have a tag cloud within my posts page which will allow the user to filter posts by clicking on a tag. However, I am running into an undefined method 'total_pages" error after making the following changes to my Post_Controller method:
class PostsController < ApplicationController
def index
if params[:tag]
#posts = Post.tagged_with(params[:tag])
else
#posts = Post.visible_to(current_user).where("posts.created_at > ?", 7.days.ago).paginate(page: params[:page], per_page: 10)
end
end
end
I am trying to use the acts-as-taggable-on gem, and this logic will show me the posts with the appropriate tags.
The issue happens in the posts/index.html.erb view:
<div class="row">
<div class="col-md-8">
<h1> Trending </h1>
<p class="lead"> Active posts this week </p>
<div id="tag_cloud">
Tag Cloud:
<% tag_cloud Post.tag_counts, %w[s m l] do |tag, css_class| %>
<%= link_to tag.name, tag_path(tag.name), class: css_class %>
<% end %>
</div>
<%= render partial: 'posts/post', collection: #posts %>
<%= will_paginate #posts %>
</div>
<div class="col-md-4">
</div>
</div>
The will_paginate line will not render all the posts on that page. The work around is getting rid of <%= will_paginate #posts %> and replacing
#posts = Post.visible_to(current_user).where("posts.created_at > ?", 7.days.ago).paginate(page: params[:page], per_page: 10)
with #posts = Post.all. However, this gives me an entire page of posts, which is ugly. Does anyone know why I am running into an undefined method 'total_pages' error?
It looks like when you're sending a tag (params[:tag]) it is fetching posts with
#posts = Post.tagged_with(params[:tag])
which is lacking the will paginate call. I believe you could get it working by adding the will paginate scope, like this:
#posts = Post.tagged_with(params[:tag]).paginate(...)

Cannot reverse order because of pagination

I want to order users by descending. However, when I add .reverse it reverses the users a page at a time, not all together.
show_followers:
<%= render #users.reverse %>
<%= will_paginate %>
Users/_user:
<%= link_to user.name, user %>
<% unless #user.nil? %>
<% if request.path == "/users/#{#user.id}/listening_to" %>
<br/>
<span id="member_since"><%= "Listening Since" %> <%= #user.relationships.find_by_followed_id(user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% if request.path == "/users/#{#user.id}/listeners" %>
<br/>
<span id="member_since"><%= "Listener Since" %> <%= user.relationships.find_by_followed_id(#user.id).created_at.strftime("%b. %d, %Y") %></span>
<% end %>
<% end %>
Controller:
#users = #user.followed_users.paginate(page: params[:page])
It seems Rails intelligently orders by the relationships_create like I wanted but it's in ascending order. I want the most recent follower to show up on the top of the list.
In the controller action, you probably have some code that looks something like this: #users = User.paginate(:page => params[:page]).
You need to put the reverse in that statement, so it looks like this: #users = User.paginate(:page => params[:page]).order('id DESC') (perhaps with id replaced by created_at).
#users = #user.followed_users.reverse.paginate(page: params[:page])
Reverse at the controller level prior to pagination

No results with pg_search from search form (Rails 3.1)

Good day!
I use pg_search to implement Full text searching in my web app. I created form where user print his data and then i try to show it but result always empty! What is wrong?
/views/users/index.html.erb
<%= render 'shared/search_form' %>
<%= will_paginate %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
/views/shared/_search_form.erb
<% search_id_attr = :q %>
<%= form_tag( users_path, :method => "get" ) do %>
<%= label_tag( search_id_attr, "Search for:" ) %>
<%= text_field_tag( search_id_attr ) %>
<%= submit_tag("Search", :name => nil ) %>
<% end %>
/controllers/users_controller.rb
class UsersController < ApplicationController
...
def index
#title = "All users"
#users = PgSearch.multisearch( params[:q] ).paginate( :page => params[:page] )
end
...
end
UPD1: After editing in /controllers/users_controller.rb I have params[:q]. Now i get such error:
ActionView::Template::Error (Missing partial pg_search/documents/document with {:handlers=>[:erb, :builder, :coffee], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* "/Users/iUser/rails_projects_terminal/sample_app/app/views"
):
6: <%= will_paginate %>
7:
8: <ul class="users">
9: <%= render #users %>
10: </ul>
11:
12: <%= will_paginate %>
app/views/users/index.html.erb:9:in `_app_views_users_index_html_erb__3107215974202561754_70174719087800'
UPD2: I created empty partial views/pg_search/documents/_document and now i just don't have any results.
I'm the author of pg_search.
You ought to rename your variable from #users to #pg_search_documents, because PgSearch.multisearch always returns objects of type PgSearch::Document, not User.
Then you will want to do something like this in your view:
<%= render 'shared/search_form' %>
<%= will_paginate %>
<ul class="users">
<%= #pg_search_documents.each do |pg_search_document| %>
<%= render pg_search_document.searchable %>
<%= render #users %>
</ul>
<%= will_paginate %>
This is because multisearch was designed for searching across multiple models.
If you want to make a search that only searches User, then you should instead use pg_search_scope to build a search scope directly on the User class. For example:
class User < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_name, :against => [:name]
end
User.search_by_name("ExR") # => returns an Active Record scope of `User` objects.
Let me know if this isn't clear. I know that the documentation has grown a bit large and should be simplified and organized so that developers have a better chance of understanding the subtleties.
Thanks!
params[:Search] will contain the name of your submit button. I think you meant params[:q]. Try that.

Resources