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'm working on this reconciliation system where users can choose which fields they would like to use when importing records. I finally got the select to pre-populate with the correct info but can't for the life of me get the checkboxes to do the same. Here's my form:
#views/match_rule/edit.html.erb
<%= form_for(#match_rules) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name, placeholder: "Rule Set Name" %>
<%= f.label :algorithm, "Choose an algorithm" %>
<%= f.select :algorithm, build_algorithm_select_options %>
<%= f.label :match_fields, "Available fields" %>
<% #field_options.each do |field| %>
<%= f.check_box :match_fields %>
<%= f.label :match_fields, "#{field.last}" %><br/>
<% end %>
<%= f.submit "Save", class: "button primary" %>
<%= link_to "Cancel", match_rule_index_path, class: "button" %>
<% end %>
Currently the corresponding controller is simply building a hash of fields so not to clutter up the view with repetitive code
#controllers/match_rule_controller.rb
def edit
#field_options = {
name: "Name",
email: "Email",
phone: "Phone Number",
gender: "Gender",
marital_status: "Marital Status",
dob: "Date of Birth",
campus: "Campus",
address: "Street Address",
city: "City",
state: "State",
zip: "Zip"
}
end
My model is serializing the fields
#models/match_rule.rb
class MatchRule < ActiveRecord::Base
has_many :inboxes
enum algorithm: [ :adjustable, :classic_minimal, :classic_standard ]
serialize :match_fields
end
and my database fields are storing all the options that should populate the checkboxes in the match_fields column
If it helps to see how I seeded the db with an array here's that:
#db/seeds.rb
classic_minimal = MatchRule.create(algorithm: 'classic_minimal', match_fields: ['name', 'email', 'phone', 'gender', 'zip'], name: 'Classic Minimal')
classic_standard = MatchRule.create(algorithm: 'classic_standard', match_fields: ['name', 'email', 'phone', 'gender', 'marital_status', 'dob', 'campus', 'address', 'city', 'state', 'zip'], name: 'Classic Standard')
adjustable = MatchRule.create(algorithm: 'adjustable', match_fields: ['name', 'phone', 'campus', 'marital_status', 'zip'], name: 'Adjustable')
I've checked out similar questions on here, the one closest to helping me have a breakthrough was the answer to this question: Set checkboxes on edit method in Rails 4 where he says to use .include? to determine the checked status, but I'm not sure what I would put in the params because I need to parse through the hash inside match_fields for each and every field and that would get pretty gnarly.
Any advice or guidance is greatly appreciated, thanks!
UPDATE
Update! Tried using fields_for but still not posting or populating.
<%= f.label :match_fields, "Available fields" %>
<%= fields_for :match_fields do |field| %>
<%= field.check_box :name %>
<%= field.label :name, "Name" %><br/>
<%= field.check_box :email %>
<%= field.label :email, "Email" %><br/>
<%= field.check_box :phone %>
<%= field.label :phone, "Phone" %><br/>
<% end %>
now when I check params on update in the console, it's saying:
"match_fields" => {
"name" => "1",
"email" => "1",
"phone" => "0"
},
but not actually posting or populating.
Figured it out.
<%= form_for(#match_rules) do |f| %>
<%= f.label :name, "Name" %>
<%= f.text_field :name, placeholder: "Rule Set Name" %>
<%= f.label :algorithm, "Choose an algorithm" %>
<%= f.select :algorithm, build_algorithm_select_options %>
<%= f.label :match_fields, "Available fields" %>
<%= f.check_box :name, { checked: #match_rules.match_fields.include?("name") } %>
<%= f.label :name, "Name" %><br/>
<%= f.check_box :email, { checked: #match_rules.match_fields.include?("email") } %>
<%= f.label :email, "Email" %><br/>
<%= f.check_box :phone, { checked: #match_rules.match_fields.include?("phone") } %>
<%= f.label :phone, "Phone" %><br/>
<%= f.check_box :gender, { checked: #match_rules.match_fields.include?("gender") } %>
<%= f.label :gender, "Gender" %><br/>
<%= f.check_box :marital_status, { checked: #match_rules.match_fields.include?("marital_status") } %>
<%= f.label :marital_status, "Marital Status" %><br/>
<%= f.check_box :dob, { checked: #match_rules.match_fields.include?("dob") } %>
<%= f.label :dob, "Date of Birth" %><br/>
<%= f.check_box :campus, { checked: #match_rules.match_fields.include?("campus") } %>
<%= f.label :campus, "Campus" %><br/>
<%= f.check_box :address, { checked: #match_rules.match_fields.include?("address") } %>
<%= f.label :address, "Street Address" %><br/>
<%= f.check_box :city, { checked: #match_rules.match_fields.include?("city") } %>
<%= f.label :city, "City" %><br/>
<%= f.check_box :state, { checked: #match_rules.match_fields.include?("state") } %>
<%= f.label :state, "State" %><br/>
<%= f.check_box :zip, { checked: #match_rules.match_fields.include?("zip") } %>
<%= f.label :zip, "Zip Code" %><br/>
<%= f.submit "Save", class: "button primary" %>
<%= link_to "Cancel", match_rule_index_path, class: "button" %>
You have to pass the .include? method inside the options hash. Now I just need to find a cleaner way to put this in the view.