0

This is my first time implementing an advanced search. I'm emulating pet finder, but for dogs and want the search functionality to be similar to that of pet finders search for pets. My desired outcome is to have the user input their desired preferences as to what kind of dog (breed, age, gender, location, etc.) they are looking for and when they click on search, it redirects and renders their desired dog. I'm not getting an error at all just not getting the desired results.

Please let me know if you need additional information.

I want to add that if I take out the if statement in searchs_controller.rb and just have: @dogs = Dog.search(params[:location], params[:breed], params[:age], params[:gender]).all then it gives me this error:

ActionView::Template::Error - PG::UndefinedFunction: ERROR:  operator does not exist: integer ~~ unknown
LINE 1: ...n LIKE '%92603%' AND breed LIKE '%corgi%' AND age LIKE '%Bab...
                                                             ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "dogs".* FROM "dogs" WHERE (location LIKE '%92603%' AND breed LIKE '%corgi%' AND age LIKE '%Baby%' AND gender LIKE '%female%'):

app/controllers/searchs_controller.rb

class SearchsController < ApplicationController

    def index
      if params[:search]                                                                                                                                    
         @dogs = Dog.search(params[:location], params[:breed], params[:age], params[:gender]).all
      else
          @dogs = Dog.all.order("age ASC")
       end
    end
end

app/models/dog.rb

Before:

class Dog < ApplicationRecord

  def self.search(location, breed, age, gender)                                                                                                           
    return all unless location.present? || breed.present? || age.present? || gender.present?
    where(['location LIKE ? AND breed LIKE ? AND age LIKE ? AND gender LIKE ?', "%#{location}%", "%#{breed.downcase}%", "%#{age}%", "%#{gender.               downcase}%"])
  end

end

After:

def self.search(location, breed, age, gender) 
    return all unless location.present? || breed.present? || age.present? || gender.present?
    where('location @@ ? AND breed @@ ? AND age = ? AND gender @@ ?', location, breed.downcase, age, gender.downcase)
  end

app/views/searchs/index.html.erb

<div class="doge-info">
   <% @dogs.each do |d| %>                                                                                                                                 
      <h2>Meet: <%= d.name %></h2>
      <h4><%= d.name %> is a <%= d.breed %></h4>

      <% if d.gender.titleize == "Female" %>
        <h4>She is <%= d.age %> years old.</h4>
      <% else %>
        <h4>He is <%= d.age %> years old.</h4>
      <% end %>

   <% end %>
 </div>

app/views/dogs/_form.html.erb

Updated 03/08:

<div class="search-for-dogs-form">
  <%= form_tag searchs_index_path, method: "get", class: "search-dogs" do %>

    <div id="form-searching-for-dogs">

      <div class="location">
        <% label_tag :location, class: "location-label" %>
        <%= number_field_tag :location, params[:location], max: 0..5, placeholder: "Zip Code", class: "zip-code-area" %>
      </div>

      <div class="dog-breed">
        <% label_tag :breed, class: "breed-label" %>
        <%= text_field_tag :breed, params[:breed], placeholder: "Breed", class: "breed-text-field" %>
      </div>

      <div class="dog-age">
        <p class="age-name">Choose an Age Range:</p>
        <%= radio_button_tag :age, "#{0..2}" %>
        <%= label_tag :age_baby, "0-2 years", class: "age-baby" %>
        <%= radio_button_tag :age, "#{3..5}" %>
        <%= label_tag :age_young, "3-5 years", class: "age-young" %>
        <%= radio_button_tag :age, "#{6..8}" %>
        <%= label_tag :age_adult, "6-8 years", class: "age-adult" %>
      </div>

      <div class="dog-gender">
        <% label_tag :gender, class: "gender-label" %>
        <%= text_field_tag :gender, params[:gender], placeholder: "Dog Gender", class: "gender-text-field" %>
      </div>

      <div class="submit-button-for-search">
        <%= submit_tag "Search for Dogs", name: nil, class: "dog-search-submit-button" %>
      </div>
    </div>
  <% end %>
</div>

app/config/routes.rb

   devise_for :admins
   root to: 'homepages#index'

   resources :dogs, only: [:index, :show]
   get "searchs/index"

   namespace :admin do
     resources :dogs
   end

db/schema.rb

create_table "dogs", force: :cascade do |t|
    t.string "name"
    t.integer "age"
    t.string "breed"
    t.string "gender"
    t.boolean "adoptable"
    t.datetime "post_date"
    t.string "color"
    t.string "size"
    t.string "birth_date"
    t.string "photo"
    t.string "location"
  end
kyle
  • 207
  • 3
  • 17

2 Answers2

1

You are using Postgresql, LIKE doesn't work the same way it does in MYSQL. You will need to use ilike or @@.

where(['location LIKE ? AND breed LIKE ? AND age LIKE ? AND gender LIKE ?', "%#{location}%", "%#{breed.downcase}%", "%#{age}%", "%#{gender.downcase}%"])

for psql would be

where('location ILIKE ? AND breed ILIKE ? AND age ILIKE ? AND gender ILIKE ?', "%#{location}%", "%#{breed.downcase}%", "%#{age}%", "%#{gender.downcase}%")

or

where('location @@ ? AND breed @@ ? AND age @@ ? AND gender @@ ?', location, breed.downcase, age, gender.downcase)

I would recommend watching this http://railscasts.com/episodes/343-full-text-search-in-postgresql?view=asciicast

and using this gem. https://github.com/activerecord-hackery/ransack

It will make it alot easier to get the results you are looking for.

nzajt
  • 1,937
  • 1
  • 15
  • 16
  • I just tried both solutions, but when trying the solution with @@, i get this: `ActionView::Template::Error - PG::UndefinedFunction: ERROR: operator does not exist: integer @@ unknown LINE 1: ...(location @@ '92603' AND breed @@ 'corgi' AND age @@ 'Baby' ... ^ HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. : SELECT "dogs".* FROM "dogs" WHERE (location @@ '92603' AND breed @@ 'corgi' AND age @@ 'Baby' AND gender @@ 'female'):` With the carrot being under @@ after age. – kyle Mar 08 '17 at 02:55
  • Is one of those columns in your database an integer? You can't use @@ or ilike with an integer. Also, make sure you can run this query in the console before you try it in the view, it will save you a lot of time. – nzajt Mar 08 '17 at 23:56
  • Yep, age is an integer. Aaah gotcha. Alright, I'll run things in the console moving forward. I updated my code above to show what I tried. – kyle Mar 09 '17 at 00:18
1

I think the problem is that you are running a LIKE against an integer. There is no description of your schema but the SQL error seems to be pointing to the fact that age is an Integer and you cannot run LIKE against integer.

If you want to run a LIKE against an Integer you first need to cast it to a VARCHAR (this can be done in SQL). In PostgreSQL you can call the following command in your query: to_char(numeric, text). It returns a String from the numeric according to a format you enter as text parameter.

Stephane Paquet
  • 2,315
  • 27
  • 31
  • Thank you, @Stephane. I'm trying to find how to implement this into my search and have to admit, I'm a little confused on how to do that. Would it be something like this? `where('location @@ ? AND breed @@ ? AND age = ? AND gender @@ ?', location, breed.downcase, to_char(age, '99'), gender.downcase) ` I tried it this way and it gives me an `Undefined Method 'to_char'` error. – kyle Mar 09 '17 at 00:50
  • 1
    @kyle, what I would recommend to do, is to break it into pieces. Start by something simple, let's say try your query with only the varchars. Remove the age for now. See if it's working and as recommended by others in this thread: try it within the Ruby console. After that, figure out the best way to transform your age (stored as an integer) into a varchar. I would recommend looking at the following stackexchange posts: http://stackoverflow.com/questions/13809547/how-do-i-convert-an-integer-to-string-as-part-of-a-postgresql-query – Stephane Paquet Mar 09 '17 at 22:24
  • http://stackoverflow.com/questions/22476601/how-to-convert-integer-to-string-and-get-length-of-string – Stephane Paquet Mar 09 '17 at 22:27
  • Hi Stephane, thank you so much for these suggestions I'll implement these steps and see what works! Thanks! – kyle Mar 09 '17 at 22:48
  • 1
    @kyle, it's always a good thing to breakdown your problems. so you can isolate the issues, what makes solving them easier. – Stephane Paquet Mar 10 '17 at 19:45