In The Middle Of All Of It

Advanced Search

November 26, 2017

I built a web based app that emulates petfinder.com. The inspiration around this was that I knew I wanted to build something, but wasn't sure what to build. I figured, I like dogs and Petfinder is a pretty cool site, so why not build a similar site, but just for dogs? Out came Dog Seekers. I built Dog Seekers to prove to myself that I was capable of building a large scale project with only the help of Google. In the past, I've implemented features to large projects, but never built an entire large scale project; top-to-bottom. If you're reading this, then I've accomplished exactly what I set out to do. There's still A LOT of work to do, but I've simply come to terms with the fact that I'm going to be working on this for a while. To me, no project is really finished, because there's always work to be done.
I learned a ton about the work it takes to build a larger scale web app, including search forms; which I'm particularly proud of. For the search form, I didn't use any gems. I built the search form from hours of googling, thinking I had a solution (but really didn't), and finally arriving at a tutorial by Justin Weiss about advanced search forms. The tutorial greatly helped me understand how search forms actually work. After arriving at the tutorial, I learned a great deal more about modules, models, scope, and so, so much more.
For the search form, I had to do the following:

  • The first thing we need to do is go into app/models/concerns/. Here I created a search_filter.rb file and created two modules.
module SearchFilter
  extend ActiveSupport::Concern

  module ClassMethods
    def search_filter(filter_params)
      results = self.where(nil)
      filter_params.each do |key, value|
      results = results.public_send(key, value) if value.present?
    end
    results
  end
end
  • With these modules, I can now include them in the model where I need to implement the search functionality. In my case, I went to my app/models/application_record.rb and added include SearchFilter. After which, I added the following code to my app/models/dog.rb. This allows me to search with scopes, which is exactly what I needed. I wanted to be able to filter the search so the user can search for specific, individual attributes of a dog. With the below code, the user can now search by location or breed or title_age or gender individually as well as all of the above.
scope :location, -> (location) { where location: location }
scope :breed, -> (breed) { where breed: breed }
scope :title_age, -> (title_age) { where title_age: title_age }
scope :gender, -> (gender) { where gender: gender }
  • With my model setup and the module in place, I can now go to my app/controllers/searchs_controller.rb and implement my search filter. Remember to add the scopes by which you want to search.
class SearchsController < ApplicationController

  def index
    @dogs = Dog.search_filter(params.slice(:location, :breed, :title_age, :gender))
  end

end
  • And of course, my app/views/shared/_header.html.erb where I have my search form.
<ul class='dog-search'>
  <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', required: true %>
        </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='search-dog-age'>
          <p class='age-name'>Choose an Age:</p>
          <%= radio_button_tag :title_age, 'baby', id: 'age-baby' %>
          <%= label_tag :title_age_baby, 'Baby: 0-2 years', class: 'age-baby' %>
          <br/>
          <%= radio_button_tag :title_age, 'young', id: 'age-young' %>
          <%= label_tag :title_age_young, 'Young: 3-5 years', class: 'age-young' %>
          <br/>
          <%= radio_button_tag :title_age, 'adult', id: 'age-adult' %>
          <%= label_tag :title_age_adult, '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>
</ul>
  • That's it! I can now search with scopes.
Back to Code Posts