Archive for July, 2008
Passenger (mod_rails) for development. Now with debugger!
Dev mojo
After reading the great posts by Geoffrey “PeepCode” Grosenbach and Manfred Stienstra about using Phusion Passenger for development I had to give it a try. My doctor she’d never heard of mod_rails but gave me antibiotics for it just in case.
After little bit of setup I can say I am much happier with this dev rig than the old ’script/server’ style. Just open a browser and the app is just waiting to serve you. Nice and agile or something.
Bugger no debugger!
One thing was missing for me though. With no –debugger switch to play with, I needed an alternative. Fortunately the brilliant ruby-debug has the solution with remote debugging. The tricky part was turning remote debugging on or off easily so we didn’t destroy our new dev mojo with onerous meddling in an environment file.
Keepin’ it real (easy)
So your working away and you run into a tough bug in some action or corner of your app. You need to break out the debugger. So the most straight forward way I have found is doing this
rake restart DEBUG=true
But how does it work. Here is a little something I prepared earlier.
In the style of passenger’s restart.txt the restart task also creates debug.txt in the tmp folder if the DEBUG switch is set to true.
Then in development.rb we look for the debug.txt file which triggers ruby-debug to be loaded. We set the ‘wait_for_connection’ option to true which gives us a chance to connect to the remote debugger when the app restarts. Finally start the debugger and clean up the debug.txt file.
From here you refresh the browser and it will it get stuck loading the page. This is because the app is waiting for you to connect to the remote debugger session. In a terminal type
rdebug -c
Once its running you can add and remove debugger statements in the code without needing to restart the debugger or the app. Now you just use the debugger as normal.
If you close the terminal or exit the debug session you can’t reconnect with it. You must do a restart with the DEBUG switch again. Once you cancel the debug session the app won’t drop into the debugger when it hits ‘debugger’ statements any more. So you can continue as normal until you need the debugger again and do a restart.
There you go, thats pretty neat and tidy and agile and whatever.
UPDATE:
I should probably mention that for ease of use and efficiency when using ruby-debug in remote mode you should probably use the ’set autoeval’ setting. To do that create a file called .rdebugrc in your home directory and put this these lines in for good measure:
set autoeval
set autolist
set autoreload
Follow this link for more info on these settings.
28 commentsRun plugin specs/tests with gem or vendored rails
When I create a plugin I set up the tests or specs to be able to run stand-alone, that is not inside Rails app. But when you want to try the plugin out inside a real app, it can help to be able run the specs against vendored version of Rails if the application has one.
So to neatly auto-detect if the plugin is in an app with vendored Rails and to use that Rails for testing, I hacked this little snippet
vendored_rails = File.dirname(__FILE__) + '/../../../../vendor/rails'
if File.exists?(vendored_rails)
Dir.glob(vendored_rails + "/**/lib").each { |dir| $:.unshift dir }
else
gem 'rails', "=#{ENV['VERSION']}" if ENV['VERSION']
end
This checks for the Rails folder in vendor with extra care by going up to where the app root would be and down through ‘vendor/rails’, rather than directly to the rails. If a vendored Rails is found it puts each module’s parent folder at the front of the load path to make sure its used ahead of the gems.
For a bonus it also allows you to specify a version of the Rails gem if you want, by setting the VERSION parameter on the command line, when not inside an app.
Afterwards you just require the Rails parts you need as usual.
require 'active_support'
require 'active_record'
If the vendored rails exists the the libraries are required from there, otherwise the gems are used. Stick it in the top of your test or spec helper.
No commentsar_mailer gem forked on GitHub, goodies added
Now that GitHub has a gem server it allows the process of managing your own fork or customisation of a gem ridiculously easy. No need for your own gem server or shipping around gem files, just put it up on github and nominate it as a gem in the project config. GitHub will automatically compile the gems using a gemspec file if present. All the info you need is here so I won’t recap it any further.
A gem which I find essential for Rails apps which send out emails is ar_mailer by Eric Hodel of Seattle Ruby Brigade and Ruby Hitsquad fame and now the maintainer of RubyGems. But there a couple of things missing. One is the need for pid files to be generated when running as a daemon to allow effective management with monitoring tools and such.
Well there just so happened to be a patch by Dylan Egan in the ar_mailer forums to add this feature, but it has been overlooked for a long time. So I thought this would be a good chance to fork it and use the GitHub gem system as well. Its now forked it and patched with some tweaks to get it working and a few fixes for the tests which broke due to changes in the latest ZenTest gem.
The project for the gem is here. To use the new gem you need to remove the old one because of the way github names your gems. It uses github username as a prefix to the gem name. This means the old gem will be loaded instead of the new gem when required in your app. But the binary will be used from the new gem causing nasty problems.
To install, first add GitHub as a gem source
sudo gem sources -a http://gems.github.com
Then
sudo gem install adzap-ar_mailer
Now when the binary is run in daemon mode you will get the pid file you need. You can specify the pid file location in the command options like so
ar_sendmail -d -p ./log/ar_sendmail.pid
Any relative paths are expanded from the app directory. You can of course use an absolute path if you wish. The file gets removed on exit as you would expect.
The other major addition is not as visible. Its a Ruby based init.d script for managing mailer startup for one or more apps. It uses a yaml based config file where you specify the app settings for each app that needs a mailer instance running. See the README and demo config for more info.
Ruby, my hammer, is starting to make everything look a nail!
Remember this is GitHub, don’t like what I have done, then fork off!
UPDATE:
If you are getting an error running the ar_sendmail binary, this is due to GitHub to setting the permission on gem binary files incorrectly. The error would be
/usr/bin/ar_sendmail:19:in `load': no such file to load -- ar_sendmail (LoadError) from /usr/bin/ar_sendmail:19
To fix it you need to run this ugly (please let me know a better way to get a gem path!!)
GEMS_PATH=`gem env path` GEM_NAME='adzap-ar_mailer' sudo chmod 755 $GEMS_PATH/gems/$GEM_NAME*/bin/*
Now you should be able to execute it as a normal user.
UPDATE 2:
Fixed the update fix and made it version non-specific
UPDATE 3:
GitHub fixed the file permissions issue so the work around is not needed anymore.
