Rails - Saving Ransack Query for later use

2020-07-23 08:34发布

I have successfully installed the Ransack gem and have it working in my app for both simple and advanced searches. I am trying to add a feature for users to "Save a Search". Essentially the idea is they can bookmark a search query, and access it later at any time.

I set it up by creating a SavedSearch model. When a user saves the search it takes the params[:q] from their ransack search and stores it in the database.

Later I pull this record from the database, and access the query. I try to recreate the search by passing the query to ransack, but it does not seem to be working. The search pulls ALL RECORDS for that model, rather than simply those that fit the query. Any idea why? I am thinking perhaps the search parameters need to be modified to a different format before passing them back to ransack? Here is my code:

Here is the code from my controller model (advanced_search action works flawlessly, but saved_search does not filter correctly when recycling the query):

  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

Here is how the search parameters from a successful query look when they are stored in the database:

{"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条回答
相关推荐>>
2楼-- · 2020-07-23 08:57

I think in the database you are storing the query as String.While you are pulling it from database @saved_search.query_parameters is returning you the string.But the ransack needs it to be a Hash.This is the main problem I guess.

While you are passing through params its gets a Hash but from database its getting String.You need to parse the string you are getting from the @query variable and then pass it to the search.

For String to Hash conversion you can have a look at How do I convert a String object into a Hash object? question's answers.

查看更多
劫难
3楼-- · 2020-07-23 09:04

As per your question:

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

this is how your param HASH looks like and you are storing it for future use(bookmark). The problem here is, these are storing as string in your database.

Two solution that I can suggest is:

1. USE HStore (http://www.postgresql.org/docs/9.0/static/hstore.html)

you can use HStore type column in your postgresql database to store those param hash which you can call as it is when required. NOTE: PostgreSQL database.

2. STRING to HASH conversion:

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

NOTE I do not recommend using eval() function, coz eval is not safe and we can't trust params

RECOMMENDATION:

another workaround for you problem I have figure out is:

1) Before saving your bookmark params, convert them to 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) Now, before passing these values to ransack search, convert them into original hash by:

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

I hope, this will help you solve your problem....

查看更多
趁早两清
4楼-- · 2020-07-23 09:06

Try this gem: https://rubygems.org/gems/ransack_advanced_search is provides a nice interface for building queries and also allow you to name and store the search for later use. Is uses the serialize method from active_record to save the query params from the database

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

  serialize :search_params
end

It will automatically convert the search_params back to a hash when you read it from the database

查看更多
登录 后发表回答