‘jaap’ wrote a rake task to convert your Rails application from using Gettext translation into the new I18n support, which is really great!
WARNING: Before you run the new rake task rake gettext_to_i18n:transform, read “So How Do You Fix It?” below
OK, so you’ve followed along in the article and now you want to test out your new localization system. Problem is when you try to start the server up script/server you get this error message:
/Users/cblackburn/Source/ruby/bols/lib/active_support/memoizable.rb:71:in `path': can't modify frozen object (TypeError)…or something similar.
What happened? Since you have frozen Rails and the rake task does not exclude the frozen vendor/rails directory, it modified memoizable.rb in ActiveSupport causing this error.
So How Do You Fix It?
Do one of the following:
- Backup lib/active_support/memoizable.rb before you run the rake task, then restore it after.
- Restore lib/active_support/memoizable.rb using your SCM.
For this project in my case it was
svn revert lib/active_support/memoizable.rbCome on guys, we should be past stupid upstream inconsistencies like this by now.
After reading all of the worthless posts regarding this error on Gentoo , I came up with the following solution:
sudo ln -s /usr/lib/libdbus-1.so.3 /usr/lib/libdbus-1.so.2
This error seems to rear its head on other platforms as well. I’m not sure if this solution will work on other platforms.
Just do it and be done.
UPDATE: Someone from the Gentoo team tried to leave a berating comment telling me to “read the _blank_ manual” and find that revdep_rebuild solves this problem. In response I can say that it indeed does NOT solve the problem. This is a really stupid bug in Gentoo and should be fixed. Come on guys! I love the product, but this is just retarded. It isn’t that difficult to fix the problem. Just do it once and for all. The amazing thing is that I still get emails and thanks for this resolution, even in Sabayon. I’m not sure who is responsible for this incompetency on the Gentoo team but there is simply no excuse.
revdep_rebuild!?!?! Only an amateur would think that nobody has tried that first.
It is likely that you have already used or have heard of AJAX. The ubiquitous example is Google Maps, which certainly wasn’t the first but is arguably the most quoted.
AJAX is a very useful technology but have you ever tried to use it across domains? For example, try to send an AJAX request from www.yoursite1.com to www.yoursite2.com. Does it work? Let me save you some time and tell you the answer is no. It won’t work by design. The Javascript specification considers cross-domain XMLHttpRequests to be a security risk, which it can be.
So, what if you have a legitimate business requirement to do cross-domain Javascript requests? The most important reason I can think of for this requirement is a third-party service, or web systems that are distributed across domains. There are many of these types of instances where cross-domain AJAX would be very valuable.
You could require the browser to download a Java applet, which would immediately alienate some browsers. You could use a Flash solution but again, many people simply won’t take the time to download the applet or plugin. More importantly for tracking services, sending Flash or Java applications to browsers on every request is simply not going to scale.
Enter Asynchronous Javascript Across Domains. How does it work?
- Javascript can dynamically generate or load more Javascript.
- Javascript can be loaded across domains.
Is the light going on yet?
So, we write some Javascript that will dynamically append a script tag
<script type="text/javascript" language="Javascript" src="http://somewhere_in_a_different_domain.com/phajad.php?data=whatever">
Lets look at an example:
Let’s say we track referrers for our client sites. One of our clients is webtalon.com. So webtalon.com places our JS tag onto all of their pages and it looks like this:
<script type="text/javascript" language="Javascript" src="http://bombast.cblackburn.com/phajad.php?id=1247">
… which spits back some code, generated on the server side, that looks something like this:
var ajad_url = 'http://bombast.cblackburn.com/';
var ajad_ndx_script = 0;
function ajad_do (u) {
// Check that we have prepended the ajad_url
if (u.substring(0, 4) != 'http') {
u = ajad_url + u;
}
// Create new JS element
var js = document.createElement('SCRIPT');
js.type = 'text/javascript';
ajad_ndx_script++;
js.id = 'ajad-' + ajad_ndx_script;
js.src = u;
// Append JS element (therefore executing the 'AJAX' call)
document.body.appendChild(js);
return true;
}
function ajad_get (r) {
// Create URL
var u = ajad_url + 'track_refer.php?r=' + escape(r) +
'&id=1247';
// Do AJAD
return ajad_do(u);
}
function ajad_send() {
// referrer
r = window.location;
// send it
ajad_get(r);
// remove the last script node.
document.body.removeChild(document.getElementById('ajad-' + ajad_ndx_script));
ajad_ndx_script--;
}
ajad_send();So what happens here? The browser loads this Javascript and calls ajad_send(). Let’s look at the ajad_send() function:
The first thing we do is to grab the referrer from the browser.
// referrer
r = window.location;This works even in Macintosh browsers as long as Javascript is turned on. Today, if someone turns off Javascript in their browser much of the web simply won’t work. So the chances they have Javascript turned on are big.
Next we call ajad_get(), passing the referrer we just collected. ajad_get is so named because we are ‘getting’ more Javascript. This call passes control to another function which actually appends a Javascript node to the browser document.
// send it
ajad_get(r);We’ll examine ajad_get() in a bit…
Lastly we remove the Javascript that was just appended. We want to keep the page clean of Javascript that we are finished using.
// remove the last script node.
document.body.removeChild(document.getElementById('ajad-' + ajad_ndx_script));
ajad_ndx_script--;Ok, so lets look at what ajad_get() does…
// Create URL
var u = ajad_url + 'track_refer.php?r=' + escape(r) +
'&id=1247';
// Do AJAD
return ajad_do(u);…not much. Here we simply build the URL which will serve two purposes:
- Pass the referrer back to the server script track_refer.php at bombast.cblackburn.com.
- Retrieve more Javascript, if necessary, to make additional AJAD calls.
Next we call ajad_do(), passing the URL we just built.
// Check that we have prepended the ajad_url
if (u.substring(0, 4) != 'http') {
u = ajad_url + u;
}
// Create new JS element
var js = document.createElement('SCRIPT');
js.type = 'text/javascript';
ajad_ndx_script++;
js.id = 'ajad-' + ajad_ndx_script;
js.src = u;
// Append JS element (therefore executing the 'AJAX' call)
document.body.appendChild(js);
return true;Ahhh, so here is where the real work takes place.
First we double-check that the calling function passed in a URL with ‘http’ prepended. In our case we have, so it should not be necessary, but double-checks are always a good idea.
Then we create a new script tag, set its type to ‘text/javascript’, increment our node counter, assign an ID to the node so we can remove it in the ajad_send() function, which we already examined, finally we assign the src attribute to the Javascript node.
Last thing is to append the node to the document.body and return true. This actually makes the AJAD request back to the server which looks something like this:
http://bombast.cblackburn.com/track_refer.php?r=https%3A//www.dmoz.org/
So back at the server side, we have a script ‘track_refer.php’ that processes the 'r=https%3A//www.dmoz.org/'. We tie that back to our client ‘webtalon.com’ using the ‘id=1247’.
Although we don't demonstrate it here, it is easy to see how the Javascript that we return from ‘track_refer.php’ could setup another call using AJAD, and so on, ad infinitum.
If you have any questions, as always, drop a comment below. I'm always interested to hear what new and improved things people are doing with code or ideas presented here.

