Consuming a public Rails API with jQuery
A previous post explained how to implement a public API in Rails. Here, we will cover how this API can be consumed with a cross-domain request using jQuery.
The idea
We’ll create a simple html file containing <ul> elements with an id. We’ll then use jQuery to fetch data (references and quantities) from the API provided by the Rails app we wrote in the previous post.
The HTML
Very basic: we’ll just have a plain HTML page (with jQuery), and add <ul> elements for products:
<ul id="1"></ul>
<ul id="2"></ul>
The function
We’ll need to fetch the data form the remote API using JSONP, since we’ll be doing a cross-domain request to a remote server (even though everything is local; more on that here). So we’ll write a function that will take the id of the remote object we want information for:
function fetchProductData(id) {
$.ajax({
url: "http://localhost:3000/products/" + id + ".js",
dataType: "jsonp",
type: "GET",
processData: false,
contentType: "application/json",
success: function (data) {
$('#' + id).
append('<li>Remote id: ' + id + '</li>').
append('<li>Reference: ' + data['product']['reference'] + '</li>').
append('<li>Quantity: ' + data['product']['quantity'] + '</li>');
}
});
};
The setup for the function is relatively simple: pass in the API url (line 3), and some other parameters. One parameter you want to take special notice of is the
dataType: "jsonp"
(line 4) which will make jQuery use JSONP
to ensure the cross-domain request completes successfully (instead of returning an empty response). jQuery will transparently take care of specifying a callback and returning the wrapped data.
If and when the AJAX request completes successfully, we find the <ul>
element to update, and add child <li>
elements with the data. You’ll notice the data structure returned is pretty straightforward: the product model we defined in the previous post had a reference and a quantity, and they’re both returned in an a key-value fashion. (You can prevent the “product” root node from being included in the json data by setting
ActiveRecord::Base.include_root_in_json = false
in an initializer in your Rails 3 app.)
Updating every element on page load
First, we’ll define a function that will update every <ul>
element on the page with a “product” class by fetching the appropriate data from the API:
function fetchData() {
$(".product").each(function (i) {
fetchProductData($(this).attr("id"));
});
};
Now, we simply have to call the fetchData
function when the page has loaded:
$(document).ready(function () {
fetchData();
});
If you now load the HTML document in a browser (while your Rails app is running), you’ll see the data being fetched from the “remote” server. Enjoy!
For completeness, the full HTML file is:
<!DOCTYPE HTML>
<html>
<head>
<title>JSONP and Rails Demo</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
function fetchProductData(id) {
$.ajax({
url: "http://localhost:3000/products/" + id + ".js",
dataType: "jsonp",
type: "GET",
processData: false,
contentType: "application/json",
success: function (data) {
$('#' + id).
append('<li>Remote id: ' + id + '</li>').
append('<li>Reference: ' + data['product']['reference'] + '</li>').
append('<li>Quantity: ' + data['product']['quantity'] + '</li>');
}
});
};
function fetchData() {
$(".product").each(function (i) {
fetchProductData($(this).attr("id"));
});
};
</script>
</head>
<body>
<ul id="1" class="product">
</ul>
<ul id="2" class="product">
</ul>
</body>
<script type="text/javascript">
$(document).ready(function () {
fetchData();
});
</script>
</html>
Would you like to see more Elixir content like this? Sign up to my mailing list so I can gauge how much interest there is in this type of content.