Two fixtures:
one:
firstname: John
lastname: Doe
user_id: 1
two:
firstname: Jane
lastname: Doe
user_id: 1
In my unit test, I have the following:
test "Searching for a contact gets the right person" do
search = Contact.search("John")
assert_equal 1, search.count
search = Contact.search("Doe")
assert_equal 2, search.count
search = Contact.search("John Doe")
assert_equal 1, search.count
search = Contact.search("John ")
assert_equal 1, search.count
search = Contact.search("Doe John")
assert_equal 1, search.count
end
…and finally my model, which calls the search method looks like:
def self.search(search)
# Check if the search query has more than one word
search_split = search.split(" ")
if search_split.count > 1
# User must be searching for a first and last name
first_word = '%' + search_split[0] + '%'
second_word = '%' + search_split[1] + '%'
conditions = "
firstname ILIKE ? OR lastname ILIKE ?
AND
firstname ILIKE ? OR lastname ILIKE ?",
first_word, first_word, second_word, second_word
where(conditions)
else
# Just searching for a first OR last name
# Strip any whitespace
str = search_split[0]
query = '%' + str + '%'
conditions = "firstname ILIKE ? OR lastname ILIKE ?", query, query
where(conditions)
end
end
All tests pass except the one that does a test for “John Doe”. It actually ends up pulling “Jane Doe” as well.
I’m thinking there is some kind of precedence issue with calling the two OR’s before the adjoining AND, but does it make sense of what I’m trying to accomplish?
I’m not at the point where I’m refactoring just yet; just trying to get to green so I can move forward. Thanks for any help in advance!
You need a bit of reorganization to get the logic you’re after:
That should match both “John Doe” and “Doe John” but not “Jane Doe” when you call:
You don’t actually need the parentheses because AND has a higher precedence than OR in Boolean Algebra (and SQL’s logic is based on Boolean Algebra) but there’s no good reason not to include them.