I was trying to store some objects in an associative array. Based on my experience with Java, Ruby, and other languages, I expected that given code like this:
1234567
var dictionary = {};var obj1 = {}; var obj2 = {};dictionary[obj1] = 'foo'dictionary[obj2] = 'bar'
The result of dictionary[obj1] would be ‘foo’ and dictionary[obj2] would be ‘bar’.
This is not the case!
The problem is that JavaScript objects are not really hash tables. They’re associative arrays, and the key can only be a String. When you insert an object into a associative array, toString() is called and that is used as the key. Unfortunately, the default toString implementation for JavaScript objects returns “[object Object]”...which is not only very unhelpful when debugging, but doesn’t provide you with a unique key for your associative array.
You can work around this problem by overriding toString. Or you can figure out another way to associate your object with a value. D’oh!
One of my favorite little AJAX tricks is posting only a few fields of the DOM with link_to_remote.
The real world application of this is when you have a composite object that needs to be created in the process of creating your main composing object. It can also be helpful when you have a dynamic interface with hidden divs within one main form and you don’t not want to pass the whole form via xhr (it could be a multipart request with a file selector).
Here is how to submit only one DOM element’s children form inputs:
The important thing to note is the :submit=>‘create_input’ which defines the DOM element whose children will be serialized and passed to the controller on submit. Also notice we haven’t defined an HTML form. Prototype is smart enough to serialize any DOM structure, not only forms. This could just as well be inside a form, but only the DOM element we specify will be sent to the server.
2. A standard controller to handle the post
12345678910
classMovieController < ApplicationControllerdefcreatereturnunless request.xhr? && request.post?# do stuff render :inline => "'#{params[:create_movie_name]}' was created"endend
And that’s it. Of course you don’t need to use link_to_remote, you could just use prototype's Ajax.Request()
123456
new Ajax.Request('/movie/create', {asynchronous:true, evalScripts:true, onFailure:function(request){handleCreateFailure(request);}, onSuccess:function(request){handleCreateSuccess(request);}, parameters:Form.serialize('create_input')});
Using this technique you are no longer forced to do full form submissions when you only want a small bit of data which will lead to a more dynamic and ‘snappy’ user experience.
Eric Chapweske develops Ruby-fueled projects at
Slantwise Design's worldwide headquarters
in Minneapolis. When not reading through Rails source code, he can likely be found
in a kitchen mastering his Korean cooking skills.
Jon Dahl started
using Ruby on Rails in 2005 and hasn't looked back. He is a founder of Zencoder, a startup offering video encoding software as a service.
Luke Francl is a developer at
Tumblon. He came
to Ruby from the Java world and still thinks database
constraints belong in the database. His personal blog
is Just Looking.