Rails 4 search function - ruby-on-rails

I have this simple search function:
class SearchController < ApplicationController
def index
if params[:search].blank?
redirect_to root_path
else
#results = Post.search(params[:search])
end
end
end
I want to implement the following functionalities but I am struggling to code:
1.How to record each of the input search terms and see whether which search terms are the most searched ones. I thought of using "first_or_create" method...
2.Give I have this title: "Peter Paul Mary", how do I split them and link_to each terms to search the search function
Please advise.

1.I think you can use two-dimensional array containing results of query for each single term.
#maching_posts = Array.new
#terms = params[:search].split
#terms.each do |term|
result = Post.where(title: term)
#maching_post << result
end
Now, you have array '#maching_post' containing results of query for each single term. Row [0] contains result of first term etc.
You can use this array to generate view. Like this:
<% #terms.each_with_index do |term, index| %>
<span>Results of <%= term %></span>
<% #maching_post[index].each do |post| %>
<%= post.title %></br>
<% end %>
<% end %>
2.To get single words from string you can use split() method.
"Peter Paul Mary".split
This method returns array ["Peter", "Paul", "Mary"]
To link each term, use
link_to 'term', controller: :search, action: :index, search: 'term'
You should use this method in loop, like
<% "Peter Paul Mary".split.each do |term| %>
<%= link_to term, controller: :search, action: :index, search: term %>
<% end %>

Related

search form in nav bar doesn't render anything

I have a search form in my nav bar
<%= simple_form_for :query, url: clients_products_path, method: :get, wrapper: :inline_form, html: {class: 'form-inline'} do |f| %>
<%= f.input :keyword, placeholder: "Recherche" %>
<%= f.submit "Valider" %>
<% end %>
In my product_controller.rb
class Clients::ProductsController < ApplicationController
def index
filter_products if params[:query].present?
#products ||= Product.all
end
private
def filter_products
return if params[:query].blank?
#products = Product.where('lower(title) LIKE ?', params[:query][:keyword]) if params[:query][:keyword].present?
end
end
My query seems to be correct as I can find product in the rails console.
but it doesn't display anything in the product#index...
Where am I wrong?
update
All products are well displayed, and everything disapear when I make a query
clients/products/index.html.erb
<% #products.each do |product| %>
<%= link_to clients_product_path(product) do %>
<%= image_tag(product.attachments.first.url) %>
<%= product.title %>
<%= product.price %>
<% end %>
<% end %>
here is the result
http://localhost:3000/clients/products?utf8=%E2%9C%93&query%5Bkeyword%5D=jean&commit=Valider
I believe your issue lies here:
#products = Product.where('lower(title) LIKE ?', params[:query][:keyword])
You need to either prepend, append or wrap your query with %. For example:
#products = Product.where('lower(title) LIKE ?', "%#{params[:query][:keyword]}%")
# Think it's the above, though could be the following:
# #products = Product.where('lower(title) LIKE "%?%"', params[:query][:keyword])
If you have a read on SQL's LIKE operator, the % operates something like a wildcard. Without these, you're searching for an exact match, rather than a phrase contained within the title. Docs are here.
Give that a shot and let me know how you get on.
First of all you are checking params[:query] twice(once when calling filter_products and second time in that function)
And their is something wrong with you filter_products function.
When you do #products ||= Product.all you get blank ActiveRecordRelation if query returns empty relation. In other words #products will always be blank if query[:keyword] doesn't match the title.
Try changing your index function to:
def index
#products = Product.where('lower(title) LIKE %?%', params[:query][:keyword].downcase) if params[:query][:keyword].present?
puts #products
#products ||= Product.all
end
If it still returns blank, then try to print #products variable.

Ruby on Rails search function solutions

I'm new to Ruby on Rails, so I have serveral questions to my search function.
Search View:
<p>
<%= form_tag students_path, :method => 'get' do %>
<p> Advanced_search: <%= check_box_tag "advanced_search", value = "1" %> </P>
<%= select_tag(:attribute, options_for_select([['Prename',0],['Lastname',1]])) %>
<%= text_field_tag :search%>
<%= submit_tag "Search"%></p>
Controller:
def index
#stud = Student.search(params[:search], params[:advanced_search], params[:attribute])
end
Model:
def self.search(search, advanced_search, attribute)
ary = []
if advanced_search
case attribute
when '0'
ary << Array(where(Student.arel_table[:prename].matches("%#{search}%")))
when '1'
ary << Array(where(Student.arel_table[:lastname].matches("%#{search}%")))
else
raise ArgumentError, 'Something strange happened! problem with select_tag in the search function'
end
elsif search
case attribute
when '0'
ary << Array(where(prename: search))
when '1'
ary << Array(where(lastname: search))
else
raise ArgumentError, 'Something strange happened! problem with select_tag in the search function'
end
else
Student.all
end
ary
end
Index View:
<% #stud.each do |student_arr|%>
<% student_arr.each do |student| %>
<li> <%= student.prename + " " + student.lastname + " " + student._format_birthday + " DaZ: " + student.daz.to_s%>
(<%= link_to "Details", action: "detail", id: student.id %>)
(<%= link_to "Edit", action: "edit", id: student.id %>) </li>
<% end %>
<% end %>
My solution works, I don't get duplicates, but the code look really badly and I have to say "look for pre- OR lastname". May anyone can help me with a better solution.
For me it would be perfect if u are just searching for a Student and u don't have to say for what u are looking for (pre- or lastname) and u don't get duplicates. Maybe a Student name is "Peter Peter" (bad example, but it could happen^^), so I just want to get Peter once in my Student_array. Besides I would like to have the option to search for an explicit prename, so if there is Student called "Hans-Peter" and Student called "Hans" but I just want to find "Hans"...
Is there a way to realize this problems with less and more beautiful code?
Thanks for help and sorry for my bad english.. I'm doing my best :)
Bye Bye
IMO, your code need a complete refactor. Here is the base to help you refactor your search logic:
# student.rb
def self.search(searched_string)
searchable_columns = %w( prename lastname )
sql_conditions = searchable_columns.map do |column_name|
"#{column_name} ILIKE :searched_string"
# use ILIKE if you are using PostgreSQL
# use LIKE if you are using MySQL or SQLite
end.join(' OR ')
where(sql_conditions, searched_string: "%#{searched_string}%")
end
Any Student record having prename or lastname containing the string searched will be returned.
You would have to change your controller's call to the search method accordingly.

Creating site-wide search in a Rails app

I'm trying to create a search form that retrieves results based on a user's query for a restaurant's name. So far I've setup its route, controller, and index view.
routes.rb
resources :search, :only => [:index]
search_controller.rb
class SearchController < ApplicationController
def index
if params[:query].present?
#restaurants = Restaurant.search(params[:query])
else
#restaurants = Restaurant.all
end
end
end
search/index.html.erb
<% #restaurants.each do |restaurant| %>
<%= restaurant.name %>
<% end %>
Here is how the search for is setup:
layouts/_header.html.erb
<%= form_for search_index_path, method: :get do |f| %>
<%= text_field_tag :query, params[:query] %>
<%= submit_tag "Search", name: nil %>
<% end %>
Right now I'm running into two problems. The first being that if I enter a query and submit, the page doesn't go to the index page. All it does is append the query to the current page I'm on:
localhot:3000/restaurant?utf8=✓&query=pizza
Second is that I'm getting every restaurant in my db on the index page (as expected). Is there a way that I can make it so the page is blank for anything other than on search requests?
Question 1
Use form_tag instead of form_for, since the latter is used to handle specific model objects and this is not the case.
Question 2
You can achieve that by:
if params[:query].present?
#restaurants = Restaurant.search(params[:query])
else
#restaurants = [] # or Restaurant.none if you need a chainable scope
end

How do I sort a Nokogiri NodeSet?

I am parsing XML returned from the Google contacts API, using XPath in Nokogiri.
def getcontact
doc = Nokogiri::XML.parse(open(url))
doc.xpath('//xmlns:feed/xmlns:entry[xmlns:title[node()]]')
end
My controller is:
def index
#mycontacts = getcontact.to_a.paginate(:page => params[:page], :per_page => 30)
end
My view is:
<% #mycontacts.each do |c| %>
<p> Name: <%= c.xpath('xmlns:title').text %> Email: <%= c.xpath('gd:email/#address').text %></p>
<% end %>
<%= will_paginate #mycontacts %>
I would like to sort by title in alphabetical order and I am wondering how to go about this. I have read that I can use sort_by, but how do I select the title from the array?
The following should work
#mycontacts.sort!{|a, b| a.xpath('xmlns:title').text <=> b.xpath('xmlns:title').text}
The block tells it to do the comparison based on the .xpath('xmlns:title').text for each object.

Ruby/Rails Simple search form and white spaces

I've implemented a "simple search form" (railscasts #37) in my app, but I wonder how:
1.) I cannot display any results if the keywords field is empty, or if the index page is loaded (I've tried search != "". Maybe there is a better way)
2.) I can add a function which avoid multiple white spaces in the search. (if users wrote something like "benoit+++" or "++benoit" in the search box, it should display results)
I don't want to use thinking sphinx as I would deploy on heroku
Here is the code:
In my user model (user.rb)
def self.search(search)
if search and search != ""
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
end
In my view (views/users/index.html.erb)
<% form_tag users_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
<% end %>
<% if #users and not #users.empty? %>
<% #users.each do |user| %>
<p><%= link_to "#{user.name}", user %></p>
.
.
.
<% end %>
<% end %>
and in my controller ( users_controller.rb)
def index
#users = User.search(params[:search])
end
Thanks for any help or ressources!!
I would change the search method:
def self.search(search)
search.blank? ? [] : all(:conditions => ['name LIKE ?', "%#{search.strip}%"])
end
something.blank? returns true if something is nil or blank.
something.strip removes all the spaces at the beginning or end of a string. If name could be made of more than 1 word and you wanted to prevent from having more than one space between the words, you could do search.strip.squeeze(" ")
Oh, I don't think you need the if #users && !#users.empty? clause in your view now.

Resources