Search bar + select tag rails - ruby-on-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 =.

Related

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.

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"

doing an OR with ransack (rails)

I have these two inputs:
<%= search_form_for #search, url: search_path, method: :post do |f| %>
<%= f.text_field :thing_false %>
<%= f.text_field :thing_null %>
<% end %>
and when they're both set to "t", I get this query executed:
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' AND "stuffs"."thing" IS NULL))
How do I make it so I get this executed?
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' OR "stuffs"."thing" IS NULL))
The ransack documentation doesn't really address this. This is the closest example that I can find:
>> User.search(:first_name_or_last_name_cont => "Rya").result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%'
OR "users"."last_name" LIKE '%Rya%')
If you don't want the user to have to select the "any" option, you can make it so that the search always uses "OR" by adding something like this in your controller:
#search = User.search(params[:q])
#search.combinator = "or"
#users = #search.result
You can also create different groupings of search fields and specify the appropriate combination within the grouping. The controller could have something like:
#search = User.search(params[:q])
(0..1).each do |index|
#search.build_grouping unless #search.groupings[index]
#search.groupings[index].combinator = "or"
end
#users = #search.result
And the view could have something like:
<%= search_form_for #search do |f| %>
<% #search.groupings.each.with_index do |grouping,index| %>
<%= f.grouping_fields grouping do |g| %>
<% if index == 0 %>
<%#= fields for first grouping here %>
<% end %>
<% if index == 1 %>
<%#= fields for second grouping here %>
<% end %>
<% end %>
<% end %>
<%= f.submit "Search" %>
<% end %>
The RansackDemo page is a good place to play around with the different search options. There is a Simple Mode and an Advanced Mode. The source code is available on github and the views there give some indication of how to put together the groupings and conditions.
Additional info is also available in RailsCast 370.
throw this under your search_form_for tag. This is assuming that you're using f:
<%= f.combinator_select %>
it'll generate a select with two options. ALL or ANY. ANY will use an OR clause. ALL will use an AND clause.

adding search functionality to a paginated page in RoR

Here is the scenario:
I have a table which renders a list of groups (id,title,description,etc) like below which is paginated, it also has a search form:
<div id="navigation" style="background:white;border:1px outset cadetblue;">
<p>
<% form_tag groups_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
</p>
</div>
<table>
.....
</table>
<%= paginate #groups %>
In my groups_controller.rb I have:
#groups = Group.search(params[:search])
#groups = Group.order("id").page(params[:page]).per(15)
which doesn't seem to be working. The pagination works but when I click
the search button it doesn't do anything.
The search function is implemented in the group.rb model:
def self.search(search)
if search
find(:all, :conditions => ['description LIKE ?', "%#{search}%"])
else
find(:all)
end
end
How do I solve this, how do I make my search form work and return results in a paginated way!
Here is the ultimate answer to this post. All the original poster needed to do was this:
#groups = Group.where("description LIKE '%#{params[:search]}%'").order('id').page(params[:page]).per(15)
In an offline discussion, it wasn't working. turns out he had BOTH will_paginate Gem and kaminari Gem for his pagination. He was crapping out when it came to .per(15). Deleting the will_paginate gem fixed it!
will_paginate isn't being actively upgraded, so if you have will_paginate and you are on Rails 3.X, get rid of will_paginate and use kaminari instead, it's a fairly painless swap out, just a bit of css work to format the pagination.
You need to combine those two calls into one, right now you are overriding the first setting of #groups with the second.
I'd add a scope to your group model
class Group
scope :search, lambda { |val| , find(:all, :conditions=>['description LIKE ?', "%#{val}%"]) }
end
Then you can do
#groups = Group.search(params[:search]).order("id").page(params[:page]).per(15)

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