Search by full name - ruby-on-rails

I am trying to write a query that finds clients by their full name.
I have a model named Client with first name, last name, and middle name fields.
I also have this client_full_name method in my User model :
def client_full_name
"#{self.Client_fname} #{self.Client_mi} #{self.Client_lname}"
end
# FOR SEARCHES
def self.search_by_client_full_name(query)
where("client_full_name like ?", "%#{query}%")
end
I have this in my controller
def index
#FOR SEARCHES
if params[:search]
#clients = Client.search_by_client_full_name(params[:search])
else
#clients = Client.all
end
end
And I have this in my Index
<h2>Search for Clients</h2>
<%= form_tag(clients_path, :method => "get", id: "search-form") do %>
Search by Client Name: <br />
<%= text_field_tag :search, params[:search], placeholder: "Search Clients" %>
<%= submit_tag "Search", :client_full_name => nil %>
<% end %>
This is the Error that I keep getting
SQLite3::SQLException: no such column: client_full_name: SELECT "clients".* FROM "clients" WHERE (client_full_name like '%John Smith%')
Thank you for the help.

This can be solution for your question.
patient_first_name_cont = "Ajay"
patient_last_name_cont = "Kumar"
shared_context = Ransack::Context.for(Request)
search_parents = Request.includes(:request_status).ransack(
{ patient_first_name_cont: patient_first_name_cont }, context: shared_context
)
search_children = Request.includes(:request_status).ransack(
{ patient_last_name_cont: patient_last_name_cont }, context: shared_context
)
shared_conditions = [search_parents, search_children].map { |search| Ransack::Visitor.new.accept(search.base)}
#req = Request.joins(shared_context.join_sources).where(shared_conditions.reduce(&:and))

You method client_full_name is an instance method of class Client:
def client_full_name
"#{self.Client_fname} #{self.Client_mi} #{self.Client_lname}"
end
It ( client_full_name ) is not a column(at least it doesn't appear to be) of your clients table. That's why you're getting this error:
SQLite3::SQLException: no such column: client_full_name: SELECT "clients".* FROM "clients" WHERE (client_full_name like '%John Smith%')
to make your query work, you need to change your method search_by_client_full_name to this(NOTE- Query below will work only for MySQL):
def self.search_by_client_full_name(query)
where("CONCAT_WS(' ', Client_fname, Client_mi, Client_lname) LIKE :q", :q => "%#{query}%")
end
For SQLite you can use || for concatenation:
def self.search_by_client_full_name(query)
where("(Client_fname || Client_mi || Client_lname) LIKE :q", :q => "%#{query}%")
end
But || will return NULL if any of the column has NULL, to avoid that you'll have to write case

Related

Filtered Search in Rails 4 using ActiveRecord Querying Interface

I have some filters in place when performing a search. I have another search filter that I am trying to implement, but can't seem to get it to work. I am having issues with the first_name last_name and building the view for that.
Controller:
if params[:address_search]
#payment_requests = #payment_requests.where('full_address ILIKE ?', "%#{params[:address_search]}%")
unless params[:unit_search].blank?
#payment_requests = #payment_requests.where('unit ILIKE ?', "%#{params[:unit_search]}%")
end
elsif params[:client_search]
#payment_requests = #payment_requests.where('email ILIKE ?', "%#{params[:client_search]}%")
elsif params[:first_name] || params[:last_name]
#payment_requests = PaymentRequest.includes(:detail).where(payment_details: { first_name: params[:first_name], last_name: params[:last_name]})
end
else
#payment_requests = #payment_requests.active
end
Views:
<div class="form-group">
<%= text_field_tag 'client_search', '', id: 'pay-client-search', placeholder: 'Email Search', class: 'general-text-area pay-filter' %>
</div>
You can try this
key = "%#{search_text}%"
#payment_requests = PaymentRequest.joins(:detail).where('payment_details.first_name LIKE :search OR payment_details.last_name LIKE :search', search: key)
P.S: Not tried this.

ActiveRecord::StatementInvalid in Show Controller

I've got a simple search form, in rails 4 app, that needs two params passed to be able to show relevant data.
I'm getting an 'Mysql2::Error: Unknown column 'data inputted' but the columns do exist. If I instead of '#search = Page.where(params[:one] && params[:two])' use '#search = Page.all' the data shows, but all of it shows.
Form
<%= form_tag(page_show_path, id: "search-form") do %>
<%= text_field_tag :one, params[:one], placeholder: "One" %>
<%= text_field_tag :two, params[:two], placeholder: "Two" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Model
def self.one(query)
where("one = ?", "%#{query}%")
end
def self.two(query)
where("two = ?", "%#{query}%")
end
Controller
def show
if (params[:one] && params[:two]).present?
#search = Page.where(params[:one] && params[:two])
else
redirect_to page_path, notice: "Not a valid combination"
end
end
You can Create and Use Scope.
scope :find_one_two, ->(query_one, query_two) { where("one = ? AND two = ? ", query_one, query_two) }
#search = Page.find_one_two(params[:one], params[:two])
OR
You can use.
#search = Page.where("one = ? AND two = ?", params[:one], params[:two])
def show
if (params[:one] && params[:two]).present?
#search = Page.where("one like ? AND two like ? ", "%#{params[:one]}%", "%#{params[:two]}%")
else
redirect_to page_path, notice: "Not a valid combination"
end
end
This may solve your problem.

this query isn't efficient

i have a single search field that is querying three different columns from two different tables: "companies" and "industries" from a positions table and "schools" from an educations table. it is successfully returning all users that meet ALL fields entered into the search field (using select_tag). this is from my view:
<%= form_tag(search_path, :method => :get, :id => "people_search") do %>
<div class="row-fluid">
<div class="span4">
<table>
<tr>
<td>
<div class="search-table" style="padding-left:55px">
<%= select_tag "all", options_for_select((#visible_companies + #visible_industries + #visible_schools).uniq, params[:all]), { :placeholder => "Search by companies, industries and schools...", :multiple => true, :js => "if (evt.keyCode == 13) {form.submit();}" } %>
</div>
</td>
<td>
<%= submit_tag "Add", id: "send-button", style:"width:175px;" %>
</td>
</tr>
</table>
</div>
<% end %>
</div>
and controller:
#visible_positions = Position.where{ is_visible.eq('true') }
#visible_educations = Education.where{ is_visible.eq('true') }
#visible_companies = #visible_positions.order("LOWER(company)").map(&:company).uniq
#visible_industries = #visible_positions.order("LOWER(industry)").map(&:industry).uniq
#visible_schools = #visible_educations.order("LOWER(school)").map(&:school).uniq
#c = #visible_positions.where{company.in(my{params[:all]})}.map(&:user_id)
#i = #visible_positions.where{industry.in(my{params[:all]})}.map(&:user_id)
#s = #visible_educations.where{school.in(my{params[:all]})}.map(&:user_id)
#C = #visible_positions.where{company.in(my{params[:all]})}.map(&:company)
#I = #visible_positions.where{industry.in(my{params[:all]})}.map(&:industry)
#S = #visible_educations.where{school.in(my{params[:all]})}.map(&:school)
#blacklist = []
#cis = #c + #i + #s
#experiences = ([#C,#I,#S].reject(&:empty?).reduce(:&))
#cis.uniq.each do |user_id|
unless #C.empty?
#C.uniq.each do |company|
unless Position.find_all_by_company(company).map(&:user_id).include?(user_id) || Position.find_all_by_industry(company).map(&:user_id).include?(user_id) || Education.find_all_by_school(company).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
unless #I.empty?
#I.uniq.each do |industry|
unless Position.find_all_by_industry(industry).map(&:user_id).include?(user_id) || Position.find_all_by_company(industry).map(&:user_id).include?(user_id) || Education.find_all_by_school(industry).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
unless #S.empty?
#S.each do |school|
unless Education.find_all_by_school(school).map(&:user_id).include?(user_id) || Position.find_all_by_company(school).map(&:user_id).include?(user_id) || Position.find_all_by_industry(school).map(&:user_id).include?(user_id)
#blacklist << user_id
end
end
end
end
unless #c.empty? && #i.empty? && #s.empty?
#users = User.find(#cis - #blacklist)
end
the search looks like this (notice the single field), with a sample query included (notice the AND filter...i'm the only user in the database that fits all search terms ['dartmouth college' for school, 'world health organization' for company, 'internet' for industry]):
i realize this is not an efficient query and am thinking of ways to speed it up, but could use some ideas at this point.
happy turkey day :)
Based on your description rather then on understanding your code I figured out something like this
User.joins(:positions, :educations).where("lower(positions.company) like lower(?) and lower(positions.industry) like lower(?) and lower(educations.school) like lower(?) and positions.is_visible and educations.is_visible", "%#{company}%", "%#{industry}%", "%#{school}%")
or if there is only one company or industry in column
User.joins(:positions, :educations).where("(lower(positions.company) = lower(?) or lower(positions.industry) = lower(?)) and lower(educations.school) = lower(?) and positions.is_visible and educations.is_visible", company,industry, school)
But to put many industries, companies, schools as params will be more complicated
and create indexes
create index positions_lower_company on positions (lower(company));
create index positions_lower_industry on positions (lower(industry));
create index educations_lower_school on educations (lower(school));
I hope it will help somehow.

Getting strange error when searching by date

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.

In Rails 3.1, how can I create an HTML table generator that uses block style formatting

I'm developing an application that displays tabular data in many different areas and I find myself constantly using the same HTML table structure over and over. For example a particular table looks like this:
%table.zebra-striped#user-table{ :cellspacing => "0" }
%colgroup
%col{:id => "email"}
%col{:id => "username"}
%col{:id => "sign-in-count"}
%col{:id => "last-sign-in-at"}
%thead
%tr
%th{:id => "email-head", :scope => "col"} E-mail
%th{:id => "username-head", :scope => "col"} Username
%th{:id => "sign-in-count-head", :scope => "col"} Sign Ins
%th{:id => "last-sign-in-at-head", :scope => "col"} Last Sign In
%tbody
- #users.each do |user|
%tr{ :class => zebra }
%td
=h user.email
%td
=h user.username
%td
=h user.sign_in_count
%td
=h user.last_sign_in_at
Ideally, I would like to create some kind of helper method where I could do something like:
= custom_table_for #users do
= column :email
= column :username do |user|
= link_to user.username, user_path(user)
= column "Sign Ins", :sign_in_count
= column :last_sign_in_at
This way I can change the formatting of the data in the columns and the column header names if I'm not happy with default values, but have the table generated for me.
I suppose I could create a normal helper, but I'd have to use arrays and I have no idea how I could include custom data formatting per column.
active_admin has something similar to this which you can see here: http://activeadmin.info/docs/3-index-pages/index-as-table.html
Any leads or ideas would be greatly appreciated.
I just came up with this:
A few points:
The line #columns = [] is a reset so you can call it more than once.
The yield in the custom_table_for calls the block that you pass it.
The block in the column method is stored and called in custom_table_for if it is set.
I included a sample class to show the usage too.
please note I did this outside of a rails app and you almost certainly want to use http://api.rubyonrails.org/classes/ActionView/Helpers/TagHelper.html#method-i-content_tag instead of the p "<table>" this is merely for sample purposes when you run it in the console.
module TableHelper
def custom_table_for(items)
#columns = []
yield
p "<table>"
#columns.each do |c|
p "<th>#{c[:value]}</th>"
end
items.each do |e|
p "<tr>"
#columns.each do |c|
e[c[:name]] = c[:block].call(e[c[:name]]) if c[:block]
p "<td>#{e[c[:name]]}</td>"
end
p "</tr>"
end
p "</table>"
end
def column(name, value = nil, &block)
value = name unless value
#columns << {:name => name, :value => value, :block => block}
end
end
class ExampleTable
include TableHelper
def test
#users = [{:email => "Email 1", :username => "Test User"}, {:email => "Email 2", :username => "Test User 2"}]
custom_table_for #users do
column :email, "Email"
column :username do |user|
user.upcase
end
end
end
end
et = ExampleTable.new
et.test
UPDATE
I migrated this to rails to use content_tags
module TableHelper
def custom_table_for(items)
#columns = []
yield
content_tag :table do
thead + tbody(items)
end
end
def thead
content_tag :thead do
content_tag :tr do
#columns.each do |c|
concat(content_tag(:th, c[:value]))
end
end
end
end
def tbody(items)
content_tag :tbody do
items.each { |e|
concat(content_tag(:tr){
#columns.each { |c|
e[c[:name]] = c[:block].call(e[c[:name]]) if c[:block]
concat(content_tag(:td, e[c[:name]]))
}
})
}
end
end
def column(name, value = nil, &block)
value = name unless value
#columns << {:name => name, :value => value, :block => block}
end
end
To compliment #gazler's response, here's a way to make a table of a single resource-- column one for attribute names, column two for their values:
module TableHelper
#resource = nil
def simple_table_for(resource)
#resource = resource
content_tag :table do
content_tag :tbody do
yield
end
end
end
def row(key, label = nil, &block)
if key.is_a? String
label = key
end
content_tag(:tr) {
concat content_tag :td, label || key.capitalize
concat content_tag(:td ){
if block_given?
yield
else
#resource.send(key)
end
}
}
end
end

Resources