I'm having trouble understanding the best way to make a advanced search form. I have had a good search on the internet, looking at some ways, but I can't get them to work, as most of the suggestions are outdated. I have asked a question already, but I think I was too specific and I wasn't able to fix my problem. I am wanting to search on different text boxes and drop down boxes with one search button.
EDIT2:
projects_controller:
def index
@projects = Project.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @projects }
end
end
def search
@project_search = Project.search(params[:search]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 2, :page => params[:page])
end
# GET /projects/1
# GET /projects/1.json
def show
@project = Project.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @project }
end
end
# GET /projects/new
# GET /projects/new.json
def new
@project = Project.new
respond_to do |format|
format.html # new.html.erb
format.json { render json: @project }
end
end
# GET /projects/1/edit
def edit
@project = Project.find(params[:id])
end
# POST /projects
# POST /projects.json
def create
@project = Project.new(params[:project])
@project.client = params[:new_client] unless params[:new_client].blank?
@project.exception_pm = params[:new_exception_pm] unless params[:new_exception_pm].blank?
@project.project_owner = params[:new_project_owner] unless params[:new_project_owner].blank?
@project.role = params[:new_role] unless params[:new_role].blank?
@project.industry = params[:new_industry] unless params[:new_industry].blank?
@project.business_div = params[:new_business_div] unless params[:new_business_div].blank?
respond_to do |format|
if @project.save
format.html { redirect_to @project, notice: 'Project was successfully created.' }
format.json { render json: @project, status: :created, location: @project }
else
format.html { render action: "new" }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
# PUT /projects/1
# PUT /projects/1.json
def update
@project = Project.find(params[:id])
respond_to do |format|
if @project.update_attributes(params[:project])
format.html { redirect_to @project, notice: 'Project was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @project.errors, status: :unprocessable_entity }
end
end
end
# DELETE /projects/1
# DELETE /projects/1.json
def destroy
@project = Project.find(params[:id])
@project.destroy
respond_to do |format|
format.html { redirect_to projects_url }
format.json { head :no_content }
end
end
private
helper_method :sort_column, :sort_direction
def sort_column
Project.column_names.include?(params[:sort]) ? params[:sort] : "project_name"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
end
Search View:
<h1>Search</h1>
<%= form_tag search_path, method: :get do %>
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<%= text_field_tag :project_name, params[:project_name] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
<table class = "pretty">
<table border="1">
<tr>
<th><%= sortable "project_name", "Project name" %> </th>
<th><%= sortable "client", "Client" %></th>
<th>Exception pm</th>
<th>Project owner</th>
<th>Tech</th>
<th>Role</th>
<th>Industry</th>
<th>Financials</th>
<th>Business div</th>
<th>Status</th>
<th>Start date</th>
<th>End date</th>
<% if false %>
<th>Entry date</th>
<th>Edited date</th>
<th>Summary</th>
<th>Lessons learned</tStackh>
<th>Customer benifits</th>
<th>Keywords</th>
<!th></th>
<!th></th>
<!th></th>
<% end %>
</tr>
<% @project_search.each do |t| %>
<tr>
<td><%= t.project_name %></td>
<td><%= t.client %></td>
<td><%= t.exception_pm %></td>
<td><%= t.project_owner %></td>
<td><%= t.tech %></td>
<td><%= t.role %></td>
<td><%= t.industry %></td>
<td><%= t.financials %></td>
<td><%= t.business_div %></td>
<td><%= t.status %></td>
<td><%= t.start_date %></td>
<td><%= t.end_date %></td>
<% if false %>
<td><%= t.entry_date %></td>
<td><%= t.edited_date %></td>
<td><%= t.summary %></td>
<td><%= t.lessons_learned %></td>
<td><%= t.customer_benifits %></td>
<td><%= t.keywords %></td>
<% end %>
<!td><%#= link_to 'Show', project %></td>
<!td><%#= link_to 'Edit', edit_project_path(project) %></td>
<!td><%#= link_to 'Destroy', project, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</table>
<br />
<%= will_paginate (@project_search) %>
<%= button_to "Search Again?", search_path, :method => "get" %>
<%# end %>
<%= button_to "Home", projects_path, :method => "get" %>
Project.rb
class Project < ActiveRecord::Base
attr_accessible :business_div, :client, :customer_benifits, :edited_date, :end_date, :entry_date, :exception_pm, :financials, :industry, :keywords, :lessons_learned, :project_name, :project_owner, :role, :start_date, :status, :summary, :tech
validates_presence_of :business_div, :client, :customer_benifits, :end_date, :exception_pm, :financials, :industry, :keywords, :lessons_learned, :project_name, :project_owner, :role, :start_date, :status, :summary, :tech
def self.search search_term
return scoped unless search_term.present?
where find(:all, :conditions => ['project_name OR client LIKE ?', "%#{search_term}%"])
end
end
Routes:
FinalApp::Application.routes.draw do
resources :projects
match "search" => "projects#search", :as => :search
root :to => 'projects#index'
end
As you can see, I'm still a fair bit away from having a finished application. I am trying to make a search form that will be able to search on the following fields: Project name, Client, ID, Industry, Role, Technology, Project Owner, Status, Start Date, End Date, and Keywords. The search form would have either text boxes or drop down menus depending on which field the user was searching for. I am wanting to chain each field and search on them all in one go. Before, I was only using project_name, and client as examples to make it easier for you to understand my code. Hopefully you can see now what I am trying to do.
You can create a new controller called search
.
Your search form:
<%= form_tag search_index_path, method: :get do %>
<%= text_field_tag :project, params[:project] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
incude in your routes.rb:
get "search/index"
your search controller:
def index
#store all the projects that match the name searched
@projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
@clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
Now you can play with @projects
and @clients
in the index view.
Just be careful, because these variables might became nil if there is no match for the search.
EDIT - I am assuming you have two models Project
and Client
- if you cannot create a new controller you can create the search action in your current controller.
def search
#store all the projects that match the name searched
@projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
@clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
And than you can use the @projects
and @clients
in the search view.
If you are trying to display the results in somewhere else (for example index
view), you can just move the above to the correct action.
def index
....
#store all the projects that match the name searched
@projects = Project.where("name LIKE ? ", "%#{params[:project]}%")
#store all the clients that match the name searched
@clients = Client.where("name LIKE ? ", "%#{params[:client]}%")
end
EDIT 2 - OK, you are trying to search by a combination of fields in the same model:
You and change your search method to add these two fields:
def self.search(search_project, search_client)
return scoped unless search_project.present? || search_client.present?
where(['project_name LIKE ? AND client LIKE ?', "%#{search_project}%", "%#{search_client}%"])
end
But please note the ||
will return scope if your search_project OR search_client are not present, you can change for AND (&&) if you prefer.
Also, the AND
will return only if both match, I mean the combination of search... You can also change it to OR
if you want.
Having the search form:
Your search form:
<%= form_tag search_index_path, method: :get do %>
<%= text_field_tag :project, params[:project] %>
<%= text_field_tag :client, params[:client] %>
<%= submit_tag "Search", name: nil %>
<% end %>
Then your controller must send the combination to the model:
@project_search = Project.search(params[:project], params[:client]).all
I think it will solve the problem...
I've been using MetaSearch in my application and found it quite convenient. If you've already considered it, what problems did you have?
There's also Ransack by the same author, it's a successor to MetaSearch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With