<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<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/"
	>

<channel>
	<title>rails-articles &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/rails-articles/</link>
	<description>Feed of posts on WordPress.com tagged "rails-articles"</description>
	<pubDate>Fri, 04 Dec 2009 09:38:23 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[Push to Multiple Git Repos]]></title>
<link>http://afreshcup.com/2009/09/19/push-to-multiple-git-repos/</link>
<pubDate>Sat, 19 Sep 2009 15:22:36 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/09/19/push-to-multiple-git-repos/</guid>
<description><![CDATA[If you&#8217;ve got a project with multiple git remotes, and you&#8217;d like to update both of them]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>If you&#8217;ve got a project with multiple git remotes, and you&#8217;d like to update both of them with a single operation, there&#8217;s an easy way to do it. Just edit your .git/config file to include a new target named &#8220;all&#8221;:</p>
<pre class="brush: ruby;">
[remote "origin"]
  url = git@github.com:ffmike/BigOldRailsTemplate.git
  fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
  remote = origin
  merge = refs/heads/master
[remote "codaset"]
  url = git@codaset.com:ffmike/bigoldrailstemplate.git
  fetch = +refs/heads/*:refs/remotes/codaset/*
[remote "all"]
  url = git@github.com:ffmike/BigOldRailsTemplate.git
  url = git@codaset.com:ffmike/bigoldrailstemplate.git
</pre>
<p>With this setup, pushes and pulls on my local master branch go to GitHub by default. But if I execute &#8216;git push all&#8217; it updates both the GitHub repository and the Codaset repository. The one little annoyance is that master then thinks it&#8217;s ahead of the remote, but that&#8217;s easily remedied by executing a &#8216;git pull&#8217; on it.</p>
<p>I&#8217;ve been using this in cases where I&#8217;m backing up a repo to a private Gitosis server as well as spreading public repos between multiple cloud services for easy backup.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Migrating to Snow Leopard for Rails Development - A Definitive Guide]]></title>
<link>http://afreshcup.com/2009/09/02/migrating-to-snow-leopard-for-rails-development-a-definitive-guide/</link>
<pubDate>Thu, 03 Sep 2009 01:40:53 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/09/02/migrating-to-snow-leopard-for-rails-development-a-definitive-guide/</guid>
<description><![CDATA[I spent a good chunk of the last couple of days upgrading one of my Macs to Snow Leopard (OS X 10.6)]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I spent a good chunk of the last couple of days upgrading one of my Macs to Snow Leopard (OS X 10.6), and keeping notes as I went. I had several goals here:</p>
<ul>
<li>Develop a repeatable process I could use on my main development box</li>
<li>Set up multiple versions of Ruby, as I expect 1.9 compatibility to be increasingly important</li>
<li>Avoid MacPorts, as it&#8217;s been problematic for me and I don&#8217;t like two copies of everything</li>
<li>Prevent disasters</li>
<li>Migrate applications and documents from the previous setup on the same box</li>
</ul>
<p>I&#8217;m pretty happy with where it all ended up, but please realize that this guide is only definitive for me: just because this is the way it worked for me does not mean it&#8217;s the only way to set things up for Rails development. I hope some folks find this helpful, but the main reason I wanted to work all this out was to handle our own in-house Macs.</p>
<p>1. Install external hard drive. <a href="http://www.amazon.com/LaCie-FireWire-External-301442U-Aluminum/dp/B001KFH6K6">I used a LaCie d2 Quadra</a>. At $150 with free shipping (we happily pay for Amazon Prime) it&#8217;s cheap insurance. Didn’t bother with their Setup Assistant (who the heck still writes software that requires Rosetta?), just erased it with Disk Utility and formatted it as one big journaled OS X volume.</p>
<p>2. Install <strong><a href="http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html">SuperDuper</a></strong> (http://www.shirt-pocket.com/SuperDuper/SuperDuperDescription.html). I’m sure <a href="http://www.bombich.com/software/ccc.html">Carbon Copy Cloner</a> is just as good, I just happen to be a SuperDuper user. Even if you&#8217;re not a paying customer, SuperDuper is free to use in interactive mode, which is all this procedure requires.</p>
<p>3. Log out and log back in with the shift key held down to prevent startup items from running.</p>
<p>4. Launch SuperDuper and back up the internal hard drive to the external hard drive with the &#8220;Backup &#8211; All Files&#8221; script.</p>
<p>5. Restart, holding down the Option key when the box restarts. This will let you choose to restart from the backup you just made. Booting from the external drive will take a lot longer than from the internal one, but don&#8217;t skip this step. You&#8217;ll feel pretty darned stupid if you bootable backup isn&#8217;t. Hold down shift after selecting the drive to bypass startup items so you don&#8217;t clutter the backup.</p>
<p>6. While you&#8217;re in there, launch terminal and :</p>
<pre><code>
gem list &#62; gemlist.txt
port list installed &#62; portlist.txt
</code></pre>
<p>I didn&#8217;t use the port list for anything myself, but it was a good reference for things I needed to install otherwise.</p>
<p>7. Now it&#8217;s time to do some cleaning up of your backup to prepare for the later migration. Mac&#8217;s Migration Assistant doesn&#8217;t offer a lot of granularity, so you need to get rid of anything from your Applications, Documents, and other descendants of your home directory that you don&#8217;t want to move. The more you delete now, the faster the migration will go, so delete any applications and documents that you don&#8217;t want on the rebuilt Mac. Good time to clean up the Dock as well. I blew away my local gems as well at this point.</p>
<p>I also recommend completely blowing away /usr/local and /opt/local to make sure you’re doing a “clean everything” install even after migrating. Edit your .bash_login to remove them from the path as well (optionally, you may want to rename these directories to have them available for reference).</p>
<p>8. If you&#8217;re a PostgreSQL user, make a backup of your databases. Tyler Hunt has <a href="http://devoh.com/posts/2009/08/postgresql-snow-leopard">clear instructions</a> for this.</p>
<p>9. Put in the Snow Leopard DVD. Ignore the Finder window when it pops up.</p>
<p>10. Power down the computer.</p>
<p>11. Unplug the backup drive. No sense taking chances.</p>
<p>12. Restart with the option key held down again. Choose the Mac OS X Install DVD to boot from.</p>
<p>13. The &#8220;Erase and Install&#8221; option is gone from the Snow Leopard installer, so when you get to the &#8220;Install Mac OS X&#8221; screen select Disk Utility from the Utilities menu instead.</p>
<p>14. Select the &#8220;Macintosh HD&#8221; partition on your hard drive. Select the Erase tab. Select the &#8220;Mac OS Extended (Journaled)&#8221; format. Click Erase. Grit your teeth and confirm.</p>
<p>15. When OS X is done reformatting the partition, close Disk Utility, click Continue on the OS X installer, and work your way through the rest of the prompts.</p>
<p>16. When you get to the &#8220;Do You Already Own a Mac?&#8221; screen (this is after the installation restart, so don&#8217;t panic when the machine restarts), plug the external drive back in. Select &#8220;From another volume on this Mac&#8221; and click Continue.</p>
<p>17. The top of the &#8220;Transfer Your Information&#8221; screen should show that you&#8217;re transferring from the external drive. Leave all the options checked and click Transfer.</p>
<p>18. Log into happy new OS X. Bask in it for a little bit. Wait a minute for Software Update to kick in, or run it manually and install whatever it comes up with. If it doesn&#8217;t find anything, that&#8217;s great.</p>
<p>19. While you&#8217;ve got the Snow Leopard DVD in the drive, pop option the Optional Installs folder and install XCode.</p>
<p>20. I personally prefer wget to curl (just habit, I suppose) which means that I have to install it:</p>
<p><a href="http://www.gnu.org/software/wget/">GNU wget home page</a></p>
<pre class="brush: bash;">
Download wget-latest.tar.gz from http://ftp.gnu.org/gnu/wget/
tar -xzvf wget-latest.tar.gz
cd wget-1.11.4/
./configure
make
sudo make install
</pre>
<p>21. I&#8217;m trying a no-MacPorts approach this time around. This means installing a current readline by hand, since multiple pieces of software still reportedly have issues with Apple&#8217;s default version:</p>
<p><a href="http://tiswww.case.edu/php/chet/readline/rltop.html">GNU Readline home page</a></p>
<pre class="brush: bash;">
wget ftp://ftp.cwru.edu/pub/bash/readline-6.0.tar.gz
tar -xvzf readline-6.0.tar.gz
cd readline-6.0
./configure
make
sudo make install
</pre>
<p>22. This is a good point to make sure your .bash_login and .bash_profile are the way you want them. For me, that’s an empty .bash_login and a pretty minimal .bash_profile. Here’s my .bash_profile, though you probably want to tune your own:</p>
<pre><code>
export PATH=/usr/local/git/bin:/usr/local/bin/src:/usr/local/bin:
  /usr/local/sbin:/usr/local/mysql/bin:~/bin:$PATH

export EDITOR='mate -w'
export PAGER=most

function parse_git_dirty {
  [[ $(git status 2&#62; /dev/null &#124; tail -n1) !=
    "nothing to commit (working directory clean)" ]] &#38;&#38; echo "*"
}
function parse_git_branch {
  git branch --no-color 2&#62; /dev/null &#124;
    sed -e '/^[^*]/d' -e "s/* \(.*\)/[\1$(parse_git_dirty)]/"
}

export PS1='\[33[1;36m\]\h\[33[0;33m\] \w \[33[31;40m\]
  $(parse_git_branch)\[33[00m\] $ '

export HISTCONTROL=erasedups
export HISTSIZE=10000
shopt -s histappend

EVENT_NOKQUEUE=yes
</code></pre>
<p>23. Snow Leopard includes a recent version of SQLite, but you know, as long as we&#8217;re building things we may as well make it current. </p>
<p><a href="http://www.sqlite.org/download.html">SQLite Download Page</a></p>
<p><a href="http://www.sqlite.org/cvstrac/wiki?p=HowToCompile">SQLite Build Instructions</a></p>
<pre class="brush: bash;">
wget http://www.sqlite.org/sqlite-amalgamation-3.6.17.tar.gz
tar -xvzf sqlite-amalgamation-3.6.17.tar.gz
cd sqlite-3.6.17/
./configure
make
sudo make install</pre>
<p>24. Now for MySQL. If you have a previous version of MySQL installed, you probably have the old MySQL preference pane, which doesn&#8217;t work under Snow Leopard. Fortunately swoon.net has recompiled a <a href="http://www.swoon.net/site/software.html">64-bit version</a>. Grab it and install it. Then pop into System Preferences and stop your MySQL server if it&#8217;s running.</p>
<p>25.  Given that there are prebuilt x64 binaries for OS X, I don&#8217;t feel any particular need to build MySQL from scratch. I&#8217;ve found anything past MySQL 5.1 to be problematic for Rails.</p>
<p><a href="http://dev.mysql.com/downloads/mysql/5.1.html#macosx-dmg">MySQL Download Page</a></p>
<p>Pick a mirror and download the &#8220;Mac OS X 10.5 (x86_64)&#8221; version. Mount the dmg and run the MySQL package and then the MySQL startup item package. Then start MySQL:</p>
<pre class="brush: bash;">
sudo /Library/StartupItems/MySQLCOM/MySQLCOM start
</pre>
<p>26. If you have existing MySQL databases to bring over from an old version, see the <a href="http://gist.github.com/177368">instructions from edward</a> &#8211; remember to change the old directory name to match the version you were running before.</p>
<p>27. SQLite and MySQL are nice, but these days I’m using PostgreSQL for new Rails work. If you want a shortcut, there’s an <a href="http://www.enterprisedb.com/products/pgdownload.do#osx">installer that runs on OS X</a>: grab it and run it. But to get best performance, you probably should build by hand. There are <a href="http://devoh.com/posts/2008/10/installing-postgresql-on-mac-os-x-10.5-leopard">good instructions</a> from Tyler Hunt for that, though you need to update the download version. Don’t install the postgres gem though; it’s slow and outdated, and anyhow there’s still work to do to get gems set up.</p>
<p><a href="http://www.postgresql.org/ftp/source/">PostgreSQL source code</a></p>
<pre class="brush: bash;">
wget ftp://ftp.postgresql.org/pub/source/v8.4.0/postgresql-8.4.0.tar.gz
tar -xvzf postgresql-8.4.0.tar.gz
cd postgresql-8.4.0
./configure --enable-thread-safety --with-bonjour
</pre>
<p>And follow Tyler&#8217;s instructions from there for installing, creating a group and user, and hooking up launchd.</p>
<p>28. <a href="http://devoh.com/posts/2009/08/postgresql-snow-leopard">Reload your old PostgreSQL databases</a>.</p>
<p>29. Databases in hand, let’s turn to ruby. Given that I expect a transition to ruby 1.9 over the next year, and I find myself wanting to test on odd rubies from time to time, I’m going to completely ignore the system ruby except to bootstrap a multiruby setup. Fortunately, the recently-released Ruby Version Manager is working great already.</p>
<p><a href="http://rvm.beginrescueend.com/">Ruby Version Manager homepage</a></p>
<pre class="brush: bash;">
sudo gem install rvm
rvm-install
rvm install 1.8.6 -C --enable-shared,--with-readline-dir=/usr/local
rvm install 1.8.7 -C --enable-shared,--with-readline-dir=/usr/local
rvm install 1.9.1 -C --enable-shared,--with-readline-dir=/usr/local
rvm install 1.9.2 -C --enable-shared,--with-readline-dir=/usr/local
rvm 1.8.7 --default
</pre>
<p>I&#8217;m skipping REE, JRuby, and Rubinius for the moment, but will likely add them to the system later.</p>
<p>30. Time to install the two problematic gems. I’m just going to do this under 1.8.7 for now, but will update the other rubies later.</p>
<p><strong>MySQL</strong>: (from <a href="http://www.gregbenedict.com/2009/08/29/fixing-ruby-gems-mysql-and-passenger-phusion-on-snow-leopard-10-6/">Greg Benedict</a>)</p>
<pre class="brush: bash;">
sudo env ARCHFLAGS=&quot;-arch x86_64&quot; gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
</pre>
<p><strong>PostgreSQL</strong>: (from <a href="http://www.icoretech.org/2009/08/how-to-install-pg-postgresql-gem-on-snow-leopard-64-bit/">iCoreTech</a>)</p>
<pre class="brush: ruby;">
sudo -s
export ARCHFLAGS='-arch x86_64'
export PATH=/usr/local/pgsql/bin:${PATH}
gem install pg
exit
</pre>
<p>31. The rest of the gems should be easier. Grab the gemlist.txt file you created way back at the start and edit it to one gem name per line. Ditch anything you know you don’t need. Then fire up IRB and run:</p>
<pre class="brush: ruby;">
File.open('/Users/mike/gemlist.txt').each_line {&amp;#124;line&amp;#124; `sudo gem install #{line.split.first}`}
</pre>
<p>Obviously change the file name to match where you put it on your own drive.</p>
<p><em>This could use some tweaking to deliver feedback.</em></p>
<p>[stalled at RedCloth?]</p>
<p>32. This is a good time to get git on the system. Fortunately, there’s an easy and functional <a href="http://code.google.com/p/git-osx-installer/">OS X installer</a> for that. Download, mount the disk image, and run the installer and shell script.</p>
<p>33. imagemagick used to be a bear, but at the moment there’s a good install script for it on GitHub. So, now that you have your shiny new copy of git:</p>
<pre class="brush: bash;">
git clone git://github.com/maddox/magick-installer.git
cd magick-installer/
./magick-installer.sh
</pre>
<p>34. I also need memcached locally. Wincent has <a href="https://wincent.com/wiki/Installing_memcached_1.4.1_on_Mac_OS_X_10.6_Snow_Leopard">good install instructions</a>:</p>
<pre class="brush: bash;">
wget http://www.monkey.org/~provos/libevent-1.4.12-stable.tar.gz
tar xvzf libevent-1.4.12-stable.tar.gz
cd libevent-1.4.12-stable
./configure
make
sudo make install
wget http://memcached.googlecode.com/files/memcached-1.4.1.tar.gz
tar xvzf memcached-1.4.1.tar.gz
cd memcached-1.4.1
./configure
make
sudo make install
</pre>
<p>35. I’d like to run <a href="http://luigimontanez.com/2008/running-a-local-gem-documentation-server-on-mac-os-x-2">gem server locally on a startup basis</a> to handle my gem RDoc needs, but I need to figure out how (or whether) that can be made to play nicely with rvm. Meanwhile, <a href="http://github.com/manalang/bdoc/tree/master">bdoc</a> is an acceptable alternative:</p>
<pre class="brush: bash;">
sudo gem install manalang-bdoc
</pre>
<p>36. Finally (for now!) I prefer most as a pager to less or more. It supports paging forwards and backwards, split windows, and can even drop the file you&#8217;re paging right into your editor of choice.</p>
<p><a href="http://www.jedsoft.org/most/">Most home page</a></p>
<p>You’ll need some prerequisites first:</p>
<p><strong>pcre</strong>:</p>
<pre class="brush: bash;">
wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-7.9.tar.gz
tar xvzf pcre-7.9.tar.gz
cd pcre-7.9
./configure
make
sudo make install
</pre>
<p><strong>Oniguruma</strong>:</p>
<pre class="brush: bash;">
wget http://www.geocities.jp/kosako3/oniguruma/archive/onig-5.9.1.tar.gz
tar xvzf onig-5.9.1.tar.gz
cd onig-5.9.1
./configure
make
sudo make install
</pre>
<p><strong>S-Lang</strong>:</p>
<pre class="brush: bash;">
wget ftp://space.mit.edu/pub/davis/slang/v2.2/slang-2.2.0.tar.gz
tar xvzf slang-2.2.0.tar.gz
cd slang-2.2.0
./configure
make
sudo make install
</pre>
<p>And now <strong>most</strong> at last:</p>
<pre class="brush: bash;">
wget ftp://space.mit.edu/pub/davis/most/most-5.0.0.tar.gz
tar xvzf most-5.0.0.tar.gz
cd most-5.0.0
./configure
make
sudo make install
</pre>
<p>And there you have it! Start to finish, this process took me about 3 hours on a MacBook Pro with around 90GB of data that I wanted to save. I expect it to take much longer on the desktop with the correspondingly larger hard drive, but much of that will be overnight backup and restore times. If you have any tweaks and suggestions, feel free to add them to the comments.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Recurring Items in a Rails Application]]></title>
<link>http://afreshcup.com/2009/07/31/recurring-items-in-a-rails-application/</link>
<pubDate>Fri, 31 Jul 2009 17:50:57 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/07/31/recurring-items-in-a-rails-application/</guid>
<description><![CDATA[I recently had to implement some recurring items in a Rails application &#8211; we&#8217;ll call the]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I recently had to implement some recurring items in a Rails application &#8211; we&#8217;ll call them &#8220;entries&#8221; here though you can use this technique for appointments, bills, or whatever else. After thinking about it for a while, I settled on:</p>
<ul>
<li>At any point, we needed to know what the next recurrence date was.</li>
<li>The potential schedules needed to be data-driven (because the client was unsure what would be needed).</li>
</ul>
<p>Here&#8217;s what I came up with. If your needs are different, you&#8217;ll no doubt need to alter it. First, the schedule model has a schedule_type, an interval, a specific value, and a description. The combination of these things lets me implement <code>Schedule#next_date</code> to return the fate for the next date given a schedule object and the current date. Here&#8217;s the model:</p>
<pre class="brush: ruby;">
class Schedule

  has_many :entries

  attr_accessible :schedule_type, :description, :interval, :specific

  SCHEDULE_TYPE = {:first =&gt; 0, :last =&gt; 1, :weekly =&gt; 2, :monthly =&gt; 3}

def next_date(current_date)
  case schedule_type
  when SCHEDULE_TYPE[:first]
    first_day = (current_date + 1.month).beginning_of_month
    wday = first_day.wday
    if specific &gt;= wday
      first_day + specific - wday
    else
      first_day + 7 + specific - wday
    end
  when SCHEDULE_TYPE[:last]
    if specific == -1
      (current_date + 1.month).end_of_month
    else
      last_day = (current_date + 1.month).end_of_month
      wday = last_day.wday
      if wday &gt;= specific
        last_day - wday + specific
      else
        last_day - wday - 7 + specific
      end
    end
  when SCHEDULE_TYPE[:weekly]
    current_date + interval.weeks
  when SCHEDULE_TYPE[:monthly]
    current_date + interval.months
  end
end
</pre>
<p>So we can have a schedule that is &#8220;first Monday of the month&#8221; or &#8220;every 3 weeks&#8221; among other things. I stock these up using <a href="http://github.com/ffmike/db-populate/tree/master">db-populate</a>; here&#8217;s some of the population file:</p>
<pre class="brush: ruby;">
Schedule.create_or_update(:id =&gt; 1,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:monthly],
  :interval =&gt; 1, :description =&gt; &quot;Every month&quot;)
Schedule.create_or_update(:id =&gt; 2,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:monthly],
  :interval =&gt; 2, :description =&gt; &quot;Every other month&quot;)

Schedule.create_or_update(:id =&gt; 4,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:weekly],
  :interval =&gt; 1, :description =&gt; &quot;Every week&quot;)

Schedule.create_or_update(:id =&gt; 8,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:first],
  :specific =&gt; 0, :description =&gt; &quot;First Sunday of every month&quot;)

Schedule.create_or_update(:id =&gt; 15,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:last],
  :specific =&gt; 0, :description =&gt; &quot;Last Sunday of every month&quot;)

Schedule.create_or_update(:id =&gt; 22,
  :schedule_type =&gt; Schedule::SCHEDULE_TYPE[:last],
  :specific =&gt; -1, :description =&gt; &quot;Last day of every month&quot;)
</pre>
<p>Then the entry model ties into the schedule model. Here are the important (for this purpose) bits of the entry class:</p>
<pre class="brush: ruby;">
class Entry &lt; ActiveRecord::Base
  belongs_to :schedule
  named_scope :ready_to_recur, lambda { &amp;#124;date&amp;#124;
    {:conditions =&gt; [&quot;recurring = 1 AND next_date &lt;= ? AND schedule_id IS NOT NULL AND next_created = 0&quot;, date ]} }
  before_save :set_up_recurrence

  def make_next_recurrence
    if recurring? &amp;&amp; !schedule_id.nil? &amp;&amp; !next_created?
      entry = Entry.create(
        :entry_date =&gt; next_date,
        :reference =&gt; reference,
        &lt;more attributes here&gt;
        :recurring =&gt; true,
        :schedule_id =&gt; schedule_id
        )
      update_attribute(:next_created, true)
    end
    entry
  end

  def set_up_recurrence
    if recurring? &amp;&amp; !schedule_id.nil?
      self.next_date = Schedule.find(schedule_id).next_date(entry_date)
      self.next_created = false if next_created.nil?
    end
    true
  end
end
</pre>
<p>Finally, the whole thing is driven by a rake task that we run every night. This task finds all the entries that are ready to recur and creates the next entry:</p>
<pre class="brush: ruby;">
desc 'Create the recurring entries for today'
task :daily_recurring_entries =&gt; :environment do
  Entry.ready_to_recur(Date.today).each do &amp;#124;entry&amp;#124;
    entry.make_next_recurrence
  end
end
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Big Old Rails Template]]></title>
<link>http://afreshcup.com/2009/07/12/big-old-rails-template/</link>
<pubDate>Sun, 12 Jul 2009 16:10:23 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/07/12/big-old-rails-template/</guid>
<description><![CDATA[A few people have asked me about the Rails application template that I&#8217;ve put together recentl]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>A few people have asked me about the Rails application template that I&#8217;ve put together recently. For those who are interested, it&#8217;s <strong><a href="http://gist.github.com/145676">now available for review and download</a></strong> as a gist. To use it, just specify the -m switch when creating a Rails application:</p>
<pre class="brush: ruby;">
rails new_app_name -m lark_template.rb
</pre>
<p>I should warn you of two things. First, it&#8217;s a pretty heavyweight template, sticking a lot of stuff into the new application. This suits me, because I have a lot of things I use in just about every application, but it may not suit you. Second, Rails templates are not one-size-fits-all; you&#8217;d be better off treating this as a starting point to steal from than a finished template to use (though if you want to use it, feel free).</p>
<p>Here&#8217;s a list of what this template sets up:</p>
<p><strong>Coding Tools</strong></p>
<ul>
<li>Authlogic for user authentication, including password resets,     anonymous_only, authenticated_only, admin_only application helpers</li>
<li>World&#8217;s simplest authorization system: manage multiple string roles on users with User#add_role, User#remove_role, User#clear_roles, and User#has_role?</li>
<li>Date formats: :us, :us_with_time, :short_day, :long_day</li>
<li>live-validations for client-side JavaScript data entry validation. Add :live_validations =&#62; true to form_for declarations to hook this up.</li>
<li>Paperclip for attachment management</li>
<li>/pages/css_test will show most CSS styles in action</li>
<li>Searchlogic for magic named scopes and search forms &#8211; http://rdoc.info/projects/binarylogic/searchlogic. Includes attribute_equals, attribute_does_not_equal, attribute_begins_with, attribute_like, attribute_ends_with, attribute_greater_than, attribute_null, attribute_blank etc. etc.</li>
<li>Stringex for extra string functionality &#8211; acts_as_url, String#to_ascii, String#to_html, String#to_url, String#remove_formatting, String.random</li>
<li>US State application helpers</li>
<li>will-paginate for pagination</li>
</ul>
<p><strong>Database Tools</strong></p>
<ul>
<li>Hooked up for PostgreSQL</li>
<li>admin-data plugin for administrative UI. http://localhost:3000/admin_data will get you to the application&#8217;s data. On production, only admin can view data, no one can edit (modify config/initializers/admin_data.rb to adjust this)</li>
<li>db-populate for seed data</li>
</ul>
<p><strong>Deployment Tools</strong></p>
<ul>
<li>fast_remote_cache strategy for deployment</li>
<li>rubiadhstrano for deployment recipes; automatically uses multiple targets, so: cap production deploy for deployment to production</li>
<li>superdeploy for additional Capistrano tasks. cap -T for full list.
</li>
</ul>
<p><strong>External Services</strong></p>
<ul>
<li>Exceptional for error tracking. Go to /pages/kaboom to test after finishing Exceptional setup.</li>
<li>New Relic for performance tracking
</li>
</ul>
<p><strong>Testing Tools</strong></p>
<ul>
<li>Shoulda and Test::Unit for testing</li>
<li>Mocha for mocking</li>
<li>Object Daddy for factories</li>
<li>Generated code is already covered by tests</li>
<li>parallel-test for faster testing. rake test:parallel:prepare[2] to set up two test databases. rake test:parallel[2] to distribute tests across two cores</li>
<li>rack-bug for request/response/perf analysis. http://localhost:3000/__rack_bug__/bookmarklet.html to add bookmarklet to browser.</li>
<li>shmacros for additional Shoulda macros: should_accept_nested_attributes_for, should_act_as_taggable_on, should_callback, should_delegate, more</li>
<li>More extra shoulda macros: should_have_before_filter, should_have_after_filter</li>
<li>metric-fu for static code analysis. rake metrics:all, configure in Rakefile</li>
<li>inaction-mailer is installed for development environment, so mails sent during dev will end up as files in /tmp/sent_mails</li>
</ul>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Finding Visitor Locations in Rails]]></title>
<link>http://afreshcup.com/2009/06/10/finding-visitor-locations-in-rails/</link>
<pubDate>Wed, 10 Jun 2009 16:43:58 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/06/10/finding-visitor-locations-in-rails/</guid>
<description><![CDATA[I&#8217;ve got an application that I work on where the client wants to track which countries they]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve got an application that I work on where the client wants to track which countries they&#8217;re seeing click-throughs from. They want this in real time and in the application&#8217;s UI, not in an external package such as Google Analytics. There are various ways to guess at country, but for the purposes of this application, basing it on the IP address and where its range is assigned proves to be good enough.</p>
<p>There are various services that will let you geolocate based on IP just by making an API call. But there&#8217;s no particular reason to go outside your own application for this; it&#8217;s pretty trivial to set up in Rails:</p>
<p>1) Download the &#8220;Complete (Country) One Table&#8221; SQL file from <strong><a href="http://ipinfodb.com/ip_database.php">IPInfoDB</a></strong>. This is the raw data necessary to do the lookups. Decompress it and then run the resulting SQL file in your application&#8217;s database. This will give you an <code>ip_group_country</code> table. There&#8217;s no need to set up a matching model; we&#8217;re just going to hit it with raw SQL.</p>
<p>2) In this particular application, we&#8217;re maintaining an Event model that holds, among other things, the IP address of the request. So the easy answer is to geolocate instances of that model when they&#8217;re created or updated:</p>
<pre class="brush: ruby;">
class Event &lt; ActiveRecord::Base
  before_save :get_country_info

  def get_country_info
    segments = remote_ip.split('.')
    ip_atom = ((segments[0].to_i * 256 + segments[1].to_i) * 256 + segments[2].to_i)*256
    result = connection.execute(&quot;SELECT * FROM `ip_group_country` where `ip_start` &lt;= #{ip_atom} order by ip_start desc limit 1;&quot;)
    row = result.fetch_row
    self.country_code = row[2]
    self.country_name = row[3]
  end

end
</pre>
<p>3) There is no #3. That&#8217;s it!</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Building Rails with Cerberus and multiruby]]></title>
<link>http://afreshcup.com/2009/05/24/building-rails-with-cerberus-and-multiruby/</link>
<pubDate>Sun, 24 May 2009 12:05:18 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/05/24/building-rails-with-cerberus-and-multiruby/</guid>
<description><![CDATA[I&#8217;ve been poking at various continuous integration software lately. Most recently I gave Cerbe]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve been poking at various continuous integration software lately. Most recently I gave <strong><a href="http://cerberus.rubyforge.org/">Cerberus</a></strong> a spin, and I must say, even though the project is a bit immature, I like its approach. My test for CI is generally &#8220;can I use it on the Rails source&#8221; as I think that provides a level of complexity beyond what I&#8217;m likely to need for my own projects. Well, I had to contribute a bit of code to get Cerberus to that point, but it works. I also set up the box so that I can build with different ruby versions, thanks to <strong><a href="http://zentest.rubyforge.org/ZenTest/Multiruby.html">multiruby</a></strong>. Here&#8217;s my notes on getting all the ducks in a row, starting with a bare-metal Debian Lenny installation.</p>
<h2>Root Tasks</h2>
<ul>
<li>log in as root</li>
<li>adduser webadmin</li>
<li>visudo &#8211; set webadmin up with sudo rights</li>
</ul>
<h2>webadmin Tasks</h2>
<ul>
<li>log in as webadmin</li>
</ul>
<h2>Prerequisites for Ruby Compiles</h2>
<ul>
<li>sudo apt-get install autoconf</li>
<li>sudo apt-get install bison</li>
<li>sudo apt-get install zlib1g-dev</li>
<li>sudo apt-get install libzlib-ruby</li>
<li>sudo apt-get install ruby-dev</li>
</ul>
<h2>rubygems install</h2>
<ul>
<li>mkdir sources</li>
<li>cd sources</li>
<li>wget http://rubyforge.org/frs/download.php/56227/rubygems-1.3.3.tgz</li>
<li>tar -xvzf rubygems-1.3.3.tgz </li>
<li>cd rubygems-1.3.3/</li>
<li>sudo ruby setup.rb</li>
<li>sudo ln /usr/bin/gem1.8 /usr/bin/gem </li>
</ul>
<h2>fastcgi (we&#8217;ll need fcgi gem later)</h2>
<ul>
<li>cd ~/sources</li>
<li>wget http://www.fastcgi.com/dist/fcgi.tar.gz</li>
<li>tar -xvzf fcgi-2.4.0.tar.gz</li>
<li>cd fcgi-2.4.0/</li>
<li>./configure</li>
<li>make</li>
<li>sudo make install</li>
<li>sudo apt-get install libfcgi-dev</li>
</ul>
<h2>Databases</h2>
<ul>
<li>sudo apt-get install  mysql-server-5.0 libmysqlclient15-dev</li>
<li>sudo apt-get install sqlite sqlite3 libsqlite-dev libsqlite3-dev</li>
<li>sudo apt-get install postgresql postgresql-server-dev-8.3</li>
<li>sudo su &#8211; postgres -c &#8216;createuser -s webadmin&#8217;</li>
<li>sudo su &#8211; postgres -c &#8216;createuser -s rails&#8217;</li>
</ul>
<h2>memcached</h2>
<ul>
<li>sudo apt-get install memcached</li>
<li>sudo /etc/init.d/memcached start</li>
</ul>
<h2>multiruby Install</h2>
<ul>
<li>sudo gem install ZenTest</li>
<li>sudo multiruby_setup mri:svn:tag:v1_8_6_368</li>
<li>sudo multiruby_setup mri:svn:tag:v1_8_7_160</li>
<li>sudo multiruby_setup mri:svn:tag:v1_9_1_129</li>
<li>sudo multiruby_setup update:rubygems</li>
</ul>
<h2>Gem Installs</h2>
<ul>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development test-unit</li>
<li><em>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development fcgi</em></li>
<li><em>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development memcache-client</em></li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development mocha</li>
<li><em>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development mysql</em></li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development pg</li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc rack</li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc thin</li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development rake</li>
<li><em>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development sqlite-ruby</em></li>
<li>sudo multiruby -S gem install &#8211;no-ri &#8211;no-rdoc &#8211;development sqlite3-ruby</li>
<li>sudo multiruby -S gem install geminstaller</li>
<li><em>sudo multiruby -S gem install SystemTimer</em></li>
<li>sudo multiruby -S gem install json</li>
</ul>
<p>Note: the italicized installs currently fail on ruby 1.9.1.</p>
<h2>git</h2>
<ul>
<li>sudo apt-get install git-core</li>
</ul>
<h2>Cerberus</h2>
<ul>
<li>sudo gem install cerberus</li>
</ul>
<p>Note: Currently, you&#8217;ll need to either pull and build cerberus from <a href="http://github.com/ffmike/cerberus/tree/master">my fork</a> or from the <a>ruby_builder</a> branch in the official repo. With the next release after 0.5.0, you should be able to use the gem install method.</p>
<h2>Create the Cerberus project and build it</h2>
<ul>
<li>cerberus add http://github.com/rails/rails/tree/master APPLICATION_NAME=rails_master_187 SCM=git</li>
<li>Edit the file ~/.cerberus/config.yml to include your own notifier information</li>
<li>Edit the file ~/.cerberus/config/rails_master_187.yml to put in the custom build info:</li>
</ul>
<pre><code>
---
publisher:
  mail:
    recipients: you@yourdomain.com
scm:
  url: git://github.com/rails/rails.git
  type: git
  # branch: 2-3-stable
builder:
  ruby:
    task: ci/ci_build.rb
    ruby_path: /home/webadmin/.multiruby/install/v1_8_7_160/bin/
    success: Rails build finished sucessfully
    failure: Rails build FAILED
    brokeness: (\d+) failures, (\d+) errors
</code></pre>
<ul>
<li>cerberus build rails_master_187</li>
</ul>
<p>Build databases for ActiveRecord</p>
<p>Note: Some of this depends on having pulled a copy of Rails to the box; the easiest way is to let Cerberus do a failing build and then create the databases.</p>
<ul>
<li>cd ~/.cerberus/work/rails_master_187/sources/activerecord/</li>
<li>mysql -uroot -e &#8216;grant all on *.* to rails@localhost;&#8217;</li>
<li>mysql -urails -e &#8216;create database activerecord_unittest;&#8217;</li>
<li>mysql -urails -e &#8216;create database activerecord_unittest2;&#8217;</li>
<li>rake postgresql:build_databases</li>
</ul>
<h2>Ready to Go</h2>
<p>Now you can run <code>cerberus build rails_master_187</code> to run a single build, or <code>cerberus build rails_master_187 force=TRUE</code> to build even if nothing has changed in the repo, or <code>cerberus buildall</code> to build everything you&#8217;ve defined. Hook it up to cron if you want periodic checks of the repo.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Seed Data in Rails 3]]></title>
<link>http://afreshcup.com/2009/05/11/seed-data-in-rails-3/</link>
<pubDate>Mon, 11 May 2009 18:07:34 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/05/11/seed-data-in-rails-3/</guid>
<description><![CDATA[One of the perennial code smells in many Rails applications is the use of migrations as a way to car]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>One of the perennial code smells in many Rails applications is the use of migrations as a way to carry seed data (data that needs to be added to the database on deployment). This doesn&#8217;t work well because it&#8217;s tough to maintain and doesn&#8217;t play well with loading up the database from the schema file.</p>
<p>Rails 3 now has a <a href="http://github.com/rails/rails/commit/4932f7b38f72104819022abca0c952ba6f9888cb">new answer to this</a>: a file convention and a rake task. The file is <code>db/seeds.rb</code> and it can contain arbitrary Ruby code, but generally it will look something like this:</p>
<pre class="brush: ruby;">
cities = City.create([{ :name =&gt; 'Chicago' }, { :name =&gt; 'Copenhagen' }])
Mayor.create(:name =&gt; 'Daley', :city =&gt; cities.first)
</pre>
<p>This file then gets run by using the new <code>db:seed</code> rake task, or via <code>rake db:setup</code> which runs create, schema:load, and seed in succession.</p>
<p>As with some other parts of Rails, this is the simplest thing that can possibly work. For a somewhat different take (that also works in Rails 2) take a look at Michael Bleigh&#8217;s <a href="http://github.com/mbleigh/seed-fu/tree/master">seed_fu</a> or my own <a href="http://github.com/ffmike/db-populate/tree/master">db-populate</a>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Announcing RailsBridge]]></title>
<link>http://afreshcup.com/2009/05/04/announcing-railsbridge/</link>
<pubDate>Mon, 04 May 2009 10:42:45 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/05/04/announcing-railsbridge/</guid>
<description><![CDATA[This morning, I&#8217;m pleased to be able to announce a new initiative that I&#8217;ve played a sma]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This morning, I&#8217;m pleased to be able to announce a new initiative that I&#8217;ve played a small part in launching: <strong><a href="http://railsbridge.org">RailsBridge</a></strong>. The easiest way to explain the reasoning behind RailsBridge is to quote from the web site:</p>
<hr />
<p>The RailsBridge Mission:</p>
<p>To create an inclusive and friendly Ruby on Rails community.</p>
<p>The RailsBridge Guidelines:</p>
<ul>
<li>First, do no harm. Then, help where you can.</li>
<li>Bridge the gap from aspiring developer to contributing community member, through mentoring, teaching, and writing.</li>
<li>Reach out to individuals and groups who are underrepresented in the community.</li>
<li>Collaborate with other groups with similar goals.</li>
</ul>
<hr />
<p>RailsBridge is the product of intense discussions among 40 or so Rails and Ruby developers. We have quite a number of projects in the launching stage, from public Rails workshops to mentoring initiatives to some fun learning experiences for Ruby newcomers.</p>
<p>But the key message of RailsBridge is simple, and goes beyond any one project: the Rails community is the product of everyone who participates, and it can be a positive force for good in the world. We think there are enough Rails developers who feel this way that the somewhat negative image of Rails that is current in some parts of the web can be revised &#8211; not by claiming that we&#8217;re welcoming, but by actually acting that way.</p>
<p>If you&#8217;re already living in the Rails community that you want, great. But if recent events have convinced you that things could be improved, come join us! If we all work together to move things forward, then the awesome Rails codebase can be joined with an equally awesome community, and everyone wins. There&#8217;s more information on the <strong><a href="http://railsbridge.org">RailsBridge</a></strong> home page, or you can come join us on the <strong><a href="http://groups.google.com/group/railsbridge">RailsBridge Google Group</a></strong> to help build a better future.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[A Painful Decision]]></title>
<link>http://afreshcup.com/2009/04/28/a-painful-decision/</link>
<pubDate>Tue, 28 Apr 2009 11:18:39 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/04/28/a-painful-decision/</guid>
<description><![CDATA[There has been some discussion in recent days in the Rails community about appropriate conference pr]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>There has been some discussion in recent days in the Rails community about appropriate conference presentations, whether women feel welcome in the Rails community, and related issues. I don&#8217;t intend to review the entire mess here &#8211; you can find it if you want it. For what it&#8217;s worth, I think the original presentation was an inappropriate and regrettable mistake. However, far more disturbing to me are the reactions to the discussion on the part of some of the Rails community.</p>
<p>Folks, the idea that women are disproportionately underrepresented in engineering and software in general, and open source development in particular, should not be new and controversial in 2009 &#8211; anyone who cares to look can find such things as the <a href="http://flosspols.org/">FLOSSpols findings</a>, or any amount of academic literature on the subject. Anyone who cares to take the time to actually talk to the women who are a part of the open source community will have no trouble getting an earful about how challenging it can be to participate.</p>
<p>I don&#8217;t want to make the mistake of speaking of &#8220;the open source community&#8221; as some monolithic bloc. People like <a href="http://dyepot-teapot.com/2009/04/26/so-now-what/">Audrey Eschright</a>, <a href="http://www.quirkey.com/blog/2009/04/27/the-ghetto-of-the-mind/">Aaron Quint</a>, <a href="http://www.rubyrailways.com/rails-is-still-a-ghetto/">Peter Szinek</a>, and <a href="http://www.chesnok.com/daily/2009/04/27/what-works-getting-more-women-involved-in-open-source/">Selena Deckelmann</a> have written about ways to address some of the fundamental problems. </p>
<p>But unfortunately for me, in parallel to the public discussion there have been private ones. I can&#8217;t reveal details without breaking confidences, but suffice it to say that a significant number of Rails core contributors &#8211; with leadership (if that&#8217;s the right word) from DHH &#8211; apparently feel that being unwelcoming and &#8220;edgy&#8221; is not just acceptable, but laudable. The difference between their opinions and mine is so severe that I cannot in good conscience remain a public spokesman for Rails. </p>
<p>So, effective immediately, I&#8217;m resigning my position with the Rails Activists.</p>
<p>I realize that some people will see this as an act of prudery on my part, or a lack of a sense of humor, or some other personal failing. That&#8217;s OK, I don&#8217;t mind. Other people (who I have a good deal of respect for) have attempted to convince me that I could do more good by staying involved with the Rails power structure and trying to work from within to change things. At this point, unfortunately, I feel sufficiently outnumbered and unwelcome that that option is no longer open.</p>
<p>This does not mean that I will stop using Rails; on a technical level, it&#8217;s still a good fit for the projects that I work on. Nor does it mean that I will stop contributing to open source projects. But I&#8217;m no longer willing to donate a substantial portion of my free time to this particular project.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Touch your Active Record Instances]]></title>
<link>http://afreshcup.com/2009/04/19/touch-your-active-record-instances/</link>
<pubDate>Sun, 19 Apr 2009 12:45:22 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/04/19/touch-your-active-record-instances/</guid>
<description><![CDATA[Now that Rails 2.3 is out and the core team has caught their collective breath, new features are sta]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Now that Rails 2.3 is out and the core team has caught their collective breath, new features are starting to make their way into Rails. The latest: an implementation of <code>touch</code> for Active Record. This is in edge for both 2-3-stable and master (to be 3.0).</p>
<p>At its simplest, <code>touch</code> is just a bit of syntactic sugar that writes the current time to the <code>updated_at</code> or <code>updated_on</code> attribute of an ActiveRecord instance. This does <em>not</em> short-circuit the validation code, so if there are errors in the instance you&#8217;ll get <code>ActiveRecord::RecordInvalid</code> raised:</p>
<pre class="brush: ruby;">
@order.touch
</pre>
<p>But wait, there&#8217;s more! You can specify a different attribute to touch if you&#8217;d like:</p>
<pre class="brush: ruby;">
@order.touch(:shipped_at)
</pre>
<p>You can also specify <code>touch</code> options when defining a <code>belongs_to</code> relationship:</p>
<pre class="brush: ruby;">
class Order
  belongs_to :customer, :touch =&gt; true
end
</pre>
<p>In this case, saving or destroying an order instance will touch the corresponding <em>customer</em> instance. This is useful in cases where, for example, you&#8217;re caching customers but want them invalidated from the cache when a counter cache changes. You can also specify a particular attribute on the parent model to touch:</p>
<pre class="brush: ruby;">
class Order
  belongs_to :customer, :touch =&gt; <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rders_updated_at
end
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Batting Clean-up]]></title>
<link>http://afreshcup.com/2009/03/23/batting-clean-up/</link>
<pubDate>Tue, 24 Mar 2009 01:46:54 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/03/23/batting-clean-up/</guid>
<description><![CDATA[I&#8217;ve spent a lot of time over the past few years working with Rails projects that were written]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve spent a lot of time over the past few years working with Rails projects that were written by other people. Sometimes I&#8217;ve come on as a subcontractor to an existing codebase, sometimes I&#8217;ve taken over when another developer got bored or fired, sometimes I&#8217;ve been asked to do a code review. </p>
<p>Over the course of these engagements I&#8217;ve come up with a strategy for getting up and running on a new-to-me Rails codebase quickly. There aren&#8217;t any hard and fast rules; there are still a lot of variable factors. But overall, I find these guidelines useful:</p>
<p>Start in environment.rb and figure out which version of Rails the project needs. In my case, I&#8217;m working with everything from 1.1.6 to 2.3.2.1 at the moment, so using gem Rails is pretty much a non-starter. If a project doesn&#8217;t have vendored Rails when I get it, it will as soon as I figure out what version it wants to see. If you do vendor Rails into a shared project where others are working with gems, don&#8217;t forget to .gitignore vendor/rails.</p>
<p>Next I look at bringing the database up from scratch. If at all possible, I ask for a copy of a current production database to avoid doing this. If I can&#8217;t get one, I&#8217;ll start by running migrations, just to see whether the migrations have been maintained. If migrating from scratch blows up, there&#8217;s always schema.rb.</p>
<p>Next comes searching the code for <code>require</code> to see if I can figure out what gems the project needs (in rare cases, there are gems specified via the <code>gem.config</code> route, but so far I&#8217;m not seeing much of that). I install and upgrade any gems I can see as required, and then try to actually run the project via <code>script/server</code>. Usually this fails a few times as I discover missing dependencies, but I like to give it a few tries so I can have the code up and running while I explore it.</p>
<p>I spend a few minutes exploring vendor/plugins to see what non-gem plugins the project depends on as well. If it&#8217;s using any that I&#8217;m not familiar with, I check out the readme &#8211; assuming there is one.</p>
<p>With the app running, I turn to the MVC heart of things. Here, the models are my first stop. If there are a reasonable number of models (say, anything under about 30) I just start at the top and look at each one, making particular note of association declarations. I haven&#8217;t found an automatic ERD tool for Rails that I like, so I use this information to sketch out an ERD by hand, sorting out how the major entities connect to each other.</p>
<p>Next for me is <code>routes.rb</code>. Looking at this file is usually a good way to judge the sophistication of the previous developers. It also gives me some URLs to try out on the running code to see what happens. After I understand the basic routing, I&#8217;ll spend some time in controller code, looking to see if it seems unduly fat or otherwise confusing.</p>
<p>Finally I&#8217;ll spot check some views and helpers to see how clean the code looks. Usually I don&#8217;t try to read all the views, though, unless the first couple I touch on show me systemic problems.</p>
<p>By the time this process is done, I usually have a rough handle on how the code is structured. Combine that with some exploratory use of the running application on my local box, and Rails&#8217; conventions, and I can go in and find the code that needs to be improved, evaluated, or fixed.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Rails 2.3.2.1]]></title>
<link>http://afreshcup.com/2009/03/18/rails-2321/</link>
<pubDate>Wed, 18 Mar 2009 16:49:56 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/03/18/rails-2321/</guid>
<description><![CDATA[Rails 2.3.2.1 is out. There&#8217;s some confusion about this floating around already, so here]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Rails 2.3.2.1 is out. There&#8217;s some confusion about this floating around already, so here&#8217;s the scoop as I understand it:</p>
<ul>
<li>The original Rails 2.3.2 gems were built including <a href="http://github.com/rails/rails/commit/39ff550fa88da9a22d8c21ca872f5e4d0d83f8d4">this commit</a> from the Rails master tree, which is critical for proper functionality.</li>
<li>The 2.3.2 tag in GitHub unfortunately points to <a href="http://github.com/rails/rails/commit/73fc42cc0b5e94541480032c2941a50edd4080c2">this commit</a>, which is before the critical fix.</li>
<li>The net result is that <code>rake rails:freeze:edge RELEASE=2.3.2</code> would freeze a bad version of Rails into your application.</li>
</ul>
<p>To fix this, the Rails team has re-tagged the master tree at a safer spot, after the critical fix. This new tag is for release 2.3.2.1. So if you&#8217;re freezing Rails 2.3 into your applications (as opposed to running it from gems) be sure to use <code>rake rails:freeze:edge RELEASE=2.3.2.1</code>. That .1 makes all the difference.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Rails 2.3: Batch Finding]]></title>
<link>http://afreshcup.com/2009/02/23/rails-23-batch-finding/</link>
<pubDate>Mon, 23 Feb 2009 12:52:20 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/02/23/rails-23-batch-finding/</guid>
<description><![CDATA[If you&#8217;ve ever worked with a huge number of Active Record objects and watched your server memo]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>If you&#8217;ve ever worked with a huge number of Active Record objects and watched your server memory at the same time, you may have noticed considerably bloat in your Rails processes. That&#8217;s because Active Record doesn&#8217;t support database cursors (alas!) so all of those records come into memory at once.</p>
<p>In Rails 2.3, ActiveRecord::Base is adding two methods to help with this problem: <code>find_in_batches</code> and <code>each</code>. Both of these methods return records in groups of 1000, allowing you to process one group before proceeding to the next, and keeping the memory pressure down:</p>
<p><code>find_in_batches</code> is the basic method here:</p>
<pre class="brush: ruby;">
Account.find_in_batches(:conditions =&gt; {:credit =&gt; true}) do &amp;#124;accts&amp;#124;
  accts.each { &amp;#124;account&amp;#124; account.create_daily_charges! }
end
</pre>
<p><code>find_in_batches</code> takes most of the options that  <code>find</code> does, with the exception of <code> <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder</code> and <code>:limit</code>. Records will always be returned in order of ascending primary key (and the primary key must be an integer). To change the number of records in a batch from the default 1000, use the <code>:batch_size</code> option.</p>
<p>The <code>each</code> method provides a wrapper around <code>find_in_batches</code> that returns individual records:</p>
<pre class="brush: ruby;">
Account.each do &amp;#124;account&amp;#124;
  account.create_daily_charges!
end
</pre>
<p>A couple of caveats: first, if you&#8217;re trying to loop through less than 1000 or so records, you should avoid the overhead of batches and use something like <code>Account.all.each</code> or a regular finder to get the records. Second, if the table is very active (i.e., has a constant stream of inserts and deletes), using the batch methods may miss records due to changes in the table between batches (whereas finding all records will at least give you a complete point-in-time snapshot).</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Updating file_column]]></title>
<link>http://afreshcup.com/2009/02/19/updating-file_column/</link>
<pubDate>Thu, 19 Feb 2009 14:11:03 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/02/19/updating-file_column/</guid>
<description><![CDATA[I recently inherited a Rails application that used an old, old version of file_column to handle atta]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I recently inherited a Rails application that used an old, old version of file_column to handle attachments. As part of bringing things up to date, I updated file_column &#8211; and then it turned out that none of the site&#8217;s thousands of images could be seen any longer. So here&#8217;s a note for anyone who ends up in the same situation.</p>
<p>It turns out that over the years, the file_column plugin changed the naming that it uses for the actual stored files. They used to live in folders with names like /42, and now they&#8217;re in folders with names like /0000/0042. So, if you go from old to new, and don&#8217;t do something, your attached files are not where the plugin is expecting to find them.</p>
<p>Now, one way to deal with this is to move all the files around. <a href="http://codesnippets.joyent.com/posts/show/1982">Here&#8217;s a snippet of code</a> you can run in IRB to migrate your hard drive to the new locations, and I&#8217;m sure that&#8217;s a fine solution in many circumstances. But I had some additional constraints that made this impractical.</p>
<p>So instead, I set file_column back to the old naming. You&#8217;ll find the relevant code in <code>PermanentUploadedFile#relative_path_prefix</code>:</p>
<pre class="brush: ruby;">
def relative_path_prefix
  @instance.id.to_s
  # raise RuntimeError.new(&quot;Trying to access file_column, but primary key got lost.&quot;) if @instance.id.to_s.empty?
  # File.join(*(&quot;%08d&quot; % @instance.id).scan(/..../))
end
</pre>
<p>The commented-out code is the current version, the live code is the old version. With this change, the latest file_column will happily find files laid down by an older version.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[A Note on Memoization in Rails]]></title>
<link>http://afreshcup.com/2009/02/12/a-note-on-memoization-in-rails/</link>
<pubDate>Fri, 13 Feb 2009 01:51:57 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/02/12/a-note-on-memoization-in-rails/</guid>
<description><![CDATA[If you&#8217;ve been following along at home, you know that memoization was added to Rails 2.2 as a ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>If you&#8217;ve been following along at home, you know that <em>memoization</em> was added to Rails 2.2 as a shortcut for a common idiom:</p>
<pre class="brush: ruby;">
def site_term_ids
  @site_term_ids &amp;#124;&amp;#124; = cached_terms.split.map
     { &amp;#124;term&amp;#124; Term.find_by_query(term).id }
end
</pre>
<p>Memoization makes it possible to perform an expensive operation once, and then cache the results for future calls to the same property. What you may have missed, though, is that this isn&#8217;t baked into Active Record; it&#8217;s a separate part of Active Support. So if you&#8217;re getting mystery errors about memoization not working, be sure you&#8217;re including the right extension:</p>
<pre class="brush: ruby;">
class Site &lt; ActiveRecord::Base
  extend ActiveSupport::Memoizable

  def site_term_ids
    cached_terms.split.map
      { &amp;#124;term&amp;#124; Term.find_by_query(term).id }
  end
  memoize :site_term_ids

end
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Digging Into the Named Scope Magic]]></title>
<link>http://afreshcup.com/2009/02/06/digging-into-the-named-scope-magic/</link>
<pubDate>Fri, 06 Feb 2009 21:46:01 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/02/06/digging-into-the-named-scope-magic/</guid>
<description><![CDATA[I got an IM this afternoon from a friend, pointing to part of the Active Record Query Interface guid]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I got an IM this afternoon from a friend, pointing to part of the <strong><a href="http://guides.rubyonrails.org/active_record_querying.html">Active Record Query Interface guide</a></strong>:</p>
<blockquote><p>Then you could call Client.males.all to get all the clients who are male. Please note that if you do not specify the all on the end you will get a Scope object back, not a set of records which you do get back if you put the all on the end.</p></blockquote>
<p>Setting up a simple named scope and testing it in irb certainly seems to indicate that this passage is wrong:</p>
<pre class="brush: ruby;">
Client.males.is_a?(Array) =&gt; true
Client.males.is_a?(ActiveRecord::NamedScope::Scope)
 =&gt; false
</pre>
<p>And yet, a moment&#8217;s reflection says that named scopes can&#8217;t simply be returning arrays of ActiveRecord objects: if they were, there would be no way to compose them.</p>
<p>As with other Rails questions, the easiest way to answer this is to fire up a text editor and dig into the Rails source &#8211; in this case, activerecord/lib/active_record/named_scope.rb, which contains the definition of the <code>Scope</code> object and the other named scope apparatus. There you&#8217;ll find this chunk of code:</p>
<pre class="brush: ruby;">
NON_DELEGATE_METHODS = %w(nil? send object_id class extend find size
 count sum average maximum minimum paginate first last empty? any?
 respond_to?).to_set
[].methods.each do &amp;#124;m&amp;#124;
  unless m =~ /^__/ &amp;#124;&amp;#124; NON_DELEGATE_METHODS.include?(m.to_s)
    delegate m, :to =&gt; :proxy_found
  end
end
</pre>
<p>So: except for a small set of explicitly-listed methods, the <code>Scope</code> object delegates everything to <code>:proxy_found</code>. And what is that? Read a bit further in the source and you&#8217;ll find out:</p>
<pre class="brush: ruby;">
def proxy_found
  @found &amp;#124;&amp;#124; load_found
end

def load_found
  @found = find(:all)
end
</pre>
<p>So: for any method not in its small list &#8211; say, the <code>inspect</code> that IRB uses to display the value of an expression &#8211; the <code>Scope</code> looks at its internal results array, running the <code>find</code> to do so if necessary. Thus we have an object that at first glance appears to be something other than what it really is. Problem solved.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Rails 2.3: Localized Views]]></title>
<link>http://afreshcup.com/2009/02/01/rails-23-localized-views/</link>
<pubDate>Sun, 01 Feb 2009 21:04:57 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/02/01/rails-23-localized-views/</guid>
<description><![CDATA[One of the late-breaking changes to sneak into Rails 2.3 is localized views. If you&#8217;re staying]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>One of the late-breaking changes to sneak into Rails 2.3 is localized views. If you&#8217;re staying at all up to date, you know that Rails sports a nifty new internationalization framework as of version 2.2. But in 2.3, if you want to show different views depending on the visitor&#8217;s locale, it&#8217;s quite simple.</p>
<p>For example, suppose you have a <code>Pages</code> controller with an <code>about</code> action. Ordinarily, this will render <code>app/views/pages/about.html.erb</code>. But if you set <code>I18n.locale = :es</code>, it will render <code>app/views/pages/about.es.html.erb</code>. If the localized template isn&#8217;t present, the undecorated version will be used.</p>
<p>But why stop there? Rails doesn&#8217;t impose any particular limits on the symbols that you can set for <code>I18n.locale</code>, so if you want, you can hijack this system to display different content depending on anything you want. For example, suppose you have some users who are &#8220;expert&#8221; who should see different pages. Just do something like this:</p>
<pre class="brush: ruby;">
before_filter :set_expert_mode

def set_expert_mode
  I18n.locale = :expert if current_user.expert?
end
</pre>
<p>And then if you provide, say, <code>index.expert.html.erb</code>, that version will be displayed to expert users. If there&#8217;s no special view, they&#8217;ll just get the normal content.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Highlighting Text in Rails]]></title>
<link>http://afreshcup.com/2009/01/29/highlighting-text-in-rails/</link>
<pubDate>Thu, 29 Jan 2009 13:06:17 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/01/29/highlighting-text-in-rails/</guid>
<description><![CDATA[Presumably you&#8217;ve seen those Web 2.0 sites that highlight random words in the marketing text t]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Presumably you&#8217;ve seen those Web 2.0 sites that highlight random words in the marketing text to draw your attention. A little-known view helper in Rails makes this sort of thing trivial. For example, you can combine this markup in your view:</p>
<pre class="brush: ruby;">
&lt;%= highlight(&quot;Rails is a fabulous framework.
  When you start 'Riding the Rails' you'll never go back.&quot;,
  &quot;Rails&quot;) %&gt;
</pre>
<p>With this bit of CSS:</p>
<pre class="brush: css;">
.highlight  { background:#ff0; }
</pre>
<p>And you get this result:</p>
<p><img class="alignnone size-full wp-image-716" title="highlight" src="http://afreshcup.wordpress.com/files/2009/01/highlight.png" alt="highlight" width="310" height="51" /></p>
<p>Easy enough. But wait, there&#8217;s more! You can specify an entire array of words and phrases to highlight:</p>
<pre class="brush: ruby;">
&lt;%= highlight(@spam.body, ['free', 'money', 'claim']) %&gt;
</pre>
<p>Even better, <code>highlight</code> supports a <code>:highlight</code> option, which lets you specify a custom string to use for highlighting. The token <code>\1</code> will be replaced with the text to be highlighted. This lets you change the HTML markup:</p>
<pre class="brush: ruby;">
&lt;%= highlight(@marketing_text, 'today',
  :highlighter =&gt; '&lt;em&gt;\1&lt;/em&gt;') %&gt;
</pre>
<p>This ability to insert arbitrary surrounding markup makes <code>highlight</code> more flexible, if you let yourself think out of the box:</p>
<pre class="brush: ruby;">
&lt;%= highlight(@memberlist, @users.map(&amp;:name),
  :highlighter =&gt; '&lt;a href=&quot;/users/\1&quot;&gt;\1&lt;/a&gt;) %&gt;
</pre>
<p>It&#8217;s worth taking a dip into <strong><a href="http://apidock.com/rails/ActionView/Helpers">ActionView::Helpers</a></strong> occasionally to see what other bits of functionality are lurking that you&#8217;ve forgotten about.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Testing Active Record with JDBC]]></title>
<link>http://afreshcup.com/2009/01/27/testing-active-record-with-jdbc/</link>
<pubDate>Tue, 27 Jan 2009 11:48:35 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/01/27/testing-active-record-with-jdbc/</guid>
<description><![CDATA[You probably already know, at least vaguely, that Rails is working on JRuby compatibility (it&#8217;]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>You probably already know, at least vaguely, that Rails is working on JRuby compatibility (it&#8217;s most of the way there, but there are a few niggling bugs left). But did you know that Active Record also supports using a variety of databases via JDBC, which is a better fit for a JRuby-backed Rails installation than the usual sqlite or MySQL choices? As of a couple of days ago, you can easily see this in action by running the Active Record test suite. Here&#8217;s how:</p>
<p>Grab a copy of edge Rails. You need to have a copy recent enough that it includes <a href="http://github.com/rails/rails/commit/4ef9845aa324679b88e19b8223dd90b774215bc6">this commit</a>.</p>
<p>You need to have JRuby installed. For the best experience with Rails, you should grab and build JRuby from its own edge. The JRubyWiki has <a href="http://wiki.jruby.org/wiki/Getting_Started">instructions on downloading source and building yourself</a>. Even if you don&#8217;t know anything about java it&#8217;s pretty simple. Here&#8217;s how I did it on a Ubuntu box:</p>
<pre class="brush: ruby;">
sudo aptitude install sun-java6-jdk
mkdir jruby_trunk
svn co http://svn.codehaus.org/jruby/trunk/jruby jruby
cd jruby
svn up
ant
ant jar-complete
</pre>
<p>I&#8217;ve got some aliases set up that make it easy to use JRuby as my interpreter when I want to. These go in .bash_login:</p>
<pre class="brush: ruby;">
alias jr='export PATH=/home/myuser/jruby_trunk/jruby/bin:/home/myuser/.gem/jruby/1.8/bin:$ORIGPATH'
alias mr187p72='export PATH=~/.multiruby/install/1.8.7-p72/bin:$ORIGPATH'
alias mr191rc1='export PATH=~/.multiruby/install/v1_9_1_rc1/bin:$ORIGPATH'
alias mroff='export PATH=$ORIGPATH'
</pre>
<p>(Note that I have a couple of other Ruby versions installed on that box via multiruby as well).</p>
<p>You&#8217;ll need to install some gems to run the Rails tests. Note the special switch to install them where JRuby will see them:</p>
<p><code>jruby -S gem install mocha mysql postgres sqlite-ruby sqlite3-ruby fcgi rack jruby-openssl</code></p>
<p>To use any of the JDBC adapters, install the glue between Active Record and JDBC:</p>
<pre class="brush: ruby;">
jruby -s gem install activerecord-jdbc-adapter
</pre>
<p>You have your choice of lots of JDBC adapters. Let&#8217;s install them all!</p>
<pre class="brush: ruby;">
jruby -s gem install activerecord-jdbc-adapter
jruby -s gem install activerecord-jdbcderby-adapter
jruby -s gem install activerecord-jdbch2-adapter
jruby -s gem install activerecord-jdbchsqldb-adapter
jruby -s gem install activerecord-jdbcmysql-adapter
jruby -s gem install activerecord-jdbcpostgresql-adapter
jruby -s gem install activerecord-jdbcsqlite3-adapter
</pre>
<p>Time to get testing. For something easy, start with MySQL:</p>
<pre class="brush: ruby;">
cd ~/rails/activerecord
jruby -S rake test_jdbcmysql
</pre>
<p>With edge Rails this morning, you&#8217;ll get 19 test failures out of 1812 tests and 6032 assertions &#8211; not too bad. How about something more java-like, the <a href="http://hsqldb.org/">hsqldb database engine</a>?  </p>
<pre class="brush: ruby;">
cd ~/rails/activerecord
jruby -S rake test_jdbchsqldb
</pre>
<p>I&#8217;m getting around 600 test failures with this one at the moment.</p>
<p>Similar testing tasks exist for all of the other adapters I listed above. With these bits of glue coming into play, and the Rails and JRuby teams working together, we&#8217;re making our way towards a point where Rails on JRuby is a robustly-supported solution.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Announcing ActionRails]]></title>
<link>http://afreshcup.com/2009/01/20/announcing-actionrails/</link>
<pubDate>Tue, 20 Jan 2009 12:43:27 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/01/20/announcing-actionrails/</guid>
<description><![CDATA[As many of you know, I&#8217;ve been increasingly active in the Rails community in the last year. Wo]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>As many of you know, I&#8217;ve been increasingly active in the Rails community in the last year. Working on projects like the <a href="http://guides.rubyonrails.org/">Rails Guides</a>, <a href="http://weblog.rubyonrails.org/edge">This Week in Edge Rails</a>, the Rails 2.2 <a href="http://github.com/rails/rails/blob/68fdfde0039f44019b6967a5565b9d390f747395/railties/doc/guides/html/2_2_release_notes.html">Release Notes</a>, and the official <a href="http://ci.rubyonrails.org/">continuous integration server</a> for Rails have thrown me into contact with the Rails core team and other prominent folks in the Rails community. A few of us have gotten to talking, and discovered that we have similar concerns about Rails and the way it gets used in the real world.</p>
<p>As a result, I&#8217;m happy to announce the launch of <strong><a href="http://www.actionrails.com/">ActionRails</a></strong>, a new consulting firm jointly owned by <strong><a href="http://m.onkey.org/">Pratik Naik</a></strong>, <strong><a href="http://therailsway.com/">Michael &#8220;Koz&#8221; Koziarski</a></strong>, and myself. We&#8217;re not trying to be another group of developers who bang out Rails applications from start to finish (though any of us will be happy to talk to you individually about such projects). Rather, we&#8217;re interested in helping customers complete successful Rails deployments and helping existing teams improve their Rails skills.</p>
<p>ActionRails is already working for a few select clients, helping them stay on top of the Rails universe, reviewing code, offering course corrections, and evaluating application architecture (among other things). You can hop over to <a href="http://www.actionrails.com/services.html">our site</a> for more information, or just <a href="mailto:MikeG1@larkfarm.com">drop me a line</a> and I&#8217;ll be glad to chat about what we can do for your team.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Using Amazon Simple Pay from Rails]]></title>
<link>http://afreshcup.com/2009/01/04/using-amazon-simple-pay-from-rails/</link>
<pubDate>Sun, 04 Jan 2009 17:10:56 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2009/01/04/using-amazon-simple-pay-from-rails/</guid>
<description><![CDATA[I&#8217;ve recently been working to integrate Amazon Simple Pay into an application. In general, thi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>I&#8217;ve recently been working to integrate <a href="http://docs.amazonwebservices.com/AmazonFPS/2007-01-08/AmazonSimplePayImplementationGuide/">Amazon Simple Pay</a> into an application. In general, this has been pretty straightforward, thanks to the <a href="http://simplepay.rubyforge.org/">simplepay</a> gem, which was recently bumped to version 0.2.0. (Amazon also has their own <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=1754&#38;categoryID=126">Ruby sample for ASP integration</a>, which came in handy for a first smoke test &#8211; though unfortunately at the moment the Amazon site is having trouble delivering that file).</p>
<p>For the most part, using the simplepay gem is quite straightforward. There&#8217;s a helper to build a payment form:</p>
<pre class="brush: ruby;">
Click here to send us $120 every year
&lt;%= simplepay_form_for(:subscription, {
  :amount                 =&gt; 120.00,
  :description            =&gt; &quot;Annual Subscription&quot;,
  :recurring_frequency    =&gt; &quot;1 year&quot;,
  :abandon_url            =&gt;  amaz_abandon_customers_url,
  :collect_shipping_address =&gt; false,
  :immediate_return       =&gt;  false,
  :ipn_url                =&gt;  amaz_ipn_customers_url,
  :process_immediately    =&gt;  true,
  :reference_id           =&gt;  @customer.id,
  :return_url             =&gt;  amaz_return_customers_url
}) %&gt;
</pre>
<p>When Amazon executes callbacks, it sends a signature parameter along so that you can verify that the request is legitimate. This is the only spot where I ran into a little gotcha. The simplepay gem includes a helper to validate the parameters of a request to see if they match the signature, but you have to be sure to take out the parameters that Rails inserts before you call it:</p>
<pre class="brush: ruby;">
def amaz_ipn
    params.delete('controller')
    params.delete('action')
     if AWS::SimplePay::IpnValidator.valid_ipn_post?
(Simplepay.aws_secret_access_key, params)
      # save the results somewhere
      render :action =&gt; 'show'
    else
      logger.info &quot;bad request from Amazon Simple Pay&quot;
      render :nothing =&gt; true, :status =&gt; 200
    end
  end
</pre>
<p>Also note that you should send back a 200 response even if you&#8217;re unable to verify the signature. This will prevent Amazon from sending the same request to you over and over again.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Coming in Rails 2.3: Simpler Rendering]]></title>
<link>http://afreshcup.com/2008/12/26/coming-in-rails-23-simpler-rendering/</link>
<pubDate>Fri, 26 Dec 2008 14:47:47 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2008/12/26/coming-in-rails-23-simpler-rendering/</guid>
<description><![CDATA[Over the years, ActionController::Base#render has grown quite a few options: render :action =&gt; ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Over the years, <code>ActionController::Base#render</code> has grown quite a few options:</p>
<pre class="brush: ruby;">
render :action =&gt; &quot;edit&quot;
render :template =&gt; &quot;products/show&quot;
render :file =&gt; &quot;/u/apps/other/warning.html&quot;
render :nothing =&gt; true
render :inline =&gt; &quot;&lt;% @product.name %&gt;&quot;
render :update {&amp;#124;p&amp;#124; p.replace_html &quot;A&quot;, &quot;Error!&quot;}
render :text =&gt; &quot;OK&quot;
render :json =&gt; @product
render <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml =&gt; @product
render :js =&gt; &quot;alert('error!');&quot;
</pre>
<p>Those options will still be in Rails 2.3, but the first three have a simpler alternative now:</p>
<pre class="brush: ruby;">
render &quot;edit&quot;
render &quot;products/show&quot;
render &quot;/u/apps/other/warning.html&quot;
</pre>
<p>Rails will figure out whether you&#8217;re rendering an action, template, or file, and do the right thing. In addition, if you like symbols, you can render an action via a symbol:</p>
<pre class="brush: ruby;">
render :edit
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Multi-variable Initialization Gotcha]]></title>
<link>http://afreshcup.com/2008/12/23/multi-variable-initialization-gotcha/</link>
<pubDate>Tue, 23 Dec 2008 18:14:43 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2008/12/23/multi-variable-initialization-gotcha/</guid>
<description><![CDATA[Sometimes the fact that I don&#8217;t know all the ins and outs of Ruby, coupled with habits carried]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Sometimes the fact that I don&#8217;t know all the ins and outs of Ruby, coupled with habits carried over from other languages, turns around to bite me. Here&#8217;s a console session demonstration of the latest problem I had:</p>
<pre class="brush: ruby;">
&gt;&gt; a = b = 2
=&gt; 2
&gt;&gt; a = 3
=&gt; 3
&gt;&gt; b
=&gt; 2
&gt;&gt; a = b = []
=&gt; []
&gt;&gt; a &lt;&lt; 2
=&gt; [2]
&gt;&gt; b
=&gt; [2]
&gt;&gt; a = []; b = []
=&gt; []
&gt;&gt; a &lt;&lt; 2
=&gt; [2]
&gt;&gt; b
=&gt; []
</pre>
<p>So, trying to initialize multiple arrays and multiple integers doesn&#8217;t work the same. Live and learn.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Auditing for attr_accessible]]></title>
<link>http://afreshcup.com/2008/12/14/auditing-for-attr_accessible/</link>
<pubDate>Mon, 15 Dec 2008 01:27:53 +0000</pubDate>
<dc:creator>Mike Gunderloy</dc:creator>
<guid>http://afreshcup.com/2008/12/14/auditing-for-attr_accessible/</guid>
<description><![CDATA[By now, you all know that you need to use attr_accessible to protect your application from having an]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>By now, you all know that <a href="http://railspikes.com/2008/9/22/is-your-rails-application-safe-from-mass-assignment">you need to use attr_accessible</a> to protect your application from having any old Active Record attribute changed by a malicious user. I find myself, in the course of consulting, looking at a great number of existing applications, and I&#8217;ve grown tired of having to open up every model and look. So, let&#8217;s be a bit smart: here&#8217;s a rake task that you can drop in any existing application to do the audit for you:</p>
<pre class="brush: ruby;">
namespace :utility do

  desc 'Find models that are not using attr_accessible'
  task :audit_attr_accessible =&gt; :environment do

    all_models = Dir.glob(
      File.join(Rails.root, 'app', 'models', '*.rb')
      ).map{&amp;#124;path&amp;#124; path[/.+\/(.+).rb/,1] }
    ar_models = all_models.select{&amp;#124;m&amp;#124;
       m.classify.constantize &lt; ActiveRecord::Base}

    ar_models.each do &amp;#124;model&amp;#124;
      model_class = model.classify.constantize
      if model_class.send(&quot;attr_accessible&quot;).empty? &amp;&amp;
         model_class.send(&quot;attr_protected&quot;).empty?
        puts model_class.class_name +
          &quot; allows unprotected mass assignment&quot;
      end
    end

  end

end
</pre>
<p>(Hat tip <a href="http://blog.matt-darby.com/2008/05/16/iterating-over-all-models-in-rails/">Matt</a> for the snippet to find all models).</pre>
</div>]]></content:encoded>
</item>

</channel>
</rss>
