rails will_paginate not work with search results - ruby-on-rails

I'm following the advanced search form revised from railscasts and i'd like to paginate search results but I don't know where put the code for pagination.
I have a model:
mineralisearch.rb
class Mineralisearch < ActiveRecord::Base
attr_accessible :keywords,:keywords1
def segnalazione_mineralis
#segnalazione_mineralis ||= find_segnalazione_mineralis
end
private
def find_segnalazione_mineralis
segnalazione_mineralis = SegnalazioneMinerali.order(:titolo)
segnalazione_mineralis = segnalazione_mineralis.where("titolo like ?", "%#
{keywords}%") if keywords.present?
segnalazione_mineralis
end
end
I have a controller
mineralisearches_controller.rb
class MineralisearchesController < ApplicationController
def new
#mineralisearch = Mineralisearch.new
end
def create
#mineralisearch = Mineralisearch.create!(params[:mineralisearch])
redirect_to #mineralisearch
end
def show
#mineralisearch = Mineralisearch.find(params[:id])
end
end
and a view
show.html.erb
<h1>Risultati della ricerca</h1>
<table class="table1">
<tr>
<th>Titolo:</th><br>
<th>Creato il:</th>
<th>Ultima Modifica il:</th>
<th></th>
</tr>
<%= render #mineralisearch.segnalazione_mineralis %>
</table>
with this partial
_segnalazione_minerali.html.erb
<tr>
<td><%= segnalazione_minerali.titolo %> </td>
<td><%= l(segnalazione_minerali.created_at, format:"%e %B %Y %k:%M:%S") %></td>
<td><%= l(segnalazione_minerali.updated_at, format:"%e %B %Y %k:%M:%S")%></td>
<td><%= link_to 'Mostra', [segnalazione_minerali.user, segnalazione_minerali]%></td>
</tr>
I know that I must put some code like
#mineralisearch = Mineralisearch.order("Titolo").page(params[:page]).per_page(10)
in the controller
and
<%= will_paginate #mineralisearch, :previous_label => 'Prec', :next_label => 'Succ' %>
but I really don't know where! I tried to put these in the show view and in the controller but they don't work!
Thanks all for help

According to will_paginate
This code
#mineralisearch = Mineralisearch.order("Titolo").page(params[:page]).per_page(10)
should be like this
#mineralisearch = Mineralisearch.order("Titolo").paginate(:page => params[:page],:per_page => 10)
And you can have this
<%= will_paginate #mineralisearch, :previous_label => 'Prec', :next_label => 'Succ' %>
in your show view.
But it is not a normal thing to have pagination in the show view currently which you wants.It is much preferred to have pagination on the index view.If you want to have like this,then you have to move the respected controller code snippet to index action and the view code snippet to the index.html.erb file.

Related

Ruby on Rails search & Result on the same page error

Here the show.html displays a dropdown, which contain Roles.
When we select the role we should able to get permission result in the same page
For that I used partial, but getting error as given in the image,
Without using partial when i tried to display in a separate display.html.erb file , I am getting proper result.
but i want to get result in same show.html.erb file.
Kindly give my some suggestions to attain the proper results
permission_controller
def display
param = params[:role]
id=param[:id]
#roles = Role.includes(:permissions).all
#uniq_controller = Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
redirect_to permissions_show_path
end
def show
#permission = Permission.new
end
show.html.erb
<%= form_tag(:controller => "permissions", :action => "display") do %>
<%= collection_select(:role, :id, Role.all, :id, :name) %>
<button type="submit">search</button>
<% end %>
<th width="25px"> <%= "Controller" %></th>
<th width="25px"> <%= "Permissions" %></th>
<% #uniq_controller.each do |permission| %>
<%= render partial:"display", locals:{permission:permission} %>
<% end %>
_display.html.erb
<thead>
<th width="25px"> <%= permission.first.gsub("_"," ") %></th>
<% permission.second.each do |cont| %>
<tr>
<th width="25px"><%= check_box_tag :permission_ids, {multiple: true},
cont.id %><%= cont.name %></th>
</tr>
<% end %>
</thead>
You haven't defined #uniq_controller in the show action which triggered that error. Just define it in the show action
def show
#permission = Permission.new
#uniq_controller = Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end
You have not defined #uniq_controller in the show action in permission_controller controller which triggers this error.
I'd recommend that you define a method called uniq_controller in permission_controller as follows:
def uniq_controller(id)
Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end
and then make it available in your view as a helper method by adding this code to your permission_controller:
helper_method :uniq_controller
So the code in permission_controller should be like:
helper_method :uniq_controller
def display
#roles = Role.includes(:permissions).all
redirect_to permissions_show_path
end
def show
#permission = Permission.new
end
def uniq_controller(id)
Role.joins(:permissions).where('roles.id=?',id).select('permissions.*').group_by { |p| p.description }
end
Then in your view show.html.erb replace:
#uniq_controller.each
with:
uniq_controller(params[:role][:id]).each
This should fix the error that you are getting and follows Rails practices, for more details about helper_method please refer to:
https://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
One more recommendation is to rename permission_controller to permissions_controller to follow Rails resources/controller naming convention.

What Controls the Mapping of the Rails Controller Method to the View Rendered?

I have a rails application which is not routing as I expected. The search method in the controller is rending show. I've cut down the code to the minimal components and I am posting them here as suggested.
Rails.application.routes.draw do
resources :backups
get 'backups/search' => 'backups#search'
resources :components
resources :backup_media
end
class Component < ActiveRecord::Base
has_many :backups
has_many :backup_media, :through => :backups
end
class BackupMedium < ActiveRecord::Base
has_many :backups
has_many :components, :through => :backups
end
class Backup < ActiveRecord::Base
belongs_to :component
belongs_to :backup_medium
# value to match either the name of the component or backup_medium
def self.search(value)
tables = "backups, components, backup_media"
joins = "backups.backup_medium_id = backup_media.id and components.id = backups.component_id"
c = find_by_sql "select * from #{tables} where components.name like '%#{value}%' and #{joins}"
b = find_by_sql "select * from #{tables} where backup_media.name like '%#{value}%' and #{joins}"
c.count > 0 ? c : b
end
end
class BackupsController < ApplicationController
def search
#backups = Backup.search(params[:search])
render 'index'
end
def index
#backups = Backup.all
end
def show
# this would normally be the code to show an individual backup
# but I'm re-using the code from index because the routing is broken
#backups = Backup.all
end
end
views/backups/_search.html.erb
<%= form_tag backups_search_path, :method => 'get' do %>
<%= label_tag(:search, "Search for:") %>
<%= text_field_tag :search, params[:search], {:placeholder => 'Component or Media' }%>
<%= submit_tag "Search", :name => nil %>
<% end %>
views/backups/index.html.erb
<h1>Listing Backups</h1>
<p id="notice"><%= notice %></p>
<%= render :partial => 'search' %>
<table>
<tr>
<th>id</th>
<th>component_id</th>
<th>backup_medium_id</th>
</tr>
<% #backups.each do |backup| %>
<tr>
<td><%= backup.id %></td>
<td><%= backup.component.name %></td>
<td><%= backup.backup_medium.name %></td>
</tr>
<% end %>
</table>
views/backups/show.html.erb is copied from index.html.erb since it is incorrectly receiving the search results
<h1>Show Backup</h1>
<p id="notice"><%= notice %></p>
<%= render :partial => 'search' %>
<table>
<tr>
<th>id</th>
<th>component_id</th>
<th>backup_medium_id</th>
</tr>
<% #backups.each do |backup| %>
<tr>
<td><%= backup.id %></td>
<td><%= backup.component.name %></td>
<td><%= backup.backup_medium.name %></td>
</tr>
<% end %>
</table>
Suggestions on improving the search method will be welcomed.
As mentioned above, after the search is executed, the show.html.erb is rendered instead of search.html.erb
For a working demo (with better code thanks to suggestions here) see
https://github.com/pamh09/rails-search-demo
You do not have a backups_search_path in your routes, therefore it is treating search in the query string as an id and thus rendering show.html.erb, so try
get 'backups/search' => 'backups#search', as: :backups_search
In debugging I found that rails consistently routed to the wrong view when it was unhappy with the return object coming from the model.

Ruby on rails-Tabular form for input taken from user

I want to print in tabular form the entries given by user. The table will contain 3 columns for name,registration number and classes attended, however the output is not as expected. Its first printing all the names and then all the registration numbers and so on. I want to print a name and the registration number according to name and classes attended.
</head><table width="100%">
<tr>
<th>NAME</th>
<th>REGISTRATION NUMBER</th>
<th>CLASSES ATTENDED</th>
</tr>
<tr>
<% #name_students.each do |t| %>
<th><%= t.name_student %></th><br>
<% end %>
<% #reg_nos.each do |t| %>
<th><%= t.reg_no %></th><br>
<% end %>
<% #classes_ats.each do |t| %>
<th><%= t.classes_at %></th><br>
<% end %>
</tr>
</table>
Here is my controller action.
class PagesController < ApplicationController
def home
#name_students = Page.all
#reg_nos = Page.all
#classes_ats = Page.all
end
def list
#name_students = Page.all
#reg_nos = Page.all
#classes_ats = Page.all
end
def add
Page.create(:name_student => params[:nam])
Page.create(:reg_no => params[:reg])
Page.create(:classes_at => params[:cls])
redirect_to :action => 'home'
end
end
If I understand what you're doing, you should probably have PagesController#home return something like #pages = Page.all object and display the data kind of like this:
<thead>
<tr>
<th>Name</th>
<th>Registration Number</th>
<th>Classes Attended</th>
</tr>
</thead>
<tbody>
<% #pages.each do |p| %>
<tr>
<td><%= p.name %></td>
<td><%= p.registration_number %></td>
<td><%= classes_attended(p.classes_attended) %></td>
</tr>
<% end %>
</tbody>
Above, classes_attended(p) is a call to a helper method that you would use to map the class names of the classes that student attended into an display-able array. Really, that kind of display logic might be better in a decorator, but a helper method should be fine for now.
Let me know if I've totally misunderstood what you're doing, and I'll delete my answer.
Edit to add:
Example index method:
def home
#pages = Page.all
end
Also, looking at your question again, is there a reason you're creating three Page objects with one attribute each instead of one Page object with all three attributes? It should probably look something like Page.create(:name_student => params[:nam], :reg_no => params[:reg], :classes_at => params[:cls]). That's pretty much the only way the solution I posted will work. Again, though, I might be totally misunderstanding what you're going for.

method of an object in index controller

This is a really simple question, but for some reason I cannot find the solution.
My controller is:
def index
#events = Event.all
#I want something here for a single event
distance = Time.now.to_date.distance_to(#event.event_date)
#days = distance[:days]
#months = distance[:months]
#years = distance[:years]
end
Then in the view:
<table>
<tbody>
<% #events.each do |event| %>
<tr>
<td><%= event.title %></td>
<td><%= event.event_date %></td>
<td> Just <%= #days %> days, <%= #months %> months and <%= #years %> years for the event </td>
</tr>
<% end %>
</tbody>
</table>
Of course it doesn't work because there is no #event.
How can I do it?
Thanks in advance!
What you are looking to do is add that functionality to individual records
I would add distance as a method on the Event class
so
class Event < ActiveRecord::Base
#... your model code here
def distance
Time.now.to_date.distance_to(self.event_date)
end
end
the controller
def index
#events = Event.all
end
and in the view
<td> Just <%= event.distance[:days] %> days, <%= event.distance[:months] %> months and <%= event.distance[:years] %> years for the event </td>
You could add some more methods to your model to make it prettier like event.distance_days or something but I will leave that as an exercise for the reader.
"I want something here for a single event."
The default way to find single records is by id:
#event = Event.find(params[:id])
But to me, it should work like that because I don't see #event called in the view.

Ruby on Rails - How to combine display Search results in the View

I have Search controller that searches 2 models - Posts and Categories. The search works, however I am unable to display results in the View correctly - I can't get category names to show up.
I am very confused and frustrated at this point and hope to find some help!
I'm pretty sure (99% sure) the problem is in the View somewhere, because I can get results to display through render inspect thingy.
SearchController.rb
class SearchController < ApplicationController
def index
#posts = Post.search(params[:search])
#categories = Category.search(params[:search])
# combine the results
#results = #posts + #categories
#results.uniq # may be necessary to remove duplicates
end
end
index.html.erb (views/search)
<%= render 'posts/posts', :posts => #posts %>
_posts.html.erb (view/posts)
<h1>Listing posts</h1>
<table>
<tr>
<th>Name</th>
<th>Category</th>
<th>Description</th>
<th>Flag</th>
</tr>
<% if posts %>
<% posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.category.name %></td>
<td><%= post.description %></td>
<td><%= post.flag %></td>
</tr>
<% end %>
<% else %>
<tr><td>No posts</td></tr>
<% end %>
</table>
I can get posts that match the search to display, but I can't display categories. How can I do this? Any help highly appreciated!! Thank you.
If you are using a search backend like sunspot solr then you would be able to combine the searches like
#search = Sunspot.search [User, Company] do
fulltext params[:search]
end
#results = #search.results
And then return the necessary values. In this example, it's showing where you can retrieve the class of the action (controller_name) may not work depending on which controller the results are returned in.
<% #results.each do |result| %>
<% case result.class.to_s %>
<% when "Company" %>
<li><%= "Company: #{result.name}" %></li>
<% when "User" %>
<li><%= "User: #{result.username}" %></li>
<% end %>
<% end %>
The answer (I include all the things I changed to make it work + few files that I didn't change but that have to be there), or How to make simple search for multiple models:
SearchController.rb
class SearchController < ApplicationController
def index
#posts = Post.search(params[:search])
end
end
post.rb
class Post < ActiveRecord::Base
attr_accessible :category_id :name :description :flag
belongs_to :category
def self.search(search)
if search
find(:all, :joins => :category, :conditions => ['posts.equipment LIKE ? OR posts.description LIKE ? or categories.name like ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
find(:all)
end
end
search/index.html.erb
<%= render 'posts/posts', :posts => #posts %>
I added 2 files _post.html.erb and _category.html.erb. They are similar, this is _post.html.erb:
post: <%= post.name %>
(This might not be necessary in some cases or for some models. I can search a third model without this file in its' views. However the third model doesn't have file like _posts.html.erb either).
Finally, _posts.html.erb remains the same:
...
<% if posts %>
<% posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= post.category.name %></td>
<td><%= post.description %></td>
<td><%= post.flag %></td>
</tr>
<% end %>
<% else %>
<tr><td>No posts</td></tr>
<% end %>
...
This works now. Can add new models to the search easily. The only other thing needed for the search is input field.

Resources