Simple example of Rails 3 + UJS using Ajax to make a remote call, and rendering the resulting JSON object
Asked Answered
H

3

11

I'm trying to add some Ajax functionality in my Rails 3 app.

Specifically, I want a button that will submit an Ajax request to call a remote function in my controller, which subsequently queries an API and returns a JSON object to the page.

Once I receive the JSON object I want to display the contents.

All of this with the new Rails 3 UJS approach, too. Is there a good example/tutorial for this online somewhere? I haven't been able to find one on google. A simple example using a button as the entry point (ie, the user clicks the button to start this process) would work, too.

Edit Let me try this with a different approach. I want to have this button query an external API, which returns JSON, and display that JSON on the page. I have no idea where to even begin. Does the button itself query the external API? Do I need to go through the controller, and have the controller query the external API, get the JSON, and give the JSON back to this page? How do I display/access the contents of this JSON? I honestly can't find a good Rails 3.x example of how to handle JSON...

Holophytic answered 25/4, 2011 at 2:1 Comment(3)
See this RailscastSollows
That's helpful, but I'm particularly looking for a JSON example, not an example that uses getScript(). I'm not quite good enough at Rails to see how this example applies to what I need...Holophytic
I also find this remarkably hard. There are lots of examples out there but they all assume you want to use action.js.erb and I don't. I think you are looking for the same thing I am. If so, I will try to find an example and reply.Ese
L
10

Here is a start:

First create your button with a link_to method in your view, for example:

=link_to "delete", "#{invitation_path(invitation)}.json", :method=>:delete, :remote=>true, :class=>"remove", :confirm=>'Are you sure you?'

Note that I am appending ".json" to the url of my resource. This is just an example of a an AJAX delete, google link_to to see the meaning of the parameters. The concept if that you make your HTTP request with the parameter :remote set to true, in other words this is translated to an AJAX call from your browser.

Second, write some javascript so that you can process what ever is the result of the AJAX call your browser will make when the user click on the link_to of step 1. For details you can see this blog post: http://www.alfajango.com/blog/rails-3-remote-links-and-forms/

An example from my site:

jQuery(function($) {
  // create a convenient toggleLoading function
  var toggleLoading = function() { $("#loading").toggle() };

  $("#pending_invitation")
    .live("ajax:loading",  toggleLoading)
    .live("ajax:complete", toggleLoading)
    .live("ajax:success", function(event, data, status, xhr) {
       var response = JSON.parse(xhr.responseText)
       if (response.result == "ok") {
          $(this).fadeOut('fast');
       }
       else {
         var errors = $('<div id="error_explanation"/>');
         errors.append('<h2>Pending invitation action error</h2><ul><li>' + response.error + '</li></ul>');
         $('#new_invitation_error').append(errors)   
       }
    });
});

where you can see that I parse the returned json and and change the html on the page based on that. Note that this js uses the CCS ids and classes defined in the top view that is not included here.

If you now want to write you own controller to spit out the json here is an example:

class InvitationsController < ApplicationController
  respond_to :html, :json

  # other methods here
  # ...

  def destroy
    @invitation = Invitation.find(params[:id])
    respond_to do |format|
      if @invitation
        @invitation.destroy
        flash[:success] = I18n.t 'invitations.destroy.success'
        format.json { render :json =>{:result => "ok", :message=>"Invitation #{params[:id]} was destroyed", :resource_id=>params[:id] } }
      else
        format.json { render :json => { :result=>"failed", :error=>"Cannot find Invitation #{params[:id]}", :resource_id=>params[:id] } }
      end
    end
  end
end

Hope this help.

Longueur answered 26/4, 2011 at 19:17 Comment(2)
you can set "data-type" => "json" in your link_to call instead of appending ".json" to route.Stepdaughter
Or in your javascript you can set $.ajaxSettings.dataType = 'json' to default every remote form to PUT/POST/DELETE json. This is part of the jquery-ujs driver: github.com/rails/jquery-ujs/blob/master/src/rails.js#L86Kilometer
N
6

Old question, but a really good overview of Ajaxifying Rails applications is:

Ajax in Rails 3.1 - A Roadmap

Negrito answered 27/1, 2012 at 7:27 Comment(1)
This is the best I've seen so far!Clorindaclorinde
S
1

Also consider returning errors in the following format:

render :json => @myobject.to_json, :status => :unprocessable_entity

This will ensure that your client can process the response as an error.

Saddlebacked answered 23/3, 2013 at 18:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.