Search code examples
ruby-on-railselasticsearchroutessearchkick

ElasticSearch handling Rails route params with nested objects


We have a Rails search route which can accept nested objects that should map to ElasticSearch operators.

For example:

{
  name: "John",
  age: {
    {gte: 20}
  }
}

The problem is that the SearchKick library throws an error when the Rails route params look like the following:

{"name"=>["Sam Terrick", "John Terrick"], "age"=>{"gte"=>"20"}}

The Searchkick library maps through these filters and does a case comparison for :gte, but the hash rocket keys do not match. ActiveSupport::HashWithIndifferentAccess doesn't get the job done.

https://github.com/ankane/searchkick/blob/master/lib/searchkick/query.rb

Is there an elegant way to handle this transformation of nested objects from the route params without having to check if each param is a Hash?


Solution

  • For that you could make use of the Rails Hash.html#method-i-deep_transform_keys:

    params = {"name"=>["Sam Terrick", "John Terrick"], "age"=>{"gte"=>"20"}}
    p params.deep_transform_keys(&:to_sym)
    # {:name=>["Sam Terrick", "John Terrick"], :age=>{:gte=>"20"}}
    

    But Rails also implements other handy method, more accurate in this case, Hash.html#deep_symbolize_keys:

    p params.deep_symbolize_keys
    # # {:name=>["Sam Terrick", "John Terrick"], :age=>{:gte=>"20"}}
    

    Same result.