Ruby/Rails Simple search form and white spaces - ruby-on-rails

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.

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.

join query works in console but not in view

I asked a previous question about how to properly structure my search query, but I find that it only works in console. What I have here is virtually identical to a search method used on another model (the other doesn't use joins), but for some reason this one returns nothing. This one also spits %5B%5D out into the url, whereas the other does not.
The search function in my model:
Class Collection
def self.search(search)
if search
joins(blob: :item).where("items.a ILIKE ?", "%#{search}%")
else
order('id DESC')
end
end
end
My controller:
#collections = if params[:search]
current_user.collections.search(params[:search]).order("created_at DESC")
else
current_user.collections.order("created_at DESC")
end
And my view:
<%= form_tag collections_path, method: 'get' do %>
<%= text_field :search, params[:search] %>
<% end %>
<% #collections.each do |c| %>
<%= c.item.a %>
blah blah
<% end %>
The terminal output I get is
`SELECT COUNT(*) FROM "collections" INNER
JOIN "blobs" ON "blobs"."id" = "collections"."blob_id" INNER JOIN
"items" ON "items"."id" = "blobs"."item_id" WHERE
"collections"."user_id" = $1 AND (items.a ILIKE '%#{search}%')
[["user_id", 1]].
Really seems like this should be working, but it's not?
Here is in the OP seeing some wrong, so the follow to the below.
In the join query, no any issue, the issue is where view & controller
You don't need the if search condition because you have already this into controller method
def self.search(search)
joins(blob: :item).where("items.a ILIKE ?", "%#{search}%")
end
Look the ILIKE key only work for PostgreSQL, if your development database is sqlite3 then the query will look like this otherwise as is
joins(blob: :item).where("lower(items.a) LIKE (?)", "%#{search.downcase}%")
change this into self.search method.
And into the controller follow this code
if params[:search].present?
#collections = current_user.collections.search(params[:search]).order("created_at DESC")
else
#collections = current_user.collections.order("created_at DESC")
end
And text field change like this
<%= text_field_tag :search, value: params[:search] %>
So the form will look like this
<%= form_tag collections_path, method: 'get' do %>
<%= text_field_tag :search, params[:search] %>
<% end %>
Hope it will work.

Search bar + select tag rails

I have a search bar + a dropdown list to search for restaurants or meals and be able to filter by category (French food, Indian, foot, etc.)
index.html.erb
<%= form_tag meals_path, method: 'get', id: 'products_search' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= select_tag :search_category, options_for_select(#categories, #categories[0]) %>
<%= submit_tag "Rechercher", name: nil %>
</p>
<% end %>
meals_controller.rb
#meals_search = #meals.search(params[:search], params[:search_category])
model/meal.rb
def self.search(search, search_category)
if search
if search && search_category == "All"
where('name LIKE ?', "%#{search}%")
elsif search == "" && search_category != "All"
where('category = ?', "%#{search_category}%")
else
where('name LIKE ? AND category = ?', "%#{search}%", "%#{search_category}%")
end
else
all
end
end
the search bar works perfectly but the category filter (search_category) does not. I actually get an empty list although you can only filter with category that has at least one restaurant or meal (so the list can't be empty).
Any idea ?
just use ransack, for advanced searching and sorting
OK so, following #vishnuprakash 's suggestion, I used the ransack gem to solve my issue:
I added gem 'ransack' to my Gemfile and ran bundle.
Then I created this form in my index.html.erb:
<%= search_form_for #q do |f| %>
<%= f.search_field :name_cont %>
<%= f.select :category_eq, options_for_select(#categories), include_blank: true %>
<%= f.submit %>
<% end %>
and meals_controller.rb:
#q = #meals.ransack(params[:q])
#meals_search = #q.result(distinct: true)
I also got rid of the function previously created in model/meals.rb.
It now works perfectly ! Do not hesitate to have a look at the ransack dock if you have similar issue. You can also DM me, I'll be happy to help.
Try to change
where('name LIKE ? AND category = ?', "%#{search}%", "%#{search_category}%")
to
where('name LIKE ? AND category = ?', "%#{search}%", search_category)
and
where('category = ?', "%#{search_category}%")
to
where('category = ?', search_category)
The %...% syntax only works with LIKE, not with =.

Rails: Display database query on HTML page, ActiveRecord

I am trying to create a search form for my rails app, the user enters a query and based off that query, I want them to see a list of links associated with that query (these links come from my 'links' table). I created the HTML form and it has the user enter a query. I use this query
<%= form_tag links_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "search", :name => nil %>
</p>
<% end %>
In my controller for the links table, I have an if statement that checks what the user has entered and it assigns Link.where('title LIKE ?', '%{#params[:search]}%') to #links. and then converts it to an array (.to_a)
Here is the statement in the index action:
def index
#links = Link.all
if params[:search]
##links = Link.find(:all, :conditions => ['title LIKE ?', '%{#params[:search]}%'])
#links = Link.where('title LIKE ?', '%{#params[:search]}%')
#links.to_a
end
end
In my index.html.erb I would like to display the result. I used <%= #links %> however, it displays the ActiveRecord: #<Link::ActiveRecord_Relation:0x0000000d5c69f0>
How could I convert the query result ActiveRecord into an array, so then I could be able to index it?
Thanks.
Don't EVER EVER EVER EVER use
#links = Link.where('title LIKE ?', '%{#params[:search]}%')
this is a security issue. Check http://railscasts.com/episodes/25-sql-injection.
In order to see all likes as an output just simply do
#links = Link.where('title LIKE ?', params[:search]')
and in Views do
<%= #links.to_a %>
That should help :)
You need to assigns #links like this:
#links = #links.to_a
By the way, if you want render link one-by-one using something like #links.each, you do not need to convert #links to array.

Searching rails and then returning a Yes or No if it exists in the database?

How do I search my rails model 'Locality' and then return: "Yes" - if the search exists or "No" if the value the user has entered into the search bar is not in the database?
Here's the search bar so far:
<%= form_tag localities_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
This is the code that I've tried to see weather it exists in the database and it works but only for the value in the () not what the user entered in the search bar.
<% if Locality.exists?(12423) %>
No
<% else %>
Yes
<% end %>
Also here is the model file:
def self.search(search)
if search
find(:all, :conditions => ['postcode LIKE ?', "%#{search}%"])
else
find(:all)
end
end
You can do something like this in the controller:
localities = Locality.where("search ILIKE ?", params[:search])
localities.any? ? #result = "YES" : #result = "NO"

Resources