Donato Donato - 3 months ago 8
JSON Question

respond with redirect on json request

I am using a bootstrap typeahead plugin. Basically, it expects a json response when you click on one of the items in the dropdown menu. However, when the item is clicked, I want to redirect to a different page; I do not want to respond with json. I don't know how to handle this situation. This is what I have:

def populate_global_search
respond_to do |format|
if params[:name] && params[:name][:value]
model = Model.where(name: params[:name][:value]
else
model = nil
end

if model.present?
format.json { redirect_to model }
else
format.json { head :ok}
end
end
end


The action is triggered from an ajax call:

$(element).bind('typeahead:selected', function(obj, datum, name) {
$.ajax({
url: that.format_url(),
data: {
name : datum
}
}).done(function(data){
...


Since the redirect_to is not a json response, nothing happens when I click on the item. What can I do?

Answer

The main problem here, you call the populate_global_search action asynchronously, respond_to block unable to redirect an asynchronously call. To resolve your problem I suggest you render the path to redirect and change the location by window.location:

The javascript code(that's just an assumption):

$(element).bind('typeahead:selected', function(obj, datum, name) {
  $.ajax({
    url: that.format_url(),
    data: {
      name : datum
    }
  }).done(function(data){
    // redirect to the desired path
    window.location = data.location;
  });

The Rails code(also assumption):

def populate_global_search
    respond_to do |format|
      if params[:name] && params[:name][:value]
        # I use find_by, because where return a collection
        model = Model.find_by(name: params[:name][:value])
      else
        model = nil
      end

      if model.present?
        # render a json objects { location: '/some_path/12' } 
        # with path which you need
        format.json { render json: { location: here_is_the_desired_path } }
      else
        format.json { head :ok }
      end
    end
  end

Bonus, your can reduce your Rails code to, this also should works:

def populate_global_search
  model = Model.find_by(name: params[:name].try(:[], :value))
  if model.present?
    render json: { location: here_is_the_desired_path }
  else
    head :ok
  end
end
Comments