<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Travis on Rails</title>
    <description>Recent Posts</description>
    <link>http://travisonrails.com/feed/posts.rss</link>
    <item>
      <title>Deploy Sinatra Application with Capistrano</title>
      <description>&lt;h3&gt;Step 0: Vendor the sinatra gem (optional).&lt;/h3&gt;

&lt;pre class="brush:bash"&gt;
  mkdir vendor
  cd vendor
  gem unpack sinatra
  mv sinatra-* sinatra
&lt;/pre&gt;

&lt;h3&gt;Step 1. Create a &lt;kbd&gt;config.ru&lt;/kbd&gt; Rack file in your project's root directory.&lt;/h3&gt;

&lt;pre class="brush:ruby"&gt;
  require 'rubygems'
  require 'vendor/sinatra/lib/sinatra.rb'

  set :public, File.expand_path(File.dirname(__FILE__) + '/public') # Include your public folder
  set :views, File.expand_path(File.dirname(__FILE__) + '/views')  # Include the views
  
  set :environment, :production

  disable :run, :reload

  require 'app_file' # replace this with your sinatra app file
  run Sinatra::Application
&lt;/pre&gt;

&lt;h3&gt;Step 2. Create a Capistrano deploy file.&lt;/h3&gt;

&lt;pre class="brush:ruby"&gt;
  set :domain, "yourdomain.com"
  set :application, "app_name"
  set :deploy_to, "/var/www/apps/#{domain}"

  set :user, "your_deploy_user"
  set :use_sudo, false

  set :scm, :git
  set :repository,  "git@github.com:you/application.git"
  set :branch, 'master'
  set :git_shallow_clone, 1

  role :web, domain
  role :app, domain
  role :db,  domain, :primary =&gt; true

  set :deploy_via, :remote_cache

  namespace :deploy do
    task :start do ; end
    task :stop do ; end
    # Assumes you are using Passenger
    task :restart, :roles =&gt; :app, :except =&gt; { :no_release =&gt; true } do
      run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
    end

    task :finalize_update, :except =&gt; { :no_release =&gt; true } do
      run "chmod -R g+w #{latest_release}" if fetch(:group_writable, true)

      # mkdir -p is making sure that the directories are there for some SCM's that don't save empty folders
      run &amp;lt;&amp;lt;-CMD
        rm -rf #{latest_release}/log &amp;amp;&amp;amp;
        mkdir -p #{latest_release}/public &amp;amp;&amp;amp;
        mkdir -p #{latest_release}/tmp &amp;amp;&amp;amp;
        ln -s #{shared_path}/log #{latest_release}/log
      CMD

      if fetch(:normalize_asset_timestamps, true)
        stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
        asset_paths = %w(images css).map { |p| "#{latest_release}/public/#{p}" }.join(" ")
        run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true", :env =&gt; { "TZ" =&gt; "UTC" }
      end
    end
  end
&lt;/pre&gt;

&lt;h3&gt;Step 3: Deploy the app.&lt;/h3&gt;

&lt;pre class="brush: bash"&gt;
  cap deploy:setup
  cap deploy
&lt;/pre&gt;

&lt;h3&gt;Step 4: Get a beer, you're done!&lt;/h3&gt;</description>
      <pubDate>Tue, 25 May 2010 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2010/05/25/deploy-sinatra-application-with-capistrano</link>
    </item>
    <item>
      <title>Nashville Rails Meetup Presentation - "Capistrano"</title>
      <description>&lt;p&gt;Here is the presentation I gave at the April 2010 &lt;a href="http://www.meetup.com/nashvillerails/"&gt;Nashville Ruby on Rails Meetup&lt;/a&gt;.&lt;/p&gt;

&lt;div style="width:425px" id="__ss_3823796"&gt;&lt;strong style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/travisroberts/capistrano-overview" title="Capistrano Overview"&gt;Capistrano Overview&lt;/a&gt;&lt;/strong&gt;&lt;object width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=capistrano-100422183749-phpapp01&amp;stripped_title=capistrano-overview" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=capistrano-100422183749-phpapp01&amp;stripped_title=capistrano-overview" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/travisroberts"&gt;Travis Roberts&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</description>
      <pubDate>Sat, 24 Apr 2010 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2010/04/24/nashville-rails-meetup-presentation-capistrano</link>
    </item>
    <item>
      <title>Nashville Rails Meetup Presentation - "Rails Page Caching"</title>
      <description>&lt;p&gt;Here is the presentation I gave at the February 2010 &lt;a href="http://www.meetup.com/nashvillerails/"&gt;Nashville Ruby on Rails Meetup&lt;/a&gt;.&lt;/p&gt;

&lt;div style="width:425px;text-align:left" id="__ss_3221485"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/travisroberts/rails-caching-3221485" title="Rails Page Caching"&gt;Rails Page Caching&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=railscaching-100218192055-phpapp02&amp;rel=0&amp;stripped_title=rails-caching-3221485" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=railscaching-100218192055-phpapp02&amp;rel=0&amp;stripped_title=rails-caching-3221485" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/travisroberts"&gt;Travis Roberts&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</description>
      <pubDate>Fri, 19 Feb 2010 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2010/02/19/nashville-rails-meetup-presentation-rails-page-caching</link>
    </item>
    <item>
      <title>Download Files with Ruby</title>
      <description>&lt;p&gt;This weekend, I remembered an old podcast I used to listen to that I wanted to hear again. It wasn't available on iTunes anymore, so I did a Google search for it. I found the show's Web site, and saw that they had a complete archive of all four seasons of the podcast (20 episodes per season). The problem was, each episode was on it's own page, with a separate page to access the download link. I started to manually try to download each episode, but that got old REALLY quickly. Why not write a simple script to do the work for me?&lt;/p&gt;

&lt;p&gt;Here's the Ruby script I whipped up in about 15 minutes:&lt;/p&gt;

&lt;pre class="brush: ruby"&gt;
require 'net/http'

1.upto(4) do |season|
  1.upto(20) do |episode|
    episode = '%02d' % episode
    puts "Downloading Season ##{season}, Episode ##{episode}"
    Net::HTTP.start("website.com") do |http|
      resp = http.get("/episode_archive/s#{season}ep#{episode}.mp3")
      open("s#{season}ep#{episode}.mp3", "w") do |file|
        file.write(resp.body)
      end
    end
    puts "Episode downloaded!"
    puts
  end
end

puts "All files downloaded!!"
&lt;/pre&gt;

&lt;p&gt;An explanation of what's going on here:&lt;/p&gt;

&lt;p&gt;
  &lt;strong&gt;Lines #3-4:&lt;/strong&gt; There are 4 seasons and 20 episodes per season, so iterate through them.&lt;br /&gt;
  &lt;strong&gt;Line #5:&lt;/strong&gt; We need to left pad the episode numbers, because that's how the files are named.&lt;br /&gt;
  &lt;strong&gt;Line #7:&lt;/strong&gt; Connect to the host.&lt;br /&gt;
  &lt;strong&gt;Line #8:&lt;/strong&gt; Get the episode (named like "s1ep05.mp3").&lt;br /&gt;
  &lt;strong&gt;Lines #9-11:&lt;/strong&gt; Save the file using the same name.
&lt;/p&gt;</description>
      <pubDate>Wed, 17 Feb 2010 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2010/02/17/download-files-with-ruby</link>
    </item>
    <item>
      <title>URL ABC</title>
      <description>&lt;p&gt;Idea taken from &lt;a href="http://2009.maxvoltar.com/articles/url-abc"&gt;http://2009.maxvoltar.com/articles/url-abc&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A: &lt;a href="http://www.amazon.com/"&gt;http://www.amazon.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;B: &lt;a href="http://blog.us.playstation.com/"&gt;http://blog.us.playstation.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;C: &lt;a href="http://code.google.com/apis/chart/"&gt;http://code.google.com/apis/chart/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;D: &lt;a href="http://www.drupal.org/"&gt;http://www.drupal.org/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;E: &lt;a href="http://www.etsy.com/"&gt;http://www.etsy.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;F: &lt;a href="http://www.flickr.com/"&gt;http://www.flickr.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;G: &lt;a href="http://www.google.com"&gt;http://www.google.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;H: &lt;a href="http://www.hulu.com/"&gt;http://www.hulu.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;I: &lt;a href="http://www.imdb.com/"&gt;http://www.imdb.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;J: &lt;a href="http://www.johnnycache.net/"&gt;http://www.johnnycache.net/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;K: &lt;a href="http://www.kbb.com/"&gt;http://www.kbb.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;L: &lt;a href="http://listode.com"&gt;http://listode.com&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;M: &lt;a href="http://malsup.com/jquery/cycle/"&gt;http://malsup.com/jquery/cycle/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;N: &lt;a href="http://www.netflix.com/"&gt;http://www.netflix.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;O: &lt;a href="http://oceanfutures.org/"&gt;http://oceanfutures.org/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;P: &lt;a href="http://www.pandora.com/"&gt;http://www.pandora.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Q: &lt;a href="http://qbnz.com/highlighter/"&gt;http://qbnz.com/highlighter/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;R: &lt;a href="http://revision3.com/"&gt;http://revision3.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;S: &lt;a href="http://www.singerco.com/"&gt;http://www.singerco.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;T: &lt;a href="http://twitter.com/"&gt;http://twitter.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;U: &lt;a href="http://us1.admin.mailchimp.com/"&gt;http://us1.admin.mailchimp.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;V: &lt;a href="http://vampireweekend.com/"&gt;http://vampireweekend.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;W: &lt;a href="http://www.wikipedia.org/"&gt;http://www.wikipedia.org/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;X: &lt;/li&gt;
  &lt;li&gt;Y: &lt;a href="http://www.youtube.com/"&gt;http://www.youtube.com/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Z: &lt;a href="http://www.zumba.com/us/"&gt;http://www.zumba.com/us/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;</description>
      <pubDate>Wed, 20 Jan 2010 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2010/01/20/url-abc</link>
    </item>
    <item>
      <title>BarCamp Nashville 09 Presentation - Symfony vs Rails</title>
      <description>&lt;p&gt;&lt;a href="http://brentertainment.com/"&gt;Brent Shaffer&lt;/a&gt; and I gave a presentation at the &lt;a href="http://barcampnashville.com/"&gt;2009 Nashville BarCamp&lt;/a&gt; titled "Test Your Might - Framework Combat" comparing Ruby/Rails with PHP/Symfony. Below is a copy of the slides we presented.&lt;/p&gt;

&lt;div style="width:425px;text-align:left" id="__ss_2277608"&gt;&lt;a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/bshafs/test-your-might-framework-combat" title="Test Your Might - Framework Combat"&gt;Test Your Might - Framework Combat&lt;/a&gt;&lt;object style="margin:0px" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=testyourmight-091019093300-phpapp02&amp;stripped_title=test-your-might-framework-combat" /&gt;&lt;param name="allowFullScreen" value="true"/&gt;&lt;param name="allowScriptAccess" value="always"/&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=testyourmight-091019093300-phpapp02&amp;stripped_title=test-your-might-framework-combat" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;"&gt;View more &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/"&gt;documents&lt;/a&gt; from &lt;a style="text-decoration:underline;" href="http://www.slideshare.net/bshafs"&gt;Brent Shaffer&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;</description>
      <pubDate>Wed, 28 Oct 2009 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2009/10/28/barcamp-nashville-09-presentation-symfony-vs-rails</link>
    </item>
    <item>
      <title>Rails Subdomain Caching</title>
      <description>&lt;p&gt;A while ago, I was working on a site that had dynamic subdomains based on cities in the database. For example, if an admin created a record for Nashville, it would create &lt;kbd&gt;http://nashville.sitename.com&lt;/kbd&gt;. The site was pretty content heavy, but didn't change a whole lot, so I wanted to cache as much as I could. The problem with caching was that the content of each page depended on the subdomain. I couldn't use the normal caching strategy because of this.&lt;/p&gt;

&lt;p&gt;To handle the subdomain routing and identification, I used the awesome &lt;a href="http://github.com/mbleigh/subdomain-fu"&gt;subdomain-fu&lt;/a&gt; plugin (which worked great). Subdomain-fu, however, does &lt;strong&gt;not&lt;/strong&gt; do the work of putting your cached files into folders named for your subdomain. Luckily, fixing this was as easy as adding a before filter to my ApplicationController.&lt;/p&gt;

&lt;pre class="brush: rails"&gt;
class ApplicationController &amp;lt; ActionController::Base
  before_filter :update_cache_location
  
  def update_cache_location
    if current_subdomain.nil?
      ActionController::Base.page_cache_directory = "#{RAILS_ROOT}/public/cache/"
    else
      ActionController::Base.page_cache_directory = "#{RAILS_ROOT}/public/cache/#{current_subdomain}/"
    end
  end
end
&lt;/pre&gt;

&lt;p&gt;That method will update the &lt;kbd&gt;page_cache_directory&lt;/kbd&gt; value to be your current subdomain (or default if you are on the main domain). Now, this takes care of one problem, but how the hell do we retrieve the cached files? I had a little bit of trouble with this, mainly because I'm not a mod_rewrite specialist. After some tinkering and testing, I finally came up with the following rules to put in my conf file to properly retrieve the cached files based on the subdomain.&lt;/p&gt;

&lt;pre class="brush: bash"&gt;
# Check for subdomain cached index
RewriteCond %{HTTP_HOST} !^www\.sitename\.com
RewriteCond %{HTTP_HOST} ^([^.]+)\.sitename\.com
RewriteRule ^/$ /cache/%1/index.html [QSA]

# Check for subdomain cached page
RewriteCond %{HTTP_HOST} !^www\.sitename\.com
RewriteCond %{HTTP_HOST} ^([^.]+)\.sitename\.com
RewriteRule ^([^.]+)$ /cache/%1/$1.html [QSA]

# Check for regular non-subdomain index
RewriteRule ^/$ /cache/index.html [QSA] 

# Check for regular non-subdomain page
RewriteRule ^([^.]+)$ /cache/$1.html [QSA]
&lt;/pre&gt;

&lt;p&gt;Those first two entries check to make sure the subdomain isn't &lt;kbd&gt;www&lt;/kbd&gt;, then checks the cache folder for a cached version of the page. The last two entries check for the regular &lt;kbd&gt;www&lt;/kbd&gt; subdomain.&lt;/p&gt;

&lt;p&gt;These entries worked great for my project, but, like I said, I'm no expert with mod_rewrite. If you see anything that can be simplified or a better way of doing something, please let me know in the comments.&lt;/p&gt;</description>
      <pubDate>Fri, 02 Oct 2009 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2009/10/02/rails-subdomain-caching</link>
    </item>
    <item>
      <title>CentOS Setup Script with Ruby, Apache, mySQL, Subverion, Git, Passenger, and ImageMagick</title>
      <description>&lt;p&gt;Recently, I participated in the &lt;a href="http://r09.railsrumble.com"&gt;Rails Rumble&lt;/a&gt; competition. If you've never heard of the Rails Rumble, it's a 48-hour coding contest where teams of 4 programmers/designers have to complete a fully-working application over the course of a weekend.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://linode.com"&gt;Linode&lt;/a&gt;, one of the sponsors, provided each team with virtual private server to host their application. This was great, but the servers were bare-bones and required a fair amount of setup. Knowing this in advance, I hoped to save some time by writing a script that would automate the process for our team so I didn't have to spend 30-45 minutes just trying to configure the server.&lt;/p&gt;

&lt;p&gt;Here are the steps I took to get Ruby, Apache, mySQL, Subversion, Git, Passenger, and ImageMagick set up on our CentOS server.&lt;/p&gt;

&lt;h3&gt;Step 1: Add custom repository listing&lt;/h3&gt;

&lt;p&gt;The default CentOS repo only has Ruby 1.8.6. While there's nothing wrong with this, I wanted to get 1.8.7. To do that, copy the following text into a file called &lt;kbd&gt;/etc/yum.repos.d/rubyworks.repo&lt;/kbd&gt;:&lt;/p&gt;

&lt;pre class="brush: bash"&gt;
[rubyworks]
name=RubyWorks
baseurl=http://rubyworks.rubyforge.org/redhat/$releasever/RPMS/$basearch
enabled=1
gpgcheck=1
gpgkey=http://rubyworks.rubyforge.org/RubyWorks.GPG.key
priority=1
&lt;/pre&gt;

&lt;h3&gt;Step 2: Bash script&lt;/h3&gt;

&lt;p&gt;The only other step is to copy the following bash script to a file (called anything you'd like), chmod it to be executable, and just run it as root (very important!). It's magic!&lt;/p&gt;

&lt;pre class="brush: bash"&gt;
#!/bin/bash

# You must run as sudo!!!!!

# update package list
yum update -y

# get all the packages required for compiling source
yum groupinstall 'Development Tools' -y

# install apache
yum install httpd mod_ssl -y

# install mySQL
yum --enablerepo=rubyworks install mysql-server mysql mysql-devel mysql-ruby -y

# set mysql and apache to start on boot
/sbin/chkconfig httpd on
/sbin/chkconfig --add mysqld
/sbin/chkconfig mysqld on
/sbin/service httpd start
/sbin/service mysqld start

# install postfix and subversion
yum install postfix subversion -y

# install git and dependencies
yum install gettext-devel expat-devel curl-devel zlib-devel openssl-devel -y
wget http://kernel.org/pub/software/scm/git/git-1.6.4.2.tar.gz
tar zxvf git-1.6.4.2.tar.gz
cd git-1.6.4.2
make prefix=/usr/local all 
sudo make prefix=/usr/local install
cd ..

# install ruby
yum install --enablerepo=rubyworks ruby ruby-devel ruby-irb ruby-rdoc ruby-ri

# install ImageMagick and all of it's required packages
yum install tcl-devel libpng-devel libjpeg-devel ghostscript-devel bzip2-devel freetype-devel libtiff-devel -y
wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
tar zxvf ImageMagick.tar.gz
cd ImageMagick-*
./configure --prefix=/usr --with-bzlib=yes --with-fontconfig=yes --with-freetype=yes --with-gslib=yes --with-gvc=yes --with-jpeg=yes --with-jp2=yes --with-png=yes --with-tiff=yes
make clean
make
make install
cd ..

# get rubygems
wget http://rubyforge.org/frs/download.php/57643/rubygems-1.3.4.tgz
tar xvzf rubygems-1.3.4.tgz
cd rubygems-1.3.4
ruby setup.rb
cd ..

# install rails
gem install rails --no-rdoc --no-ri

# install rmagick
gem install rmagick --no-rdoc --no-ri

# install mysql gem
gem install mysql --with-mysql-config=/usr/bin/mysql_config --no-ri --no-rdoc

# install passenger and apache module
gem install passenger --no-ri --no-rdoc
passenger-install-apache2-module
&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; This worked great for me on a Linode 360 running CentOS 5.2. If you have any additions or changes, leave them in the comments and I'll be sure to add them. You can also get the entire script in a gist &lt;a href="http://gist.github.com/151026"&gt;here&lt;/a&gt;.&lt;/p&gt;</description>
      <pubDate>Mon, 31 Aug 2009 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2009/08/31/centos-setup-script-with-ruby-apache-mysql-subverion-git-passenger-and-imagemagick</link>
    </item>
    <item>
      <title>Ruby Script to Add Apache Virtual Host Entry</title>
      <description>&lt;p&gt;When you're working with Rails, you never really have to add a virtual host entry for development (unless you use Passenger). You can always just fire up &lt;kbd&gt;script/server&lt;/kbd&gt; and navigate to http://localhost:3000.&lt;/p&gt;

&lt;p&gt;At my new job, I'm doing a lot of work on PHP and Drupal sites, which require you to add an entry to your host file and add a virtual host conf file for Apache. After only going through this process twice, I was already tired of it. I wrote the following script to automate the process for me.&lt;/p&gt;

&lt;pre class="brush: ruby"&gt;
#!/usr/bin/ruby

########################################
##### VARIABLES YOU NEED TO CHANGE #####
########################################

host_dir  = '/etc/hosts'            # path to your hosts file
sites_dir = '/Library/Webserver'    # path to the directory where you keep your sites (NO TRAILING SLASH!!!)
conf_dir  = '/etc/apache2/sites'    # path to directory where named conf files live

########################################

unless ARGV[0]
  puts "Usage: add_site sitename [hostname_for_url]"
  puts "Example: add_site sample sample.dev"
  exit
end

name = ARGV[0].strip
hostname = ARGV[1].nil? ? ARGV[0] : ARGV[1].strip

# first things first: make sure named conf file doesn't exist already
if File.exists?("#{conf_dir}/#{name}.conf")
  puts "Conf file named #{name}.conf already exists!"
  exit
end

# check to make sure host file exists
if File.exists?(host_dir)
  
  puts "Adding entry to #{host_dir}."
  File.open(host_dir, 'a') do |host_file|
    # append host entry to end of file
    host_file.puts "127.0.0.1\t#{hostname}"
  end
  puts "Host entry added!"
  
  puts "Adding named conf file."
  File.open("#{conf_dir}/#{name}.conf", 'a') do |host_file|
    # add entry
    host_file.puts &amp;lt;&amp;lt;EOF
&amp;lt;VirtualHost *:80&amp;gt;
  ServerName #{hostname}

  DocumentRoot "#{sites_dir}/#{name}"
	DirectoryIndex index.php
	&amp;lt;Directory "#{sites_dir}/#{name}"&amp;gt;
		Options FollowSymLinks MultiViews Includes
		AllowOverride All
		Order allow,deny
		Allow from all
	&amp;lt;/Directory&amp;gt;
&amp;lt;/VirtualHost&amp;gt;
EOF
  end
  puts "Conf entry added!\n"
  
  puts "Restarting apache.\n"
  system "apachectl graceful"
  puts "Done!"
  
end
&lt;/pre&gt;

&lt;p&gt;What you need to do to get this to work:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Change the variables at the top of the file (path to your hosts file, path to the folder where you keep your development site, and path to the directory where you want to keep your named conf files).&lt;/li&gt;
  &lt;li&gt;Rename the file to &lt;kbd&gt;add_site&lt;/kbd&gt;(with no extension) and move to your &lt;kbd&gt;/usr/bin&lt;/kbd&gt; directory.&lt;/li&gt;
  &lt;li&gt;Chmod the file to be executable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now you can run the &lt;kbd&gt;add_site&lt;/kbd&gt; command and provide it with the name of the site folder and optionally the name of the local domain you'd like to use.&lt;/p&gt;</description>
      <pubDate>Mon, 10 Aug 2009 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2009/08/10/ruby-script-to-add-apache-virtual-host-entry</link>
    </item>
    <item>
      <title>Rails DELETE requests with JQuery</title>
      <description>&lt;p&gt;When I write admin controls for for a Rails app, I like to make the delete links just fire off an Ajax request, delete the record, and remove the element from the page. This is easy with the Rails default setup using Prototype. All you have to do is use &lt;kbd&gt;link_to_remote&lt;/kbd&gt; with a &lt;kbd&gt;:method =&amp;gt; 'delete'&lt;/kbd&gt; to make Rails do all the work. The problem is, this is the code that Rails generates:&lt;/p&gt;

&lt;pre class="brush: rails"&gt;
&amp;lt;%= link_to_remote(&amp;quot;Delete&amp;quot;, :url =&amp;gt; admin_post_path(post), :method =&amp;gt; :delete) %&amp;gt;
&amp;lt;!- turns into: --&amp;gt;
&amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;new Ajax.Request(&amp;#x27;/users/63&amp;#x27;, {asynchronous:true, evalScripts:true, method:&amp;#x27;delete&amp;#x27;});); return false;&amp;quot;&amp;gt;Delete&amp;lt;/a&amp;gt;
&lt;/pre&gt;

&lt;p&gt;While this isn't terrible, it's certainly not very pretty. Surely we can make the code cleaner and simpler!&lt;/p&gt;

&lt;p&gt;Well, we've recently switched to using JQuery for all of our new apps at &lt;a href="http://www.plexusweb.com"&gt;Plexus&lt;/a&gt;. Unless you use the JRails plugin, the &lt;kbd&gt;link_to_remote&lt;/kbd&gt; helper no longer works when using JQuery. I figured this would be a good time to switch the remote calls to be handled separately by JavaScript, instead of spitting out a ton of script in the HTML.&lt;/p&gt;

&lt;p&gt;It's easy to just hijack links via JavaScript and have them submit via Ajax, but how do we handle REST requests that require the DELETE method?&lt;/p&gt;

&lt;p&gt;I decided to just add a specific class to all links that I wanted to be hijacked by JavaScript, then add the code in my js file to handle the links with Ajax. My DELETE links would look like this:&lt;/p&gt;

&lt;pre class="brush: rails"&gt;
&amp;lt;!- Link that uses DELETE method --&amp;gt;
&amp;lt;%= link_to &amp;#x27;Delete&amp;#x27;, entry_path(entry), :class =&amp;gt; &amp;#x27;remote-delete&amp;#x27; %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;The key to hijacking the link is to include the hidden &lt;kbd&gt;_method&lt;/kbd&gt; attribute set to 'delete'. My JavaScript to hijack the link would look like this:&lt;/p&gt;

&lt;pre class="brush: javascript"&gt;
$(document).ready(function() {
  $(&amp;#x27;a.remote-delete&amp;#x27;).click(function() {
    // we just need to add the key/value pair for the DELETE method
    // as the second argument to the JQuery $.post() call
    $.post(this.href, { _method: &amp;#x27;delete&amp;#x27; }, null, &amp;quot;script&amp;quot;);
    return false;
  });
});
&lt;/pre&gt;

&lt;p&gt;This converts every link that has the &lt;kbd&gt;remote-delete&lt;/kbd&gt; class to an Ajax request with the DELETE method!&lt;/p&gt;</description>
      <pubDate>Wed, 20 May 2009 00:00:00 +0000</pubDate>
      <link>http://travisonrails.com/2009/05/20/rails-delete-requests-with-jquery</link>
    </item>
  </channel>
</rss>
