Aymen Bou
Aymen Bou

Reputation: 1109

Using Select2 Ajax call with Ruby on Rails and ElasticSearch

I'm trying to implement a select2 search to dynamically produce results based on the users inputted data.

As the user is typing, it should send a GET request to an action that runs the query against ElasticSearch, ElasticSearch should then return a number of objects which I can convert into JSON.

I'm not seeing any results being displayed underneath the select2 searchfield, eventhough the query is being executed against ElasticSearch, and it's returning results based on the users data.

DashboardController.rb

def card_search
    if params[:query].present?
      cards = Elasticsearch::Model.search(params[:query]).records.first(1)
      hash = {}
      hash["results"] = cards.map{|v| v.serializable_hash(only: [:name]) }
      render json: hash.to_json
    else
      render json: []
    end
end

dashboard.html.erb

$(".js-data-example-ajax").select2({
  ajax: {
    url: "/dashboard/card_search",
    dataType: 'json',
    type: "GET",
    delay: 250,
    data: function (term, page) {
      return {
        query: term,
        page: page
      };
    },
    formatResult: function (item) { return item.name; },
    formatSelection: function (item) { return item.name; },
    results: function (data, page) {
      return data;
    },
    cache: true
  },
  placeholder: 'Search for a card',
  minimumInputLength: 1,
});

Parameters are successfully passed into the controller from the javascript:

Parameters: {"query"=>"Charizard", "page"=>"1"}

ElasticSearch produces array of results which is converted into JSON:

"{\"results\":[{\"name\":\"Charizard\"}]}"

When ElasticSearch returns an array and the JSON is returned to the AJAX call, this error is produced:

select2.min.self-65a8000f26302b289c7ae3bdc1ef1831667c2613a3f8f9896177bb441612e583.js?body=1:22 Uncaught TypeError: Cannot read property 'toUpperCase' of undefined

Upvotes: 0

Views: 437

Answers (1)

Aymen Bou
Aymen Bou

Reputation: 1109

Solved!

I realised I had my JSON in the wrong format even though I was following the official select2 documentation: https://select2.org/data-sources/formats

So instead of storing my data in a hash and then converting that to json.

I looped through my results from ElasticSearch and stored each result in an array. I then converted this array to json and then returned it back to the AJAX call.

def card_search
    if params[:query].present?
      cards = Elasticsearch::Model.search(params[:query]).records.first(1)
      array = []

      cards.each do |c|
        array << c
      end

      render json: array.to_json
    else
      render json: []
    end
end

I also had to change the way I format my results on the select2 initializer. I needed to loop through each data item, and specify the id and the text of each result so that select2 could display it.

results: function (data) {
  var results = [];
  $.each(data, function(index, item){
    results.push({
      id: item.id,
      text: item.name
    });
  });
  return {
      results: results
  };
},

Upvotes: 0

Related Questions