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
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.
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.
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
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.
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.