(GoRails)在导航栏增加自动的搜索功能(jquery插件:easyautocomplete)(gem 'ransack' 搜索对象4000✨)...

Global Autocomplete Search

需要用到一个JQuery插件和一个搜索对象的gem

 

EasyAutocomplete jQuery插件:

https://github.com/pawelczak/EasyAutocomplete

http://easyautocomplete.com/guide#sec-data-file

功能很强大,具体的看guide,写的很详细。

 

gem 'ransack'(4000✨)

 一个面向对象的搜索:https://github.com/activerecord-hackery/ransack


 

我的app:见imac电脑 ~/自我练习/embeddable_comments ⮀ ⭠ autoquery ⮀ 

git上:    https://github.com/chentianwei411/embeddable_comments


 

 

1. 激活一个Ajax request

2.server查询,把查询结果放入一个JSON对象,然后返回到浏览器。

3.JS库EasyAutocomplete将得到这些结果并显示它们。

 

第一步添加<script>

1.在<head>添加

<!-- Using jQuery with a CDN 加上jquery文件 -->
<script src="//code.jquery.com/jquery-1.11.2.min.js"></script>

2.把文件放入assets/javascripts和stylesheets

官网下载,http://easyautocomplete.com/download

  • easy-autocomplete.css和easy-autocomplete.themes.css放入Rails app的 app/asset/stylesheets文件夹。
  • jquery.easy-autocomplete.js放入javascript文件夹。
  • 在application.js中加上//= require jquery.easy-autocomplete
  • 在application.scss中加上*= require easy-autocomplete和*=require easy-autocomplete.thems

⚠️ 我使用unprocessed sass file。

#在assets/stylesheets/application.scss, 添加:
@import "easy-autocomplete";

 

 

3. 在浏览器的console上试试:

看文档:http://easyautocomplete.com/guide#sec-data-file

先要在web page上添加一个<input id="basics">

然后在console上输入(图):

在网页山的input标签上输入任意字符都会出现options的data列表:

 

 


 

⚠️在rails console遇到一个❌:

Refused to load the script 'http://code.jquery.com/jquery-1.11.2.min.js' 
because it violates the following Content Security Policy directive:
"script-src 'self' https: 'unsafe-eval'".

 

这是因为我使用vue.js后根据推荐的步骤加上了下面的代码:

Rails.application.config.content_security_policy do |policy|
  if Rails.env.development?
    policy.script_src :self, :https, :unsafe_eval, :unsafe_inline
  else
    policy.script_src :self, :https
  end
end

 


 

 

第二步: 添加路径。

get :search, controller: :main  //或者 get 'search', to: "main#search"

输入rails routes可查看

 

建立一个main_controller.rb

class MainController < ApplicationController
  def index

  end

  def search
    render json: {movies: [], directors: []}
  end
end

 

在浏览器输入localhost:3000/search 

渲染JSON:

 

第三步,设置controller

添加gem 'ransack'(4000✨)

 一个面向对象的搜索:https://github.com/activerecord-hackery/ransack

 支持Rails5.2

任何增强搜索的gem都可以,还可以使用searchkick(4600?)

 

增加2个table:

rails g model director name
rails g model movie name director:references
rails db:migrate

#添加seed:
# 这里使用了Array#zip方法,即把几个数组压缩。
# https://github.com/gorails-screencasts/gorails-episode-192/blob/master/db/seeds.rb
rails db:seed

#添加路径routes.rb
resources :movies
resources :directors

 

class MainController < ApplicationController
 ...

  def search
    @movies   = Movie.ransack(params[:q]).result(distinct: true)
    @directors = Directors.ransack(params[:q]).result(distinct: true)
  //可以限制条数.limit(5) end end

 

 新建views/main/search.json.jbuilder

json.movies do
  json.array!(@movies) do |movie|
    json.name movie.name
    json.url movie_path(movie)
  end
end

json.directors do
  json.array!(@directors) do |director|
    json.name director.name
    json.url director_path(director)
  end
end

 

添加一个回调before_action :force_json, only: :search

这样浏览器输入的url后缀会被转化为.json

 

class MainController < ApplicationController
  before_action :force_json, only: :search

  ...略...

  private

  def force_json
    request.format = :json
  end
end

  

class MainController < ApplicationController
 ...

  def search
    @movies   = Movie.ransack(params[:q]).result(distinct: true)
    @directors = Directors.ransack(params[:q]).result(distinct: true).limit(5)
  //name_cont限制查询的key是name
  end
end

此时在浏览器输入参数:http://localhost:3000/search?q=Wall

不会成功显示搜索结果,需要提供明确的column_name和predicate谓语:

这里使用:

  • name_cont:  名字中包括。。。
  • name_start   开始的名字是。。。
  @movies = Movie.ransack(name_cont: params[:q]).result(distinct: true).limit(5)
  @directors = Director.ransack(name_start: params[:q]).result(distinct: true).limit(5)

 

 

简单解释:(具体看git)

1. ransack()用于查询数据库表:Movie

例子: Movie.ransack(name: "dent"):

Ransack::Search<class: Movie, 
          base: Grouping <conditions: [Condition <attributes: ["name"], predicate: cont, values: ["dent"]>], combinator: and>>

 

2. result()用于从得到查询结果,所有的匹配记录。

#<ActiveRecord::Relation [#<Movie id: 5, name: "Resident Evil: The Final Chapter", director_id: 5, created_at: "2018-11-22 02:43:18", updated_at: "2018-11-22 02:43:18">, 
#<Movie id: 25, name: "Resident Evil: The Final Chapter", director_id: 25, created_at: "2018-11-22 02:43:18", updated_at: "2018-11-22 02:43:18">,
                 ...略]
>

  

 导航栏中的搜索框:

  

第四步:

修改controller: 根据url的格式来使用不同的模版

  • http://localhost:3000/search.json
  • http://localhost:3000/search.html

 

新增asset/javascripts/search.js,加上对搜索框的事件的操作

document.addEventListener("turbolinks:load" ,function() {
  //取导航条的搜索框input元素。
  //input = document.querySelector("[data-behavior='autocomplete']")
  //因为要使用jQuery的事件, 所以必须用jQuery对象。
  $input = $("[data-behavior='autocomplete']") 

//指定参数1. getValue。根据对象中的key得到value。
//指定参数2. url。根据input phrase得到json数据;
//这里url是一个函数,接收phrase并发送它到一个api.

//从service返回的Response被转化为list. var options
= {
getValue: "name", url: function(phrase) { return "/search.json?q=" + phrase;
//return "/search?q=" + phrase + "&format=json"; } categories: [ {
     //listLocation.当响应的数据非常复杂时,可以指定list的位置。 listLocation:
"movies"      header: "<strong>Movies</strong>", }, { listLocation: "directors"      header: "<strong>Directors</strong>", }
], list: {
//easyautocomplete库的event
//这个插件提供的3个行为function函数:getSelectedItemData()
onChooseEvent: function() { var url
= $input.getSelectedItemData().url       $input.val("") Turbolinks,visit(url) //使用Turbolinks.vist(location)发出请求并处理响应。 },
     //可以添加动画函数,具体往下看?。 },
//延迟发送请求,避免每个字母都发送请求。
requestDelay: 500 } $input.easyAutocomplete(options) })

 

附加:

autocomplete plugin:

Templates:

可以让你修改view的suggestions list建议列表。

不同的可视风格,包括输入框的形状,颜色。这些都可以自己客制!

还可以附加小的图片:http://easyautocomplete.com/

 

Animation

插件提供了简单的动画设置,如fade, silde.等视觉效果!

    list: {
        showAnimation: {
            type: "fade", //normal|slide|fade
            time: 400,
            callback: function() {}
        },

        hideAnimation: {
            type: "slide", //normal|slide|fade
            time: 400,
            callback: function() {}
        }
    }

 

其他辅助功能:

  • 完全匹配match,
  • 排序sort,
  • 显示list的数量,
  • 延迟请求的数据requestDelay: 500✅
    • 这用于当准备ajax response data接收大量resources时。
    • 可以避免发送多重的请求数据。当用户打字非常快时,需要一个延迟,来避免每个字母都发送一个请求。

 


 


 

附加:

如果使用ransack.

参考git.

在首页root添加一个搜索框,并显示搜索到的movies名字和url。

在controller, 添加

class HomeController < ApplicationController
  def index
    @q = Movie.ransack(params[:q])
    @movies = @q.result(distinct: true)
  end
end

 

在index.html.erb

  • 使用helper方法search_form_for: 本例子需要提供url
  • 使用helper方法sort_link()。sort_link有多种设置,根据需要看git文档
<%= search_form_for @q, url: root_path do |f| %>
  <%= f.label :name_cont %>
  <%= f.search_field :name_cont%>
  <%= f.submit %>
<% end %>


<h3>Movies</h3>
<table class="table table-border table-hover">
  <thead>
    <th>
      <%= sort_link(@q, :name,"Movie name", default_order: :desc) do%>
        <strong>Movie Name</strong>
      <% end %>
    </th>
    <th>url</th>
  </thead>

  <tbody>
    <% @movies.each do |movie| %>
      <tr>
        <td><%= movie.name%></td>
        <td><%= movie_path(movie) %></td>
      </tr>
    <% end %>
  </tbody>
</table>

 

 

 


 

使用高级功能

为了能够生成复杂的查询语句如: AND/OR, groupings等,ransack使用Rails's nested attributes functionality。

这需要多一点准备工作,但它能够产生更绚丽的搜索交互。唯一一个明显的缺点是要求使用HTTP POST方法代替GET。

 

⚠️Ransack#search方法等同于ransack方法。但最好还是用ransack方法。因为search方法可能和其他gem冲突!

 

Associations

可以使用Ransack来搜索关联的对象。 has_many, belongs_to

加上includes()方法即可

def index
    @q = Supervisor.ransack(params[:q])
    @supervisors = @q.result.includes(:department, :employees)
  end

 

 

Search Matchers

Ransack提供了大量的predicates

https://github.com/activerecord-hackery/ransack

 

Problem with DISTINCT selects

⚠️distince: true会生成SELECT DISTINCT

在使用includes关联上其他表时,需要注意。

 

验证白名单黑名单

默认,搜索和整理sort是在你的model上被通过验证的。无需把类方法/scopes加入白名单。

Ransack提供了ActiveRecord::Base4种方法。你可以从新定义类方法进行验证。

 

Grouping queries by OR instead of AND

默认使用AND grouping。可以通过添加m: 'or'来改变查询hash

def index
  @q = Artist.ransack(params[:q].try(:merge, m: 'or'))
  @artists = @q.result
end

 

SQL query becomes WHERE..OR.. 

 

能够配合I18n

能够配合SimpleForm

 

转载于:https://www.cnblogs.com/chentianwei/p/9822492.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值