Today, we will learn how to implement Complex Search Term on Rails, also how to install Bootstrap with Bower and generate fake data with Faker gem.
Install new project with name “complex_search”-
$ rails new complex_search -d postgresql
Configure database.yml file inside config-
# config/database.yml default: &default adapter: postgresql encoding: unicode username: postgres # Based on your username password: 123456 # Based on your password # For details on connection pooling, see rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
Then open your command prompt & write below command for database migration-
$ cd complex_search $ bundle exec rake db:create $ bundle exec rake db:migrate $ bundle exec rails server
Write localhost:3000 to your browser & will show below image-
We just completed the project setup, now needs to setup Bootstrap.
There are three ways to install Bootstrap into a Rails application: as a Ruby Gem, by referencing a publicly available version hosted on a CDN, or by downloading it and storing it within our application’s source.
Bower itself as a package manager for the web. It was created by Twitter and is analogous to RubyGems, but manages front-end assets (including CSS frameworks like Bootstrap and JavaScript libraries like Angular). Bower is written in JavaScript, and so it requires a JavaScript runtime in order to work. That means you’ll have to install Node JS.
$ npm install -g bower
Then-
# complex_search/Gemfile gem 'bower-rails'
We can install with bundler.
$ bundle install
We have to create Bowerfile file in the root directory then install Bootstrap.
# complex_search/Bowerfile asset 'bootstrap-sass-official'
Then-
$ bundle exec rake bower:install
Add bootstrap to our asset pipeline
# complex_search/app/assets/stylsheet/application.css /* *= require_tree. *= require_self ➤ *= require 'bootstrap-sass-official' */
We are just done with installing Bootstrap with Bower!
Now we will generate a model called Customer for implementing complex search term-
$ rails generate model Customer first_name:string last_name:string email:string username:string
The migration file created & look like below-
# complex_search/db/migrate/timestamps_create_customers.rb class CreateCustomers < ActiveRecord::Migration[5.0] def change create_table :customers do |t| t.string :first_name, null: false t.string :last_name, null: false t.string :email, null: false t.string :username, null: false t.timestamps null: false end add_index :customers, :email, unique: true add_index :customers, :username, unique: true end end
Then execute following command-
$ rake db:migrate
# complex_search/Gemfile gem 'faker'
Then, we’ll install it the gem-
$ bundle install
After that-
# complex_search/db/seeds.rb 500.times do |i| Customer.create!( first_name: Faker::Name.first_name, last_name: Faker::Name.last_name, username: "#{Faker::Internet.user_name}#{i}", email: Faker::Internet.user_name + i.to_s + "@#{Faker::Internet.domain_name}") end
Then execute the above code-
$ bundle exec rake db:seed
We just created 500 fake data (rows) in database!
Building the search UI
$ rails generate controller customers index
# complex_search/config.routes.rb resources :customers, only: [:index]
# complex_search/app/controller/customers_controller.rb class CustomersController < ApplicationController def index @customers = Customer.all.limit(10) end end
# complex_search/app/views/customers/index.html.erb <h1>Customer Search</h1> <section class="search-form"> <%= form_for :customers, method: :get do |f| %> <div class="input-group input-group lg"> <%= label_tag :keywords, nil, class: "sr-only" %> <%= text_field_tag :keywords, nil, placeholder: "First Name, Last Name, or Email Address", class: "form-control input-lg" %> <span class="input-group-btn"> <%= submit_tag "Find Customers", class: "btn btn-primary btn-lg" %> </span> </div> <% end %> </section> <section class="search-results"> <h1 class="h3">Results</h1> <ol class="list-group"> <% @customers.each do |customer| %> <li class="list-group-item clearfix"> <h3 class="pull-right"> <small class="text-uppercase">Joined</small> <%= l customer.created_at.to_date %> </h3> <h2 class="h3"> <%= customer.first_name %> <%= customer.last_name %> <small><%= customer.username %></small> </h2> <h4><%= customer.email %></h4> </li> <% end %> </ol> </section>
Now create a file inside models called “customer_search_term.rb” and then write following code-
# complex_search/app/models/customer_search_term.rb class CustomerSearchTerm attr_reader :where_clause, :where_args, :order def initialize(search_term) search_term = search_term.downcase @where_clause = "" @where_args = {} if search_term =~ /@/ build_for_email_search(search_term) else build_for_name_search(search_term) end end def build_for_name_search(search_term) @where_clause << case_insensitive_search(:first_name) @where_args[:first_name] = start_with(search_term) @where_clause << " OR #{case_insensitive_search(:last_name)}" @where_args[:last_name] = start_with(search_term) @order = "last_name asc" end def build_for_email_search(search_term) @where_clause << case_insensitive_search(:first_name) @where_args[:first_name] = start_with(extract_name(search_term)) @where_clause << " OR #{case_insensitive_search(:last_name)}" @where_args[:last_name] = start_with(extract_name(search_term)) @where_clause << " OR #{case_insensitive_search(:email)}" @where_args[:email] = search_term @order = "lower(email) = " + ActiveRecord::Base.connection.quote(search_term) + "desc, last_name asc" end def start_with(search_term) search_term + "%" end def case_insensitive_search(field_name) "lower(#{field_name}) like :#{field_name}" end def extract_name(email) email.gsub(/@.*$/,'').gsub(/[0-9]+/,'') end end
Then modify code in controller file-
# complex_search/app/controllers/customers_controller.erb class CustomersController < ApplicationController PAGE_SIZE = 10 def index if params[:keywords].present? @keywords = params[:keywords] customer_search_term = CustomerSearchTerm.new(@keywords) @customers = Customer.where(customer_search_term.where_clause, customer_search_term.where_args).order(customer_search_term.order) else @customers = [] end end end
And that’s all! We have implemented a full & complex search feature on the Rails project.
Happy coding 🙂
Leave a Reply