如何创建搜索功能 - Ruby On Rails

时间:2016-01-15 05:09:18

标签: ruby ruby-on-rails-3 ruby-on-rails-4

我正在尝试为应用创建搜索功能。我有一个名为搜索的服务对象,所有搜索逻辑都在此对象中。

使用=> [ [0] [], [1] [ [0] About { :id => 2, :title => "About", :slug => "about", :meta_description => "", :meta_keywords => "", :content => "<p>Lorem ipsum about</p>", :position => 1, :published => true, :on_menu => true, :created_at => Wed, 13 Jan 2016 00:44:08 UTC +00:00, :updated_at => Fri, 15 Jan 2016 04:05:52 UTC +00:00 } ], [2] [], [3] [] ] 查询提交搜索表单时,搜索控制器中的@results是以下数组。

class SearchService
  attr_accessor :query

  def initialize(query)
    @query = query
  end

  # searchable_fields_by_model
  CONDITIONS_BY_MODEL = {
    Page => [:title, :content],
    NewsArticle => [:title, :content]
    User => [:first_name, :last_name]
  }

  def raw_results
    ActiveRecord::Base.transaction do
      CONDITIONS_BY_MODEL.flat_map do |model, fields|
        Array(fields).map do |field|
          model.where(["#{field} LIKE ?", "%#{query}%"])
        end
      end
    end
  end
end

这是我的搜索对象。查看用户属性与Pages和NewsArticle的不同之处?好。现在去看看。

content

以下是我的观点。目前,该视图仅显示titlefirst_name。但我的用户有last_name.page-header %h1 Search#index - @results.each do |results| - results.each do |r| %p= r.title %p= r.content ,因此无法显示。我需要一种方法来显示所有模型的结果,它需要干净,所以如果我添加另一个模型来搜索完全不同的属性,它仍然会显示。你会怎么做?

class SearchController < ApplicationController
  def index
    @results = SearchService.new(params[:q]).results
  end
end

搜索控制器

{{1}}

1 个答案:

答案 0 :(得分:1)

如何解决这个问题。

class SearchController < ApplicationController
  def index
    @results = SearchService.new(params[:q]).results

    @page_results = []
    @news_article_results = []
    @category_results = []

    @results.each do |resource|
      if resource.class == Page
        @page_results << resource
      elsif resource.class == NewsArticle
        @news_article_results << resource
      elsif resource.class == Category
        @category_results << resource
      else
      end
    end
  end
end

class SearchService
  MIN_QUERY_LENGTH = 3
  attr_accessor :query

  def initialize(query)
    raise ArgumentError if query.length < MIN_QUERY_LENGTH
    @query = query
  end

  # searchable_fields_by_model
  CONDITIONS_BY_MODEL = {
    Page => [:title, :content],
    NewsArticle => [:title, :content],
    Category => :name,
  }

  def results
    @results ||= ActiveRecord::Base.transaction do
      CONDITIONS_BY_MODEL.flat_map do |model, fields|
        Array(fields).flat_map do |field|
          model.where(["#{field} LIKE ?", "%#{query}%"])
        end
      end
    end
  end
end

这是我的观点

.page-header
  %h1 Search Results
  %h2= "For #{params[:q]}"
  %br
  %h2 Pages
  - @page_results.each do |resource|
    %p= link_to "#{resource.title}", page_path(resource.slug)
    = resource.content.html_safe

  %h2 News Article
  - @news_article_results.each do |resource|
    %p= link_to "#{resource.title}", news_article_path(resource.slug)
    = resource.content.html_safe

  %h2 Category
  - @category_results.each do |resource|
    %p= link_to "#{resource.name}", category_path(resource.slug)