Reputation: 11
I have 2 models with the following fields to be queried.
Customer
:first_name
:last_name
:address
:email
Relatives
:first_name
:last_name
:address
:title
A Customer
has many Relatives
.
I am trying to write a search()
method that will return a collection of Customer
records where either the fields of the Customer
or 1+ of it's related Relatives
match the query.
The goal is to be able to iterate a collection of Customer
records. If customer.relatives.present?
, I will know to loop through the related Relative
models provided with the Customer
- that the models in that collection match the query.
I currently have something like this:
class Customer < ActiveRecord::Base
has_many :relatives
def self.search(params={})
cols = %i(address caseworker last_name)
conds = []
cols.reject! { |col| params[col].blank? }
conds << cols.collect { |col| "clients.#{col} like ?" }.join(" or ")
cols.each { |col| conds << "%#{params[col]}%" }
query = self.send(:where, conds)
# @todo query relatives here!
end
end
Where I get stuck:
Customer
models that don't match the search, but do have a Relative
matching the search.
search()
on the Relative
model - which I believe I can write - but am again unsure how fill out the @todo
above to eager-load only those Relative
that match the query.I'm looking for any bump in the right direction.
Upvotes: 1
Views: 200
Reputation: 4837
This gem is a simple implementation of search and full-text search for mysql databases https://github.com/makandra/dusen
You might have to do a bit of coding to make the gem working properly such as define search_text etc. But this gem would take care of the rest.
Upvotes: 0
Reputation: 9278
Depending on your database, you might want to look into something like pg_search
for full-text searching.
After the search indexes are built, eager-loading Relatives that match the Customer query is trivial.
class Customer < ActiveRecord::Base
include PgSearch
has_many :relatives
pg_search_scope :search,
:against => [:address, :caseworker, :last_name]
:associated_against => {
:relatives => [:address, :caseworker, :last_name]
}
end
Customer.search("foobar").preload(:relatives)
Upvotes: 2