<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Perplexed Labs &#187; ruby</title>
	<atom:link href="http://blog.perplexedlabs.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.perplexedlabs.com</link>
	<description>web development war stories from the frontlines to the backend</description>
	<lastBuildDate>Sat, 24 Jul 2010 16:27:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</title>
		<link>http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/</link>
		<comments>http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 13:00:32 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[mod_wsgi]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[phusion passenger]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[subversion]]></category>

		<guid isPermaLink="false">http://blog.perplexedlabs.com/?p=408</guid>
		<description><![CDATA[I finally got around to setting up a more sophisticated deployment system for some of my apps. These apps include some built on a custom PHP framework and others that are Python / Django apps. I figured I'd share my experience... Why is a high-level deployment infrastructure important? Deployment is something that should be simple, [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/' rel='bookmark' title='Permanent Link: Installing Ruby Enterprise Edition with Phusion Passenger'>Installing Ruby Enterprise Edition with Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/' rel='bookmark' title='Permanent Link: 8 Books To Get A Developer For The Holidays'>8 Books To Get A Developer For The Holidays</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I finally got around to setting up a more sophisticated deployment system for some of my apps.  These apps include some built on a custom PHP framework and others that are Python / Django apps.  I figured I'd share my experience...</p>
<p>Why is a high-level deployment infrastructure important?  Deployment is something that should be simple, accessible, and repeatable.  It should be as close to a "single click" as possible.  Previously, for me, it was a bash script that exported some SVN branches.  While this worked fine, as projects progress, you want some accountability, history, and the ability to roll back mission critical applications when something goes wrong with a deploy.</p>
<p><a href="http://www.capify.org/">Capistrano</a> is an open source, command line, deployment tool that provides all of these features.  It's written in Ruby.  You leverage a variety of built in "recipes" (Capistrano's term for a deployment script) that execute certain procedures to deploy an app.  Out-of-the-box it's ideally built to deploy a Rails app.  However, after some minor tweaks it can deploy most anything and do it well.  It can restart servers, update symlinks, change permissions - pretty much anything.  It assumes you access your POSIX compliant server via SSH via the same password (or have ssh keys setup).</p>
<p><a href="http://labs.peritor.com/webistrano">Webistrano</a> is an open source web front-end for Capistrano.  It's a convenience layer that abstracts the command line away and provides an interface to perform the same tasks.  This interface shows history as well as providing a convenient GUI for creating new deployment projects, stages, and recipes.  Highly recommended.</p>
<p>Let's get down to business.  This post makes a few assumptions about things you've already installed and used previously.</p>
<ul>
<li><a href="http://www.ruby-lang.org/en/">Ruby 1.8.5</a>+
<li><a href="http://rubyforge.org/projects/rubygems/">RubyGems</a>
<li><a href="http://www.mysql.com/">MySQL 5.0</a>+
<li><a href="http://www.apache.org/">Apache 2</a>+
<li><a href="http://subversion.tigris.org/">Subversion</a> and a repository containing the "production" branch of your app.
</ul>
<h3>Installing Capistrano</h3>
<p>Well, this is an easy one (you probably want to do this as root):</p>
<blockquote><p>
gem install capistrano
</p></blockquote>
<h3>Installing Webistrano</h3>
<p>Also fairly easy, with a little splash of configuration.</p>
<blockquote><p>
# wget http://labs.peritor.com/webistrano/attachment/wiki/Download/webistrano-1.4.zip<br />
# unzip webistrano-1.4.zip<br />
# mv webistrano-1.4 /path/to/where/you/want/webistrano
</p></blockquote>
<p>Setup the database tables and create a new webistrano user (obviously be conscious of your security preferences for access to your database in the host and password portions):</p>
<blockquote><p>
# mysql<br />
mysql> CREATE DATABASE `webistrano`;<br />
mysql> CREATE USER 'webistrano'@'localhost' IDENTIFIED BY 'password';<br />
mysql> GRANT ALL PRIVILEGES ON `webistrano`.* TO 'webistrano'@'localhost' WITH GRANT OPTION;
</p></blockquote>
<p>Now, in the directory where you placed webistrano you're going to want to copy <i>config/database.yml.sample</i> to <i>config/database.yml</i>.  Edit this file, in the production area, to match your database settings.  By default the file expects a socket to connect, you can chase this by specifying <i>host:</i> and <i>port:</i>.  (Keep in mind Webistrano is simply a Rails app).</p>
<p>You should now be able to have Rails migrate the new database you created.  In the webistrano directory:</p>
<blockquote><p>
# RAILS_ENV=production rake db:migrate
</p></blockquote>
<p>Finally, copy <i>config/webistrano_config.rb.sample</i> to <i>config/webistrano_config.rb</i> and edit according to your preferred mail settings.</p>
<p>We can now test to see if webistrano is working properly by serving it via mongrel:</p>
<blockquote><p>
# ruby script/server -d -e production -p 3000
</p></blockquote>
<p>This starts a single mongrel daemon, using the production environment, listening on port 3000.  You should now be able to hit http://127.0.0.1:3000/ and get the Webistrano login prompt.  If this is working, kill that mongrel instance.</p>
<p>For longer term serving I decided to go with Phusion Passenger (essentially mod_rails for Apache).  It's a nearly zero configuration solution for serving a rails app and will feel at home to anyone with experience serving PHP apps via Apache and mod_php.</p>
<h3>Installing Phusion Passenger</h3>
<p>Again, as root:</p>
<blockquote><p>
# gem install passenger<br />
# passenger-install-apache2-module
</p></blockquote>
<p>The second command will invoke an installer which compiled Passenger and provides instructions on integrating it into your Apache config.  Essentially, edit your httpd.conf as follows (<strong>these were specific to my install, make sure to use the ones provide by the installer for you</strong>):</p>
<blockquote><p>
LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9/ext/apache2/mod_passenger.so<br />
PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.2.9<br />
PassengerRuby /usr/bin/ruby
</p></blockquote>
<p>Now you can simply add VirtualHost entries to your httpd.conf for any of your Rails apps.  Let's add one for Webistrano:</p>
<blockquote><p>
&lt;VirtualHost *:80&gt;<br />
ServerName webistrano.mydomain.com<br />
DocumentRoot /path/to/webistrano/public<br />
&lt;/VirtualHost&gt;
</p></blockquote>
<p>Yes, Passenger makes it that simple.  Add configuration directives as needed for your environment.</p>
<p>Now Webistrano should be serving from the VirtualHost you specified, seamlessly, via Passenger.</p>
<h3>Deploying A Non-Rails App</h3>
<p>Now the fun stuff.</p>
<p>Capistrano breaks things down into projects, stages, and recipes.  Each app you want managed by capistrano should be it's own project.  Each project should have a stage for at least production and optionally staging and development.</p>
<p>Hosts are added globally and form the targets of a deploy for any given project.  Hosts can include web, app, and database servers.</p>
<p>Deployments in Capistrano are done to a child directory under "releases" named via the date and time of the deployment.  By default 5 releases are kept and available to rollback to.  Upon successful deployment a symlink (default is called "current" and can be modified via the <i>current_path</i> configuration variable) is updated to that release directory.  It is this symlink that should be targeted by your webserver (your DocumentRoot in Apache).</p>
<p>Capistrano also creates a "shared" directory that is symlinked to in each release useful for storing logs and other data that should be maintained through each deployment.</p>
<p>For non-rails apps you'll use the "Pure File" project type when creating your new project.  Upon project creation you can add configuration variables specific to your project.  I recommend using <i>:export</i> instead of <i>:checkout</i> for <i>deploy_via</i> for production subversion deployments as this doesn't expose .svn directories.  Use an SSH user that has enough permissions to create directories where your deploy will occur or, specify <i>use_sudo</i> to true and create a new configuration variable <i>admin_runner</i> and set it to the same user as <i>runner</i>.</p>
<p>Add a stage to your new project for "production".  In the "Manage Hosts" page add a new host for each of your application servers.  Then add each host as a target of your "production" stage of your project.</p>
<p>At this point you should be able to execute the "Setup" task for your "production" stage.  This is a one time task that simply creates the directories.</p>
<p>Assuming this went successfully, try doing a "Deploy" and see if that finishes without error.  You might have to play around with permissions and other minor issues - post a comment if you have any specific questions.</p>
<p>For my PHP framework there are a couple specific tasks I wanted to run in addition to the default Capistrano tasks.  You do this by creating custom recipes in the "Manage Recipes" page in Webistrano.  Recipes are simply procedures written in ruby.  Here's what my recipe looks like:</p>
<pre class="brush: ruby;">
namespace :deploy do
	task :setup, :except =&gt; { :no_release =&gt; true } do
		dirs = [deploy_to, releases_path, shared_path]
		dirs += shared_children.map { |d| File.join(shared_path, d) }
		run &quot;#{try_sudo} mkdir -p #{dirs.join(' ')} &amp;&amp; #{try_sudo} chmod g+w #{dirs.join(' ')}&quot;
		run &quot;chmod 777 #{shared_path}/log&quot;
	end

	task :finalize_update, :except =&gt; { :no_release =&gt; true } do
		run &quot;mkdir -p #{latest_release}/app/tmp&quot;
		run &quot;chmod -R 777 #{latest_release}/app/tmp&quot;
		run &quot;rm -rf #{latest_release}/app/logs&quot;
		run &quot;ln -s #{shared_path}/log #{latest_release}/app/logs&quot;
		run &quot;cp #{latest_release}/public_html/.htaccess-production #{latest_release}/public_html/.htaccess&quot;
		run &quot;cp #{latest_release}/app/config/config-production.php #{latest_release}/app/config/config.php&quot;
		run &quot;cp #{latest_release}/app/config/db-default.php #{latest_release}/app/config/db.php&quot;
		run &quot;cp #{latest_release}/app/config/memcache-default.php #{latest_release}/app/config/memcache.php&quot;
	end
end
</pre>
<p>If you're not familiar with Ruby - what this code is essentially doing is overwriting two tasks in the :deploy namespace with my custom code.</p>
<p>The first, :setup, simply duplicates the base :setup functionality discussed above (creating the releases and shared directories) and chmods the shared log directory to be writable.</p>
<p>The second, :finalize_update, performs a variety of configuration tasks for a PHP app built with my framework.  Also, you'll notice that I'm removing my app's logs directory and symlinking to the shared log directory.  This way all releases will log to the same directory, consistently.  </p>
<p>In my case all of these procedures are command line instructions.  Alternatively, you can do a variety of things leveraging the full breadth of the Ruby language and any gem you'd like to introduce.   Things such as accessing your CDN API to clear image, JS, or CSS caching, etc.</p>
<h3>Deploying Django Apps</h3>
<p>First off it's worth noting that I serve my Django apps via mod_wsgi.  To make the deployment process easier here's what my app.wsgi script looks like:</p>
<pre class="brush: python;">
import os
import sys

appdir = os.path.normpath(os.path.join(os.path.realpath(os.path.dirname(__file__)), '..'))
sys.path.insert(0, appdir)
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
os.environ['PYTHON_EGG_CACHE'] = os.path.join(appdir, '.python-eggs')
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>This code allows us to avoid having to hardcode paths in the wsgi script (and thus avoid having to change them when we deploy).  It assumes the following directory structure:</p>
<blockquote><p>
.python-eggs (egg cache)<br />
apps (apps path is added to python system path in settings.py)<br />
public (where your .wsgi script resides)<br />
site_media<br />
templates<br />
settings.py<br />
settings-production.py (used for deploy)<br />
urls.py<br />
...
</p></blockquote>
<p>If you follow this convention, the following Capistrano recipe works great:</p>
<pre class="brush: ruby;">
namespace :deploy do
	task :setup, :except =&gt; { :no_release =&gt; true } do
		dirs = [deploy_to, releases_path, shared_path]
		dirs += shared_children.map { |d| File.join(shared_path, d) }
		run &quot;#{try_sudo} mkdir -p #{dirs.join(' ')} &amp;&amp; #{try_sudo} chmod g+w #{dirs.join(' ')}&quot;
		run &quot;chmod 777 #{shared_path}/log&quot;
	end

	task :finalize_update, :except =&gt; { :no_release =&gt; true } do
		run &quot;rm -rf #{latest_release}/logs&quot;
		run &quot;ln -s #{shared_path}/log #{latest_release}/logs&quot;
		run &quot;cp #{latest_release}/settings-production.py #{latest_release}/settings.py&quot;
		run &quot;mkdir -p #{latest_release}/.python-eggs&quot;
		run &quot;chmod 777 #{latest_release}/.python-eggs&quot;
	end
end
</pre>
<h3>Fin</h3>
<p>This should give you a nice intro to leveraging Capistrano via Webistrano.  Feel free to comment with questions, suggestions, or anything else!</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/' rel='bookmark' title='Permanent Link: Installing Ruby Enterprise Edition with Phusion Passenger'>Installing Ruby Enterprise Edition with Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/' rel='bookmark' title='Permanent Link: 8 Books To Get A Developer For The Holidays'>8 Books To Get A Developer For The Holidays</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>8 Books To Get A Developer For The Holidays</title>
		<link>http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/</link>
		<comments>http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 13:30:06 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Book Reviews]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Clojure]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[book review]]></category>
		<category><![CDATA[clojure]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programmer]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.perplexedlabs.com/?p=385</guid>
		<description><![CDATA[Send this to your significant other/parent/relative/friend so, instead of that sweater, you get one of these nuggets of awesome this Christmas. The Pragmatic Programmer: From Journeyman to Master Write better, cleaner, more maintainable code. Learn how to manage your projects and focus on shipping your product. With insight that covers the gamut of software development [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/28/django-1-0-template-development-sample-chapter-serving-multiple-templates/' rel='bookmark' title='Permanent Link: Django 1.0 Template Development: Sample Chapter &#8220;Serving Multiple Templates&#8221;'>Django 1.0 Template Development: Sample Chapter &#8220;Serving Multiple Templates&#8221;</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Send this to your significant other/parent/relative/friend so, instead of that sweater, you get one of these nuggets of awesome this Christmas.</p>
<h3><a href="http://www.amazon.com/gp/product/020161622X?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=020161622X">The Pragmatic Programmer: From Journeyman to Master</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=020161622X" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>Write better, cleaner, more maintainable code.  Learn how to manage your projects and focus on shipping your product.  With insight that covers the gamut of software development from low level to management<br />
this one is a must have for anyone involved in this industry.</p>
<h3><a href="http://www.amazon.com/gp/product/1934356344?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1934356344">The Passionate Programmer: Creating a Remarkable Career in Software Development</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=1934356344" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>Highly recommended!  <a href="http://blog.perplexedlabs.com/2009/07/29/book-review-the-passionate-programmer/">Read my full review</a>.</p>
<h3><a href="http://www.amazon.com/gp/product/0735619670?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0735619670">Code Complete: A Practical Handbook of Software Construction</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=0735619670" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>Another classic "software construction" book.  Sharpen your saw with timeless information that can be applied to any project in any language.  Less bugs, more productivity, more programmer happiness.</p>
<h3><a href="http://www.amazon.com/gp/product/1430219483?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1430219483">Coders at Work</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=1430219483" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>This one is different.  Written as a set of interview transcripts with 15 legendary industry giants, this book is a fantastic insight into how some of the great minds think.  It's inspiring to hear it from the source, must have!</p>
<h3><a href="http://www.amazon.com/gp/product/1934356336?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=1934356336">Programming Clojure</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=1934356336" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>A developer should learn at least one new language a year.  This year that language should be Clojure.  Clojure is a dynamic, general purpose, language targeting the Java virtual machine and designed for multi-threaded use.  It's growing popularity, ability to leverage the Java standard library, and its multi-threaded nature make this a must have.</p>
<h3><a href="http://www.amazon.com/gp/product/0201835959?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0201835959">The Mythical Man-Month: Essays on Software Engineering</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=0201835959" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>Another classic.  Primarily discusses project management from the perspective of Fred Brooks and his experiences at IBM.  Brooks' Law states that "adding manpower to a late software project makes it later".</p>
<h3><a href="http://www.amazon.com/gp/product/0321344758?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0321344758">Don't Make Me Think: A Common Sense Approach to Web Usability</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=0321344758" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>Web developers should always keep in mind the user of the product their creating.  Usability becomes increasingly important as applications move to the web.  The design and usability of your app can make or break its success.  This classic is a must read.</p>
<h3><a href="http://www.amazon.com/gp/product/0201633612?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=390957&#038;creativeASIN=0201633612">Design Patterns: Elements of Reusable Object-Oriented Software</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=0201633612" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /></h3>
<p>This classic known most commonly as the "gang of four" book is the definitive reference on design patterns.  Covering all of the most common cases and time and time again serving as an invaluable source of information.</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/28/django-1-0-template-development-sample-chapter-serving-multiple-templates/' rel='bookmark' title='Permanent Link: Django 1.0 Template Development: Sample Chapter &#8220;Serving Multiple Templates&#8221;'>Django 1.0 Template Development: Sample Chapter &#8220;Serving Multiple Templates&#8221;</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter and SD News</title>
		<link>http://blog.perplexedlabs.com/2009/07/31/twitter-and-sd-news/</link>
		<comments>http://blog.perplexedlabs.com/2009/07/31/twitter-and-sd-news/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 17:24:28 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[hacker news]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.perplexedlabs.com/?p=336</guid>
		<description><![CDATA[Motivation: SD News is a "social news site" (basically a Hacker News clone), written in Rails, that I work on as part of my efforts with a Christian publishing company I run with some friends.  As part of the administrative backend, I wanted to be able to send posts to our Twitter profile.  The site [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2008/02/26/flickr-rss-and-ruby/' rel='bookmark' title='Permanent Link: Flickr, RSS, and Ruby'>Flickr, RSS, and Ruby</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><strong>Motivation:</strong> <a href="http://news.sensusdivinitatis.com">SD News</a> is a "social news site" (basically a Hacker News clone), written in Rails, that I work on as part of my efforts with a Christian publishing company I run with some friends.  As part of the administrative backend, I wanted to be able to send posts to our <a href="http://twitter.com/sdpub">Twitter profile</a>.  The site is still young, and the community still growing, so I wanted the admins to have complete control over what gets sent to Twitter.  I had thought of automating this process based on which items have the most votes in a given time period, but trust is easy to lose and all it would take is 1 or 2 irrelevant, or irreverent. posts to lose that trust.</p>
<p><strong>Methodology:</strong> I would first need a good Twitter gem for Ruby, and I'd need to decide which URL shortening service I'd use.  <a href="http://twitter.rubyforge.org/">Ruby Twitter</a> seemed to be the simplest gem for Twitter.  For the URL shortening I chose bit.ly, because the <a href="http://github.com/philnash/bitly/tree/master">bitly gem</a> seemed like the easiest, and the documentation was good.  My plan of attack was:</p>
<ol>
<li>Grab one item from the queue, that has not been Twittered</li>
<li>Shorten the URL via bitly</li>
<li>Send the item's title and shortened URL to Twitter</li>
<li>Save the shortened URL in the database so I could retrieve stats later</li>
</ol>
<p>The script that did this would be run every hour.<br />
<strong><br />
Implementation: </strong>The two gems made this an almost trivial implementation.</p>
<pre class="brush: ruby;">
require 'twitter'
require 'bitly'

@item = Item.find(:first, :conditions =&gt; &quot;send_to_twitter = 1 and twitterd = 0&quot;, :order =&gt; &quot;posted_on desc&quot;)

if !@item.nil?
   b = Bitly.new(username, password)
   @url = b.shorten(&quot;http://news.sensusdivinitatis.com/item/#{@item.id}&quot;).short_url

   httpauth = Twitter::HTTPAuth.new(username, password)
   base = Twitter::Base.new(httpauth)
   base.update(&quot;#{@item.title[0...110]} - #{@url}&quot;) #shorten the title if it's too long

   Item.update(@item.id, :twitterd =&gt; 1, :bitly_url =&gt; @url) #save the bit.ly url
end
</pre>
<p>That's pretty much it.  Incidentally, the bitly gem makes it very easy to grab the stats for any URL.  For instance, if you wanted to see how many clicks a given URL has received:</p>
<pre class="brush: ruby;">
require 'twitter'
require 'bitly'

@item = Item.find(id)
b = Bitly.new(username, password)
@clicks = b.stats(i.bitly_url).stats[&quot;clicks&quot;]
</pre>
<p>Done.</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2008/02/26/flickr-rss-and-ruby/' rel='bookmark' title='Permanent Link: Flickr, RSS, and Ruby'>Flickr, RSS, and Ruby</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/' rel='bookmark' title='Permanent Link: Be Language Agnostic &#8211; Solve the Problem!'>Be Language Agnostic &#8211; Solve the Problem!</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2009/07/31/twitter-and-sd-news/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Be Language Agnostic &#8211; Solve the Problem!</title>
		<link>http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/</link>
		<comments>http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 14:15:28 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.perplexedlabs.com/?p=280</guid>
		<description><![CDATA[I like Python. I like Ruby. I like C, C++, and Objective-C. I like Java. I also (actually) like PHP. I like programming - get it? Use whatever gets the job done and done well. Use whatever achieves the performance and scalability you require for a given task. Use what makes sense given a specific [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/' rel='bookmark' title='Permanent Link: 8 Books To Get A Developer For The Holidays'>8 Books To Get A Developer For The Holidays</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/03/20/django-and-python-first-impressions-part-ii/' rel='bookmark' title='Permanent Link: Django and Python First Impressions &#8211; Part II'>Django and Python First Impressions &#8211; Part II</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I like Python.  I like Ruby.  I like C, C++, and Objective-C.  I like Java.  I also (actually) like PHP.  I like programming - get it?  Use whatever gets the job done and done well.  Use whatever achieves the performance and scalability you require for a given task.  Use what makes sense given a specific problem's domain.  <del datetime="2009-06-09T13:43:01+00:00">Use whatever aligns itself with the way your mind works</del>.  Don't be a one trick pony (that isn't a Django reference).  Learn multiple languages, their strengths, and their weaknesses.  Understand when a language's strengths will allow you to solve a problem faster, easier, better.  Don't force a square peg through a round hole.</p>
<p>Watch <strong><a href="http://www.itworld.com/video?bcpid=1578108607&#038;bclid=1588003312&#038;bctid=23220283001">this</a></strong> video.  It's excellent food for thought and drives home the importance, as a programmer, of learning new, different, languages to expand your ability to solve problems in a variety of ways.  The video mentions the <a href="http://en.wikipedia.org/wiki/Sapir%E2%80%93Whorf_hypothesis">Sapir–Whorf hypothesis</a> which suggests that a particular language influences how a person understands and interacts with the world.  This makes a lot of sense.</p>
<p><strong>A programmer who thinks only in terms of a single language will attempt to solve every problem with that language.  You need more than one tool on your belt because not every problem is a nail.</strong></p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/11/30/8-books-to-get-a-developer-for-the-holidays/' rel='bookmark' title='Permanent Link: 8 Books To Get A Developer For The Holidays'>8 Books To Get A Developer For The Holidays</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/03/20/django-and-python-first-impressions-part-ii/' rel='bookmark' title='Permanent Link: Django and Python First Impressions &#8211; Part II'>Django and Python First Impressions &#8211; Part II</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2009/06/01/be-language-agnostic-solve-the-problem/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Django and Python First Impressions &#8211; Part II</title>
		<link>http://blog.perplexedlabs.com/2009/03/20/django-and-python-first-impressions-part-ii/</link>
		<comments>http://blog.perplexedlabs.com/2009/03/20/django-and-python-first-impressions-part-ii/#comments</comments>
		<pubDate>Fri, 20 Mar 2009 15:05:51 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.perplexedlabs.com/?p=190</guid>
		<description><![CDATA[I've spent more time with Django the past couple days. Read my installation guide and my first impressions to get caught up. I wanted to address a couple issues I came across as I was exposed to certain architectural designs of Django. It might be helpful to note which books available today cover Django 1.0. [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/02/08/getting-started-with-django-and-python-first-impressions/' rel='bookmark' title='Permanent Link: Getting Started with Django and Python &#8211; First Impressions'>Getting Started with Django and Python &#8211; First Impressions</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/08/13/adventures-in-django-and-python-part-iii/' rel='bookmark' title='Permanent Link: Adventures in Django and Python &#8211; Part III'>Adventures in Django and Python &#8211; Part III</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/29/django-1-1-released/' rel='bookmark' title='Permanent Link: Django 1.1 Released'>Django 1.1 Released</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I've spent more time with Django the past couple days.  Read my <a href="http://www.perplexedlabs.com/2008/11/10/setup-python-25-mod_wsgi-and-django-10-on-centos-5-cpanel/">installation guide</a> and my <a href="http://www.perplexedlabs.com/2009/02/08/getting-started-with-django-and-python-first-impressions/">first impressions</a> to get caught up.  I wanted to address a couple issues I came across as I was exposed to certain architectural designs of Django.</p>
<p>It might be helpful to note which books available today cover Django 1.0.  I do realize that the "official" Django book covering 1.0 is in the works, but, in the meantime I recommend <a href="http://www.amazon.com/gp/product/0132356139?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=0132356139">Python Web Development with Django (Developer's Library)</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=0132356139" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> and <a href="http://www.amazon.com/gp/product/1430210478?ie=UTF8&#038;tag=perplabs-20&#038;linkCode=as2&#038;camp=1789&#038;creative=9325&#038;creativeASIN=1430210478">Pro Django (Expert's Voice in Web Development)</a><img src="http://www.assoc-amazon.com/e/ir?t=perplabs-20&#038;l=as2&#038;o=1&#038;a=1430210478" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />.</p>
<p>Lets start with the template system.  While Django's template system is powerful, I'm sure, it's basically a free for all of file names and directory structures.  You could conceivably create a single 'templates' directory and place all of a projects template files in that directory (naming the files as you please) for any and all the apps that compose the project.  While it's not recommended you actually do that, Django would support it because it doesn't seem to really dictate or enforce any particular convention.  I feel like Rails, comparatively speaking, provides solid conventions for a developer to follow in terms of file naming, directory naming, and directory structure.</p>
<p>I was also surprised at the fact that Django does NOT bundle a pluralization library.  Even simple cases (ending in <strong>y</strong> to <strong>ies</strong>) aren't handled automatically.  A model named 'Category' appears as 'Categorys'.  It does provide support for explicitly specifying plural names for Models via the <strong>verbose_name_plural</strong> Meta property:</p>
<pre class="brush: python;">
class Category(models.Model):
    name = models.CharField(max_length=128)
    class Meta:
        verbose_name_plural = 'categories'
</pre>
<p>Coming from a world of a custom built PHP framework - it's REALLY nice to have features like the command line sandbox to be able to play with Models and interact with the project's codebase.  It's also great that Django bundles a development webserver for a quick and easy create-test-edit cycle.  It recognizes changes to your code while it's running - there's no need to restart manually.</p>
<p>The effects are immeasurable with respect to the fact that Python functions are first-class.  Django uses this extensively (such as your URL configuration or default values for Models).  It's extremely intuitive to be able to do the following in your Model definition:</p>
<pre class="brush: python;">
class Post(models.model)
    stamp = models.DateTimeField(default=datetime.now)
</pre>
<p>Notice this wasn't written as <strong>datetime.now()</strong>.  That would actually execute the function when the class is declared and all entries would receive an identical stamp.  Instead we're passing a <em>reference</em> to the function.  Django detects this and calls the function when the Model is instantiated.</p>
<p>I'm also excited about the way the Django framework handles requests and responses.  The concept of the view receiving an HttpRequest object, giving context, and returning an HttpResponse object just makes sense.  It's very much in line with the way HTTP works.  It's simple, powerful, and elegant.</p>
<p>I've read about (<a href="http://www.youtube.com/watch?v=i6Fr65PFqfk">and watched video of</a>) some issues that people have with Django.  These usually refer to difficulties one <em>may</em> have scaling it.  Lack of built-in support for multiple databases and sharding are cited, among other reasons.  I think, for what it's able to do right out of the box, it's fantastic.  Scaling (in general) isn't always straightforward.  In many cases it requires specific tools and solutions for the task at hand.  These issues should in no way prevent you from using Django for a project!</p>
<p>More soon.</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/02/08/getting-started-with-django-and-python-first-impressions/' rel='bookmark' title='Permanent Link: Getting Started with Django and Python &#8211; First Impressions'>Getting Started with Django and Python &#8211; First Impressions</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/08/13/adventures-in-django-and-python-part-iii/' rel='bookmark' title='Permanent Link: Adventures in Django and Python &#8211; Part III'>Adventures in Django and Python &#8211; Part III</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/29/django-1-1-released/' rel='bookmark' title='Permanent Link: Django 1.1 Released'>Django 1.1 Released</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2009/03/20/django-and-python-first-impressions-part-ii/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Installing Ruby Enterprise Edition with Phusion Passenger</title>
		<link>http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/</link>
		<comments>http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 15:00:18 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[phusion]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby enterprise edition]]></category>

		<guid isPermaLink="false">http://www.perplexedlabs.com/?p=121</guid>
		<description><![CDATA[I've been using Phusion Passenger for a few months now and I'm really pleased with it.  The performace vs. Mongrel is better, but what makes it so useful is the ease of deployment.  Being able to setup a vhost in Apache just like you would for a PHP application was very appealing to me.  Having [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/' rel='bookmark' title='Permanent Link: Ruby On Rails and SliceHost Part 1: Initial Setup'>Ruby On Rails and SliceHost Part 1: Initial Setup</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/31/twitter-and-sd-news/' rel='bookmark' title='Permanent Link: Twitter and SD News'>Twitter and SD News</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I've been using <a href="http://www.modrails.com/">Phusion Passenger</a> for a few months now and I'm really pleased with it.  The performace vs. Mongrel is better, but what makes it so useful is the ease of deployment.  Being able to setup a vhost in Apache just like you would for a PHP application was very appealing to me.  Having previously worked with the Apache/Rails/Mongrel/mod_proxy stack in an "enterprise" environment for over a year, I have experienced pretty much every nightmare deployment scenario possible.  I recently decided to install Phusion's <a href="http://www.rubyenterpriseedition.com/">Ruby Enterprise Edition</a>, which promises up to a 33% savings in memory usage.</p>
<p>Before you do anything, and to save you trouble down the road, I recommend generating a list of all the gems currently installed.  You'll need this later because you'll have to reinstall all of them in Ruby Enterprise Edition.</p>
<blockquote><p>$ gem list</p>
<p>*** LOCAL GEMS ***</p>
<p>actionmailer (2.0.2)<br />
actionpack (2.0.2)<br />
activerecord (2.0.2)<br />
activeresource (2.0.2)<br />
activesupport (2.0.2)<br />
acts_as_taggable (2.0.2)<br />
amazon-ecs (0.5.3)<br />
cgi_multipart_eof_fix (2.5.0)<br />
daemons (1.0.10)<br />
fastthread (1.0.1)<br />
gem_plugin (0.2.3)<br />
hpricot (0.6)<br />
mongrel (1.1.4)<br />
mysql (2.7)<br />
passenger (1.0.1)<br />
rails (2.0.2)<br />
rake (0.8.1)<br />
rspec (1.1.3)<br />
will_paginate (2.2.2)<br />
xml-simple (1.0.11)</p></blockquote>
<p>Copy your list and save it somewhere.  Next, we download and extract the current version of Ruby Enterprise Edition.  The latest version number can be found at the <a href="http://www.rubyenterpriseedition.com/download.html">download page</a>.</p>
<blockquote><p>$ wget http://rubyforge.org/frs/download.php/48623/ruby-enterprise-1.8.6-20081215.tar.gz<br />
$ tar xzvf ruby-enterprise-1.8.6-20081215.tar.gz</p></blockquote>
<p>And run the installer</p>
<blockquote><p>$ ./ruby-enterprise-1.8.6-20081215/installer</p></blockquote>
<p>As the installation proceeds, you'll be prompted for an installation directory.  I went with the default.  When the installation is over, you should see a message like this:</p>
<blockquote><p>Ruby Enterprise Edition is successfully installed!<br />
If want to use Phusion Passenger (http://www.modrails.com) in combination<br />
with Ruby Enterprise Edition, then you must reinstall Phusion Passenger against<br />
Ruby Enterprise Edition, as follows:</p>
<p>/opt/ruby-enterprise-1.8.6-20081215/bin/passenger-install-apache2-module</p>
<p>Make sure you don't forget to paste the Apache configuration directives that<br />
the installer gives you.</p>
<p>If you ever want to uninstall Ruby Enterprise Edition, simply remove this<br />
directory:</p>
<p>/opt/ruby-enterprise-1.8.6-20081215</p>
<p>If you have any questions, feel free to visit our website:</p>
<p>http://www.rubyenterpriseedition.com</p>
<p>Enjoy Ruby Enterprise Edition, a product of Phusion (www.phusion.nl)</p></blockquote>
<p>I do want to use Ruby Enterprise Edition and Apache, so I immediately installed the Apache module.</p>
<blockquote><p>$ /opt/ruby-enterprise-1.8.6-20081215/bin/passenger-install-apache2-module</p></blockquote>
<p>You need to pay attention to the Apache directives that this installation generates, since you'll have to put them into your httpd.conf:</p>
<blockquote><p>The Apache 2 module was successfully installed.</p>
<p>Please edit your Apache configuration file, and add these lines:</p>
<p>LoadModule passenger_module /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so<br />
PassengerRoot /opt/ruby-enterprise-1.8.6-20081215/lib/ruby/gems/1.8/gems/passenger-2.0.6<br />
PassengerRuby /opt/ruby-enterprise-1.8.6-20081215/bin/ruby</p></blockquote>
<p>What that message doesn't explain is that, if you previously installed Passenger <strong>without</strong> Ruby Enterprise Edition, you need to comment out any old directives attached to that previous setup.  I made that mistake the first time around.</p>
<p>Next you have to reinstall all the gems that you were using with old Ruby, including Rails:</p>
<blockquote><p>/opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem install rails --version 2.0.2</p></blockquote>
<p>Just to prove my point, if you listed all of Enterprise Ruby's gems at this point, the list would look something like this:</p>
<blockquote><p>$ /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem list</p>
<p>*** LOCAL GEMS ***</p>
<p>actionmailer (2.2.2, 2.0.2)<br />
actionpack (2.2.2, 2.0.2)<br />
activerecord (2.2.2, 2.0.2)<br />
activeresource (2.2.2, 2.0.2)<br />
activesupport (2.2.2, 2.0.2)<br />
fastthread (1.0.1)<br />
mysql (2.7)<br />
passenger (2.0.6)<br />
rack (0.9.1)<br />
rails (2.2.2, 2.0.2)<br />
rake (0.8.3)</p></blockquote>
<p>None of my old gems are installed.  Once Rails is installed, you need to reinstall your old gems:</p>
<blockquote><p>$ /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem install will_paginate<br />
$ /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem install xml-simple<br />
$ /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem install hpricot<br />
$ /opt/ruby-enterprise-1.8.6-20081215/bin/ruby /opt/ruby-enterprise-1.8.6-20081215/bin/gem install rmagick</p></blockquote>
<p>And on and on.  If you haven't used Passenger before, check out the <a href="http://www.modrails.com/documentation/Users%20guide.html#_deploying_a_ruby_on_rails_application">Deployment Guide</a>.  If you have used Passenger and your Rails apps are already set up in Apache to take advantage of it's deployment procedures, simply restart Apache.</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/' rel='bookmark' title='Permanent Link: Ruby On Rails and SliceHost Part 1: Initial Setup'>Ruby On Rails and SliceHost Part 1: Initial Setup</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/07/31/twitter-and-sd-news/' rel='bookmark' title='Permanent Link: Twitter and SD News'>Twitter and SD News</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Ruby On Rails and SliceHost Part 1: Initial Setup</title>
		<link>http://blog.perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/</link>
		<comments>http://blog.perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/#comments</comments>
		<pubDate>Mon, 04 Feb 2008 20:42:54 +0000</pubDate>
		<dc:creator>Eric</dc:creator>
				<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[centos]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[slicehost]]></category>

		<guid isPermaLink="false">http://perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/</guid>
		<description><![CDATA[I recently purchased a VPS from SliceHost.com. After ruling out a shared host and deciding on a VPS setup, SliceHost seemed to offer the most for my money. My initial setup is the 256slice, which offers 256mb RAM, 10GB of storage, and 100GB of bandwidth for $20 a month. Being able to build my own [...]


Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/' rel='bookmark' title='Permanent Link: Installing Ruby Enterprise Edition with Phusion Passenger'>Installing Ruby Enterprise Edition with Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/11/15/setup-python-2-6-4-mod_wsgi-2-6-and-django-1-1-1-on-centos-5-3-cpanel/' rel='bookmark' title='Permanent Link: Setup Python 2.6.4, mod_wsgi 2.6, and Django 1.1.1 on CentOS 5.3 (cPanel)'>Setup Python 2.6.4, mod_wsgi 2.6, and Django 1.1.1 on CentOS 5.3 (cPanel)</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>I recently purchased a VPS from <a href="http://www.slicehost.com">SliceHost.com</a>. After ruling out a shared host and deciding on a VPS setup, SliceHost seemed to offer the most for my money.   My initial setup is the 256slice, which offers 256mb RAM, 10GB of storage, and 100GB of bandwidth for $20 a month.  Being able to build my own stack from scratch is very appealing, especially as most of my side projects are written in <a href="http://www.rubyonrails.org/">Rails</a>.  My goal was to have <a href="http://httpd.apache.org/">Apache 2.2</a> as a front-end server, proxying requests to <a href="http://mongrel.rubyforge.org/">mongrel</a> or a <a href="http://mongrel.rubyforge.org/docs/mongrel_cluster.html">cluster of mongrels</a>, with <a href="http://dev.mysql.com/downloads/mysql/5.0.html">MySQL 5.0</a> as the database.  Of course I also wanted to have <a href="http://www.ruby-lang.org/en/downloads/">Ruby 1.8.6</a> and Rails 2.0.2.  Another useful, though optional, tool is <a href="http://www.phpmyadmin.net/home_page/index.php">phpMyAdmin</a>.  I am also using <a href="http://www.centos.org/">CentOS 5.0</a>, first because of my familiarity with it and second because it's well documented and supported.  The following is the first of a multipart tutorial about how I set this all up.  In future installments I will detail how to secure and optimize each installation as well as enable Apache proxying and mongrel clustering.</p>
<p><strong>Change the default root password</strong></p>
<blockquote><p>&gt;passwd</p></blockquote>
<p><strong>Update all yum packages</strong></p>
<blockquote><p>&gt;yum update</p></blockquote>
<p><strong>Bring in some standard packages</strong></p>
<blockquote><p>&gt;yum install wget openssl-devel lynx zlib zlib-devel vixie-cron curl lynx subversion make gcc automake</p></blockquote>
<p><strong>Install Apache</strong></p>
<blockquote><p>&gt;yum install httpd</p></blockquote>
<p><strong>Setup your domain records</strong><br />
<a href="http://articles.slicehost.com/2007/10/24/creating-dns-records"> http://articles.slicehost.com/2007/10/24/creating-dns-records</a></p>
<p><strong>Create your VirtualHosts in Apache's httpd.conf</strong><br />
<a href="http://httpd.apache.org/docs/2.2/vhosts"> http://httpd.apache.org/docs/2.2/vhosts</a><br />
Note: Apache's conf directory will be /etc/httpd/conf.  Don't forget to restart Apache after setting up each new vhost:</p>
<blockquote><p>&gt;service httpd restart</p></blockquote>
<p>See <a href="http://mongrel.rubyforge.org/docs/apache.html">http://mongrel.rubyforge.org/docs/apache.html</a> for details on how to get Apache and mongrel to play with each other.</p>
<p><strong>Start Apache</strong></p>
<blockquote><p>&gt;httpd service start</p></blockquote>
<p><strong>Install MySQL</strong></p>
<blockquote><p>&gt;yum install mysql mysql-server</p></blockquote>
<p>See <a href="http://dev.mysql.com/doc/">http://dev.mysql.com/doc/</a> for post-installation instructions (setting up initial accounts, etc.)</p>
<p><strong>Install Ruby (1.8.6)</strong></p>
<blockquote><p>&gt;wget ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6-p111.tar.gz<br />
&gt;gzip -d ruby-1.8.6-p111.tar.gz<br />
&gt;tar xvf ruby-1.8.6-p111.tar.gz<br />
&gt;cd ruby-1.8.6-p111.tar.gz<br />
&gt;./configure<br />
&gt;make<br />
&gt;make install</p></blockquote>
<p><strong>Install Ruby Gems (1.0.1)</strong></p>
<blockquote><p>&gt;wget http://rubyforge.org/frs/download.php/29548/rubygems-1.0.1.tgz<br />
&gt;tar xvf rubygems-1.0.1.tgz<br />
&gt;cd rubygems-1.0.1.tgz<br />
&gt;ruby setup.rb</p></blockquote>
<p><strong>Install Rails (2.0.2)</strong></p>
<blockquote><p>&gt;gem install rails --include-dependencies</p></blockquote>
<p><strong>Install Mongrel</strong></p>
<blockquote><p>&gt;gem install mongrel</p></blockquote>
<p><strong>Optional for phpMyAdmin<br />
Install php</strong></p>
<blockquote><p>&gt;yum install php</p></blockquote>
<p><strong>Install php extensions necessary for phpMyAdmin</strong></p>
<blockquote><p>&gt;yum install php-mcrypt<br />
&gt;yum install php-mbstring</p></blockquote>
<p><strong>I</strong><strong>nstall phpmyadmin</strong><br />
<a href="http://www.phpmyadmin.net/documentation/#setup">http://www.phpmyadmin.net/documentation/#setup</a></p>
<p>Any comments or feedback is appreciated.</p>


<p>Related posts:<ol><li><a href='http://blog.perplexedlabs.com/2009/01/13/installing-ruby-enterprise-edition-with-phusion-passenger/' rel='bookmark' title='Permanent Link: Installing Ruby Enterprise Edition with Phusion Passenger'>Installing Ruby Enterprise Edition with Phusion Passenger</a></li>
<li><a href='http://blog.perplexedlabs.com/2009/11/15/setup-python-2-6-4-mod_wsgi-2-6-and-django-1-1-1-on-centos-5-3-cpanel/' rel='bookmark' title='Permanent Link: Setup Python 2.6.4, mod_wsgi 2.6, and Django 1.1.1 on CentOS 5.3 (cPanel)'>Setup Python 2.6.4, mod_wsgi 2.6, and Django 1.1.1 on CentOS 5.3 (cPanel)</a></li>
<li><a href='http://blog.perplexedlabs.com/2010/02/08/deployment-using-capistrano-and-webistrano-via-rails-and-phusion-passenger/' rel='bookmark' title='Permanent Link: Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger'>Deployment Using Capistrano / Webistrano via Rails / Phusion Passenger</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.perplexedlabs.com/2008/02/04/building-a-rails-capable-slice-from-scratch/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
