Search for item name from multiple fields on Ruby on Rails - ruby-on-rails

I'm trying to enable a search for an item, and then have that item listed if the search is completed. I can get it to work for both instances, but not at the same time. My code:
def search
#results=0
if !params[:searchinput].empty?
#results=1
#searchinput = params[:searchinput]
#searchcriteria="%#{params[:searchinput]}%"
#productlist = Product.where("productname like ? OR description like ?", #searchcriteria)
end
end
I get the following error:
Is the formatting with the productlist statement wrong?

The problem is you have to pass in two variables. If that is #searchcriteria then pass that in.
def search
#results=0
if !params[:searchinput].empty?
#results=1
#searchinput = params[:searchinput]
#searchcriteria="%#{params[:searchinput]}%"
#productlist = Product.where("productname like ? OR description like ?", #searchcriteria, #second_variable)
end
end

the productlist statement should look like the following:
#productlist = Product.where("productname like ? OR description like ?", #searchcriteria, #searchcriteria)

Related

ActiveRecord how to use Where only if the parameter you're querying has been passed?

I'm running a query like the below:
Item.where("created_at >=?", Time.parse(params[:created_at])).where(status_id: params[:status_id])
...where the user can decide to NOT provide a parameter, in which case it should be excluded from the query entirely. For example, if the user decides to not pass a created_at and not submit it, I want to run the following:
Item.where(status_id: params[:status_id])
I was thinking even if you had a try statement like Time.try(:parse, params[:created_at]), if params[created_at] were empty, then the query would be .where(created_at >= ?", nil) which would NOT be the intent at all. Same thing with params[:status_id], if the user just didn't pass it, you'd have a query that's .where(status_id:nil) which is again not appropriate, because that's a valid query in itself!
I suppose you can write code like this:
if params[:created_at].present?
#items = Item.where("created_at >= ?", Time.parse(params[:created_at])
end
if params[:status_id].present?
#items = #items.where(status_id: params[:status_id])
end
However, this is less efficient with multiple db calls, and I'm trying to be more efficient. Just wondering if possible.
def index
#products = Product.where(nil) # creates an anonymous scope
#products = #products.status(params[:status]) if params[:status].present?
#products = #products.location(params[:location]) if params[:location].present?
#products = #products.starts_with(params[:starts_with]) if params[:starts_with].present?
end
You can do something like this. Rails is smart in order to identify when it need to build query ;)
You might be interested in checking this blog It was very useful for me and can also be for you.
If you read #where documentation, you can see option to pass nil to where clause.
blank condition :
If the condition is any blank-ish object, then #where is a no-op and returns the current relation.
This gives us option to pass conditions if valid or just return nil will produce previous relation itself.
#items = Item.where(status_condition).where(created_at_condition)
private
def status_condition
['status = ?', params[:status]] unless params[:status].blank?
end
def created_at_condition
['created_at >= ?', Time.parse(params[:created_at])] unless params[:created_at].blank?
end
This would be another option to achieve the desired result. Hope this helps !

building a simple search form in Rails?

I'm trying to build a simple search form in Ruby on Rails, my form is simple enough basically you select fields from a series of options and then all the events matching the fields are shown. The problem comes when I leave any field blank.
Here is the code responsible for filtering the parameters
Event.joins(:eventdates).joins(:categories).where
("eventdates.start_date = ? AND city = ? AND categories.name = ?",
params[:event][:date], params[:event][:city], params[:event][:category]).all
From what I get it's that it looks for events with any empty field, but since all of them have them not empty, it wont match unless all 3 are filled, another problem arises when I try to say, look events inside a range or array of dates, I'm clueless on how to pass multiple days into the search.
I'm pretty new to making search forms in general, so I don't even know if this is the best approach, also I'm trying to keep the searches without the need of a secialized model.
Below is probably what you are looking for. (Note: If all fields all blank, it shows all data in the events table linkable with eventdates and categories.)
events = Event.joins(:eventdates).joins(:categories)
if params[:event]
# includes below where condition to query only if params[:event][:date] has a value
events = events.where("eventdates.start_date = ?", params[:event][:date]) if params[:event][:date].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("city = ?", params[:event][:city]) if params[:event][:city].present?
# includes below where condition to query only if params[:event][:city] has a value
events = events.where("categories.name = ?", params[:event][:category]) if params[:event][:category].present?
end
To search using multiple days:
# params[:event][:dates] is expected to be array of dates.
# Below query gets converted into an 'IN' operation in SQL, something like "where eventdates.start_date IN ['date1', 'date2']"
events = events.where("eventdates.start_date = ?", params[:event][:dates]) if params[:event][:dates].present?
It will be more easy and optimised . If you use concern for filter data.
Make one concern in Model.
filterable.rb
module Filterable
extend ActiveSupport::Concern
module ClassMethods
def filter(filtering_params)
results = self.where(nil)
filtering_params.each do |key, value|
if column_type(key) == :date || column_type(key) ==
:datetime
results = results.where("DATE(#{column(key)}) = ?",
Date.strptime(value, "%m/%d/%Y")) if
value.present?
else
results = results.where("#{column(key)} Like ? ", "%#{value}%") if
value.present?
end
end
results
end
def resource_name
self.table_name
end
def column(key)
return key if key.split(".").count > 1
return "#{resource_name}.#{key}"
end
def column_type(key)
self.columns_hash[key].type
end
end
end
Include this concern in model file that you want to filter.
Model.rb
include Filterable
In your controller Add this methods
def search
#resources = Model.filter(class_search_params)
render 'index'
end
def class_search_params
params.slice(:id,:name) #Your field names
end
So, It is global solution. You dont need to use query for filter. just add this concern in your model file.
That's it.

How to combining two search parameters in Rails

I am just getting into Rails and want to preform a simple search FROM destination TO destination. I have the basic search functionality working and connected to the database but when I choose FROM and TWO the output is combined and I get all transports FROM the specific text and all transports TO the specific text. I want to filter them and only have the ones that go FROM TO.
Here is what I have so far.
class Transport < ApplicationRecord
def self.searchfrom(searchfrom)
where("strtloc LIKE ?", "%#{searchfrom}%")
end
def self.searchto(searchto)
where("endloc LIKE ?", "%#{searchto}%")
end
end
I basically want to add AND in between the two parameters but I am stuck.
This is my transports_controller.rb
if params[:searchfrom]
#transports = Transport.searchfrom(params[:searchfrom])
else
#transports = Transport.all
end
if params[:searchto]
#transports = Transport.searchto(params[:searchto])
else
#transports = Transport.all
end
I also want the ability to only select FROM. So I cant really do a simple AND statement. But one at a time.
Any help apreciated!
Please check this answer:
Ruby on Rails: Search Form - multiple search fields
You should find this is related to you problem.
You can do either of the following:
#transports = Transport.where("strtloc LIKE ? AND endloc LIKE ?", "#{params[:searchfrom]}%", "#{params[:searchto]}%")
It'll do an AND operations between the two parameters.
or
#transports = Transport.where("strtloc LIKE ?", "#{params[:searchfrom]}%")
# first search for start locations
#transports = #transports.where("endloc LIKE ?", "#{params[:searchto]}%")
# then search for end locations in the result of start location.
Also check: HERE

Duplicate results from Rails search (Railscast #111)

I'm getting a weird result when doing a search I've implimented from Railscast #111 (Advanced Search).
The search results are coming through OK from the entries that I have, but when the result is more than 1 (Iv'e only tested for two results) - it doubles the results. So when I expect two results, I get 4 (rendering out in a table).
The weird part is that when I expect 1 result, it only renders the 1 result.
I have a feeling it has something to do with my 'Search.rb' file which gives the search parameters. Can someone else shed some light on why this would be giving duplicate results?
class Search < ActiveRecord::Base
def entries
#entries ||= find_entries
end
private
def find_entries
entries = Entry.order(:firstname)
entries = entries.where("firstname like ?", "%#{firstname}%") if firstname.present?
entries = entries.where("lastname like ?", "%#{lastname}%") if lastname.present?
entries
end
end
I am searching by either firstname or lastname, but the entries have more fields in them.
Try
def find_entries
entries = Entry.order(:firstname)
if !firstname.blank?
entries = entries.where("firstname like ?", "%#{firstname}%")
if !lastname.blank?
entries = entries.where("lastname like ?", "%#{lastname}%")
end
else
if !lastname.blank?
entries = entries.where("lastname like ?", "%#{lastname}%")
end
end
entries
end

More than one ActiveRecord query at once?

Here's an action in my controller. What it currently does is display all Guides that have a least any spelling of the word 'abyss' in it. What I'd like to do is display all guides that have either any spelling of 'abyss' or any spelling of 'cat' in it as well.
I've tried all sorts of '%cat%' combinations, but can't find the right place to put it.
How do I make this work?
def abyss
t = Guide.arel_table
#guides = Guide.where(t[:title].matches('%abyss%'))
end
Try with or as follows:
def abyss
t = Guide.arel_table
#guides = Guide.where(t[:title].matches('%abyss%').or(t[:title].matches('%cat%')))
end
You can use find_by_sql to simplify such queries:
def abyss
#guides = Guide.find_by_sql(["select * from guides where title LIKE ? OR title LIKE ?", '%abyss%', '%cat%'])
end

Resources