How to Automatically Link URLs in Rails

Let’s say you have a Rails app and you’d like any URLs in any plain text string to be automatically hyperlinked. Well, then you’ll need this:
.gsub(/((http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(([0-9]{1,5})?/.*)?)/, '<a href='1'>1</a>')

For example:
I blog at http://garrickvanburen.com

Through:
"I blog at http://garrickvanburen.com".description.gsub(/((http|https)://[a-z0-9]+([-.]{1}[a-z0-9]+)*.[a-z]{2,5}(([0-9]{1,5})?/.*)?)/, '<a href='1'>1</a>')

Results in:
I blog at http://garrickvanburen.com

Ququoo.com: Twitter Timesheet Looking For Beta-Friends

Ququoo.com, my first Rails app is finally up and at a place where I’m happy with it.

Ququoo turns Twitter into a timesheet – by grouping your tweets and measuring the time between them.

As with any web app that was launched moments ago, there’s probably a few more things to tidy up and sort out. That said, Ququoo is looking for some beta-friends. If you’re interested and have a Twitter account; add ququoo

Elsewhere, Ed Kohler wonders if something like Ququoo.com can find an audience:

“I’m sure there are plenty of Twitter users who bill or their time on a consulting basis who would love to be able to Tweet their billable hours.” – Ed Kohler

Rails: Cookies, Frozen Gems, and TextDrive

Jon Steinhorst once told me a movies are rewritten from script to shoot, and again from shoot to editing. I spent a good chunk of this week re-writing a Ruby on Rails app to go from development to production.

Works fine in development. Not at all in production.

The issue was a combination of frozen gems and cookies.

First off, while TextDrive recommends depending on your vendor directory for any Ruby gems unique to your project, I found success with Geoffrey Grosenbach‘s Freeze Other Gems Rake task that sends them to /lib

Secondly, I wasn’t able to reliably set and retrieve cookies. Turns out I needed to access the cookie with a string, not a symbol.

All the resources I found say this should work in the controller
cookies[:the_timezone]

But it doesn’t, this does:
cookies['the_timezone']

Then in the view (specifically a select menu) I need to use this:
time_zone_options_for_select(cookies['the_timezone'].value,TZInfo::Timezone.us_zones,TZInfo::Timezone)

How To Deploy Rails with SVN and Capistrano to a Secondary Domain on TextDrive

I just deployed my first rails app to one of my secondary domains on TextDrive’s shared hosting space.

If that sounds like a recipe for disaster….you’re right!

While Rails is a great development tool, there’s lots of work to do in simplifying, stabilizing, and documenting the deployment process. The app in question is very, very tiny for the express purpose of getting deployment nailed. In fact, it’s taken me longer to deploy than to develop.

For you, and Future Garrick, here’s the process.

  1. Freeze Rails so you’re not plagued with different-version-itis:
    rake rails:freeze:edge TAG=rel_-2-3
  2. Create an Subversion repository in your primary domain,
    Not in your secondary domain. If the repository is in a secondary domain, your primary account can’t see it. Using your primary domain and primary account is easier – if not as tidy as I’d like.
  3. Give your primary account access to the new Subversion repository.
  4. Grab the TextDrive deploy.rb from nuby on rails. Verify deploy_to and server.document-root are /web and /web/public respectively.
  5. Do the initial import into the repository and an initial checkout back to your local machine.
  6. cd to your local app and run cap setup. Confirm you now have a /web/shared directory. It should contain the following directories: log, pids, and system. In log you should have at least production.log and fastcgi.crash.log. Create and chmod them to 666 if they don’t exist.
  7. Follow TextDrive’s instructions for setting up lighttpd, rails, and a proxy.
  8. Change the /web/public/ paths in APPNAME.conf and rails.sh to /web/current/public/
  9. Follow TextDrive’s instructions to start up lighttpd and rails.
    Running their rails.sh file didn’t work for me, editing and manually running the script did.

After all this, cap deploy will deploy your app for you as advertised.

After I tweak a couple more dials and flip a couple more switches I’ll point you to the app.

Learning the Rails

I’m taking a week off of active programming to focus on better understanding 3 aspects of Rails development I’ve been wistfully ignoring: Migrations, Testing, and Deployment.

There’s a tiny, fun little project I’m using as the venue for these subjects.

One week from today (May 1) is what I’m giving myself on this effort. Any longer and it’ll be a distraction rather than a learning exercise.

I’ve always have a conceptual issue with Migrations. While migrations make it super easy to iteratively change the database, I’m accustomed to having the database a rock solid representation of, well, the database. My inclination is to look in and modify the database directly, then within create_[model].rb, then within schema.rb. Having bits of the model strewn about numerous migration files feels messy.

I’ll get used to it. Probably even savor it once I wrap my head around it.

How To Install MacPorts, Apache2, Rails, MySql, Mongrel, and Subversion on an Intel Mac

Now that I’m just about ready to deploy my first rails app, I thought I’d get the deployment environment set up rock solid on both the production and the development machines (one Mac Mini and one MacBookPro).

Like many other tutorials on this same subject, your mileage may vary. In fact I’m writing this now, because mine did. After stalling out in many of the tutorials all different places, this is what worked for me.

  1. Download and install MacPorts (used to be DarwinPorts)
  2. Open up a terminal and type:
    sudo port selfupdate
    making sure everything is the way it should be.
    If you’re like me, you get port: command not found in return.
  3. I fixed this by opening up .bash_profile in a text editor (Textmate: mate ~/.bash_profile) and adding the line
    export PATH=/opt/local/bin:$PATH
  4. Next download and install MySQL5
    I grabbed the binary from the bottom of the MySQL 5 download page. It comes with a System Preference Pane and checkbox for auto-startup. I’m using CocoaSQL for admin.
  5. Change the MySQL5 root password

    /opt/local/lib/mysql5/bin/mysqladmin -u root password 'new-password'
    /opt/local/lib/mysql5/bin/mysqladmin -u root -h [HOSTNAME] password 'new-password'
  6. Next load up the Apache2 package
    sudo port install apache2
    (this takes a while)
  7. sudo launchctl load -w /Library/LaunchDaemons/org.macports.apache2.plist to launch Apache2 on startup. I’ve disabled Apple’s default Web Sharing in the System Preferences.
  8. Create an initial http.conf file
    cd /opt/local/apache2/conf
    sudo cp httpd.conf.sample httpd.conf
  9. Start up Apache2
    sudo /opt/local/apache2/bin/apachectl -k start
  10. Load up http://localhost. It should say “It works!”

  11. sudo port install fcgi
    sudo port install lighttpd +ssl
    sudo port install mod_fastcgi
  12. Next load up Subversion package with the mod_dav_svn for Apache2
    sudo port install subversion +mod_dav_svn +tools
  13. Next load up Ruby, RubyGems, Termios, RB-MySQL5 Bridge, and ImageMagick Packages
    sudo port install ruby
    sudo port install rb-rubygems
    sudo port install rb-termios
    sudo port install rb-fcgi
    sudo port install rb-mysql (I had some errors on this one.)
    sudo port install imagemagick
  14. Install a bunch of useful gems, like rails and capistrano.

    sudo gem install --include-dependencies rake
    sudo gem install --include-dependencies rails
    sudo gem install --include-dependencies termios
    sudo gem install --include-dependencies capistrano


    sudo gem install daemons gem_plugin mongrel mongrel_cluster --include-dependencies
    sudo gem install --include-dependencies mongrel
    sudo gem install --include-dependencies mongrel_cluster


    sudo gem install mysql --
    --with-mysql-dir=/usr/local/mysql
    --with-mysql-include=/usr/local/mysql/include/
    --with-mysql-lib=/usr/local/mysql/lib/
    --with-mysql-config=/usr/local/mysql/bin/mysql_config

    (thanks to d. robert adams for the last bit)
  15. Create a rails app
    rails testapp
  16. Connect the rails app to mongrel

    cd /RAILS/ROOT/OF/TESTAPP
    mongrel_rails cluster::configure -e development -p 8000 -a 127.0.0.1 -N3 -c /RAILS/ROOT/OF/TESTAPP

SSHKeychain.socket Error on Rake Remote:Setup

Still working through deploying a Rails app (if you’ve been following along, I got Subversion plugged in yesterday). Today was setting up the deployment by running:
rake remote:setup

The process kept erroring out saying:
No File or Directory - /tmp/501/SSHKeychain.socket

Turns out I had a bunch of cruft in ~/.MacOSX/properties.plist. After cutting out the offending xml and restarting. Everything worked as expected.

Using Names in Rails Routes Instead of IDs

I spent tonight cranking through some Ruby on Rails has_many :through association oddities and after pounding my head against the keyboard, I decided to shift gears and figure out Ruby On Rails Routes.

By default, the Rails expects ID to be passed in URL strings. But that’s really lame, and passing words is much cooler so, how do you do that?

Turns out, it’s so simple no one talks about it (vs. so hard no one’s figured it out).

Take the following example:
http://mydomain/friend/show/1

What’s ‘show’? Who’s friend 1? Don’t they have a name?
Sure they do. Let’s say their name is ‘Wooster’

Here’s how to make turn the above url string into:
http://mydomain/friend/wooster

  1. Get the name of the database column storing your friends’ names (let’s say it’s ‘name’).
  2. In config/routes.rb add, somewhere above the default route:
    map.connect 'friend/:name', :controller => 'friends', :action => 'show'
  3. Now, in friends_controller, find def show and change it to:
    @friend = Friend.find_by_name(params[:name])
  4. Lastly, all the id-based urls pointing to our good friend Wooster need to be updated to reflect the name-based change. Like the one your Friends list.rhtml file.
    'show', :name => friend.name

Locally Running Multiple Rails Apps on OS X

There’s a couple of place describing how to support multiple Rails apps locally. They were either unavailable or way more complicated than I’d like (the HowtoDeployMoreThanOneRailsAppOnOneMachine at the RubyonRails wiki was both). Here’s how I was able to get multiple Rails apps running under Apache on OS X 10.4 Tiger.

  1. Created 2 Rails apps; AppOne and AppTwo
  2. In each of the apps’ public/index.html file I changed “Welcome to Ruby on Rails” to “Welcome to AppOne” and “Welcome to AppTwo” respectively. (You don’t need to do this, though it did seem to be the easiest way to see when it works.)
  3. Opened up and unlocked NetInfoManager, duplicated machines > localhost twice, renamed one “appone” and the other “apptwo”.
  4. Opened up Apache’s httpd/httpd.conf file, uncommented NameVirtualHost *:80 and added the VirtualHost blocks.

    NameVirtualHost *:80

    <virtualhost *>
    ServerName AppOne
    DocumentRoot /Users/garrickvanburen/Rails/AppOne/public/
    <directory /Users/garrickvanburen/Rails/AppOne/public/>
    Options ExecCGI FollowSymLinks
    AllowOverride all
    Allow from all
    Order allow,deny
    </virtualhost>


    <virtualhost *>
    ServerName AppTwo
    DocumentRoot /Users/garrickvanburen/Rails/AppTwo/public/
    <directory /Users/garrickvanburen/Rails/AppTwo/public/>
    Options ExecCGI FollowSymLinks
    AllowOverride all
    Allow from all
    Order allow,deny
    </virtualhost>

  5. Restarted Apache > sudo apachectl graceful
  6. Opened up two browers; one to http://appone/ and the other to http://apptwo/
  7. Clapped and victoriously declared “Yea” to an empty room.

As I should have known, this blew up my non-Rails localhosting – specifically phpMyAdmin. Repeating the steps above for phpmyadmin returned access to my database.

What’s Your Favorite Open Source Project?

Hello gentle reader, I’m looking for your favorite open source projects; applications, websites, services. If the code is available for free and you’re a big fan, throw them in the comments.

    I’ll start:
    WordPress – weblog engine and content management system
    Ruby on Rails – web application framework
    CocoaMySQL – OS X desktop MySQL database manager
    Adium – Multi-protocol Instant Messaging client