Rails - 保存Ransack查询以供以后使用

时间:2015-10-10 16:19:25

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

我已经成功安装了Ransack gem,并在我的应用程序中使用它进行简单和高级搜索。我正在尝试为用户添加一项功能,以便"保存搜索"。基本上这个想法是他们可以为搜索查询加书签,并在以后随时访问它。

我通过创建SavedSearch模型进行设置。当用户保存搜索时,它从搜索搜索中获取params [:q]并将其存储在数据库中。

稍后我从数据库中提取此记录,并访问该查询。我尝试通过将查询传递给ransack来重新创建搜索,但它似乎没有工作。搜索会为该模型提取所有记录,而不仅仅是那些符合查询的记录。知道为什么吗?我想也许在将搜索参数传回ransack之前,需要将搜索参数修改为不同的格式?这是我的代码:

以下是我的控制器模型中的代码(advanced_search操作完美无缺,但在回收查询时saved_search无法正确过滤):

  def advanced_search
    @query = params[:q]
    @saved_search = SavedSearch.new
    @q = Variant.search(params[:q])
    @q.build_grouping unless @q.groupings.any?
    @variants  = params[:distinct].to_i.zero? ?
      @q.result.paginate(per_page: 100, page: params[:page]) :
      @q.result.includes(:supplier).paginate(per_page: 100, page: params[:page])

    respond_with @variants
  end

  def saved_search
    @id = params[:id]
    @saved_search = SavedSearch.find(@id)
    @query = @saved_search.query_parameters
    @distinct = @saved_search.distinct

    @q = Variant.search(@saved_search.query_parameters)
    @q.build_grouping unless @q.groupings.any?
    @variants  = @distinct.to_i.zero? ?
      @q.result.paginate(per_page: 100, page: params[:page]) :
      @q.result.includes(:supplier).paginate(per_page: 100, page: params[:page])

    render 'advanced_search'
  end

以下是成功查询的搜索参数在存储在数据库中时的外观:

{"g"=>{"0"=>{"m"=>"and", "c"=>{"0"=>{"a"=>{"0"=>{"name"=>"total_revenue"}}, "p"=>"gt", "v"=>{"0"=>{"value"=>"1000"}}}}}}, "s"=>{"0"=>{"name"=>"stock_health", "dir"=>"asc"}}}

3 个答案:

答案 0 :(得分:2)

根据你的问题:

{"g"=>{"0"=>{"m"=>"and", "c"=>{"0"=>{"a"=>{"0"=>{"name"=>"total_revenue"}}, "p"=>"gt", "v"=>{"0"=>{"value"=>"1000"}}}}}}, "s"=>{"0"=>{"name"=>"stock_health", "dir"=>"asc"}}}

这就是你的param HASH的样子,你将它存储起来以备将来使用(书签)。这里的问题是,这些是在数据库中存储为字符串。

我建议的两个解决方案是:

<强> 1。使用HStore(http://www.postgresql.org/docs/9.0/static/hstore.html

您可以在postgresql数据库中使用HStore类型列来存储那些您可以在需要时调用的param哈希。注意:PostgreSQL数据库。

<强> 2。 STRING到HASH转换:

How do I convert a String object into a Hash object?

  

注意我不建议使用eval()函数,因为eval不安全且我们不能信任params

<强>建议:

我解决的问题的另一个解决方法是:

1)在保存书签参数之前,将它们转换为json

# suppose bookmark is a column you are using in SavedSearch table to store those ransack search params[:q] then

bookmark = {"g"=>{"0"=>{"m"=>"and", "c"=>{"0"=>{"a"=>{"0"=>{"name"=>"total_revenue"}}, "p"=>"gt", "v"=>{"0"=>{"value"=>"1000"}}}}}}, "s"=>{"0"=>{"name"=>"stock_health", "dir"=>"asc"}}}

@saved_search = SavedSearch.new(save_search_params)
@saved_search.bookmark = bookmark.to_json
@saved_search.save

2)现在,在将这些值传递给ransack搜索之前,请将它们转换为原始哈希:

require 'json'
@saved_search = SavedSearch.find(id)
original_bookmark = JSON.parse(@saved_search.bookmark)

我希望,这会帮助您解决问题....

答案 1 :(得分:1)

我认为在数据库中你将查询存储为String.While你从数据库中提取它@saved_search.query_parameters返回你的字符串。但是ransack需要它成为一个Hash。这是我的主要问题猜测。

当你通过params时,它会得到一个Hash,但是从数据库获取String。你需要解析你从@query变量得到的字符串,然后将它传递给搜索。

对于String to Hash转换,您可以查看How do I convert a String object into a Hash object?个问题的答案。

答案 2 :(得分:1)

试试这个宝石:https://rubygems.org/gems/ransack_advanced_search 提供了一个很好的界面来构建查询,还允许您命名和存储搜索以供以后使用。是使用active_record中的serialize方法来保存数据库中的查询参数

class SavedSearch < ActiveRecord::Base
  validates_presence_of :context, :description, :search_params

  serialize :search_params
end

当您从数据库中读取它时,它会自动将search_params转换回哈希值