I was trying to implement a Search Bar and when i tested, it worked in a strange way: only the last letters could be found, or the whole name.
I'm sorry if the problem is simple to solve, i'm new to Ruby On Rails, and i really need this fixed and i couldn't find out how to fix it myself.
(Sorry about my bad English)
Here's my html:
<div class="search">
<%= form_for root_path, :url => {:action => "search"}, class: 'navbar-form' do |f| %>
<%= text_field_tag 'ad[price_min]', #ads_min, :placeholder => "Price min", class: "form-control embed-responsive-item" %>
<%= text_field_tag 'ad[price_max]', #ads_max, :placeholder => "Price max", class: "form-control embed-responsive-item" %>
<%= text_field_tag 'ad[title]', #ads_text, :placeholder => "Search xablau by name", class: "form-control embed-responsive-item" %>
<button class="btn btn-info" ><i class="glyphicon glyphicon-search"></i></button>
<% end %>
</div>
Here's my controller:
def search
if params[:ad].present?
#ads_min = params[:ad][:price_min]
#ads_max = params[:ad][:price_max]
#ads_title = params[:ad][:title]
#ads = Ad.search( params[:ad] )
else
#ads = Ad.all
end
render :action => 'index'
end
Here's my model:
def self.search(query)
price_min = query[:price_min].present? ? "price >= #{query[:price_min].to_f}" : nil
price_max = query[:price_max].present? ? "price <= #{query[:price_max].to_f}" : nil
title = query[:title].present? ? "title LIKE '%#{query[:title]}'" : nil
query = [title, price_min, price_max].compact.join(" AND ")
return Ad.where( query )
end
You have to use ILIKE and %text% instead of %text
title = query[:title].present? ? "title ILIKE '%#{query[:title]}%'" : nil
Because %text% matches with any string that contains text but %text matches only with string that have text on the end of string.
PS: you have to rewrite the search method because it's insecure put a user based text in sql. Do not do that "title LIKE '%#{query[:title]}'" Write something like that where("title ILIKE ?", "%#{params[:q]}%")
Related
I'm teaching myself ruby on rails and getting into all sorts of tangled up shenanigans. I've attached snippets of my MVC down below - I want to have a search bar for a database of pet foods with four entries at this point: two text inputs for ingredients the user WANTS and DOESNT want, and then two sub-menus of checkboxes of frequently WANTED or UNWANTED ingredients.
My text input searches are working (despite messy model string processing code), but I can't figure out how to use a form_with or collections_check_box to be able to append a checked Frequently-unwanted-thing to the :ingredientsno parameter. All I can seem to do is to duplicate the parameter in the HTML link as "...ingredientsno=agar&ingredientsno=&..." -- when I use a hash form, I end up getting a jumbled URL that adds in a bunch of stuff for EACH entry in the hash regardless of if it's checked, which is also not what I want.
Do I need to make a new parameter or property for the checkboxes? Any tips?
Controller:
def index
#products=Product.where(nil)
#common_unwanted={'agar','carrageenan','by-product'}
#product_search = Product.search_ingredients(params[:ingredientsyes],params[:ingredientsno]).all
Model:
class Product < ApplicationRecord
scope :filter_by_ingredientyes, -> (ing) {where('ingredients ILIKE all(array[?])', "#{ing}%")}
scope :filter_by_ingredientno, -> (ing) {where.not('ingredients ILIKE all(array[?])', "#{ing}%")}
def self.search_ingredients(wantstr,nowantstr)
if wantstr || nowantstr
splitstr = wantstr.downcase.split(/\s*,\s*/)
.map { |s| s.gsub(/[_%]/, '%' => '\\%', '_' => '\\_') }
.map { |s| '%' + s + '%' }
splitstr_excl = nowantstr.downcase.split(/\s*,\s*/)
.map { |s| s.gsub(/[_%]/, '%' => '\\%', '_' => '\\_') }
.map { |s| '%' + s + '%' }
puts"test1"
puts splitstr.length
puts"test2"
puts splitstr_excl.length
if splitstr.length>=1 && splitstr_excl.length>=1
incl_results = Product.where('ingredients ILIKE all(array[?])', splitstr)
results=incl_results.where.not('ingredients ILIKE all(array[?])', splitstr_excl)
elsif splitstr.length>=1
results = Product.where('ingredients ILIKE all(array[?])', splitstr)
elsif splitstr_excl.length>=1
incl_results = Product.where.not('ingredients ILIKE all(array[?])', splitstr_excl)
incl_results
else
self.all
end
#findbool=Product.where('ingredients ILIKE ?', '%'+want+ '%')
#findbool=Product.where('ingredients ILIKE ?', '%'+want+ '%')
else
self.all
end
end
View:
<h3> Search by ingredient: </h3>
<%= form_with(model: #product, method: :get) do |form| %>
<%= form.label :query, "Contains:" %>
<%= form.text_field :ingredientsyes, value: params[:ingredientsyes] %>
<%= form.label :query, "Contains no:" %>
<table>
<%= form.text_field :ingredientsno, value: params[:ingredientsno] %>
<br>
<%= form.submit "Search" %>
<% end %>
<p> Searching for (<%= params[:ingredientsyes] %>) and no (<%= params[:ingredientsno] %>)
<%= form_with(model: #product, method: :get) do |form| %>
<%= form.submit "Reset" %>
<% end %>
Hi I need when I type minimum number and the maximum number to show all the cars in between something like this https://www.lpauto.ca/used-cars-vancouver?Makes=Audi
Here is my form
<%= form_for "",url: cars_path, role: "search", method: :get do %>
<%= text_field_tag :searchp, #search_pricen_term,placeholder: "Min..." %>
<%= text_field_tag :searchpx, #search_pricex_term,placeholder: "Max..." %>
<% end %>
In the controller in index
if params[:searchp]
#search_pricen_term = params[:searchp]
#cars= #cars.search_by(#search_pricen_term)
end
In the model
def self.search_by(search_pricen_term)
where("price <= :search_pricen_term OR price >= :search_pricex_term ",
search_pricen_term: search_pricen_term )
end
Updated the where condition in the model class by using 'scope'
which receives both minimum and maximum value and returns all the cars
between the given range.
Hope this helps.
In the controller, pass both minimum and maximum value to the model.
if params[:searchp] || params[:searchpx]
#search_pricen_term = params[:searchp]
#search_pricex_term = params[:searchpx]
#cars = Car.between_range(#search_pricen_term, #search_pricex_term)
end
In View,
<%= form_for "",url: cars_path, role: "search", method: :get do %>
<%= text_field_tag :searchp, #search_pricen_term,placeholder: "Min..." %>
<%= text_field_tag :searchpx, #search_pricex_term,placeholder: "Max..." %>
<%= submit_tag "Submit" %>
<% end %>
In the model,
scope :between_range, -> (min, max) { where("price >= ? OR price <= ?", min, max) }
I try to pass 2 options for search. First [:q] for input text by visitor and another one from model camping "nomdep" (like departement in english). When i try to search by input it's works, but since i try to add select_tag i have an error
ERROR
undefined method `map' for nil:NilClass
I m lost, do u have any ideas ?
Sorry for my english, i m french.
Home_controler.rb
def index
if params[:q].nil?
"Entrez un mot clef"
else
#campings = Camping.__elasticsearch__.search params[:q,:nomdep]
#camping = Camping.all
end
end
def result
if params[:q].nil?
#campings = []
else
#campings = Camping.__elasticsearch__.search(params[:q]).page(params[:page]).per(14).results
end
end
View
<div class="search">
<%= form_tag(result_path, method: :get) %>
<%= text_field_tag :q, params[:q], class:"search-query form-control" %>
<%= select_tag(:nomdep, options_for_select(#camping)) %>
<%= submit_tag "Partez", class:"btn btn-danger", name: nil %>
</div>
EDIT
Now i dont have any error but the search dont work if [:q] empty. So if i only select_tag => no result.
How fix this ?
My full home_controller.rb
class HomeController < ApplicationController
def index
#camping = Camping.all
if params[:q].nil?
"Entrez un mot clef"
else
#campings = Camping.__elasticsearch__.search params[:q, :nomdep]
end
end
def result
if params[:q].nil?
#campings = []
else
#campings = Camping.__elasticsearch__.search(params[:q]).page(params[:page]).per(14).results
end
end
end
my view
<div class="search">
<%= form_tag(result_path, method: :get) %>
<%= select_tag :nomdep, options_from_collection_for_select(#camping, :id, :nomdep), prompt: "Département" %>
<%= text_field_tag :q, params[:q], class:"search-query form-control" %>
<%= submit_tag "Partez", class:"btn btn-danger", name: nil %>
</div>
#camping = Camping.all
This variable will be nil unless :q was passed in params to index action. options_for_select(#camping) will attempt to call #map on this variable and raise error when it is not initialized.
You should make sure it is initialized. For example, try rewriting your action:
def index
#camping = Camping.all
if params[:q].nil?
"Entrez un mot clef"
else
#campings = Camping.__elasticsearch__.search params[:q]
end
end
I want to say a big big big THANKS to #Baradzed ! We talked yesterday and he find a solution thats work perfectly !
home_controller.rb
class HomeController < ApplicationController
def index
#camping = Departement.all
if params[:q].blank? || params[:nomdep].blank?
#campings = Camping.__elasticsearch__.search params[:nomdep]
else
#campings = Camping.__elasticsearch__.search params[:q]
end
end
def result
querystring = params.slice(:nomdep, :other_param, :any_params_except_q_because_we_will_process_q_separately)
.select{|k,v| v.present?}
.map {|key, value| "#{key}:\"#{value.gsub(/([#{Regexp.escape('\\+-&|!(){}[]^~*?:/')}])/, '\\\\\1') }\""}
.join(" AND ")
freetext = params[:q]
freetext.gsub!(/([#{Regexp.escape('\\+-&|!(){}[]^~*?:/')}])/, '\\\\\1')
querystring = ["*#{freetext}*",querystring].select{|v| v.present?}.join(" AND ") if params[:q].present?
if querystring.blank?
flash[:notice] = "Aucune mots clefs"
redirect_to action: :index and return
else
#campings = Camping.__elasticsearch__.search(
query: { query_string: {
query: querystring
}}).page(params[:page]).per(14).results
end
#hash = Gmaps4rails.build_markers(#campings) do |camping, marker|
marker.lat camping.latitude
marker.lng camping.longitude
marker.infowindow render_to_string(:partial => "/campings/infowindow", :locals => { :camping => camping})
marker.picture ({
"url" => "http://avantjetaisriche.com/map-pin.png",
"width" => 29,
"height" => 32})
end
end
end
view
<div class="search">
<%= form_tag(result_path, method: :get) %>
<%= select_tag :nomdep, options_from_collection_for_select(#camping, :nomdep, :nomdep), prompt: "Département" %>
<%= text_field_tag :q, params[:q], class:"search-query form-control" %>
<%= submit_tag "Partez", class:"btn btn-danger", name: nil %>
I'm making an application where the user can search Amazon (with Vacuum) through my application for books, then be able to record the data of the book to their library.
When you search for a book, it goes through every result and puts each in a thumbnail. In every thumbnail there is a button that opens a modal with a form with hidden tags. When the user clicks the submit button, the book's title is saved into a new book. The only problem is that the title is saved like {:value=>"the title of the book that was saved"}
Here is the part of new.html.erb which has the search box:
<%= form_tag({controller: "books", action: "new"}, method: "get", id: "search-form") do %>
<%= text_field_tag :keywords, params[:keywords], placeholder: "Search for a book", class: "form-control" %>
<% end %>
Here is the part of new.html.erb which has the hidden form:
<% #results.each do |result| %>
…
<%= form_for #book do |f|%>
<%= hidden_field_tag :title, class: 'form-control', value: result.name %>
<%= f.submit "Add book", class: "btn btn-default green-hover" %>
<% end %>
…
<% end %>
Here are the new and create actions in my controller:
def new
#book = current_user.books.build if logged_in?
# Search actions
if params[:keywords]
request = Vacuum.new
request.configure(
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
associate_tag: 'my associate tag is here'
)
keywords = params[:keywords]
params = {
'SearchIndex' => 'Books',
'Keywords'=> keywords,
'ResponseGroup' => "ItemAttributes,Images"
}
raw_results = request.item_search(query: params)
hashed_results = raw_results.to_h
#results = []
hashed_results['ItemSearchResponse']['Items']['Item'].each do |item|
result = OpenStruct.new
result.title = item['ItemAttributes']['Title']
result.url = item['DetailPageURL']
result.image_url = item['MediumImage']['URL']
result.author = item['ItemAttributes']['Author']
result.pages = item['ItemAttributes']['NumberOfPages']
#results << result
end
end
end
def create
#book = #list.books.build(book_params)
if #book.save
flash[:success] = #book.title + "was added to your log."
redirect_to list_path(#book.list_id)
else
render 'books/new'
end
end
I tried to use gsub within book.rb to fix it, but that only changed the text within the flash message and it still saved as {:value=>"the title of the book that was saved"}.
after_create :init
private
def init
puts "Init was called!"
self.title.gsub!('{:value=>"', " ")
self.title.gsub!('"}', " ")
end
How can I change it so that it doesn't save the title with the {:value=>} around it?
I don't think the hidden field tag is right.
<%= hidden_field_tag :title, class: 'form-control', value: result.name %>
Try
<%= hidden_field_tag :title, result.name %>
Your title is being saved as a hash not a string. Use hash accessing methods:
t = title[:value]
puts t #=> "the tile of the book that was saved"
I'm trying to make report page, on which user will choose start and end date and push buttopn report. Then hidden div became visible.
My search isn't on partial.
I am using jquery_datepicker so here is my code from view:
<%= form_tag(:controller => "financial_reports", :action => "index", :method => "post")%>
<%= datepicker_input "financial_report","start_date", :dateFormat => "dd/mm/yy" %>
<%= datepicker_input "financial_report","end_date", :dateFormat => "dd/mm/yy" %>
<%= submit_tag "Run Report"%>
<% end %>
Here is my code from controller:
def search
#financial_reports = current_user.financial_reports.search(params[:start_date], params[:end_date]
render :index
end
In my Model:
def self.search(from,to)
find(:all, :conditions => [ "BETWEEN ? AND ?", from, to])
end
And it gives me error:
ActiveRecord::StatementInvalid in FinancialReportsController#search
SELECT `financial_reports`.* FROM `financial_reports` WHERE `financial_reports`.`user_id` = 67 AND (BETWEEN NULL AND NULL)
and below this:
Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"AMobLLRV3aAlNn6b4Au+1nRP2AN1TLQcBCytBXhDA/g=",
"type"=>"",
"financial_report"=>{"start_date"=>"05/08/2012",
"end_date"=>"11/08/2012"},
"commit"=>"Run Report",
"method"=>"post"}
Where is my error ?
If both parameters are set at all times, you can use:
#financial_reports = current_user.financial_reports.where(:created_at => ((params[:start_date].to_date)..(params[:end_date].to_date))
If that's not the case, you could (for example) do this:
#financial_reports = current_user.financial_reports
if params[:start_date].present?
#financial_reports = current_user.financial_reports.where("created_at >= ?", params[:start_date])
end
if params[:end_date].present?
#financial_reports = current_user.financial_reports.where("created_at <= ?", params[:end_date])
end
You will probably want to encapsulate this in scopes.