0

This is what I want to accomplish without using a gem hopefully. I have a search function on one of my views where I desire to allow people to enter a first and last name in a single field, have my class method search both first and last names and produce a list. I currently have the following ugly code where it will do a full text search on both fields. Have mercy on me :) I am new to SQL and PostgreSQL. I have only done basic queries.

  def self.text_search(query)
    if query.present?
      q1, q2, q3, q4 = query.split(' ')
      case
      when q4 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR first_name @@ :q3 OR first_name @@ :q4 OR last_name @@ :q1 OR last_name @@ :q2 OR last_name @@ :q3 OR last_name @@ :q4', q1: q1, q2: q2, q3: q3, q4: q4)
      when q3 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR first_name @@ :q3 OR last_name @@ :q1 OR last_name @@ :q2 OR last_name @@ :q3', q1: q1, q2: q2, q3: q3)
      when q2 != nil
        where('first_name @@ :q1 OR first_name @@ :q2 OR last_name @@ :q1 OR last_name @@ :q2', q1: q1, q2: q2)
      else
        where('first_name @@ :q1 OR last_name @@ :q1', q1: q1)
      end
    else
      scoped
    end
  end

This code works where it searches for the entire word in both fields and produces all records that match. However what I would like to do is to be able to search columns starting with the values entered in the search box. For example if someone enters 'Pat' the query will select Pat, Patrick, Patrice, Patricia, etc. I'm sure that there is a better way to write even the code I have included where I can list all the values I want to check for first_name and last_name (or at least I hope there is).

I have been doing a lot of web searches today regarding this. I found a lot of information about various aspects of this. I saw how to create a regular expression using variables. This one was obvious to me. My problem was figuring out how to pass that information into my where clause. I tried for example the following code for all four fields.

qr1 = /^#{q1}/

Then I did a similar where clause where I checked both first_name and last_name for all four values. My queries did not return any rows.

where ('first_name ~ :qr1', qr1: qr1)

I also saw solutions about checking a substring comparing it to an array. The problem I see with that solution is that you have to know how long the value entered is before you can be successful with that. Here is a Stack Overflow post with an example:

Select where first letter in a range ( PostgreSQL )

I have also watched RailsCasts #343 (Pro) where it discusses to_tsvector and plainto_tsquery but frankly I got lost. Maybe this is my answer but I could sure use some help. It is clear as mud to me.

4
  • Why don't you want to use a gem? There are plenty of libraries out there that will make this task a lot easier. Commented Dec 18, 2012 at 4:37
  • For example, the github.com/ernie/squeel gem. Commented Dec 18, 2012 at 7:11
  • have you tried this out? github.com/Casecommons/pg_search Commented Dec 18, 2012 at 9:51
  • After I wrote this question and gave this some more thought I decided to attempt to implement pg_search. That gem was discussed in the RailsCasts I mentioned but at the time it was clear as mud. Maybe I had too much on my mind at the time I watched it. I decided to check it out again. I went to github and saw how I could select I think :prefix to do the starting with feature. This time I was successful in implementing it. Thanks so much for your input. I will save the link to squeel as a reference. Commented Dec 18, 2012 at 12:45

1 Answer 1

0
def self.text_search(query)
  if query.present?
    arr = query.split(' ').map { |q| "%#{q}" }

    where('first_name ~~* ANY(ARRAY[:arr]) OR last_name ~~* ANY(ARRAY[:arr])', arr: arr)
  else
    scoped
  end
end

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.