12/08/2018, 13:08

Gem Filterrific

1. Giới thiệu Filterrific là gem hỗ trợ lọc, sắp xếp và tìm kiếm trong danh sách các bản ghi một cách rất dễ dàng. 2. Hướng dẫn cài đặt để tạo ứng dụng trong bài viết này, ta có thể tạo một ứng dụng tìm kiếm, lọc, sắp xếp một danh sách các sinh viên, ta đặt tên nó là app'user. Ta cài ...

1. Giới thiệu

Filterrific là gem hỗ trợ lọc, sắp xếp và tìm kiếm trong danh sách các bản ghi một cách rất dễ dàng.

2. Hướng dẫn cài đặt để tạo ứng dụng

trong bài viết này, ta có thể tạo một ứng dụng tìm kiếm, lọc, sắp xếp một danh sách các sinh viên, ta đặt tên nó là app'user.

1.PNG

  1. Ta cài đặt gem trong # Gemfile và bundle install
   gem 'filterrific'
  1. Thêm Filterrific cho Student model của bạn:
    # app/models/student.rb
    class Student < ActiveRecord::Base
      belongs_to :country

      # db columns:
      # integer: id
      # string: first_name
      # string: last_name
      # text: email
      # integer: country_id
      # datetime: created_at

      filterrific(
        default_filter_params: { sorted_by: 'created_at_desc' },
        available_filters: [
          :sorted_by,
          :search_query
          :with_country_id
        ]
      )

      # ActiveRecord association declarations

      scope :search_query, lambda { |query|
          return nil  if query.blank?
          terms = query.downcase.split(/s+/)
          terms = terms.map { |e|
            (e.gsub('*', '%') + '%').gsub(/%+/, '%')
          }
          num_or_conds = 2
          where(
            terms.map { |term|
              "(LOWER(students.first_name) LIKE ? OR LOWER(students.last_name) LIKE ?)"
            }.join(' AND '),
            *terms.map { |e| [e] * num_or_conds }.flatten
          ).
      }

      scope :sorted_by, lambda { |sort_key|
        direction = (sort_option =~ /desc$/) ? 'desc' : 'asc'
          case sort_option.to_s

          when /^name_/

          when /^country_name_/

            order("LOWER(countries.name) #{ direction }").includes(:country)
          else
            raise(ArgumentError, "Invalid sort option: #{ sort_option.inspect }")
          end
      }

      scope :with_country_id, lambda { |country_ids|
        where(country_id: [*country_ids])
      }

      def self.options_for_sorted_by
        [
          ['Name (a-z)', 'name_asc'],
          ['Registration date (newest first)', 'created_at_desc'],
          ['Registration date (oldest first)', 'created_at_asc'],
          ['Country (a-z)', 'country_name_asc']
        ]
      end
    end
Trong # app/models/country.rb
    class Country < ActiveRecord::Base
      # db columns:
      # integer: id
      # string: name

      has_many :students

      def self.options_for_select
        order('LOWER(name)').map { |e| [e.name, e.id] }
      end
    end
  1. Sử dụngFilterrific trong StudentsController#index:
    # app/controllers/students_controller.rb
    class StudentsController < ApplicationController

      def index
        @filterrific = initialize_filterrific(
          Student,
          params[:filterrific],
          select_options: {
            sorted_by: Student.options_for_sorted_by,
            with_country_id: Country.options_for_select
          },
          persistence_id: 'shared_key',
          default_filter_params: {},
          available_filters: [],
        ) or return

        @students = @filterrific.find.page(params[:page])

        # Respond to html for initial page load and to js for AJAX filter updates.
        respond_to do |format|
          format.html
          format.js
       end

      rescue ActiveRecord::RecordNotFound => e
        # There is an issue with the persisted param_set. Reset it.
        puts "Had to reset filterrific params: #{ e.message }"
        redirect_to(reset_filterrific_url(format: :html)) and return
      end
      ...

    end
  1. Sử dụngFilterrific trong view

    Tại file app/views/students/index.html.erb

    <h1>Students</h1>
      <%#
        Filterrific adds the `form_for_filterrific` view helper:
        * adds dom id 'filterrific_filter'
        * applies javascript behaviors:
          * AJAX form submission on change
          * AJAX spinner while AJAX request is being processed
        * sets form_for options like :url, :method and input name prefix
      %>
      <%= form_for_filterrific @filterrific do |f| %>
        <div>
          Search
          <%# give the search field the 'filterrific-periodically-observed' class for live updates %>
          <%= f.text_field(
            :search_query,
            class: 'filterrific-periodically-observed'
          ) %>
        </div>
        <div>
          Country
          <%= f.select(
            :with_country_id,
            @filterrific.select_options[:with_country_id],
            { include_blank: '- Any -' }
          ) %>
        </div>
        <div>
          Registered after
          <%= f.text_field(:with_created_at_gte, class: 'js-datepicker') %>
        </div>
        <div>
          Sorted by
          <%= f.select(:sorted_by, @filterrific.select_options[:sorted_by]) %>
        </div>
        <div>
          <%= link_to(
            'Reset filters',
            reset_filterrific_url,
          ) %>
        </div>
        <%# add an automated spinner to your form when the list is refreshed   %>
          <%= render_filterrific_spinner %>
      <% end %>

      <%= render(
        partial: 'students/list',
        locals: { students: @students }
      ) %>

Trong _list.html.erb

    <%# app/views/students/_list.html.erb %>
    <div id="filterrific_results">

      <div>
        <%= page_entries_info students # provided by will_paginate %>
      </div>

      <table>
        <tr>
          <th>Name</th>
          <th>Email</th>
          <th>Country</th>
          <th>Registered at</th>
        </tr>
        <% students.each do |student| %>
          <tr>
            <td><%= link_to(student.full_name, student_path(student)) %></td>
            <td><%= student.email %></td>
            <td><%= student.country_name %></td>
            <td><%= student.decorated_created_at %></td>
          </tr>
        <% end %>
      </table>
    </div>

    <%= will_paginate students # provided by will_paginate %>

Trong app/views/students/index.js.erb

      <%# app/views/students/index.js.erb %>
      <% js = escape_javascript(
        render(partial: 'students/list', locals: { students: @students })
      ) %>
      $("#filterrific_results").html("<%= js %>");

Trong application.js ta viết

      //= require filterrific/filterrific-jquery

Sắp xếp theo tiêu đề cột trong app/views/students/_list.html.erb

      <div id="filterrific_results">
        <div>
          <%= page_entries_info students # provided by will_paginate %>
        </div>
        <table>
          <tr>
            <th><%= filterrific_sorting_link(@filterrific, :name) %></th>
            <th><%= filterrific_sorting_link(@filterrific, :email) %></th>
            <th><%= filterrific_sorting_link(@filterrific, :country) %></th>
            <th><%= filterrific_sorting_link(@filterrific, :registered_at) %> </th>
          </tr>
          <% students.each do |student| %>
            <tr>
              <td><%= link_to(student.full_name, student_path(student)) %></td>
              <td><%= student.email %></td>
              <td><%= student.country_name %></td>
              <td><%= student.decorated_created_at %></td>
            </tr>
          <% end %>
        </table>
      </div>

      <%= will_paginate students # provided by will_paginate %>
  1. Kết luận

    Việc sử dụng gem cho phép lọc, sắp xếp và tìm kiếm một cách tương đối dễ dàng

0