I have this filter in my tutos index:
= simple_form_for :query, url: tutos_path, method: :get, wrapper: :inline_form, html: {class: 'form-inline'} do |f|
= f.input :keyword, placeholder: "Keyword"
= f.input :category, collection: (Category.all.map {|c| c.name}) , prompt: "Select a category"
= f.input :user, collection: (User.order('nickname ASC').all.map {|u| u.nickname}), prompt: "Select a user"
= f.button :submit, "Find", class:"btn btn-warning"
= link_to t("search_form.best"), best_voted_path, class: "btn btn-default"
= link_to t("search_form.all"), tutos_path, class: "btn btn-default"
-if user_signed_in?
= link_to t("search_form.create"), new_tuto_path, class:"btn btn-success"
After filtering I can't get back to my tutos_path through my link_to:
I have this error:
NoMethodError at /en/tutos
undefined method `[]' for nil:NilClass
in my controller I have:
def index
#tutos = Tuto.all
filter_tutos
end
def filter_tutos
#tutos = Tuto.search(params[:query][:keyword]).includes(:user, :category) if params[:query][:keyword].present?
#tutos = Tuto.joins(:user).where('users.nickname LIKE ?', params[:query][:user]) if params[:query][:user].present?
#tutos = Tuto.joins(:category).where('categories.name LIKE ?', params[:query][:category]) if params[:query][:category].present?
end
The error is coming from your params[:query][:keyword].present? and the other ones alike, because it's evaluated as params, then params[:query]. If one of these evaluates to nil, and then trying to run nil[:query], hence [] isn't defined on NilClass, it returns an error.
You'll need to check for nil in the function:
def filter_tutos
return if params[:query].nil? # Don't bother, if the query is nil
#tutos = Tuto.search(params[:query][:keyword]).includes(:user, :category) if params[:query][:keyword].present?
#tutos = Tuto.joins(:user).where('users.nickname LIKE ?', params[:query][:user]) if params[:query][:user].present?
#tutos = Tuto.joins(:category).where('categories.name LIKE ?', params[:query][:category]) if params[:query][:category].present?
end
As far as I remember, params is always set in the Controller. If this is not the case, you'll need to adapt your nil-checks for that as well.
To make it fit your own answer, and have a fallback method, you could do like so, to check if
def index
filter_tutos if params[:query].present?
#tutos ||= Tuto.all
end
To make sure that #tutos are set. It'll be set to Tuto.all if it's nil from the method filter_tutos.
I finally found out...
in my controller:
def index
if params[:query].present?
filter_tutos
else
#tutos = Tuto.all
end
end
in my view instead of my = link_to t("search_form.all"), tutos_path, class: "btn btn-default"
I did:
= link_to t("search_form.all"), {controller: 'tutos', action: 'index'}, class: "btn btn-success"
Related
All,
please help me with a simple feature...I can´t determine the error.
So this is my simple user story
Expected: As a user I want to get a list of results based on my search-criteria (e.g. title, description)
Actual: What I get :-( always the full list of pins, instead of the filtered one.
For this, I use the gems pg_search and my view is written in HAML
application.html.haml including the search-bar:
.container
= form_tag pins_path, method: :get, class: "search", role: "search" do
.container
= form_tag pins_path, method: :get, class: "navbar-form navbar-right", role: "search" do
%p
= text_field_tag :search, params[:search], class: "form-control"
= submit_tag "Search", name: nil, class: "btn btn-default"
pins_controller:
def index
if params[:query].present?
#pins = Pin.search_for(params[:query])
else
#pins = Pin.all.order("created_at DESC")
end
end
And finally index.html.haml:
- #pins.each do |pin|
.box.panel.panel-default
= link_to (image_tag pin.image.url), pin
.panel-body
%h2= link_to pin.title, pin
%p.user
Submitted by
= pin.user.email
You are passing search params, whicle in controller you are expecting query param and so checking if params[:query] present or not
So replace params[:query] with params[:search] in your controller or change your input filed name to query in your search form.
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 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]}%")
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've got this bunch of code
<%= link_to admin_conference_statuses_path(conference_id: #conference.id), class: "btn btn-primary", method: :post, remote: true do %>
<span id="span">Comm invoiced out Venue</span>
<% end %>
<%= link_to admin_conference_statuses_path(conference_id: #conference.id), class: "btn btn-primary", method: :post, remote: true do %>
<span id="span">Cross charged to Client</span>
<% end %>
And I have this in my controller
def create
conference_id = params[:conference_id] #Keep the same
#conference_status = ConferenceStatus.find_by_conference_id(conference_id)#Keep the same
#conference_status = ConferenceStatus.new unless #conference_status#Keep the same
#conference_status.conference_id = params[:conference_id]
#conference_status.invoiced_out_user_id = current_user.id
#conference_status.invoiced_out_datetime = DateTime.now
if #conference_status.save
# Success
else
# Failure
end
end
Now, when one button is pressed it grabs the id and puts it into a database.
How would I go about adding it so that when button 2 (opposed to button 1) is pressed it puts current user id into a column called "cross_charged_user_id"
If you have the answer could you post it and explain what it does, so I know for next time?
Thanks
Sam
You can pass one extra parameter to second link. Then depending on this extra parameter you can assign the current user as cross_charged_user.
The html code look like:
<%= link_to admin_conference_statuses_path(#conference), class: "btn btn-primary", method: :post, remote: true do %>
<span id="span">Comm invoiced out Venue</span>
<% end %>
<%= link_to admin_conference_statuses_path(#conference, cross_site_to_client: true), class: "btn btn-primary", method: :post, remote: true do %>
<span id="span">Cross charged to Client</span>
<% end %>
And the controller just check the params[:cross_site_to_client] and assign the current user
if params[:cross_site_to_client].present?
#conference_status.cross_site_to_client_id = current_user.id
end
Even You can cleanup your code as well
#conference_status = ConferenceStatus.find_or_create_by_conference_id(params[:conference_id])
if params[:cross_site_to_client].present?
#conference_status.cross_site_to_client = current_user
else
#conference_status.invoiced_out_user = current_user
end
#conference_status.invoiced_out_datetime = DateTime.now
#conference_status.save