I'm attempting to a create a simple form that allows me to run a new search on the existing 'results' page using simple form.
The exact same code works fine when performing the search from another (landing) page. However, when I try to insert it into the results page I'm getting
undefined method 'vtype' for #
<Venue::ActiveRecord_Relation:0x007fd6860eb730>
vtype is both a table column and also the name of the param i'm passing to search on.
The simple_form looks like this:
<%= simple_form_for :results, html: { class: "form-inline justify-content-center" } do |f| %>
<%= f.error_notification %>
<%= f.select :vtype, options_for_select([['Happy Hours Anywhere','Anywhere'],['After Work Drinks','After Work Drinks'],['Somewhere to Relax with Friends', 'Relaxing with Friends'], ['A Club Night','Club Night'], ['Somewhere for Date Night','Date Night'], ['A Place to Watch Sports', 'Watching Sports']]),{} ,:class => "form-control select-box font-lightweight" %>
starting
<%= f.select :date, options_for_select(dates_for_search_select.each_with_index.map{|d, i| [d[1],d[0]]}), {}, :class => "form-control select-box font-lightweight" %>
at
<%= f.select :time, options_for_select(times_for_search_select.each_with_index.map{|d, i| [d[1],d[0]]}), {}, :class => "form-control select-box font-lightweight" %>
</h4>
<%= f.button :submit, 'Discover', :class => 'btn btn-block btn-danger btn-embossed top-margin ' %>
<%end%>
My controller looks like this:
def results
if params.has_key?(:results)
##results = Venue.joins(:offers).where("offers.offertype = '2-4-1'")
#finddate = (params[:results][:date]).to_date
#findtime = (params[:results][:time]).to_time
#resultsdate = DateTime.new(#finddate.year,#finddate.month,#finddate.day,#findtime.hour)
#results = Venue.joins(:offers).where(["venues.vtype = ? and offers.start >= ?", params[:results][:vtype], #resultsdate])
else
#results = Venue.joins(:offers).where(["offers.start = ?", Date.today])
end
end
What's wrong with this form running on the 'results' page?
Related
I have the following form:
<div class='panel' id='panel-advanced-search'>
<%= form_tag contacts_path, method: :get do %>
<div>
<div class='advanced_search'>
<div>
<%= label_tag "Contact Type" %>
<%= select_tag(:contact_type, options_for_select(Contact::TYPES, selected: params[:contact_type]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Prospect Strength" %>
<%= select_tag(:prospect_strength, options_for_select(Contact::PROSPECT_STRENGTHS, selected: params[:prospect_strength]), prompt: 'Any', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Customer" %>
<%= collection_select(:customer_account_id, :customer_account_id, Customer.order(:name), :id, :name, { prompt: '' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Supplier" %>
<%= collection_select(:supplier_account_id, :supplier_account_id, Supplier.order(:name), :id, :name, { prompt: '' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Company Name" %>
<%= text_field_tag :company_name %>
</div>
<div>
<%= label_tag "Name" %>
<%= text_field_tag :name %>
</div>
<div>
<%= label_tag "Job Title" %>
<%= text_field_tag :title %>
</div>
<div>
<%= label_tag "Postcode" %>
<%= text_field_tag :postcode %>
</div>
<div>
<%= label_tag :created_at, 'Created From' %>
<div class="date-picker">
<%= text_field_tag :created_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag :updated_at, 'Created To' %>
<div class="date-picker">
<%= text_field_tag :updated_at, nil, class: 'date-picker-select' %>
<span class="date-picker-btn">
<span class="icon-calendar" aria-hidden="true"></span>
</span>
</div>
</div>
<div>
<%= label_tag "Tags" %>
<%= collection_select(:tag_list, :tag_list, #tags.order(:name), :name, :name, {}, { class: 'select2', multiple: true }) %>
</div>
<div>
<%= label_tag "Assignee" %>
<%= collection_select(:assigned_to, :assigned_to, User.all, :id, :name, { prompt: 'Any' }, class: 'customSelect select2') %>
</div>
<div>
<%= label_tag "Obsolete?" %>
<%= select_tag(:obsolete, options_for_select(['Obsolete', 'All'], selected: params[:obsolete]), prompt: 'Not obsolete?', class: 'customSelect') %>
</div>
<div>
<%= label_tag "Send Results To" %>
<%= select_tag(:subsequent_action, options_for_select([
['Report', 'report'],
['CSV Export', 'csv_export'],
['New Event', 'new_event']
]), prompt: 'None', class: 'customSelect') %>
</div>
</div>
<div class="advanced_search_btns">
<%= submit_tag submit_text %>
<%= link_to secondary_btn, contacts_path, class: 'btn-medium' %>
</div>
</div>
<% end %>
</div>
and the following method in the model
def self.advanced_search
Contact.where('
contact_type LIKE :search OR
prospect_strength LIKE :search OR
customer_account_id LIKE :search OR
supplier_account_id LIKE :search OR
company_name LIKE :search OR
name LIKE :search OR
title LIKE :search OR
postcode LIKE :search OR
created_at LIKE :search OR
updated_at LIKE :search OR
tag_list LIKE :search OR
assigned_to LIKE :search OR
obsolete LIKE :search
', search: "%#{search}%"
)
end
How do I go about using this method so the user can use this search form with multiple params? I already have the following in the index method for a basic search so I need to have both search forms
def index
#per_page = params[:per_page] || 20
#tags = ActsAsTaggableOn::Tag.all
if params[:search].present?
#contacts = Contact.search(params[:qs], params[:search]).order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
else
#contacts = Contact.all.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
end
end
Edit Updated the form above to the complete form, ideally, I would like the forms functionality to be entirely in the model.
Edit #2
This is the basic search:
model
QUICK_SEARCH_FIELDS = {
name: {
column_names: 'contacts.name'
},
customers: {
joins_table: :customer,
column_names: 'contacts.name',
filters: { contact_type: 'customer' }
},
suppliers: {
joins_table: :supplier,
column_names: 'contacts.name',
filters: { contact_type: 'supplier' }
},
tags: {
tagged_with: true
}
}.with_indifferent_access
def self.search(field, query)
field = QUICK_SEARCH_FIELDS[field]
contact = all
contact = contact.joins(field[:joins_table]) if field[:joins_table]
contact = contact.where(field[:filters]) if field[:filters]
contact = contact.where("#{field[:column_names]} LIKE ?", "%#{query}%") if field[:column_names]
contact = contact.tagged_with(query) if field[:tagged_with]
contact
end
form
<div class='panel' id='panel-search'>
<%= form_tag contacts_path, method: :get do %>
<div class='l-inline-row-block'>
<div class='l-inline-col width_120px'>
<%= select_tag(:qs, options_for_select(Contact::QUICK_SEARCH_FIELDS.keys(), selected: params[:qs]), class: 'customSelect') %>
</div>
<div class='l-inline-col'>
<%= search_field_tag :search, params[:search] %>
</div>
<div class='l-inline-col' style='width: 100px;'>
<%= submit_tag submit_text %>
</div>
</div>
<% end %>
</div>
you may need to make view adjustments and you cannot just use the search term/query for all fields:
1.make sure the fields inside the form in your view are all the same names of the columns in the Contact model that need to be searched
2.add a hidden field inside each form so you can determine which search this is (there is another option but this one is less work)
3.change the collection_select where user can only select one field to select_tag in order to not mess up query building
every field that is filled will pass a value- you can build a hash including column/form-field entered and their value e.g { contact_type: "value1", prospect_strength: "value2" }
after that, you would need to build a query using that hash and query the DB
this would look like so:
In your view:
add this in the advanced search form
<%= hidden_field_tag :search_type, :advanced %>
and in your normal search add this
<%= hidden_field_tag :search_type, :normal %>
In your model:
def self.advanced_search(values_by_column_name) # values_by_column_name is a hash passed from the controller
tag_list = values_by_column_name.delete("tag_list")
sql_query = values_by_column_name.keys.map { |column| "#{column} LIKE :#{column}" }
sql_query = sql_query.join(" OR ")
values_by_column_name = values_by_column_name.transform_values { |value| "%#{value}%" }.symbolize_keys
relation = Contact.where(sql_query, values_by_column_name)
relation = relation.tagged_with(tag_list) if tag_list
relation
end
in your controller:
ADVANCED_SEARCH_FIELDS = [
:contact_type,
:prospect_strength,
:customer_account_id,
:supplier_account_id,
:company_name,
:name,
:title,
:postcode,
:created_at,
:updated_at,
{tag_list: []},
:assigned_to,
:obsolete,
]
def index
#per_page = params[:per_page] || 20
#tags = ActsAsTaggableOn::Tag.all
if advanced_search?
#contacts = Contact.advanced_search(advanced_search_params)
elsif normal_search?
#contacts = Contact.search(params[:qs], params[:search])
else
#contacts = Contact.all
end
#contacts = #contacts.order(sort_column + ' ' + sort_direction).paginate(page: params[:page], per_page: #per_page)
end
def advanced_search?
params[:search_type] == "advanced" && advanced_search_params.any?
end
def normal_search?
params[:search_type] == "normal" && params[:search].present?
end
def advanced_search_params
#_advanced_search_params ||= params.permit(ADVANCED_SEARCH_FIELDS).select { |_, v| v.present? }.to_h
end
I have an application that has hundreds of products. I created a simple filter search bar and it works great for a single parameter, but I would like to add multiple parameters and return any product that contains one of the search parameters.
Here is my working code for a single parameter; I would show what I've tried to add multiple params, but I am a bit out of my depth.
products_controller.rb
def index
#products = Product.all.order('LOWER(name)')
if params[:q]
#products = Product.where('name ILIKE ?', "%#{params[:q]}%").all.order('LOWER(name)')
end
end
_searchbar.html.erb
<div class="form-inline">
<%= form_tag(products_path, :method => "get", id: 'search-form', :html => {class: 'form'}) do %>
<div class="form-group">
<%= text_field_tag :q, params[:q], placeholder: 'Product Name', class: 'form-control' %>
</div>
<%= submit_tag 'Search', class: 'btn btn-primary' %>
<% end %>
</div>
We should know the operation behind. The sql query must be like this:
select * from products where name ilike '%name1%' or name ilike '%name2%';
According you code:
select * from products where name ilike '%name1,name2%'
That's incorrect.
Try to the following:
# :query need to be an array
# Eg:
# "Product name 1, Product name 2, Product name 3" => params[:q].split(', ')
# => ["Product name 1", "Product name 3", "Product name 3"]
search_string = []
query.each { |q| search_string << "name ILIKE ?" }
search_string = search_string.join(' OR ')
Product.where(search_string, *query)
You can do that using following steps like if you need to use input field then form look like this
<div class="form-inline">
<%= form_tag(products_path, :method => "get", id: 'search-form', :html => {class: 'form'}) do %>
<div class="form-group">
<%= text_field_tag :x, params[:x], placeholder: 'Product Name1', class: 'form-control' %>
</div>
<div class="form-group">
<%= text_field_tag :y, params[:y], placeholder: 'Product Name2', class: 'form-control' %>
</div>
<div class="form-group">
<%= text_field_tag :z, params[:z], placeholder: 'Product Name3', class: 'form-control' %>
</div>
<%= submit_tag 'Search', class: 'btn btn-primary' %>
<% end %>
</div>
Or you need this filtering key is in the checkbox then form look like this
<%= form_tag(products_path, :method => "get", id: 'search-form', :html => {class: 'form'}) do %>
<%= check_box_tag("x[]", "x") %> Xname
<%= check_box_tag("y[]", "y") %> Yname
<%= check_box_tag("z[]", "z") %> Zname
<%= submit_tag 'Search', class: 'btn btn-primary' %>
<% end %>
Now update the controller look like this
if params[:x] || params[:y] || params[:z]
#products = Product.where('true')
#products = #products.where('name ILIKE ?', "%#{params[:x]}%") unless params[:x].blank?
#products = #products.where('name ILIKE ?', "%#{params[:y]}%") unless params[:y].blank?
#products = #products.where('name ILIKE ?', "%#{params[:z]}%") unless params[:z].blank?
#products = #products.order('LOWER(name)')
else
#products = Product.all.order('LOWER(name)')
end
Hope it helps
When I try to create an "Action" I get this error.
My Actions controller:
class ActionsController < ApplicationController
def new
#match_set = MatchSet.find(params[:match_set_id])
#fixture = #match_set.fixture
#teams = Team.where("id = " + #fixture.home_team_id.to_s + " OR id = " + #fixture.away_team_id.to_s)
#players = Player.where("team_id = " + #teams.ids.first.to_s + " OR id = " + #teams.ids.last.to_s)
#action = #match_set.actions.new
end
def create
#match_set = MatchSet.find(params[:match_set_id])
#action = #match_set.actions.new(action_params)
if #action.save
redirect_to match_set(#match_set)
else
render "actions/new"
end
end
private
def action_params
params.require(:action).permit(:team_id, :player_id, :position, :action_type, :action_result)
end
end
It is submitted from this form in views/actions/new.html.erb:
<%= form_for [#match_set, #action] do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<!-- Team -->
<%= f.label :team_id %>
<%= f.collection_select :team_id, #teams,:id, :name, {include_blank: "Select team..."}, {class: "form-control"} %>
<!-- Player -->
<%= f.label :player_id %>
<%= f.collection_select :player_id, #players,:id, :last_name, {include_blank: "Select player..."}, {class: "form-control"} %>
<!-- Position -->
<%= f.label :position %>
<%= f.select :position, options_for_select(['1', '2', '3', '4', '5', '6']), {include_blank: "Select position on court..."}, class: "form-control" %>
<!-- Action Type -->
<%= f.label :action_type %>
<%= f.select :action_type, options_for_select(['Attack', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Action Result -->
<%= f.label :action_result %>
<%= f.select :action_result, options_for_select(['Score', 'Block', 'Pass', 'Set']), {include_blank: "Select action_type..."}, class: "form-control" %>
<!-- Submit Button -->
<%= f.submit "Add Action", class: "btn btn-primary" %>
<% end %>
Also the relevant routes:
resources :fixtures, shallow: true do
resources :match_sets, shallow: true do
resources :actions
end
end
I'm getting an error on this line in the controller:
params.require(:action).permit(:team_id,:player_id,
:position,:action_type,:action_result)
I have also noticed that my parameters seem to be disappearing but again have no clue as to the cause.
Parameters:
{"utf8"=>"✓", "authenticity_token"=>"BqbEOfL7hEA8XSMXDvMW2qQ2uR74Egp5
jJvtQlsuyV2TikZJ+6hTIEMH05gy8TM6r3ZglFDRUFBl7ScZD1czCQ==",
"commit"=>"Add Action", "match_set_id"=>"15"}
Any help is appreciated.
action is a reserved word in rails. You will need to change your model name.
Rails provides a few params on each request such as:
params[:controller] # maps to your controller name
params[:action] # maps to an action with your controllers
http://api.rubyonrails.org/classes/ActionDispatch/Routing.html
I need a form that includes 1 radio button, 1 submit button and a checkbox for each listed item.
Upon submit, the form should save a separate record for each checked item. Each saved item should include the value of the radio button along with other hidden values.
The form renders but crashes upon submit. The error message is:
undefined method `permit' for #<Array:0x007fb4b3b1a520>
My code is:
<%= form_tag(controller: "handoffs", action: "create", method: "post") %>
<%= radio_button_tag(:attend, "arrive") %>
<%= label(:handoff_arrive, "drop-off") %>
<%= radio_button_tag(:attend, "depart") %>
<%= label(:handoff_depart, "pick-up") %>
<% #parent.children.each do |child| %>
<%= check_box_tag "handoff[][check]" %>
<strong>
<%= child.fname %>
<%= child.mname %>
<%= child.lname %>
</strong><br>
<% group = Group.find(child.group_id) %>
<%= hidden_field_tag "handoff[][attend]" %>
<%= hidden_field_tag "handoff[][group_name]", :value => group.name %>
<%= hidden_field_tag "handoff[][child_id]", :value => child.id %>
<%= hidden_field_tag "handoff[][center_id]", :value => #center.id %>
<%= hidden_field_tag "handoff[][escort_fname]", :value => #parent.fname %>
<%= hidden_field_tag "handoff[][escort_lname]", :value => #parent.lname %>
<%= hidden_field_tag "handoff[][child_fname]", :value => child.fname %>
<%= hidden_field_tag "handoff[][child_mname]", :value => child.mname %>
<%= hidden_field_tag "handoff[][child_lname]", :value => child.lname %>
<% end %>
<%= button_to :submit, :class => 'f_submit' %>
<% end %>
Controller actions:
def new
#handoff = Handoff.new
#parent = current_parent
#center = Center.find(#parent.center_id)
end
def create
params["handoff"].each do |handoff|
if params[:handoff["check"]] != ""
#handoff = Handoff.new(handoff_params)
#handoff.save
end
end
end
def handoff_params
params.require(:handoff).permit(:attend, :group_name, :child_id, :center_id, :escort_fname, :escort_lname, :child_fname, :child_mname, :child_lname)
end
Request parameters (in error report)
{"utf8"=>"✓",
"authenticity_token"=>"snqrS130bXNV4bmMHOMlXeyhX2rWFVpmY/PYIv0jn97MBOLSWWw2jBbeYGPyjt7O9l5pRVNuFiu1qOwkGpELTA==",
"attend"=>"depart", "handoff"=>[{"check"=>"1", "attend"=>"",
"group_name"=>"{:value=>\"Gifted\"}", "child_id"=>"{:value=>60}",
"center_id"=>"{:value=>4}", "escort_fname"=>"{:value=>\"Richard\"}",
"escort_lname"=>"{:value=>\"Messing\"}",
"child_fname"=>"{:value=>\"Aaron\"}",
"child_mname"=>"{:value=>\"Lawrence\"}",
"child_lname"=>"{:value=>\"Schwartz\"}"}, {"check"=>"1", "attend"=>"",
"group_name"=>"{:value=>\"Arts & Crafts\"}",
"child_id"=>"{:value=>61}", "center_id"=>"{:value=>4}",
"escort_fname"=>"{:value=>\"Richard\"}",
"escort_lname"=>"{:value=>\"Messing\"}",
"child_fname"=>"{:value=>\"Joseph\"}",
"child_mname"=>"{:value=>\"Michael\"}",
"child_lname"=>"{:value=>\"Messing\"}"}], "method"=>"post",
"controller"=>"handoffs", "action"=>"create"}
I had similar case. First you need to create array with all values that you would like to export I used helper to do that. I'll show you my example:
def get_table_of_keywords(keywords)
exact_keywords = []
keyword_array.each do |key|
if !key.blank?
exact_keywords << {keyword: key, created_at: DateTime.now.in_time_zone, updated_at: DateTime.now.in_time_zone }
end
end
exact_keywords
end
And the you are using create:
#inserted_keywords = #campaign.keywords.create(get_table_of_keywords(params[:keyword][:keyword])) # add new keywords to the list
I have a search form that searches a geocoded model called property. The geocode search works fine. However when I introduce more params to the search it returns incorrect results.
I have two boolean columns on the property model, smokers and pets. In my URL I notice that the same query param for pets is inserted twice:
http://localhost:3000/properties?utf8=%E2%9C%93&location=L17+6DD&distance=10&pets=false&pets=true&smokers=false&commit=Search
I'm using Rails 4.2.6, Ruby 2.3.0 and PostgreSQL
Search form:
<%= form_tag properties_path, method: :get do %>
<%= label :location, "Search properties near : " %>
<%= text_field_tag :location, params[:location] %>
<%= label :distance, "Distance : " %>
<%= text_field_tag :distance, params[:distance] %>
<%= label :pets, "Pets : " %>
<%=hidden_field_tag 'pets', false%>
<%=check_box_tag 'pets', true %>
<%= label :smokers, "Smokers : " %>
<%=hidden_field_tag 'smokers', false%>
<%=check_box_tag 'smokers', true %>
<%= submit_tag "Search" %>
<% end %>
Properties controller action:
def index
if params[:location].present?
#properties = Property.near(params[:location], params[:distance] || 10)
.where("pets = :pets", {pets: params[:pets]})
.where("smokers = :smokers", {smokers: params[:smokers]})
else
#properties = Property.all
end
end
Remove the hidden field tags :
<%=hidden_field_tag 'pets', false%>
<%=hidden_field_tag 'smokers', false%>
For null value issue use this :
<%= check_box_tag 'pets', 'boolean_attribute', {}, 'true', 'false' %>
<%= check_box_tag 'smokers', 'boolean_attribute', {}, 'true', 'false' %>
OR leave your form as it is manage params in controller like :
#properties = Property.near(params[:location], params[:distance] || 10)
.where("pets = :pets", {pets: params[:pets] || false})
.where("smokers = :smokers", {smokers: params[:smokers] || false})