I have a problem with a piece of JavaScript code – a snippet is shown below. Basically the code is issuing a getJSON request to a rails controller and then should process the returned data, building an HTML table and then embedding it in a Div. It doesn’t work. I have tried stepping through it with alerts, etc – all to no avail. The data is retrieved from the rails controller and I can verify that. I have placed the piece of code that issues and processes the getJSON request in the niddle of the Rails Welcome page – this is not all mine. The code is below:
<!DOCTYPE html>
<html>
<head>
<title>Ruby on Rails: Welcome aboard</title>
<style type="text/css" media="screen">
body {
margin: 0;
margin-bottom: 25px;
padding: 0;
background-color: #f0f0f0;
font-family: "Lucida Grande", "Bitstream Vera Sans", "Verdana";
font-size: 13px;
color: #333;
}
h1 {
font-size: 28px;
color: #000;
}
a {color: #03c}
a:hover {
background-color: #03c;
color: white;
text-decoration: none;
}
#page {
background-color: #f0f0f0;
width: 750px;
margin: 0;
margin-left: auto;
margin-right: auto;
}
#content {
float: left;
background-color: white;
border: 3px solid #aaa;
border-top: none;
padding: 25px;
width: 500px;
}
#sidebar {
float: right;
width: 175px;
}
#footer {
clear: both;
}
#header, #about, #getting-started {
padding-left: 75px;
padding-right: 30px;
}
#header {
background-image: url("images/rails.png");
background-repeat: no-repeat;
background-position: top left;
height: 64px;
}
#header h1, #header h2 {margin: 0}
#header h2 {
color: #888;
font-weight: normal;
font-size: 16px;
}
#about h3 {
margin: 0;
margin-bottom: 10px;
font-size: 14px;
}
#about-content {
background-color: #ffd;
border: 1px solid #fc0;
margin-left: -55px;
margin-right: -10px;
}
#about-content table {
margin-top: 10px;
margin-bottom: 10px;
font-size: 11px;
border-collapse: collapse;
}
#about-content td {
padding: 10px;
padding-top: 3px;
padding-bottom: 3px;
}
#about-content td.name {color: #555}
#about-content td.value {color: #000}
#about-content ul {
padding: 0;
list-style-type: none;
}
#about-content.failure {
background-color: #fcc;
border: 1px solid #f00;
}
#about-content.failure p {
margin: 0;
padding: 10px;
}
#getting-started {
border-top: 1px solid #ccc;
margin-top: 25px;
padding-top: 15px;
}
#getting-started h1 {
margin: 0;
font-size: 20px;
}
#getting-started h2 {
margin: 0;
font-size: 14px;
font-weight: normal;
color: #333;
margin-bottom: 25px;
}
#getting-started ol {
margin-left: 0;
padding-left: 0;
}
#getting-started li {
font-size: 18px;
color: #888;
margin-bottom: 25px;
}
#getting-started li h2 {
margin: 0;
font-weight: normal;
font-size: 18px;
color: #333;
}
#getting-started li p {
color: #555;
font-size: 13px;
}
#sidebar ul {
margin-left: 0;
padding-left: 0;
}
#sidebar ul h3 {
margin-top: 25px;
font-size: 16px;
padding-bottom: 10px;
border-bottom: 1px solid #ccc;
}
#sidebar li {
list-style-type: none;
}
#sidebar ul.links li {
margin-bottom: 5px;
}
</style>
<script src="/javascripts/jquery.js" type="text/javascript"></script>
<script type="text/javascript">
function about() {
info = document.getElementById('about-content');
if (window.XMLHttpRequest)
{ xhr = new XMLHttpRequest(); }
else
{ xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
xhr.open("GET","rails/info/properties",false);
xhr.send("");
info.innerHTML = xhr.responseText;
info.style.display = 'block'
}
</script>
<script type="text/javascript">
alert('Start of JSON Routine');
$(document).ready( function() {
alert('Attach a JQuery Live event to the button');
$('#getdata-button').live('click', function() {
alert("Get JSON data");
$.getJSON('http://0.0.0.0:3000/getjson/1', function(data) {
alert('Processing returned JSON data');
var tmp = '<table border=1>';
for (i=0;i<data.length;i++)
{
tmp = tmp +'<tr>';
tmp = tmp + '<td>' + data[i].book.price + '</td>';
tmp = tmp + '<td>' + data[i].book.title + '</td>';
tmp = tmp + '<td>' + data[i].book.author + '</td>';
tmp = tmp + '<td>' + data[i].book.ISBN + '</td>';
tmp = tmp + '<td>' + data[i].book.yearPublished + '</td>';
tmp = tmp + '<td>' + data[i].book.volume + '</td>';
tmp = tmp + '<td>' + data[i].book.publisher + '</td>';
tmp = tmp + '<td>' + data[i].book.edition + '</td>';
tmp = tmp + '<td><a href=# onclick=\"alert('+ i +')\">View</a></td>';
tmp = tmp + '</tr>';
}
tmp = tmp + '</table>';
alert('About to insert Table into DOM in content Div');
$('#showdata').html(tmp);
}); //getJSON end
}); //getdata-button end
}); //document.ready end
alert('End of JSON routine');
</script>
</head>
<body>
<div id="page">
<div id="sidebar">
<ul id="sidebar-items">
<li>
<h3>Browse the documentation</h3>
<ul class="links">
<li><a href="http://api.rubyonrails.org/">Rails API</a></li>
<li><a href="http://stdlib.rubyonrails.org/">Ruby standard library</a></li>
<li><a href="http://corelib.rubyonrails.org/">Ruby core</a></li>
<li><a href="http://guides.rubyonrails.org/">Rails Guides</a></li>
</ul>
</li>
</ul>
</div>
<a href="#" id="getdata-button">Get JSON Data</a>
<script>alert("Before the JMC div");</script>
<div id="showdata">JMC</div>
<script>alert("Past the JMC div");</script>
<div id="content">
<h1>Welcome aboard</h1>
<h2>You’re riding Ruby on Rails!</h2>
</div>
<div id="about">
<h3><a href="rails/info/properties" onclick="about(); return false">About your application’s environment</a></h3>
<div id="about-content" style="display: none"></div>
</div>
<div id="getting-started">
<h1>Getting started</h1>
<h2>Here’s how to get rolling:</h2>
<ol>
<li>
<h2>Use <code>rails generate</code> to create your models and controllers</h2>
<p>To see all available options, run it without parameters.</p>
</li>
<li>
<h2>Set up a default route and remove or rename this file</h2>
<p>Routes are set up in config/routes.rb.</p>
</li>
<li>
<h2>Create your database</h2>
<p>Run <code>rake db:migrate</code> to create your database. If you're not using SQLite (the default), edit <code>config/database.yml</code> with your username and password.</p>
</li>
</ol>
</div>
</div>
<div id="footer"> </div>
</div>
</body>
</html>
Here is the JSON data I get back when I just invoked the URL/ Controller action directly from the browser:
[
{
"book":{
"price":"25.52",
"created_at":"2011-10-27T22:35:04Z",
"ISBN":"",
"author":"Obie Fernandez",
"title":"Rails 3 Way, The (2nd Edition)",
"updated_at":"2011-10-27T22:35:04Z",
"yearPublished":"2010",
"id":1,
"publisher":"Addison-Wesley",
"volume":"2",
"edition":"second edition"
}
},
{
"book":{
"price":"23.94",
"created_at":"2011-10-27T22:39:37Z",
"ISBN":"",
"author":"Michael Hartl",
"title":"Ruby on Rails 3 Tutorial: Learn Rails by Example",
"updated_at":"2011-10-27T22:39:37Z",
"yearPublished":"2010",
"id":2,
"publisher":"Addison-Wesley",
"volume":"",
"edition":"first edition"
}
},
{
"book":{
"price":"24.97",
"created_at":"2011-10-27T22:42:42Z",
"ISBN":"",
"author":"Cloves Carneiro Jr. and Rida Al Barazi",
"title":"Beginning Rails 3 ",
"updated_at":"2011-10-27T22:42:42Z",
"yearPublished":"2009",
"id":3,
"publisher":"Apress",
"volume":"",
"edition":"first edition"
}
}
]
Anything else that might be useful. The Rails logs show the request being handled correctly.
When I step through the script, the alerts come up in a starnge sequence:
THe first alert I get is “Here at start of JSON Routine”, followed by “Finished document ready routine” and then “Attach a JQuery Live event to the button”. I then click the button for getdata and then a # appears at the end of the URL and then nothing.
MOved the script into the head – same outcome.
SWitched #content to #showdata – same outcome.
Final Edit:
The problem is solved thanks to the input of many people.
There were a number of issues, but the final issue was a same origin error in that the URL on the getJSON request was different to the URL making the request. The request had 0.0.0.0:3000/getjson/1 whereas the requesting URL was localhost:3000/getjson/1. Very hard to spot and the lack of return / status info with getJSON made it more difficult. Anyway thanks is due to all contributors, who all made valid contributions. I hope I have the expertise to contribute myself someday.
Alright Joe, you need to start with the simplest case possible… clean up all of your HTML and get rid of everything that you do not need. I tested this and verified that it works on my local Rails server.
I mocked up the Rails controller action to return your JSON data using:
You shouldn’t need to change your Rails controller code since you said it was working. I just wanted to show you how I mocked it up for your future reference.
Now, replace the contents of your HTML file with this:
Notice that I am using the
$.ajaxmethod which allows me to specify an error handler callback. I would recommend using this way of doing things until you become more familiar with jQuery and feel confident that you can start using the other AJAX helpers.I hope this helps!