<?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>Daddy Fixes Everything &#187; Rails</title>
	<atom:link href="http://blog.spoolz.com/category/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.spoolz.com</link>
	<description>A father and programmer&#039;s skewed view of the world</description>
	<lastBuildDate>Sun, 26 Apr 2009 03:29:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Apache Virtual Hosts, Rails, Rack, Passenger on Local Net</title>
		<link>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/</link>
		<comments>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/#comments</comments>
		<pubDate>Thu, 12 Mar 2009 19:51:03 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[sinatra]]></category>
		<category><![CDATA[virtual host]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=143</guid>
		<description><![CDATA[This one has been bugging me for a couple of years and I just didn&#8217;t want to put in the time and testing to nail it down. But tonight was my night.
The Problem
Here in my development palace I have a couple of laptops that I use for development and an Ubuntu (hardy) server as a [...]]]></description>
			<content:encoded><![CDATA[<p>This one has been bugging me for a couple of years and I just didn&#8217;t want to put in the time and testing to nail it down. But tonight was my night.</p>
<h3>The Problem</h3>
<p>Here in my development palace I have a couple of laptops that I use for development and an Ubuntu (hardy) server as a <a href="http://rubyonrails.org/">Rails</a>/<a href="http://rack.rubyforge.org/">Rack</a> sandbox that I run with <a href="http://modrails.com">Passenger</a>. While I have always been able to serve up either a Rails or <a href="http://www.sinatrarb.com/">Sinatra</a> project, I typically have 3 or 4 going at the same time. But I had to access them with urls like: <em>http://192.168.0.2/project1</em> and <em>http://192.168.0.2/project2</em>.</p>
<p>So, what&#8217;s the problem, eh?</p>
<p>Well, for starters, you can&#8217;t do anything concerning subdomains. That&#8217;s a show stopper for many apps.</p>
<p>Second, it really messes with your environment variables like <em>["PATH_INFO"]</em>. So if you do any routing and you expect the base url to be <em>&#8216;/&#8217;</em>, it won&#8217;t be. The root url will be &#8216;/projectx&#8217;. Bummer.</p>
<h3>The Solution</h3>
<p>To remedy the issues with non-<a href="http://en.wikipedia.org/wiki/Top-level_domain">tld</a> virtual hosts (also called sub URIs?) we need to add the domains to the laptops and server, then add the virtualhosts on the server for apache. This means that I can now goto <em>http://project1.ubuntu.remote</em> url to get to my rails/rack app.</p>
<p>For reference, I am using the following:</p>
<ul>
<li>Laptops: Mac OS X, 10.5.7 and 10.4.11</li>
<li>Server: <a href="http://www.ubuntu.com/">Ubuntu</a> Desktop 8.04LTS, <a href="http://www.apache.org/">Apache</a>/2.2.8 (Ubuntu) <a href="http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html">mod_fastcgi</a>/2.4.6 PHP/5.2.4-2ubuntu5.5 with <a href="http://modrails.com">Suhosin-Patch Phusion_Passenger/2.0.6</a></li>
</ul>
<h4>On Each Laptop</h4>
<p>These instructions are for Mac OS X, but should be identical for your favorite flavor of *nix. We are going to add some friendly names to our ubuntu server using it&#8217;s ip address (192.168.0.2). In this example we will be able to access the root web documents using <em>http://ubuntu.remote</em>, and one of our Sinatra projects using <em>http://project1.ubuntu.remote</em>.</p>
<p><strong>Important!</strong> Don&#8217;t use a name ending in <em>&#8216;.local&#8217;</em>. While it did work for me, I read about a few instances where some systems will not resolve domain names ending in .local outside the local machine. Also, don&#8217;t change <strong>anything</strong> else in your /etc/hosts file except to add the lines at the end.</p>
<pre class="brush: python">
mate /etc/hosts

# add the following line to the END of your /etc/hosts file and save
# note: there is a &lt;space&gt; character between the ip address and each host name
192.168.0.2 ubuntu.remote project1.ubuntu.remote
</pre>
<h4>On The Server: Hosts File</h4>
<p>Nothing will work until we tell the server machine that it can accept incoming traffic from our new friendly names. Similar to on the mac, we need to edit our /etc/hosts file but we will add a slightly different line. In this case we are telling the server that incoming traffic from &#8216;ubuntu.remote&#8217; and &#8216;gems.ubuntu.remote&#8217; are just names for the localhost (127.0.0.1).</p>
<pre class="brush: shell">sudo pico /etc/hosts

# add the following line to the end of our /etc/hosts file and save
# you can added after your existing 127.0.0.1 line if you wish
127.0.0.1 ubuntu.remote project1.ubuntu.remote
</pre>
<h4>On The Server: VirtualHosts</h4>
<p>As a final step we will need to add or change the virtual host definitions for your rails/rack project. Depending on your Apache setup or Linux distro, the default enabled site may be slightly different and you may have to adapt your virtual host file to your default setup.</p>
<p>First, in my /etc/apache2/apache.conf file, I have the following line near the end of the file. This was to eliminate a warning every time apache was started/restarted. It may affect your virtual host default, but shouldn&#8217;t, so add it if you get errors.</p>
<pre class="brush: shell">
#added near end of /etc/apache2/apache.conf
ServerName localhost
</pre>
<p>Next we need to check our default virtual host setup to see how the NameVirtualHost is defined. We will duplicate that in each new virtual host that we add. The parts we are looking is the NameVirtualHost and VirtualHost near the top. They could be &#8216;NameVirtualHost *&#8217; and &#8216;&lt;VirtualHost *&gt;&#8217; or &#8216;NameVirtualHost *:80&#8242; and &#8216;&lt;VirtualHost *:80&gt;&#8217;. See the pattern? We need to use the same definition in our new virtual files.</p>
<p>Let&#8217;s check our default virtual host setup:</p>
<pre class="brush: shell">
cd /etc/apache2/sites-enabled
ls # your are looking for the name of your default site file

  total 0

  lrwxrwxrwx 1 root root 36 2009-02-27 18:49 000-default -&gt; /etc/apache2/sites-available/default

cat /etc/apache2/sites-enabled/000-default

  NameVirtualHost *
  &lt;VirtualHost *&gt;
    ServerAdmin webmaster@localhost
  # snipped several lines #
  &lt;/VirtualHost&gt;
</pre>
<p>On my system the NameVirtualHost is &#8216;*&#8217;, so that is what we need to use for the new virtual host. In this case, I am going to add a virtual host file for a rack based project. It&#8217;s a Sinatra app, but that doesn&#8217;t matter as this will work for any rack based project, even a rails/rack project (since rails 2.2.2?).</p>
<p>Also, I like using the Apache2 system to enable and disable sites. It&#8217;s clean, easy to use, and if any apache admin comes along they will know exactly what is going on.</p>
<p>It&#8217;s also work mentioning that you should disable or delete any existing virtual host files that you were using previously.</p>
<pre class="brush: shell">cd /etc/apache2/sites-available
sudo pico gems

# enter this as your virtual host setup
&lt;VirtualHost *&gt;
  ServerName project1.ubuntu.remote

  DocumentRoot &quot;/path/to/your/application/project/public&quot;

  RackEnv production
  &lt;directory &quot;/path/to/your/application/project/public&quot;&gt;
    Order allow,deny
    Allow from all
  &lt;/directory&gt;
&lt;/VirtualHost&gt;

# save the file and reload apache

sudo /etc/init.d/apache2 reload
</pre>
<h4>The Fun Part</h4>
<p>Assuming you saw no errors when you reloaded apache, you should be able to go to your new urls see both the root files and your rack application.</p>
<p>http://ubuntu.remote</p>
<p>http://project1.ubuntu.remote</p>
<p><strong>Dyn-O-Mite!</strong></p>
<h3>Bonus Points!</h3>
<p>For extra credit, let&#8217;s say you have admin access to your router, and you are one of those gotta-have-control-of-everything dudes (or dudettes) so you installed a 3rd party firmware. You&#8217;re in luck! You can probably add some custom entries in your DNS and you don&#8217;t have to edit the /etc/hosts files on your laptop.</p>
<p>I installed <a href="http://www.polarcloud.com/tomato/">Tomato firmware</a> on my Linksys wireless router. Tomato uses <a href="http://localhost:9292/doc_root/actionmailer-1.3.6/rdoc/index.html">Dnsmasq</a> with allows you to set internal host names.</p>
<p>Maybe I&#8217;ll cover that in another post.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2009/03/12/apache-virtual-hosts-rails-rack-passenger-on-local-net/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Authlogic &#8211; Rails Authentication Done Right</title>
		<link>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/</link>
		<comments>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 21:56:24 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[authentication]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=119</guid>
		<description><![CDATA[Sorry to borrow the title line directly from Ben&#8217;s site, but Authlogic is the authentication system I have been looking for. Bye, bye restful authentication. Hello easy, simple, get out of my way, easily upgradeable, smartly written Authlogic.
I shouldn&#8217;t disrespect restful authentication much as she has been with me for over a year now. But [...]]]></description>
			<content:encoded><![CDATA[<p>Sorry to borrow the title line directly from Ben&#8217;s site, but <a href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Authlogic</a> is the authentication system I have been looking for. Bye, bye restful authentication. Hello easy, simple, get out of my way, easily upgradeable, smartly written Authlogic.</p>
<p>I shouldn&#8217;t disrespect restful authentication much as she has been with me for over a year now. But every time I had to install, setup, and get the basics working in RA I couldn&#8217;t help gnashing my teeth. I jumped on the RA bandwagon like so many other Rails developers looking for an authentication system that just and move on to more important things.</p>
<p>Enter Authlogic by Ben Johnson of <a href="http://www.binarylogic.com/">BinaryLogic</a>. By luck, I was starting a new rails app this week, so I decided to take Authlogic out for a test drive. Following Ben&#8217;s <a title="Tutorial: Authlogic Basic Setup" href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Tutorial: Authlogic Basic Setup</a> I had a basic login/logout/session management system up and running in a ridiculously little amount of code. The best part of Authlogic is that it truly get&#8217;s out of my way and provides me with what I need&#8230; a robust and secure methodology of authentication and session management.</p>
<p>The benefits of Authlogic are:</p>
<ul>
<li>It&#8217;s a plugin and a gem. When Ben pushes an update, getting the latest release is super simple.</li>
<li>It&#8217;s a plugin and a gem. This keeps the authentication code separate from your codes, the way it should be.</li>
<li>Session are treated like ActiveRecord objects. This is just as cools as it sounds and is very Rails-like.</li>
<li>Better security. Authlogic uses a non-reversible token that is changed on every session initiation and password change, thus virtually eliminating session persistence and brute force session attacks.</li>
<li>Ben Johnson. Ben knows what he is doing and has been quickly releasing updates.</li>
<li>Ben Johnson. Sorry for the repetition, but Ben also has a nice series of tutorials with supporting project code you can download.
<ul>
<li><a title="Tutorial: Reset passwords with Authlogic the RESTful way" href="http://www.binarylogic.com/2008/11/16/tutorial-reset-passwords-with-authlogic">Tutorial: Reset passwords with Authlogic the RESTful way</a></li>
<li><a title="Tutorial: Authlogic Basic Setup" href="http://www.binarylogic.com/2008/11/3/tutorial-authlogic-basic-setup">Tutorial: Authlogic Basic Setup</a></li>
</ul>
</li>
</ul>
<div>Read more on on <a href="http://www.binarylogic.com/2008/10/25/authlogic-released-rails-authentication-done-right">BinaryLogic</a> or get it at <a href="http://github.com/binarylogic/authlogic/tree/master">Github</a>.</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/11/20/authlogic-rails-authentication-done-right/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Butt Biter: Rails &#8216;truncate&#8217; Method Broken in Ruby 1.8.7</title>
		<link>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/</link>
		<comments>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 04:01:48 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[butt biter]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=38</guid>
		<description><![CDATA[This one threw me for far too many minutes. In ActionView::Helpers::TextHelper the truncate method is broken for Ruby 1.8.7. I&#8217;m not exactly sure the version of ruby that it stopped working for, but I was previously on 1.8.6, and I don&#8217;t recall it not working. But after I upgraded to the latest patchlevel of 1.8.7, truncate [...]]]></description>
			<content:encoded><![CDATA[<p>This one threw me for far too many minutes. In <a href="http://www.railsbrain.com/api/rails-2.1.0/doc/index.html?a=C00000713&amp;name=TextHelper">ActionView::Helpers::TextHelper</a> the <a href="http://www.railsbrain.com/api/rails-2.1.0/doc/index.html?a=M002044&amp;name=truncate">truncate</a> method is broken for Ruby 1.8.7. I&#8217;m not exactly sure the version of ruby that it stopped working for, but I was previously on 1.8.6, and I don&#8217;t recall it not working. But after I upgraded to the latest patchlevel of 1.8.7, truncate stopped working.</p>
<h3><span style="color: #800000;">Update 12/2/08: Fixed in Rails 2.2! (<a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/867">read more</a>)</span></h3>
<p>The error that I received was thus:</p>
<p><code>ActionView::TemplateError (undefined method `length' for #) on line #83 of dashboard/index.html.erb:<br />
</code></p>
<p>Fortunately, someone has submitted a <a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/867">ticket to Rails core</a>. I hope it&#8217;s applied in the Rails 2.2.0 release.</p>
<p><span id="more-38"></span></p>
<h3>Current Method, Done Busted</h3>
<p>As of Rails 2.1.0, this is the current method (Rails 2.0.2 is similar, and also broken).</p>
<pre class="brush: ruby">&lt;br /&gt;
# File actionpack/lib/action_view/helpers/text_helper.rb, line 49&lt;br /&gt;
def truncate(text, length = 30, truncate_string = &quot;...&quot;)&lt;br /&gt;
if text&lt;br /&gt;
l = length - truncate_string.chars.length&lt;br /&gt;
chars = text.chars&lt;br /&gt;
(chars.length &gt; length ? chars[0...l] + truncate_string : text).to_s&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
</pre>
<p>The problem is that <em>chars</em> method called on the string object (<em>truncate_string</em>) returns an &lt;Enumerable::Enumerator&gt; object. And according to the Ruby 1.8.7 RDoc, there is no &#8216;length&#8217; method in Enumerable::Enumerator. To be honest, I can&#8217;t find the &#8216;chars&#8217; method in any of the Ruby <a href="http://www.ruby-doc.org/core/">1.8.6 docs</a> or <a href="http://www.ruby-doc.org/core-1.8.7/index.html">1.8.7 docs</a>. I guessing that it may have been Rails method at some time.</p>
<h3>Fix #1</h3>
<p>The fix is to get rid of all the <em>chars</em> methods. On the bug ticket, the author gives his fix, but you are going to have to monkey-patch rails, or change the method name.</p>
<pre class="brush: ruby">&lt;br /&gt;
def truncate(text, length = 30, truncate_string = &quot;...&quot;)&lt;br /&gt;
if text&lt;br /&gt;
l = length - truncate_string.chars.to_a.length&lt;br /&gt;
chars = text.chars&lt;br /&gt;
(chars.to_a.length &gt; length ? chars.to_a[0...l].to_s + truncate_string : text).to_s&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
</pre>
<h3>Fix #2 (mine, tiny bit better?)</h3>
<p>I&#8217;m not exactly sure why the string needs to be converted to an array, when the <a href="http://www.ruby-doc.org/core/classes/String.html#M000789">length</a> function works just dandy on string objects. So I added this to my <em>application_helper.rb</em> file. Also, in the submitted patch, the result of the ternary is converted to a string (.to_s), when all the resulting methods of the ternary return strings. Unnecessary IMHO and probably left over from when the string object was converted to an enumerable. Note that I started with the Rail 2.0.1 version, so it&#8217;s slightly different than if I started with the 2.1.0 version.</p>
<pre class="brush: ruby">&lt;br /&gt;
def truncate_string(text, length = 30, truncate_string = &#039;...&#039;)&lt;br /&gt;
if text.nil? then return end&lt;br /&gt;
l = length - truncate_string.length&lt;br /&gt;
text.length &gt; length ? text[0...l] + truncate_string : text&lt;br /&gt;
end&lt;br /&gt;
</pre>
<p>Yeah, yeah, I could have monkey-patched the TextHelper module, but why tempt fate if you don&#8217;t have to. A quick find/replace on &#8216;truncate&#8217; to &#8216;truncate_string&#8217; is all that was necessary. Works for me.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/09/02/butt-biter-rails-truncate-method-broken-in-ruby-187/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails Ubuntu Server VM with VMPlayer</title>
		<link>http://blog.spoolz.com/2008/07/30/ruby-on-rails-ubuntu-server-vm-with-vmplayer/</link>
		<comments>http://blog.spoolz.com/2008/07/30/ruby-on-rails-ubuntu-server-vm-with-vmplayer/#comments</comments>
		<pubDate>Wed, 30 Jul 2008 23:15:41 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[vm]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=21</guid>
		<description><![CDATA[I had to setup a Ubuntu (8.04) Server virtual machine and get Rails up-to-speed on it this morning, so I thought I would document my steps for those who find the need to repeat. Here is what I needed:

A production server, not a development server, with only what is necessary
A virtual machine that runs under [...]]]></description>
			<content:encoded><![CDATA[<p>I had to setup a Ubuntu (8.04) Server virtual machine and get Rails up-to-speed on it this morning, so I thought I would document my steps for those who find the need to repeat. Here is what I needed:</p>
<ul>
<li>A production server, not a development server, with only what is necessary</li>
<li>A virtual machine that runs under <a href="http://www.vmware.com/download/player/">VMware Player</a></li>
<li><a href="http://www.ubuntu.com/products/WhatIsUbuntu/serveredition">Ubuntu Server</a>, 8.04 is the current, referred to as Hardy Heron</li>
<li><a href="http://httpd.apache.org/">Apache2</a> with <a href="http://www.modrails.com">Phusion Passenger</a> to handle Rails applications</li>
<li><a href="http://www.ruby-lang.org/en/">Ruby</a>, <a href="http://rubyforge.org/projects/rubygems/">Rubygems</a>, <a href="http://www.rubyonrails.org/">Ruby on Rails</a>, a full Rails stack</li>
<li><a href="http://www.mysql.com/">MySQL Server</a> and <a href="http://www.sqlite.org/">SQLite</a>,  with <a href="http://www.phpmyadmin.net/">phpMyAdmin</a> to admin MySQL server</li>
<li>All native drivers for Rails (MySQL and SQLite)</li>
<li><a href="http://www.openssh.com/">OpenSSH</a> server to access the server</li>
<li><a href="http://www.postfix.org/">Postfix</a> to send (only) emails</li>
</ul>
<p>What you need to start:</p>
<p><span id="more-21"></span></p>
<ol>
<li>VMware Player installed. Download it from <a href="http://www.vmware.com/download/player/">VMware</a> directly and follow their instructions (aptitude has older version 1.x)</li>
<li><a href="http://www.ubuntu.com/getubuntu/download">Download the Ubuntu 8.04 Server ISO file</a> for your machine. For torrent users, <a href="http://releases.ubuntu.com/8.04/ubuntu-8.04.1-server-i386.iso.torrent">download the current i386 torrent file</a>.</li>
<li>Download my <a href="http://blog.spoolz.com/wp-content/uploads/2008/07/ubuntu840server.vmx">VMX</a> and <a href="http://blog.spoolz.com/wp-content/uploads/2008/07/ubuntu840servervmdk.zip">VMDK</a> files (vmplayer config and empty virtual disk).</li>
</ol>
<h3>Step 1: Setup Directory and Config File</h3>
<p>Create a new directory somwhere (I called mine &#8216;Ubuntu840Server&#8217;) and copy the Ubuntu ISO file and the VMX and VMDK (don&#8217;t forget to unzip) files into it. You will need to do some quick editing to the Ubuntu840Server.vmx file, so fire up your favorite editor (in Ubuntu Desktop, right-click and Open with &#8220;Text Editor&#8221;). The only sections you may need to edit are:</p>
<ul>
<li><em>ide1:1.filename</em>, make sure it matches the name of your ISO file, something like &#8220;ubuntu-8.04.1-serverr-i386.iso&#8221;</li>
<li><em>fileSearchPath</em>, change to the path of the directory you created</li>
</ul>
<h3>Step 2: Run VMWare Player</h3>
<p>Run VMware Player and open the Ubuntu840Server.vmx. If all the config settings are correct and the ISO files is in the directory, you should boot into Ubuntu Installer.</p>
<h3>Step 3: Install Ubuntu Server</h3>
<p>I won&#8217;t go into details here because Ubuntu has <a href="https://help.ubuntu.com/8.04/serverguide/C/index.html">step-by-step instructions on how to install</a>. But the short story is: <em>accept the defaults</em>.</p>
<p>There is one selection that will make installation easier, select LAMP Server when asked for the Software selection. <a href="http://en.wikipedia.org/wiki/LAMP_%28software_bundle%29">LAMP</a> stands for Linux/Apache/MySQL/PHP. It will install all those packages and configure them automatically for you.</p>
<p><a href="http://blog.spoolz.com/wp-content/uploads/2008/07/picture-1.png"><img class="alignnone size-medium wp-image-22" title="picture-1" src="http://blog.spoolz.com/wp-content/uploads/2008/07/picture-1-300x151.png" alt="" width="300" height="151" /></a></p>
<p>Note: even though I selected a LAMP server, for some reason it did not install Apache/Mysql/PHP. If this happens to you, just do the following after the server re-boots:</p>
<p><code>sudo apt-get install apache mysql-server php5 libapache2-mod-php5 php5-mysql<br />
</code></p>
<h3>Step 4: Get the Latest Updates</h3>
<p>If everything went well, you should reboot into Ubuntu Server and see the <em>login:</em> prompt. Go ahead and login with the username and password you supplied during the installation. Make sure you have the latest updates for Ubuntu by running (this may take a while):</p>
<p><code>sudo apt-get update<br />
sudo apt-get upgrade<br />
</code></p>
<h3>Step 5: Install OpenSSH</h3>
<p>I like to administer my VMs from the terminal via SSH. Ubuntu Server does not come preconfigured with an SSH server, so lets install one:</p>
<p><code>sudo apt-get install openssh-client<br />
sudo apt-get install openssh-server<br />
</code></p>
<p>You don&#8217;t really need the openssh-client, but I like to have it in case I ever need to ssh from the server to somewhere else. I can&#8217;t recommend enough that you secure your SSH server. If you server is exposed to the internet, <strong>it will be attacked</strong>, and one of the favorite vulnerabilities is SSH. Read this article on <a href="http://www.supportsmb.com/2007/02/20/how-to-secure-openssh/">how to Secure an OpenSSH Server</a>!</p>
<h3>Step 6: Install phpMyAdmin</h3>
<p>Since we are using MySQL, having a graphic administration program is nice and it&#8217;s hard to beat phpMyAdmin. I installed it from aptitude, but it did not set the proper aliases for apache2, so there are a few extra steps:</p>
<p><code>sudo apt-get install phpmyadmin</p>
<p># create a site file for apache2<br />
sudo pico /etc/apache2/sites-available/phpmyadmin</p>
<p># enter the following in pico<br />
Alias /phpmyadmin/ "/usr/share/phpmyadmin/"<br />
Alias /phpmyadmin "/usr/share/phpmyadmin/"<br />
&lt;Directory "/usr/share/phpmyadmin/" &gt;<br />
  Options Indexes FollowSymLinks MultiViews<br />
  AllowOverride None<br />
  Order allow,deny<br />
  Allow from all<br />
  Deny from none<br />
&lt;/Directory&gt;</p>
<p># close and save pico, then enter this to enable the phpmyadmin site<br />
sudo a2ensite phpmyadmin<br />
sudo /etc/init.d/apache2 restart<br />
</code></p>
<h3>Step 7: Install Ruby</h3>
<p>Next we need to install ruby. We&#8217;ll use the aptitude pre-built binaries to save time and make it easier to update in the future, but you may wish to install it from source. We also install the sqlite3 database because it is the default used by Rails 2.X and many test packages, but you can omit if you want.</p>
<p><code>sudo aptitude install ruby1.8-dev ruby1.8 ri1.8 rdoc1.8 irb1.8 libreadline-ruby1.8 libruby1.8 libopenssl-ruby sqlite3 libsqlite3-ruby1.8 build-essential mysql-client libmysqlclient15-dev postfix<br />
</code></p>
<p>Note that we installed the &#8216;build-essential&#8217; package. This package is necessary for you to install any other software from source (like native msql drivers and phusion passenger). We also install the postfix package, you can just accept the defaults.</p>
<p>Next you will need to set some symlinks so that the libraries will be located when needed.</p>
<p><code>sudo ln -s /usr/bin/ruby1.8 /usr/bin/ruby<br />
sudo ln -s /usr/bin/ri1.8 /usr/bin/ri<br />
sudo ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc<br />
sudo ln -s /usr/bin/irb1.8 /usr/bin/irb<br />
</code></p>
<p>Now, when you should see your ruby package when you check the version from the terminal.</p>
<p><code>karl@ubuntuserver:~$ ruby -v<br />
ruby 1.8.6 (2007-09-24 patchlevel 111) [i486-linux]<br />
</code></p>
<h3>Step 8: Install RubyGems</h3>
<p>RubyGems is a package manager like aptitude that makes is trivial to add/update/delete resources that ruby (and Rails) will need. It&#8217;s also how you will install and update Rails. We are going to install RubyGems from source as the aptitude package is quite out-of-date. RubyGems is a self-updating application, and when installed from aptitude, aptitude will complain and you may accidentally downgrade RubyGems.</p>
<p><code># create a sources directory in your home<br />
mkdir ~/sources<br />
cd ~/sources</p>
<p>#download gem package, see <a href="http://rubyforge.org/projects/rubygems/">rubygems homepage</a> for the latest<br />
wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz</p>
<p># decompress the files and setup rubygems<br />
tar xzvf rubygems-1.2.0.tgz<br />
cd  rubygems-1.2.0<br />
sudo ruby setup.rb</p>
<p># add a symlink<br />
sudo ln -s /usr/bin/gem1.8 /usr/bin/gem</p>
<p>#update rubygems<br />
sudo gem update --system<br />
sudo gem update<br />
</code></p>
<h3>Step 9: Install Ruby on Rails</h3>
<p>All this work, and we are finally here. Too bad installing Rails is so easy. Just this one line.</p>
<p><code>sudo gem install rails </code><br />
and a couple more gems you will probably need&#8230;<br />
<code># install the native (faster) mysql driver<br />
sudo gem install mysql</p>
<p># if you want native (faster) sqlite3 drivers, for production<br />
sudo apt-get install libsqlite3-dev<br />
sudo gem install sqlite3-ruby</code></p>
<p>You can install any more gems you may need at this time with &#8217;sudo gem install <em>package-name</em>&#8216;, but if you are using rails 2.1 or greater, you can now add rubygem requirements to your <em>environment.rb</em> file and use rake to automatically installed gem dependencies.</p>
<h3>Step 10: Install Phusion Passenger</h3>
<p>There are many ways to host a Rails application, but at this time, <a href="http://www.modrails.com">Phusion Passenger</a> gets the nod for the easiest to deploy and our experience has been rock-solid in reliability. These install steps are from the <a href="http://modrails.com/install.html">Passenger website installation instructions</a>:</p>
<p><code>sudo gem install passenger<br />
sudo apt-get install apache2-prefork-dev<br />
sudo passenger-install-apache2-module<br />
# and follow the instructions</p>
<p># after phusion installs, you will see instructions to edit your Apache configuration file<br />
#  to add lines to the end of the file<br />
sudo pico /etc/apache2/apache2.conf</p>
<p># add the lines given in the installation screen, because they can be different for each machine, I can't post the instructions here</p>
<p># restart apache webserver<br />
sudo /etc/init.d/apache2 restart<br />
</code></p>
<p>You will also be given a sample virtual host file to setup your Rails application. At this point you can copy an existing Rails app over to the new server, or follow along for a quick setup of a new Rails app.</p>
<h3>Step 11: Create a Rails Application (optional)</h3>
<p>We are going to create a very quick Rails application to test that our installation is working.</p>
<p><code>cd ~/<br />
rails tester<br />
script/generate scaffold Blog name:string content:text<br />
rake db:migrate RAILS_ENV=production</p>
<p># setup apache<br />
sudo a2dissite default  # we don't need this anymore<br />
sudo pico /etc/apache2/sites-available/tester</p>
<p>#enter the following in pico<br />
&lt;VirtualHost *:80&gt;<br />
  ServerName localhost<br />
  DocumentRoot /home/user_name/tester/public<br />
&lt;/VirtualHost&gt;</p>
<p># activate this site<br />
sudo a2ensite tester<br />
sudo /etc/init.d/apache2 restart<br />
</code></p>
<p>Now you can visit your site by going to http://address_of_server/ and you should see your rails application!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/07/30/ruby-on-rails-ubuntu-server-vm-with-vmplayer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>[UPDATE] Capistrano Deploy for Shared Hosting with GIT Repository</title>
		<link>http://blog.spoolz.com/2008/05/28/update-capistrano-deploy-for-shared-hosting-with-git-repository/</link>
		<comments>http://blog.spoolz.com/2008/05/28/update-capistrano-deploy-for-shared-hosting-with-git-repository/#comments</comments>
		<pubDate>Wed, 28 May 2008 17:47:16 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[rails capistrano]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=14</guid>
		<description><![CDATA[Like I said in my original post Capistrano Deploy for Shared Hosting with GIT Repository, I would add the ability to rotate log files and backup your database. Also added a couple of niceties while I was at it.

Updated for Capistrano 2.3
Added backup of mysql database to local machine
Added log rotation and backup to local machine
DRYed things up [...]]]></description>
			<content:encoded><![CDATA[<p>Like I said in my original post <a href="http://blog.spoolz.com/2008/04/30/capistrano-deploy-for-shared-hosting-with-git-repository/">Capistrano Deploy for Shared Hosting with GIT Repository</a>, I would add the ability to rotate log files and backup your database. Also added a couple of niceties while I was at it.</p>
<ul>
<li>Updated for <a href="http://weblog.jamisbuck.org/2008/5/2/capistrano-2-3-0">Capistrano 2.3</a></li>
<li>Added backup of mysql database to local machine</li>
<li>Added log rotation and backup to local machine</li>
<li>DRYed things up just a touch (delete_files, delete_directories)</li>
</ul>
<p>Just run a &#8216;cap -T&#8217; to see all the new functions.</p>
<pre class="brush: ruby">
cap -T
</pre>
<h3>CAP db:backup</h3>
<p>&#8216;cap db:backup&#8217; will execute a mysqldump, so obviously, this only works on mysql databases. But you could adapt that to any db fairly easily. It dumps the file and bzips it and then downloads it into a &#8216;/backups&#8217; directory in your project.</p>
<p><span id="more-14"></span></p>
<p>In addition, before you do any deploy function that executes a migration, the <em>db:backup</em> will be called first. Just a little safety net before you dive into the deep waters and potentially do something that could keep you awake at night.</p>
<h3>CAP log:rotate</h3>
<p>&#8216;cap log:rotate&#8217; will stop the server, bzip the production.log file, delete the production.log file and transfer the compressed file to your &#8216;/backups&#8217; directory in your project. It should be noted that there is a <em>slight</em> chance that someone could use the website in the fraction of a second it takes to bzip the log file and you would lose those log entries, or rails could throw an error because it could not find the &#8216;production.log&#8217; file that it thought exists. So my recommendation it to run the &#8216;cap log:rotate&#8217; at slow system usage times, or rewrite the task to completely disable the application before bzipping the log file.</p>
<h3>New /backups Directory</h3>
<p>Both the <em>log:rotate</em> and <em>db:backup</em> task will create a new &#8216;/backups&#8217; directory in your project. You will most certainly want to add &#8220;backups/**&#8221; to your .gitignore so that the dump files are not pulled into source control.</p>
<h3>For Capistrano 2.3</h3>
<p>Since my original post, Capistrano 2.3 has arrived. You can read all about it&#8217;s goodness <a href="http://weblog.jamisbuck.org/2008/5/2/capistrano-2-3-0">here</a>. One feature it allowed is the ability to ignore files and directory from source control. I added a &#8216;copy_exclude&#8217; to ignore all GIT files (.git directory, .gitignore file) instead of removing them from the deployed release after it&#8217;s copied to the server.</p>
<p>So if you have not upgraded to 2.3, you will need to comment out the &#8216;copy_exclude&#8217; line, and uncomment the &#8216;remove_git_directories&#8217; task.</p>
<pre class="brush: ruby">
ssh_options[:keys] = %w(~/.ssh/id_dsa ~/.ssh/id_rsa)

set :application, &quot;vbsfinder&quot;
set :repository,  &quot;git@192.168.0.2:vbsfinder.git&quot;
set :domain, &quot;vbsfinder.com&quot;

# user is the login name for the shared hosting account
# it should also be the name of your home directory i.e. /home/my-user-name
set :user, &quot;vbsfinde&quot;

# this will place you app outside your /public_html
# and protect your app file from exposure
set :deploy_to, &quot;/home/#{user}/#{application}&quot;

set :scm, :git
# set :deploy_via, :remote_cache  # if your server has direct access to the repository
set :deploy_via, :copy        # if you server does NOT have direct access to the repository (default)
set :git_shallow_clone, 1     # only copy the most recent, not the entire repository (default:1)
set :copy_exclude, [&quot;.git&quot;, &quot;.gitignore&quot;]

ssh_options[:paranoid] = false
set :use_sudo, false

set :keep_releases, 2  # only keep a current and one previous version to save space

role :app, domain
role :web, domain
role :db,  domain, :primary =&gt; true

task :update_public, :roles =&gt; [:app] do
  run &quot;chmod 755 #{release_path}/public&quot;
  run &quot;chmod 755 #{release_path}/public/dispatch.*&quot;
end

task :copy_system_stopped_files, :roles =&gt; [:app] do
  run &quot;cp -f #{release_path}/public/system_stopped/* #{shared_path}/system_stopped/&quot;
end

after &quot;deploy:update_code&quot;, :update_public
after &quot;deploy:update_code&quot;, :copy_system_stopped_files

# ****** Removed for Capistrano version &gt;= 2.3
# remove the .git directory and .gitignore from the current release
# task :remove_git_directories, :roles =&gt; [:app] do
#   delete_directories &quot;#{release_path}/.git&quot;
#   delete_files &quot;#{release_path}/.gitignore&quot;
# end
# this lets up keep the system_stopped files in project
# after &quot;deploy:update_code&quot;, :remove_git_directories

# create a symlink from the current/public to ~/public_html
task :create_public_html, :roles =&gt; [:app] do
  run &quot;ln -fs #{current_path}/public ~/public_html&quot;
end
after &quot;deploy:cold&quot;, :create_public_html

# create a directory in shared to hold files that will be served
# when the system is stopped, and a config directory
task :create_shared_directories, :roles =&gt; [:app] do
  run &quot;mkdir -p #{shared_path}/system_stopped&quot;
  run &quot;mkdir -p #{shared_path}/config&quot;
end
after &quot;deploy:setup&quot;, :create_shared_directories 

# remove the symlink for ~/public_html
task :remove_public_html, :roles =&gt; [:app] do
  delete_directories &quot;~/public_html&quot;
end

# creates a symlink to ~/public_html to the shared/system_stopped directory
# places files you want served in this dir for when the system is stopped
task :create_public_html_to_stopped, :roles =&gt; [:app] do
  run &quot;ln -fs #{shared_path}/system_stopped ~/public_html&quot;
end

# we need to override the default start/stop/restart functions
namespace :deploy do
  desc &quot;Restart the web server. Killing all FCGI processes.&quot;
  task :restart, :roles =&gt; :app do
    # for most hosts, all you need to do is stop all FCGI processing running
    run &quot;killall -q dispatch.fcgi&quot;
    # but some hosts can restart by touching the dispatch file
    #run &quot;chmod 755 #{current_path}/public/dispatch.fcgi&quot;
    #run &quot;touch #{current_path}/public/dispatch.fcgi&quot;
  end

  desc &quot;Start the web server. Really nothing to do for shared hosting.&quot;
  task :start, :roles =&gt; :app do
    remove_public_html
    create_public_html
    deploy.restart
  end

  desc &quot;Stop the web server and present maintenance page.&quot;
  task :stop, :roles =&gt; :app do
    remove_public_html
    create_public_html_to_stopped
  end

  namespace :web do
    desc &quot;Make application web accessible again.&quot;
    task :enable, :roles =&gt; [:app] do
      deploy.start
    end

    desc &quot;Present system maintenance page to users.&quot;
    task :disable, :roles =&gt; [:app] do
      deploy.stop
    end

  end
end

# a little help here from Brandon Keepers
# http://opensoul.org/2007/2/9/automatically-backing-up-your-remote-database-on-deploy
namespace :db do
  desc &quot;Backup the remote production database&quot;
  task :backup, :roles =&gt; :db, <img src='http://blog.spoolz.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> nly =&gt; { :primary =&gt; true } do
    require &#039;yaml&#039;

    filename = &quot;#{application}.dump.#{timestamp_string}.sql.bz2&quot;
    file = &quot;/tmp/#{filename}&quot;

    on_rollback { delete_files file }
    db = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), &#039;database.yml&#039;))).result)[&#039;production&#039;]

    run &quot;mysqldump -u #{db[&#039;username&#039;]} --password=#{db[&#039;password&#039;]} #{db[&#039;database&#039;]} | bzip2 -c &gt; #{file}&quot;  do |ch, stream, data|
      puts data
    end

    `mkdir -p #{File.dirname(__FILE__)}/../backups/`
    download file, &quot;backups/#{filename}&quot;
    delete_files file
  end
end

before &quot;deploy:migrate&quot;, &quot;db:backup&quot;
before &quot;deploy:migrations&quot;, &quot;db:backup&quot;

namespace :log do
  desc &quot;Compress and copy log file to local machine&quot;
  task :rotate, :roles =&gt; [:app] do
    logfiles = capture( &quot;ls -x #{shared_path}/log&quot; ).split

    if logfiles.index( &#039;production.log&#039; ).nil?
      logger.info &quot;production.log was not found, no rotation performed&quot;

    else
      filename = &quot;#{application}.production.log.#{timestamp_string}.log.bz2&quot;
      logfile = &quot;#{shared_path}/log/production.log&quot;

      deploy.restart # stop the server
      run &quot;bzip2 #{logfile}&quot; # bzips the production.log and removes it

      `mkdir -p #{File.dirname(__FILE__)}/../backups/`
      download &quot;#{logfile}.bz2&quot;, &quot;backups/#{filename}&quot;
      delete_files &quot;#{logfile}.bz2&quot;
    end
  end
end

def timestamp_string
  Time.now.strftime(&quot;%Y%m%d%H%M%S&quot;)
end

def delete_files(*args)
  run &quot;rm -f #{args.join(&#039; &#039;)}&quot;
end

def delete_directories(*args)
  run &quot;rm -rf #{args.join(&#039; &#039;)}&quot;
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/05/28/update-capistrano-deploy-for-shared-hosting-with-git-repository/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Butt Biter: Fix State Abbreviations &amp;&amp; Large Data Set Updates</title>
		<link>http://blog.spoolz.com/2008/05/13/butt-biter-fix-state-abbreviations-large-data-set-updates/</link>
		<comments>http://blog.spoolz.com/2008/05/13/butt-biter-fix-state-abbreviations-large-data-set-updates/#comments</comments>
		<pubDate>Tue, 13 May 2008 23:50:27 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[butt biter]]></category>
		<category><![CDATA[rake]]></category>
		<category><![CDATA[state]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=11</guid>
		<description><![CDATA[Ran into a little butt biter today&#8230; I imported a few thousand addresses that had the state in long form, like &#8216;Arizona&#8217;. But I commonly used the us_states plugin for popup selection of states. Well, us_states will be looking for state abbreviations, like &#8216;AZ&#8217; when it selects it&#8217;s selected value. So what&#8217;s a girl (or [...]]]></description>
			<content:encoded><![CDATA[<p>Ran into a little butt biter today&#8230; I imported a few thousand addresses that had the <em>state</em> in long form, like &#8216;Arizona&#8217;. But I commonly used the <a href="http://svn.techno-weenie.net/projects/plugins/us_states/">us_states</a> plugin for popup selection of states. Well, us_states will be looking for state abbreviations, like &#8216;AZ&#8217; when it selects it&#8217;s selected value. So what&#8217;s a girl (or dude) to do? You gotta convert them states!</p>
<p>But there are a few concerns:</p>
<ul>
<li>you need to iterate over a large set of records, maybe an entire table</li>
<li>there may be memory issues with loading such a large set</li>
</ul>
<p>The following rake task demonstrates a technique that is more memory efficient than loading the entire model/attributes (table/fields) into memory. Only load the &#8216;id&#8217; and &#8217;state&#8217; attributes when you need to find your initial record set. The &#8216;id&#8217; will be used to find the record for updating, and the state is need to find the new abbreviation.</p>
<p><span id="more-11"></span></p>
<pre class="brush: ruby">
#only load id and state attributes to save memory
Organization.find( :all, :select =&gt; &#039;id, state&#039; )

#load the entire attribute list, uses more memory
Organization.find(:all)
</pre>
<p>Organization.find(:all) just sucked up a ton of memory on my machine and slowed things down a bit. But if you only have a few hundred or a few thousand records in your table, you may not see much of a difference</p>
<p>There are some cons though. For every record that needs updating, there will be a query in addition to the update. That&#8217;s because the entire record&#8217;s attributes need to be loaded for update (at least mine did), so a find using the id along with the update is necessary. This technique really shines when you only need to change a minority of records.</p>
<p>You may not need to load additional attributes if no other attributes are called or modified in your model. In my case, I geocode each address, so the Organization model will need other fields during it&#8217;s execution both to read and to update. Though I could turn off the geocoding temporarily for this rake task and thus not need to load the rest of the attributes.</p>
<p>Save this in your /lib/tasks directory:</p>
<pre class="brush: ruby">
namespace :db do
  namespace <img src='http://blog.spoolz.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rgs do

    desc &quot;Convert states to two-letter abbr.&quot;
    task :convert_states =&gt; :environment do
      US_STATES = [[&quot;Alaska&quot;, &quot;AK&quot;],[&quot;Alabama&quot;, &quot;AL&quot;],[&quot;Arkansas&quot;, &quot;AR&quot;],[&quot;Arizona&quot;, &quot;AZ&quot;],[&quot;California&quot;, &quot;CA&quot;],[&quot;Colorado&quot;, &quot;CO&quot;],[&quot;Connecticut&quot;, &quot;CT&quot;],[&quot;District of Columbia&quot;, &quot;DC&quot;],[&quot;Delaware&quot;, &quot;DE&quot;],[&quot;Florida&quot;, &quot;FL&quot;],[&quot;Georgia&quot;, &quot;GA&quot;],[&quot;Hawaii&quot;, &quot;HI&quot;],[&quot;Iowa&quot;, &quot;IA&quot;],[&quot;Idaho&quot;, &quot;ID&quot;],[&quot;Illinois&quot;, &quot;IL&quot;],[&quot;Indiana&quot;, &quot;IN&quot;],[&quot;Kansas&quot;, &quot;KS&quot;],[&quot;Kentucky&quot;, &quot;KY&quot;],[&quot;Louisiana&quot;, &quot;LA&quot;],[&quot;Massachusetts&quot;, &quot;MA&quot;],[&quot;Maryland&quot;, &quot;MD&quot;],[&quot;Maine&quot;, &quot;ME&quot;],[&quot;Michigan&quot;, &quot;MI&quot;],[&quot;Minnesota&quot;, &quot;MN&quot;],[&quot;Missouri&quot;, &quot;MO&quot;],[&quot;Mississippi&quot;, &quot;MS&quot;],[&quot;Montana&quot;, &quot;MT&quot;],[&quot;North Carolina&quot;, &quot;NC&quot;],[&quot;North Dakota&quot;, &quot;ND&quot;],[&quot;Nebraska&quot;, &quot;NE&quot;],[&quot;New Hampshire&quot;, &quot;NH&quot;],[&quot;New Jersey&quot;, &quot;NJ&quot;],[&quot;New Mexico&quot;, &quot;NM&quot;],[&quot;Nevada&quot;, &quot;NV&quot;],[&quot;New York&quot;, &quot;NY&quot;],[&quot;Ohio&quot;, &quot;OH&quot;],[&quot;Oklahoma&quot;, &quot;OK&quot;],[&quot;Oregon&quot;, &quot;OR&quot;],[&quot;Pennsylvania&quot;, &quot;PA&quot;],[&quot;Rhode Island&quot;, &quot;RI&quot;],[&quot;South Carolina&quot;, &quot;SC&quot;],[&quot;South Dakota&quot;, &quot;SD&quot;],[&quot;Tennessee&quot;, &quot;TN&quot;],[&quot;Texas&quot;, &quot;TX&quot;],[&quot;Utah&quot;, &quot;UT&quot;],[&quot;Virginia&quot;, &quot;VA&quot;],[&quot;Vermont&quot;, &quot;VT&quot;],[&quot;Washington&quot;, &quot;WA&quot;],[&quot;Wisconsin&quot;, &quot;WI&quot;],[&quot;West Virginia&quot;, &quot;WV&quot;],[&quot;Wyoming&quot;, &quot;WY&quot;],[&quot;APO-Military&quot;, &quot;APO&quot;],[&quot;FPO-Military&quot;, &quot;FPO&quot;]]
      org_count = Organization.count
      cnt = 0
      Organization.transaction do
        Organization.find(:all, :select =&gt; &#039;id, state&#039;).each do |org|
          puts &quot;#{cnt += 1} of #{org_count}: #{org.state}&quot;
          e = US_STATES.assoc(org.state)
          Organization.find(org).update_attribute_with_validation_skipping( :state, e.last ) unless e.nil?
        end
      end
    end

  end
end
</pre>
<p><a href="http://blog.spoolz.com/wp-content/uploads/2008/05/rollback.jpg"><img class="alignright alignnone size-medium wp-image-12" style="float: right;" title="rollback" src="http://blog.spoolz.com/wp-content/uploads/2008/05/rollback.jpg" alt="" width="129" height="61" /></a>Briefly, it iterates through the entire <em>Organization</em> table using only the &#8216;id&#8217; and &#8217;state&#8217; attributes. Next, it looks through the US_STATES array for a match of the state&#8217;s long name. If a match is found, then it loads the entire record, and updates the attribute without validations (your call here, but since you are just changing the state we can skip validations pretty safely). Everything is wrapped in a transaction so if there are any problems along the way, all updates are ROLLBACKed.</p>
<p>I usually add some sort of record-by-record output to the screen (via &#8216;puts&#8217;) so there is a visual indication of the progress. I used a counter, ala record number, with the &#8217;state&#8217; value to give me some feedback.</p>
<p>You could also silence the logger as this task may be generating a lot of log entries. My log soared to over 30Mb. But remember, if you silence the log there will be no error logging either, but you should see any errors on the rake console. Note the <em>double pipes</em> inside the block with nothing inside.</p>
<pre class="brush: ruby">
# wrap this inside the transaction
Organization.silence { ||
  # my beautiful code
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/05/13/butt-biter-fix-state-abbreviations-large-data-set-updates/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Capistrano Deploy for Shared Hosting with GIT Repository</title>
		<link>http://blog.spoolz.com/2008/04/30/capistrano-deploy-for-shared-hosting-with-git-repository/</link>
		<comments>http://blog.spoolz.com/2008/04/30/capistrano-deploy-for-shared-hosting-with-git-repository/#comments</comments>
		<pubDate>Thu, 01 May 2008 03:55:22 +0000</pubDate>
		<dc:creator>Karl</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[capistrano]]></category>
		<category><![CDATA[GIT]]></category>

		<guid isPermaLink="false">http://blog.spoolz.com/?p=4</guid>
		<description><![CDATA[Would you like to deploy your Rails apps on a shared hosting account via Capistrano? I keep a couple of small projects on A Small Orange and since I update them so infrequently, I can never remember all the steps. Duh, that&#8217;s what Capistrano was made for. So I took a night and wrote the [...]]]></description>
			<content:encoded><![CDATA[<p>Would you like to deploy your Rails apps on a shared hosting account via Capistrano? I keep a couple of small projects on A Small Orange and since I update them so infrequently, I can never remember all the steps. Duh, that&#8217;s what Capistrano was made for. So I took a night and wrote the following deployment script. There are a couple of requirements:</p>
<ul>
<li>Your project is in a GIT repository, local or remote.</li>
<li>The GIT repository only needs to be accessible from your local machine (ASO servers do not support GIT).</li>
<li><span style="color: #800000;"><strong>WARNING</strong></span>: <span style="text-decoration: underline;">running any part of this script will completely delete your /public_html directory</span>!</li>
<li>You only need modify the first FOUR &#8217;set&#8217; lines.</li>
</ul>
<p>A shared/system_stopped directory will be created on the server, any files in here will be served when you do a &#8216;cap deploy:web:disable&#8217;. You can add a &#8217;system_stopped&#8217; directory to your project and those files will automatically be copied into the shared directory.</p>
<p>This script works best if you start from the beginning as this is a new deployment as a couple of directories need to be created:</p>
<pre>
<pre class="brush: css">
deploy:setup
deploy:check
deploy:cold
</pre>
</pre>
<p>There are a few commented out lines that you may wish to uncomment. I tried to explain their use, so you may wish to read over each function.</p>
<p>Lest I repeat myself&#8230; <span style="color: #800000;"><strong>WARNING</strong></span>: this will completely delete your /public_html directory! Make sure you have a backup before you run <span style="text-decoration: underline;">any</span> function in this script.</p>
<p>I plan on adding a full db backup option (run before migrations, or at will) and a production.log rotation.</p>
<pre>
<pre class="brush: ruby">set :application, &quot;mywebapp&quot;
set :repository,  &quot;git@myrepository.com:mywebapp.git&quot;
set :domain, &quot;mywebapp.com&quot;

# user is the login name for the shared hosting account
# it should also be the name of your home directory i.e. /home/my-user-name
set :user, &quot;myusername&quot;

# this will place you app outside your /public_html
# and protect your app file from exposure
set :deploy_to, &quot;/home/#{user}/#{application}&quot;

set :scm, :git
# set :deploy_via, :remote_cache  # if your server has direct access to the repository
set :deploy_via, :copy  # if you server does NOT have direct access to the repository (default)
set :git_shallow_clone, 1  # only copy the most recent, not the entire repository (default:1)

ssh_options[:paranoid] = false
set :use_sudo, false

set :keep_releases, 2  # only keep a current and one previous version to save space

role :app, domain
role :web, domain
role :db,  domain, :primary =&gt; true

task :update_public, :roles =&gt; [:app] do
  run &quot;chmod 755 #{release_path}/public&quot;
  run &quot;chmod 755 #{release_path}/public/dispatch.*&quot;
end
# remove the .git directory and .gitignore from the current release
task :remove_git_directories, :roles =&gt; [:app] do
  run &quot;rm -rfd #{release_path}/.git&quot;
  run &quot;rm #{release_path}/.gitignore&quot;
end
# this lets us keep the system_stopped files in project
task :copy_system_stopped_files, :roles =&gt; [:app] do
  run &quot;cp -f #{release_path}/public/system_stopped/* #{shared_path}/system_stopped/&quot;
end

after &quot;deploy:update_code&quot;, :update_public
after &quot;deploy:update_code&quot;, :copy_system_stopped_files
after &quot;deploy:update_code&quot;, :remove_git_directories

# create a symlink from the current/public to ~/public_html
task :create_public_html, :roles =&gt; [:app] do
  run &quot;ln -fs #{current_path}/public ~/public_html&quot;
end
after &quot;deploy:cold&quot;, :create_public_html

# create a directory in shared to hold files that will be servered
# when the system is stopped, and a config directory
task :create_shared_directories, :roles =&gt; [:app] do
  run &quot;mkdir -p #{shared_path}/system_stopped&quot;
  run &quot;mkdir -p #{shared_path}/config&quot;
end
after &quot;deploy:setup&quot;, :create_shared_directories 

# remove the symlink for ~/public_html
task :remove_public_html, :roles =&gt; [:app] do
  run &quot;rm ~/public_html&quot;
end

# creates a symlink to ~/public_html to the shared/system_stopped directory
# places files you want served in this dir for when the system is stopped
task :create_public_html_to_stopped, :roles =&gt; [:app] do
  run &quot;ln -fs #{shared_path}/system_stopped ~/public_html&quot;
end

# we need to override the default start/stop/restart functions
namespace :deploy do
  desc &quot;Restart the web server. Killing all FCGI processes.&quot;
  task :restart, :roles =&gt; :app do
    # for most hosts, all you need to do is stop all FCGI processing running
    run &quot;killall -q dispatch.fcgi&quot;
    # but some hosts can restart by touching the dispatch file
    #run &quot;chmod 755 #{current_path}/public/dispatch.fcgi&quot;
    #run &quot;touch #{current_path}/public/dispatch.fcgi&quot;
  end

  desc &quot;Start the web server. Really nothing to do for shared hosting.&quot;
  task :start, :roles =&gt; :app do
    remove_public_html
    create_public_html
    deploy.restart
  end

  desc &quot;Stop the web server and present maintenance page.&quot;
  task :stop, :roles =&gt; :app do
    remove_public_html
    create_public_html_to_stopped
  end

  namespace :web do
    desc &quot;Make application web accessible again.&quot;
    task :enable, :roles =&gt; [:app] do
      deploy.start
    end

    desc &quot;Present system maintenance page to users.&quot;
    task :disable, :roles =&gt; [:app] do
      deploy.stop
    end

  end
end</pre>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.spoolz.com/2008/04/30/capistrano-deploy-for-shared-hosting-with-git-repository/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
