Capistrano is an amazing tool for deploying Rails applications - and like they say when you have a hammer everything looks like a nail...so when I was tasked with developing a way to deploy a simple marketing web site for my company I looked first to Capistrano. I wanted to make it so that non-developers could get set up correctly and then do a "cap deploy" to deploy the current state of the web site. The Capistrano documentation is not great, so I googled around for how I might be able to deploy a non Rails application and found this. That link will lead you to a great blog entry by Pat Nakijima that explains how to deploy a non Rails application with Capistrano. Pat's version of this even sets up the Apache conf file and restarts the apache server using apachectl. I pared down his version because our conf file was going to remain fairly static so I wasn't worried about updating it or restarting Apache for changes to take effect. Also, with the web server hosting many different virtual host I wouldn't want to get stuck if someone had changed any of the conf files and Apache didn't restart correctly...
So here is my minimal version of deploying a simple web site with Capistrano (basically Pat's code with Apache related stuff removed and a micro task that removes the Capfile and config/ directories from the release):
Sunday, February 10, 2008
Saturday, February 09, 2008
Rails Send Data Through a Pipe with IO.popen
While having trouble getting Unix zip to play nice with Ruby's Tempfile I found that it was much easier to just avoid a temp file altogether by using a pipe create with IO.popen. Example code below shows how you might zip up a directory and send it back to the user from a controller:
Sunday, February 03, 2008
Minify Rails Javascript and CSS with YUI Compressor
Here is a simple rake task to minify your javascript and css in a rails application using the YUI Compressor. You will need to have java set up correctly on the system and have the YUI Compressor jar in the lib directory of your Rails application to run this code.
You could drop this in lib/tasks/minify.rake and run it when deploying to production. If deploying with Capistrano, you might put it in the :after_update_code task:
This technique should work fine with Rails asset caching (explained here by the guys at maintainable software). Couple that with gzip compression by your web server and you should get dramatically reduced download times for your javascript and CSS.
A couple of caveats --
First, some javascript may not minify without problems. For example read this post by Andrew Dupont which talks about compressing prototype. I didn't seem to have a problem using the YUI Compressor with prototype but I haven't thoroughly tested it yet.
Second, I would prefer if the code above placed the minified version in different output directories. (Primarily so you don't accidentally check your minified versions into your SCM system.) Originally I did this putting the minified code in public/javascriptx and public/stylesheetx, respectively. Then I looked into how to get rails to easily look in different directories for javascript and css files. I found the JAVASCRIPTS_DIR and STYLESHEETS_DIR constants and thought I was all set -- then I then ran into the problem that changing:
in an initializer didn't really work as expected. Due to what looks to me like a bug in Rails 2.0 the files are still fetched from the original locations in spite of changing these constants - so I decided to stop messing with it and watch the Super Bowl.
If you don't like messing with Java to do something like this and are only concerned with compressing javascript then I would recommend reading this article by the guys at maintainable software. They give an example of using jsmin.rb for javascript minification.
You could drop this in lib/tasks/minify.rake and run it when deploying to production. If deploying with Capistrano, you might put it in the :after_update_code task:
This technique should work fine with Rails asset caching (explained here by the guys at maintainable software). Couple that with gzip compression by your web server and you should get dramatically reduced download times for your javascript and CSS.
A couple of caveats --
First, some javascript may not minify without problems. For example read this post by Andrew Dupont which talks about compressing prototype. I didn't seem to have a problem using the YUI Compressor with prototype but I haven't thoroughly tested it yet.
Second, I would prefer if the code above placed the minified version in different output directories. (Primarily so you don't accidentally check your minified versions into your SCM system.) Originally I did this putting the minified code in public/javascriptx and public/stylesheetx, respectively. Then I looked into how to get rails to easily look in different directories for javascript and css files. I found the JAVASCRIPTS_DIR and STYLESHEETS_DIR constants and thought I was all set -- then I then ran into the problem that changing:
in an initializer didn't really work as expected. Due to what looks to me like a bug in Rails 2.0 the files are still fetched from the original locations in spite of changing these constants - so I decided to stop messing with it and watch the Super Bowl.
If you don't like messing with Java to do something like this and are only concerned with compressing javascript then I would recommend reading this article by the guys at maintainable software. They give an example of using jsmin.rb for javascript minification.
Labels:
compress,
css,
javascript,
minify,
rails,
yui compressor
Monday, January 28, 2008
Rails Forgery Protection (CSRF) and Ajax
Rails 2.0 has forgery protection against CSRF attacks built in. If you stick to standard rails helpers you won't need to take any extra steps and the forgery protection will just work - reason being, the helpers will automatically add the appropriate parameters. For example form helpers will a hidden tag with the name "form_authenticity_token" and a value "big stinking authenticity token."
If you step into the land of raw Ajax, however, you will need to take care of passing this value yourself (unless you are sending GET requests, you don't need to send the token with a GET request). So where do you get the value? You use the helper form_authenticity_token of course. But I don't recommend using this value directly as it can throw and exception if you call it with forgery protection turned off (in tests for example). Instead, write your own helper in app/helpers/application_helper.rb, something like this:
Now in your view you can write the value where you need it or you can store the value in a javascript variable for later use:
Now when you make an Ajax request you just need to make sure you provide this value under the name "authenticity_token". For prototype.js, you can stuff this along in the options to the family of Ajax request functions:
If you are using the amazing Ext JS, you might send it along with something like this:
Oh, also, if you want to turn off this forgery protection you can remove it entirely by commenting out protect_from_forgery in your main application.rb controller or disable / enable it on an action by action basis in a controller with:
And of course that takes either an :except or :only value.
If you step into the land of raw Ajax, however, you will need to take care of passing this value yourself (unless you are sending GET requests, you don't need to send the token with a GET request). So where do you get the value? You use the helper form_authenticity_token of course. But I don't recommend using this value directly as it can throw and exception if you call it with forgery protection turned off (in tests for example). Instead, write your own helper in app/helpers/application_helper.rb, something like this:
Now in your view you can write the value where you need it or you can store the value in a javascript variable for later use:
Now when you make an Ajax request you just need to make sure you provide this value under the name "authenticity_token". For prototype.js, you can stuff this along in the options to the family of Ajax request functions:
If you are using the amazing Ext JS, you might send it along with something like this:
Oh, also, if you want to turn off this forgery protection you can remove it entirely by commenting out protect_from_forgery in your main application.rb controller or disable / enable it on an action by action basis in a controller with:
And of course that takes either an :except or :only value.
Saturday, January 26, 2008
Firefox Greasemonkey Outlook Web Access Extension Part I
Other posts on OWAX: [ Part II | Part III ]
Stuck using Outlook Web Access to access your email via Firefox? Painful isn't it? Microsoft has seen fit to make sure many features are not available if you aren't using Internet Exploder. Take, for example, the case where your mailbox fills up and you need to clean out your trash -- hmmmm, no way to "Select All" so that you can at least delete messages a little faster. Thankfully Greasmonkey makes writing site specific extensions fairly painless. Here is my Outlook Web Access with my extension installed...look mom, Select All!

Grab the extension here. Source code shown below:
Stuck using Outlook Web Access to access your email via Firefox? Painful isn't it? Microsoft has seen fit to make sure many features are not available if you aren't using Internet Exploder. Take, for example, the case where your mailbox fills up and you need to clean out your trash -- hmmmm, no way to "Select All" so that you can at least delete messages a little faster. Thankfully Greasmonkey makes writing site specific extensions fairly painless. Here is my Outlook Web Access with my extension installed...look mom, Select All!

Grab the extension here. Source code shown below:
Subscribe to:
Posts (Atom)