RubyNoob gets all Ajaxy
April 23rd, 2006
Or:
"How I got some cool Ajax stuff to work with Ruby on Rails"
This weekend, my goal was to get my first original Ruby on Rails application working on my development box. I have achieved at least some sort of success! My app, such as it is, allows a user to enter a tag from her del.icio.ous account and then the app calls the del.icio.us REST API for that tag, strips out the html links and puts them into a text area. The user can then edit the text returned and save the tag/results combination into the database. It's not too exciting, but it's been a lot of fun to get together.
I created this app just like the tutorial in the Agile Pragmatic book. First, I created a very simple database with just one table containing just two columns: tags and results. "Tags" is kind of a misnomer for now though, since del.icio.us doesn't expose an API call for returning results for more than 1 tag at a time. Eventually I'll code in the intersection stuff myself.
So, generating the scaffold created a super simple, though working, app for adding new queries and editing, deleting, etc. So, now I needed to put in my del.icio.us magic. Since I'm not a javascript or Ajax wizard, I decided to just add in a link for the user to click on to retrieve the links from del.icio.us. However, I wanted to do this in a groovy ajaxy fashion so that the page doesn't refresh - the values just magically appear in the text area.
Here's what the screen looks like:
So, I intended to use the RoR/Ajax method link_to_remote to call a method on my controller which would do the del.icio.us call and the paste the result into the text area. Hoo boy. This isn't as simple as it sounds, especially considering the dearth of documentation. First, add this line between the 'head' tags of your layout.rhtml file:
Here's what the link_to_remote call basically looks like:
This creates a link called "Get Results", indicates that the 'query_results' control (the text area) will be updated, and it shows that the "get_results" method on the controller will be called. Cool, right? Wrong! Here's what gave me such a huge headache yesterday. When control passes to the controller, there's no way to get at the value of the textbox where the user has entered a tag! I tried and tried and just couldn't figure this part out. Finally, after sending an email to the rails mailing list. After chewing on some advice, here's how I rewrote my link_to_remote:
The magic is the :with option. This sticks the "tags" parameter into the params array that the controller gets. $F() is a shorthand way of writing Form.Element.getValue(). So, my guess is that the :with option allows you to pass in-line javascript. No clue, other than it works! There is no mention of the :with option in the docs for link_to_remote, but here's what the docs for observe_field says about it:
"A JavaScript expression specifying the parameters for the XMLHttpRequest. This defaults to ‘value’, which in the evaluated context refers to the new field value. If you specify a string without a "=", it’ll be extended to mean the form key that the value should be assigned to. So :with => "term" gives "’term’=value". If a "=" is present, no extension will happen." Also: "Additionally, you may specify any of the options documented in link_to_remote." So, yeah, if I'd seen that 4 hours earlier, I'd have been saved a lot of grief. Oh well. Now you know.
Finally, how do we get the del.icio.us text into the text area? Here's the pertinent bits out of my get_results method in my controller:
The important part here is using the render method. In the block, you have access to the elements on the page, so that's how we're able to stick the results into our text area. So, after the user types in a tag and clicks on the "Get Results" link, there's just a bit of waiting and then the text area magically updates:
The next thing to work on is probably some sort of groovy ajaxy "in progress" animation, so that the user knows not to click the link 20 times. It doesn't take too long to retrieve the results though. Also, I'm sure that there's probably a million different, better ways to write this code, so if you have any suggestions, please leave a comment! Thanks for reading!
"How I got some cool Ajax stuff to work with Ruby on Rails"
This weekend, my goal was to get my first original Ruby on Rails application working on my development box. I have achieved at least some sort of success! My app, such as it is, allows a user to enter a tag from her del.icio.ous account and then the app calls the del.icio.us REST API for that tag, strips out the html links and puts them into a text area. The user can then edit the text returned and save the tag/results combination into the database. It's not too exciting, but it's been a lot of fun to get together.
I created this app just like the tutorial in the Agile Pragmatic book. First, I created a very simple database with just one table containing just two columns: tags and results. "Tags" is kind of a misnomer for now though, since del.icio.us doesn't expose an API call for returning results for more than 1 tag at a time. Eventually I'll code in the intersection stuff myself.
So, generating the scaffold created a super simple, though working, app for adding new queries and editing, deleting, etc. So, now I needed to put in my del.icio.us magic. Since I'm not a javascript or Ajax wizard, I decided to just add in a link for the user to click on to retrieve the links from del.icio.us. However, I wanted to do this in a groovy ajaxy fashion so that the page doesn't refresh - the values just magically appear in the text area.
Here's what the screen looks like:
So, I intended to use the RoR/Ajax method link_to_remote to call a method on my controller which would do the del.icio.us call and the paste the result into the text area. Hoo boy. This isn't as simple as it sounds, especially considering the dearth of documentation. First, add this line between the 'head' tags of your layout.rhtml file:
1 2 |
<%= javascript_include_tag "prototype" %> |
1 2 |
<%= link_to_remote("Get Results", :update => 'query_results' :url => { :action => :get_results }) %> |
1 2 3 4 |
<%= link_to_remote("Get Results", :update => 'query_results', :with => "'tags=' + $F('query_tags')", :url => { :action => :get_results }) %> |
"A JavaScript expression specifying the parameters for the XMLHttpRequest. This defaults to ‘value’, which in the evaluated context refers to the new field value. If you specify a string without a "=", it’ll be extended to mean the form key that the value should be assigned to. So :with => "term" gives "’term’=value". If a "=" is present, no extension will happen." Also: "Additionally, you may specify any of the options documented in link_to_remote." So, yeah, if I'd seen that 4 hours earlier, I'd have been saved a lot of grief. Oh well. Now you know.
Finally, how do we get the del.icio.us text into the text area? Here's the pertinent bits out of my get_results method in my controller:
1 2 3 4 5 6 7 8 9 10 11 12 |
render :update do |page|
page['query_results'].value =''
@tags = params["tags"]
@results = "No Results"
if @tags.strip.length > 0
...
#Stick the results of the del.icio.us code into @results
...
end
page['query_results'].value = @results
end
|
The next thing to work on is probably some sort of groovy ajaxy "in progress" animation, so that the user knows not to click the link 20 times. It doesn't take too long to retrieve the results though. Also, I'm sure that there's probably a million different, better ways to write this code, so if you have any suggestions, please leave a comment! Thanks for reading!
June 10th, 2007 at 07:21 PM Good stuff Terry. That's an interesting challenge you had - and you're right, the :with option doesn't seem to be documented very well... I suppose the easier way to go about it is to live without the AJAX submission of the form and instead use form_remote_tag to enclose your "tags" and "get results" button. Then, the value of your tags text_field would be passed automatically to the resulting action. Anyway, your solution works well too! The "in progress" thing is pretty fun. You can use the "spinner.gif" from your typo installation. Show us when you're done!
June 10th, 2007 at 07:21 PM Thanks Brian. I wish I could just expose my little application little by little as I develop it, but I'm afraid I might develop memory leaks or some other symptom of immature code and get the ISP upset. I'll for sure deploy it and let everyone know when it's available. It won't be too jaw-dropping, but I think it's a great project to learn from. I'm not sure how much effort goes into getting the in progress stuff working, and at this point with the millions of other things I have going, I'm not sure I want to fight that fight right now. Either way, I'll give it a little bit of time soon and see what happens. I suppose that might be a worthy writeup as well!
June 10th, 2007 at 07:21 PM The progress is quite simple. Well, because Rails makes it simple. Stick an image_tag with the spinner graphic inside a div tag. Make sure the div is initially hidden by doing something like
June 10th, 2007 at 07:21 PM Oooh. My comment went bye-bye. Sorry about that.
June 10th, 2007 at 07:21 PM Feel free to continue. :D You're leaving me all hanging and stuff...
June 10th, 2007 at 07:21 PM LOL... you should be able to dig it up through your Typo admin. It got cut off because I put some code in there... which Typo doesn't like unless you allow one of the text filters (e.g. Markdown) in your comments.
June 10th, 2007 at 07:21 PM (That's better!) The progress is quite simple. Well, because Rails makes it simple. Stick an image_tag with the spinner graphic inside a div tag. Make sure the div is initially hidden by doing something like <div id='wait' style='display:none;'>. Then, either use the :loading and :complete options on the link_to_remote tag or add code to your RJS to show and hide the div at the right times. Good luck!
June 10th, 2007 at 07:21 PM Heh - I figured it was relatively easy. I'll see if I can wired it up tonight.
June 10th, 2007 at 07:21 PM Woo hoo! I got it to work. It's awfully simple. I'll be posting an article soon...
June 10th, 2007 at 07:21 PM fgfgbvbcxbcxbxbxb
June 10th, 2007 at 07:21 PM A specific centre stood one casino funnily. Primary data is one satisfactory father. Greek committee is this coherent class. Eh, one faint online casino angrily blanched by the middle police. This characteristic gambling rid the history hungrily.
June 10th, 2007 at 07:21 PM One accessible casino forbade this work gamely. One sir is flamboyantly agreed. Well, one poker strategies is more angry than the revolutionary boy. By the way, that inner person constantly grunted between this massive story. It's diverse to be patted! A unique activity boomed this letter logically. I played that poker during one computer.
Sorry, comments are closed for this article.