<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-30954145</id><updated>2011-12-21T08:00:11.868-08:00</updated><title type='text'>Progress vs. Perfection</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-30954145.post-524085720148258163</id><published>2008-12-12T11:30:00.000-08:00</published><updated>2009-01-14T11:40:15.377-08:00</updated><title type='text'>TDD: I am finally getting it</title><content type='html'>My friend Mark and I have talked a lot in the past about doing more at unit testing.  That's something I've really been focusing on lately and one of the things that has come out of it is that code written for unit tests is subtly different than code not.  This became crystal clear to me just a moment ago as I was writing this code:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://pastie.org/322821"&gt;http://pastie.org/322821&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The first way I wrote it was a somewhat untestable way of doing things: in order to test AllowPost my unit test had to know all about our configuration stuff and it just couldn't easily be tested without a bunch of dependencies.  Of course, my unit test framework doesn't know about those dependencies without making it jump through a whole bunch of hoops.  By re-writing it the second way, the method AllowPost was an atomic unit that could be tested without knowing about the other stuff.&lt;br /&gt;&lt;br /&gt;Of course, I want some tests that cover "the other stuff", but that's at a higher level.  First, I have to get the lowest levels of tests working before the higher level tests will, otherwise it's all spaghetti.&lt;br /&gt;&lt;br /&gt;This may all be old news to you, but for me it really drove home the phrase "test-driven development"...in other words, the tests are actually shaping the code.  Suddenly, it makes so much sense why, in order for TDD to be effective, you have to write the tests first.  Otherwise, you may end up with code that isn't testable in terms of a unit test framework.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-524085720148258163?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/524085720148258163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=524085720148258163' title='40 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/524085720148258163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/524085720148258163'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2008/12/tdd-i-am-finally-getting-it.html' title='TDD: I am finally getting it'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>40</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-2974299624794855893</id><published>2008-05-09T02:56:00.001-07:00</published><updated>2008-05-09T02:59:25.127-07:00</updated><title type='text'>attachment_fu (with rmagick) on windows not working</title><content type='html'>man, i had a heck of a time getting attachment_fu (using rmagick) on windows working tonight.  let me just start with this: if you're having problems, just reboot.  it would have saved me an hour.&lt;br /&gt;&lt;br /&gt;i followed all the instructions and fixed all the hacks, yet for some reason thumbnails were not generating and the height and width was not being saved.  there are lots and lots of articles out there on these topics.  most of them discuss how the size isn't being saved, but in my case the size &lt;span style="font-style: italic;"&gt;was&lt;/span&gt; being saved.&lt;br /&gt;&lt;br /&gt;how'd fix it: i rebooted the machine and it worked.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-2974299624794855893?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/2974299624794855893/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=2974299624794855893' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2974299624794855893'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2974299624794855893'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2008/05/attachmentfu-with-rmagick-on-windows.html' title='attachment_fu (with rmagick) on windows not working'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-7898829975276361155</id><published>2008-02-17T18:04:00.000-08:00</published><updated>2008-02-17T18:17:10.613-08:00</updated><title type='text'>How To Upgrade to Rails 2.0 from 1.2.5</title><content type='html'>I had to upgrade my Rails app last night to 2.0.2 from 1.2.5.  This is a brief overview of what it took to make it happen.  I'll write some other posts soon with more details.  A little background: I'm using InstantRails and the Aptana RadRails IDE on Windows XP SP2.&lt;br /&gt;&lt;br /&gt;Here's what I did:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Installed Instant Rails 2.0.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Checked out a working copy of my code from SVN&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Updated environments.rb: RAILS_GEM_VERSION = '2.0.2'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fired it up: didn't work.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I'm using acts_as_tree and acts_as_list, so I needed to install those plugins.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fired it up: didn't work.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;I'm also using Comatose, and there was an error with the "template_root".  Bottom line: after reading some message boards, etc. I removed and reinstalled the Comatose plugin and that fixed it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fired it up: didn't work.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Was getting this error:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Status: 500 Internal Server Error&lt;br /&gt;  A secret is required to generate an integrity hash for cookie session data. Us&lt;br /&gt;e config.action_controller.session = { :session_key =&gt; "_myapp_session", :secret&lt;br /&gt; =&gt; "some secret phrase of at least 30 characters" } in config/environment.rb&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Well, that message says it all, so I changed that.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fired it up: was working.  Now, navigated my app...errors.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Had to change ':dependent =&gt; true' to ':dependent =&gt; :destroy'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Removed the line(s) config/environments/development.rb:12:  config.breakpoint_server = true&lt;br /&gt;from configuration since the setting has no effect anymore.&lt;br /&gt;  Instead, start `script/server` with the "-u" or "--debugger" option (or "-h"&lt;br /&gt;  to see all the options).  This wasn't causing an error, but while trying to figure out the dependent =&gt; :destroy thing, I read it on someone's blog, so I removed it.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Also, had to install the classic_pagination plugin.  (Really, every blog out there says I should upgrade to will_paginate, but my blog is about progress vs. perfection.  Old school pagination works for me for now, so I'll stick with it.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Fired it up...everything running, but still some functionality isn't working.  (Gee...I wish I'd writen *all* the unit tests.  Okay, let's debug.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Opened RadRails, imported existing directory into a project.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Got this error: rad rails "Cannot find gem for Rails ~&gt;2.0.2.0:"...had to switch workspace because I installed the new Instant Rails and RadRails was still pointing at the old one.  (Not an issue if you overwrite, but I'm running my concurrently.)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Hmmm...the server runs through Aptana RadRails, but debugger is slow as heck...turns out that I updated ruby-debug-ide when I updated gems and that un-checked the checkbox for using the fast debugger in the IDE.  Also, had to install ruby-debug-base.  (I don't think this was required before, but once I installed it the debugger worked.)&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Whew, well, I haven't found my bug yet, but that's how far I've progressed.  Hopefully this will help the next guy out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-7898829975276361155?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/7898829975276361155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=7898829975276361155' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7898829975276361155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7898829975276361155'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2008/02/how-to-upgrade-to-rails-20-from-125.html' title='How To Upgrade to Rails 2.0 from 1.2.5'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-9102869006856571484</id><published>2007-12-31T15:02:00.001-08:00</published><updated>2007-12-31T15:33:22.463-08:00</updated><title type='text'>Rails vs. ASP.NET (Really, Ruby vs C#)</title><content type='html'>Where have I been...why the lack of posts: a) holidays, b) knee injury playing basketball (that required surgery to repair) has slowed me down, c) recently, I've started to work on a project where ASP.NET using C# was the requirement.  &lt;br /&gt;&lt;br /&gt;So, I haven't been working in Rails for a few weeks and it's been a few years since I've used ASP.NET or C#, so I've had to jump back into it a little to refresh myself.&lt;br /&gt;&lt;br /&gt;Now, look, I'm not trying to start a religious war here: ASP.NET and Rails each have their own benefits and drawbacks.  However, I would like to say this: for simple web sites Rails is so much &lt;span style="font-style:italic;"&gt;easier&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Here's a simple example: I've got a URL stored in the database, such as http://www.mysite.com/foo/fee/foh.htm and I need to get the foh.htm (which isn't stored).  &lt;br /&gt;&lt;br /&gt;ASP.NET with C#&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    public string FileName&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            char[] delim = { '/' };&lt;br /&gt;            string[] a = this.Url.Split(delim);&lt;br /&gt;            return a[a.Length - 1];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;  &lt;br /&gt;Rails with Ruby&lt;br /&gt;&lt;code&gt;&lt;pre&gt;  def filename&lt;br /&gt;    self.url.split('/').last&lt;br /&gt;  end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I'm sure I'm not the first person to make this comparison.  I just felt compelled to speak out about the many moments during the day where it takes me several minutes longer to do something with ASP.NET and C# than Ruby and Rails.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-9102869006856571484?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/9102869006856571484/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=9102869006856571484' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/9102869006856571484'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/9102869006856571484'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/12/rails-vs-aspnet-really-ruby-vs-c.html' title='Rails vs. ASP.NET (Really, Ruby vs C#)'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-8402606529254794752</id><published>2007-12-20T09:53:00.000-08:00</published><updated>2007-12-20T10:01:38.259-08:00</updated><title type='text'>How to Make Subversion via HTTP work with RailsMachine (and Capistrano)</title><content type='html'>Last night I setup my site on RailsMachine.  Overall, it was a very pleasant experience.  One bugaboo that I ran into:&lt;br /&gt;&lt;br /&gt;I have my Subversion repository setup using http, not svn+ssh.  The repository is hosted at Joyent and I don't recall why I set it up this way, but there must have been a reason.&lt;br /&gt;&lt;br /&gt;Anyhoo...so, I'm plugging away with RailsMachine and using Capistrano for the first time and it's all pretty sweet, except for I can't seem to access my svn repository.  Cap would reach the point in the script where it made the HTTP request and I would see the HTTP authentication, but I had no way to type in my user/pass combo, and it would fail.&lt;br /&gt;&lt;br /&gt;Long story short: RailsMachine requires that you run Cap using a user called "deploy", and those are the credentials that Cap passes via HTTP Authentication to the svn repository.  So, I was able to get it to work by simply creating a user for my svn repository called "deploy" with the same password as "deploy" on my RailsMachine server.  Everything works fine now!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-8402606529254794752?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/8402606529254794752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=8402606529254794752' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8402606529254794752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8402606529254794752'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/12/how-to-make-subversion-via-http-work.html' title='How to Make Subversion via HTTP work with RailsMachine (and Capistrano)'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-40489445506493417</id><published>2007-12-11T09:33:00.000-08:00</published><updated>2007-12-11T10:11:26.403-08:00</updated><title type='text'>more on attachment_fu on windows</title><content type='html'>In my previous post about &lt;a href="http://progress-vs-perfection.blogspot.com/2007/11/attachmentfu-with-rmagick-on-windows.html"&gt;attachment_fu (with rmagick) on windows&lt;/a&gt;, I did something sort of silly in the #create action of my controller: Windows required a little time to catch up because the file system loaded the file slower that attachemnt_fu needed it.  To solve that problem, I added "sleep 5" immediately before MyObject#save.&lt;br /&gt;&lt;br /&gt;The problem with that hack is every time I need to #save I have to remember to insert the "sleep 5" hack.  That's a mistake waiting to happen.  So, I moved the sleep to the model, like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;  class MyObject &lt; ActiveRecord::Base&lt;br /&gt;    def before_save&lt;br /&gt;      sleep 5  ## &lt;&lt;-- pauses so Windows can catch up.  &lt;br /&gt;    end&lt;br /&gt;  end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;It's much more logical that this code is part of the model because the delay is fundamentally a part saving the object, not a part of responding to an action.  &lt;br /&gt;&lt;br /&gt;This also address the notion of keeping your controllers skinny and your models fat.  Jamis Buck blogs very eloquently about this notion &lt;a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-40489445506493417?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/40489445506493417/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=40489445506493417' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/40489445506493417'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/40489445506493417'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/12/more-on-attachmentfu-on-windows.html' title='more on attachment_fu on windows'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-1642765449920383029</id><published>2007-11-19T22:42:00.001-08:00</published><updated>2007-11-19T23:43:49.595-08:00</updated><title type='text'>attachment_fu (with rmagick) on windows</title><content type='html'>Today, I've been working to get attachment_fu working with rmagick on Windows.  At first, it wasn't uploading the file properly and after much Googling implemented these changes to get it working.&lt;br /&gt;&lt;br /&gt;1.  I added a pause to my #create in order to allow Windows time to catch up.  In short, Ruby is moving faster than the Windows file system, and it was trying to create a record for a file that didn't exist yet.  Here's what I did:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;  def create&lt;br /&gt;    @upload = Upload.new(params[:upload])&lt;br /&gt;    sleep 5  ## &lt;&lt;-- pauses so Windows can catch up.  Probably would be&lt;br /&gt;             ## smart to make this something like sleep 5 if OS == Windows&lt;br /&gt;             ## obviously, that's not the right syntax.&lt;br /&gt;    if @upload.save&lt;br /&gt;      flash[:notice] = 'Upload was successfully created.'&lt;br /&gt;      redirect_to :action =&gt; 'list'&lt;br /&gt;    else&lt;br /&gt;      render :action =&gt; 'new'&lt;br /&gt;    end&lt;br /&gt;  end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I am fully aware that this is a hack, but it gets the job done.&lt;br /&gt;&lt;br /&gt;2.  I continued to get the error message "Size is not included in the list".  Long story short, this is the error message attachment_fu returns when the file size exceeds the limit set in the model.  In addition, it provides this message if no file is provided at all which is a duplicate error because validates_as_attachment is already doing a validates_presence_of against the size.&lt;br /&gt;&lt;br /&gt;So, in order to create some better error messaging, and following the notions of how to hack a plugin from &lt;a href="http://errtheblog.com/post/19679"&gt;this blog post&lt;/a&gt;, I created a new plugin called attachment_fu_hacks and in init.rb added this code:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;klass = Numeric&lt;br /&gt;klass.class_eval do&lt;br /&gt;  def to_human&lt;br /&gt;    units = %w{B KB MB GB TB}&lt;br /&gt;    e = (Math.log(self)/Math.log(1024)).floor&lt;br /&gt;    s = "%.1f" % (to_f / 1024**e)&lt;br /&gt;    s.sub(/\.?0*$/, ' ' + units[e])&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;klass = Technoweenie::AttachmentFu::InstanceMethods&lt;br /&gt;klass.module_eval do&lt;br /&gt;  &lt;br /&gt;  # overrides attachment_fu.rb:342 b/c to provide better error messages&lt;br /&gt;  def attachment_attributes_valid?&lt;br /&gt;   &lt;br /&gt;    attr_name = :size&lt;br /&gt;    enum = attachment_options[attr_name]&lt;br /&gt;    val = send(attr_name)&lt;br /&gt;    if !enum.nil? &amp;&amp; !val.nil? &amp;&amp; !enum.include?(val)&lt;br /&gt;      err_msg = enum.end.to_human&lt;br /&gt;      errors.add attr_name, "of file is too big (must be less than #{err_msg})"&lt;br /&gt;    end&lt;br /&gt;    &lt;br /&gt;    attr_name = :content_type&lt;br /&gt;    enum = attachment_options[attr_name]&lt;br /&gt;    val = send(attr_name)&lt;br /&gt;    if !enum.nil? &amp;&amp; !val.nil? &amp;&amp; !enum.include?(val)&lt;br /&gt;      err_msg = enum.join(', ').gsub(/image\//, '.') unless enum.nil?&lt;br /&gt;      errors.add attr_name, "is not supported (must be #{err_msg})"      &lt;br /&gt;    end&lt;br /&gt;  end&lt;br /&gt;end  &lt;br /&gt;&lt;br /&gt;klass = Technoweenie::AttachmentFu::ClassMethods&lt;br /&gt;klass.module_eval do&lt;br /&gt;  # overrides attachment_fu.rb:106 b/c i don't think it's necessary &lt;br /&gt;  # to evaluate size or content_type if there is no file&lt;br /&gt;  def validates_as_attachment&lt;br /&gt;    validates_presence_of :filename&lt;br /&gt;    validate              :attachment_attributes_valid?&lt;br /&gt;  end  &lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I recognize that there might be a more idiomatic Ruby way to write attachment_attributes_valid?, but I prefer this because it's very clear as to what's going on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-1642765449920383029?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/1642765449920383029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=1642765449920383029' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1642765449920383029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1642765449920383029'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/11/attachmentfu-with-rmagick-on-windows.html' title='attachment_fu (with rmagick) on windows'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-4989555404240679236</id><published>2007-11-08T16:42:00.000-08:00</published><updated>2007-11-08T16:52:18.693-08:00</updated><title type='text'>Issue with has_many and Array.empty?</title><content type='html'>I've posted a narrative of my issue on the &lt;a href="http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/ba40ce266ed53161/7f43de07f06dbdcb#7f43de07f06dbdcb"&gt;Google Rails Group&lt;/a&gt;: &lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;br /&gt;/app/controllers/document_groups_controller.rb&lt;br /&gt;  def show&lt;br /&gt;    @document_group = DocumentGroup.find(params[:id])&lt;br /&gt;    @journal = Journal.find(params[:journal_id])&lt;br /&gt;    @document_group_templates = @document_group.document_templates&lt;br /&gt;    @logger = RAILS_DEFAULT_LOGGER&lt;br /&gt;    &lt;br /&gt;    #&lt;br /&gt;    # this is the money line: comment it out and @document_group_templates.empty?&lt;br /&gt;    # is true in the view.  leave it in, and it's false.  true is correct.&lt;br /&gt;    #&lt;br /&gt;    @logger.debug "###### ---&gt;" + @document_group_templates.inspect&lt;br /&gt;    #&lt;br /&gt;    # it turns out that this triggers the SQL to be run by Rails that acutally&lt;br /&gt;    # populates the @document_group_templates Array.&lt;br /&gt;    #&lt;br /&gt;&lt;br /&gt;    render :action =&gt; :show, :layout =&gt; 'ajax_div'&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;/app/views/document_groups/show.rhtml&lt;br /&gt;#&lt;br /&gt;#@document_group_templates.empty? evaluates to true without the inspection above&lt;br /&gt;#&lt;br /&gt;&amp;lt;% if !@document_group_templates.empty? %&amp;gt;&lt;br /&gt;# &lt;br /&gt;# now, what's interesting is that if i change this to &lt;br /&gt;#&lt;br /&gt;#  if @document_group_templates.count &amp;gt; 0&lt;br /&gt;#&lt;br /&gt;# that also triggers the SQL to be run.  but, interestingly, #size does not &lt;br /&gt;# trigger the SQL.&lt;br /&gt;#&lt;br /&gt; &amp;lt;ul&amp;gt;&lt;br /&gt; &amp;lt;% &lt;br /&gt;  @document_group_templates.each do |child| &lt;br /&gt;            %&amp;gt;&amp;lt;li&amp;gt;&amp;lt;%= link_to child.name, :controller =&amp;gt; :template, :action =&amp;gt; :show, :id =&amp;gt; child.id %&amp;gt;&amp;lt;%&lt;br /&gt;  end&lt;br /&gt;  %&gt;&lt;br /&gt;  &amp;lt;/ul&amp;gt;&lt;br /&gt;&amp;lt;% end %&amp;gt;&lt;br /&gt;&lt;br /&gt;/app/models/document_group.rb&lt;br /&gt;class DocumentGroup &lt; ActiveRecord::Base&lt;br /&gt;  has_many :document_templates, :order =&gt; :document_group_position&lt;br /&gt;  acts_as_tree :counter_cache =&gt; true&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;/app/models/document_template.rb&lt;br /&gt;class DocumentTemplate &lt; ActiveRecord::Base&lt;br /&gt;  belongs_to :document_group, :counter_cache =&gt; true&lt;br /&gt;  acts_as_list :scope =&gt; :document_group, :column =&gt; :document_group_position&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-4989555404240679236?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/4989555404240679236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=4989555404240679236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4989555404240679236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4989555404240679236'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/11/issue-with-arrayempty.html' title='Issue with has_many and Array.empty?'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-6420129065754230983</id><published>2007-11-05T13:59:00.000-08:00</published><updated>2007-11-05T14:12:28.734-08:00</updated><title type='text'>How to call render :partial properly</title><content type='html'>At some point, you may be going bananas because you're getting this error:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;NoMethodError in DocumentController#new&lt;br /&gt;undefined method `include?' for :new:Symbol&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;and the problem is that you're doing this somewhere:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;render :partial =&gt; :new&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;instead of this:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;render :partial =&gt; 'new'&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;This error is spawned by the method partial_pieces in /ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_view/partials.rb:90 which is trying to figure out if the partial you're calling is in the directory of the current controller, or some other directory.  Here's that code:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;89      def partial_pieces(partial_path)&lt;br /&gt;90        if partial_path.include?('/')&lt;br /&gt;91          return File.dirname(partial_path), File.basename(partial_path)&lt;br /&gt;92        else&lt;br /&gt;93          return controller.class.controller_path, partial_path&lt;br /&gt;94        end&lt;br /&gt;95      end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;The error comes from line 90.  Seems like if this were inserted at line 89.5, then this problem could be handled more gracefully&lt;br /&gt;&lt;code&gt;&lt;pre&gt;partial_path = partial_path.to_s if partial_path.is_a? Symbol&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;given the fuzzyness of symbols and strings, it would seem to make sense to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-6420129065754230983?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/6420129065754230983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=6420129065754230983' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6420129065754230983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6420129065754230983'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/11/how-to-call-render-partial-properly.html' title='How to call render :partial properly'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-8973844359430203280</id><published>2007-10-29T17:45:00.001-07:00</published><updated>2007-10-29T17:50:28.201-07:00</updated><title type='text'>How to Avoid and Infinite Loop with before_save and after_save</title><content type='html'>I have an entity that looks something like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;journal&lt;br /&gt;  author_first_name&lt;br /&gt;  author_last_name&lt;br /&gt;  journal_name&lt;br /&gt;  journal_email_address&lt;/pre&gt;&lt;br /&gt;where&lt;br /&gt;&lt;pre&gt;journal_name = author_first_name + ' ' + author_last_name&lt;br /&gt;journal_email_address = journal_name + '-' id&lt;/pre&gt;&lt;br /&gt;I had journal_name and journal_email_address implemented as attributes on the Journal model, but the time came along where, for various reasons, it has become valuable to also store that information in the database. So, what I thought I’d do, in app/models/journal.rb:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;def make_journal_name&lt;br /&gt;  self.journal_name = self.author_first_name + ' ' + self.author_last_name&lt;br /&gt;end  &lt;br /&gt;&lt;br /&gt;def make_inbound_email&lt;br /&gt;  self.inbound_email = self.journal_name.gsub(/[^a-zA-Z0-9]/, '') + '-' + self.id.to_s&lt;br /&gt;end&lt;br /&gt;def before_save&lt;br /&gt;  make_journal_name&lt;br /&gt;  make_inbound_email&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;which works fine in the case of an update of an existing record. However, it does not work in the case of a creation of a new record because before saving self.id does not exist. The result was my e-mail addresses are looking like “SallyJones-” as opposed to “SallyJones-64”.&lt;br /&gt;&lt;br /&gt;Okay, I thought, “since I need an ID to work with I’ll move this to after_save,” like so:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;def after_save&lt;br /&gt;  make_journal_name&lt;br /&gt;  make_inbound_email&lt;br /&gt;  self.save&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;but that creates an infinite loop.&lt;br /&gt;&lt;br /&gt;The solution to this problem is to use an undocumented method: update_without_callbacks.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;def after_save&lt;br /&gt;  make_journal_name&lt;br /&gt;  make_inbound_email&lt;br /&gt;  self.update_without_callbacks&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;update_without_callbacks is an instance method on ActiveRecord::Base, but for some reason it’s undocumented. In fact, it explicitly has :nodoc set in the source, although I can’t figure out why. To me, it seems that having more documented is better than having less.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-8973844359430203280?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/8973844359430203280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=8973844359430203280' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8973844359430203280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8973844359430203280'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/how-to-avoid-and-infinite-loop-with.html' title='How to Avoid and Infinite Loop with before_save and after_save'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-3460136318470347554</id><published>2007-10-24T17:05:00.000-07:00</published><updated>2007-10-24T17:33:01.185-07:00</updated><title type='text'>The Rails Way</title><content type='html'>A big part of using Rails is understanding that if you conform to "The Rails Way" things are much easier.  Of course, The Rails Way might not work for your project, and in that case, Rails might not be the right framework choice.  But, you have to learn The Rails Way in order to know.&lt;br /&gt;&lt;br /&gt;I can't claim to explain The Rails Way completely, but I've been helping a new (to Rails) developer on my team get up and running, so I've been having to coach him to see  The Rails Way.&lt;br /&gt;&lt;br /&gt;I started by talking about "entities".  An entity is a thing like a "widget"...some object in our application domain that we need to represent.  By convention, the names of the database table, unit tests, models, controllers, views, layouts and helpers must always coordinated in Rails to the name of the entity.  So, with our "widget" entity, this is how they should be:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;DB Table: widgets&lt;br /&gt;&lt;li&gt;Model: app/models/widget.rb&lt;br /&gt;&lt;li&gt;Controller: app/controllers/widgets_controller.rb&lt;br /&gt;&lt;li&gt;View: app/views/widget/...&lt;br /&gt;&lt;li&gt;Layout: app/views/layouts/widgets.rhtml&lt;br /&gt;&lt;li&gt;Helper: app/helpers/widgets_helper.rb&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The beautiful thing about Rails is that by using generators, this gets managed for you.  Here’s the approach I always take when creating an entity.  This can be done through an IDE (such as RadRails, which is what I use) or on the command line...I’ll use the command line here:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;font face="courier new"&gt;cd path/to/rails/app&lt;/font&gt;&lt;br /&gt;&lt;li&gt;&lt;font face="courier new"&gt;ruby ./script/generate model Widget&lt;/font&gt; which will generate your model file and your migration file with the proper table name.&lt;br /&gt;&lt;li&gt;Open up the migration, add the appropriate columns and save.&lt;br /&gt;&lt;li&gt;&lt;font face="courier new"&gt;rake db:migrate&lt;/font&gt; to apply your migration to the DB.&lt;br /&gt;&lt;li&gt;&lt;font face="courier new"&gt;ruby ./script/generate scaffold Widget&lt;/font&gt; which will create your controller, views, layout and helper.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Generators create a starting point to start editing, and it also gets all the file names correct.  Let’s talk about the editing that needs to happen.  Personally, I always do my editing in this order:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Migration&lt;br /&gt;&lt;li&gt;Model&lt;br /&gt;&lt;li&gt;Controllers&lt;br /&gt;&lt;li&gt;Views&lt;br /&gt;&lt;li&gt;Layouts&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;This makes the most sense to me because I’m starting with the raw data, and working my way forward to what the user sees on the web page.&lt;br /&gt;&lt;br /&gt;A little background on controllers (a good article to read is this: http://www.softiesonrails.com/search?q=rest+101): Your standard CRUD controller has 8 actions:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Create (Create): /widgets/create&lt;br /&gt;&lt;li&gt;Show (Read): /widgets/show/:id&lt;br /&gt;&lt;li&gt;Update (Update): /widgets/update/:id&lt;br /&gt;&lt;li&gt;Destroy (Delete): /widgets/destroy/:id&lt;br /&gt;&lt;li&gt;New (precursor to create): /widgets/new&lt;br /&gt;&lt;li&gt;Edit (precursor to update): /widgets/edit/:id&lt;br /&gt;&lt;li&gt;List (lists all entities): /widgets/list&lt;br /&gt;&lt;li&gt;Index (the default action): /widgets&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;When, you generate your scaffold, it’s going to automatically generate the 8 actions above.  When designing entities if you have methods that don't fit within one of those actions then it's typically an indication that your entity model could our should be designed differently.&lt;br /&gt;&lt;br /&gt;(A great example of how it's all about entity design is the login and logout actions for a User.  I was thinking the other day about where the login and logout methods belong because they make sense on a User, but they aren't one of the above eight actions.  Of course, I was thinking about it all wrong: login and logout are really the Create and Destroy methods on the Session entity, and Session entities belong to a User.)&lt;br /&gt;&lt;br /&gt;Finally, a note in regard to the relationships between views, controllers and models in the context of validation.  The typical user pattern in relation to creating an entity is:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;User visits &lt;font face="courier new"&gt;/widgets/new&lt;/font&gt; page&lt;br /&gt;&lt;li&gt;Enters data, click submit.&lt;br /&gt;&lt;li&gt;&lt;font face="courier new"&gt;/widgets/new&lt;/font&gt; POSTs to Widgets#create&lt;br /&gt;&lt;li&gt;Widgets#create puts the data in the DB, then (if you look at the scaffold generated controller)&lt;ul&gt;&lt;br /&gt;&lt;li&gt;If success, calls &lt;font face="courier new"&gt;redirect_to&lt;/font&gt;&lt;br /&gt;&lt;li&gt;If fails, calls &lt;font face="courier new"&gt;render :action =&gt; :new&lt;/font&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;br /&gt;Why in one case does it redirect, and the other does it render?  It all has to do with a little method call that should appear in your new widgets view, i.e. &lt;font face="courier new"&gt;/widgets/new&lt;/font&gt;:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;&lt;%= error_messages_for 'widget' %&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;See, a model has the capability to validate it’s attributes (e.g. lookup validates_presence_of in the Rails docs for examples of these capabilities).  When you call Object#save the validation routines are executed and if the model doesn’t validate (i.e. Object#save returns false) we render the new action again.  &lt;font face="courier new"&gt;error_messages_for&lt;/font&gt; looks up the failures and automagically renders error messaging.  &lt;br /&gt;&lt;br /&gt;The beauty of generators is that &lt;font face="courier new"&gt;script/generate scaffold Widget&lt;/font&gt; sets all of this up for you.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-3460136318470347554?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/3460136318470347554/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=3460136318470347554' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3460136318470347554'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3460136318470347554'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/rails-way.html' title='The Rails Way'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-4522395494461637006</id><published>2007-10-18T09:29:00.000-07:00</published><updated>2007-10-18T09:34:09.282-07:00</updated><title type='text'>The Problem with Rails Plugins</title><content type='html'>The other day Mark asked if I was using active_scaffold.  The answer is that I have a perfect use for it, and I installed it, and it works perfectly for what I need it for.  However, it also overrides some core Rails functions, and when I execute functionality in my portion of the app the active_scaffold version of those functions are throwing exceptions.  For example:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;class ActionController::Routing::RouteSet &lt;br /&gt;  def generate_with_nil_id_awareness(*args) &lt;br /&gt;    args[0].delete(:id) if args[0][:id].nil? &lt;br /&gt;    generate_without_nil_id_awareness(*args) &lt;br /&gt;  end &lt;br /&gt;  alias_method_chain :generate, :nil_id_awareness &lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;Now, to me, ActionController::Routing::RouteSet seems like a pretty core function in Rails.  Of course, it may be the case that I’ve done something wrong and their updated version is catching that error.  (You can read more on that here: http://groups.google.com/group/activescaffold/browse_thread/thread/1c4e2f30e8b00ac6/309665c0a85d65c8).&lt;br /&gt;&lt;br /&gt;However, my thinking is that I don’t need some plugin f’ing with my app.  In fact, this points to a major issue with plugins…they’re not these self-contained units, i.e. components...but, rather, they are mixed in with the core Rails framework and our apps.  This means we must think very carefully about which plugins we’ll use because, effectively, we need to know them as well as we know our own code.  In other words, they are not black boxes...they are just code we import into our app that somebody else wrote (and is kind enough to share).  For example, active_scaffold installs 138 files, and who knows how many kLOCs of code, and who knows what funky stuff they’ve done.&lt;br /&gt;&lt;br /&gt;So, long story short, I’m not using active_scaffold because I don’t trust that there isn't come code in there that's gonna mess up my app, and it's too much code for me to review and become familiar with.  Any ideas on an alternative?  &lt;br /&gt;&lt;br /&gt;I’ve looked at Streamlined, Hobo Scaffolding Extensions.  According to the docs, Streamlined doesn’t do nested records editing which I require, Scaffolding Extensions handles nested record editing, but isn't the best UX, and Hobo has the same problem as Radiant CMS...I have to put my app into theirs, not their app into mine.  (However, both Radiant and Hobo seem like nice platforms for the right project, just not the one I'm currently working on.)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-4522395494461637006?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/4522395494461637006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=4522395494461637006' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4522395494461637006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4522395494461637006'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/problem-with-rails-plugins.html' title='The Problem with Rails Plugins'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-6944301898337001410</id><published>2007-10-12T10:19:00.001-07:00</published><updated>2007-10-12T10:21:33.079-07:00</updated><title type='text'>What does "idiomatic Ruby" mean?</title><content type='html'>From a chat with &lt;a href="http://www.avogen.com"&gt;Mark&lt;/a&gt; today, in regard to reading a post where I used the word "idiomatic":&lt;br /&gt;&lt;code&gt;&lt;pre&gt;(10:10:42) Mark: idiomatic, what a word&lt;br /&gt;(10:11:12) Scott Porad: yes, i don't even know what it means...but people &lt;br /&gt;say it when they mean, "there's a more clever way to write this in ruby".&lt;br /&gt;(10:11:26) Mark: Peculiar to or characteristic of a given language.&lt;br /&gt;(10:12:05) Mark: nice, one of the descriptions of idiomatic, uses idiomatic &lt;br /&gt;to describe it: Characterized by proficient use of idiomatic expressions&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-6944301898337001410?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/6944301898337001410/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=6944301898337001410' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6944301898337001410'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6944301898337001410'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/what-does-idiomatic-ruby-mean.html' title='What does &quot;idiomatic Ruby&quot; mean?'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-7732724323712820333</id><published>2007-10-11T16:45:00.001-07:00</published><updated>2007-10-11T16:59:54.905-07:00</updated><title type='text'>Acts As Authenticated and Reset Password</title><content type='html'>Using Acts as Authenticated, imagine this use case:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;User forgets password...has reset code sent to their e-mail.&lt;br /&gt;&lt;li&gt;User receives e-mail, clicks link to reset password.&lt;br /&gt;&lt;li&gt;User arrives on reset password page and thinks, "hmmm...I think I'll go visit the homepage instead".&lt;br /&gt;&lt;li&gt;User types http://www.yoursite.com/ in their browser (or clicks a link the header, or whatever).&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;What happens is that when the user clicks the link in the email it takes them to /account/reset_password which looks up their account by the reset code on the link (which was sent in the e-mail) &lt;span style="font-weight:bold;"&gt;&lt;span style="font-style:italic;"&gt;and it logs them in&lt;/span&gt;&lt;/span&gt;.  So, when they decide, "hmmm...I think I'll go visit the homepage instead," the user is now logged in, but has not reset their password.  &lt;br /&gt;&lt;br /&gt;To me, that seems to present a problem.  So, I added a before_filter to my ApplicationController that verifies that all logged in users must have a nil password reset code otherwise they are redirected to /account/change_password.  (The password reset code isn't cleared until after the user has successfully changed their password.)&lt;br /&gt;&lt;br /&gt;In the ApplicationController I added:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;before_filter :ensure_password_reset&lt;/pre&gt;&lt;/code&gt;and&lt;br /&gt;&lt;code&gt;&lt;pre&gt;module AuthenticatedSystem&lt;br /&gt;  def ensure_password_reset&lt;br /&gt;    redirect_to :controller =&gt; :account, :action =&gt; :change_password unless reset_password_has_been_changed&lt;br /&gt;  end&lt;br /&gt;  &lt;br /&gt;  def reset_password_has_been_changed&lt;br /&gt;    if logged_in?&lt;br /&gt;      if current_user.password_reset_code.nil?&lt;br /&gt;        return true&lt;br /&gt;      else&lt;br /&gt;        return false&lt;br /&gt;      end&lt;br /&gt;    else&lt;br /&gt;      true&lt;br /&gt;    end&lt;br /&gt;  end  &lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;I'm certain that there is a more idiomatic Ruby way to write reset_password_has_been_changed, but I couldn't think of it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-7732724323712820333?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/7732724323712820333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=7732724323712820333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7732724323712820333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7732724323712820333'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/acts-as-authenticated-and-reset.html' title='Acts As Authenticated and Reset Password'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-6867011779483389925</id><published>2007-10-10T10:08:00.000-07:00</published><updated>2007-10-10T16:18:27.356-07:00</updated><title type='text'>Fixing a Blank Password Bug in Acts As Authenticated</title><content type='html'>I came across a bug in Acts As Authenticated when users tried to change their passwords.  If they submitted the form with nothing in the new or confirm new password text field, then no error was thrown, but the password wasn't changed either.&lt;br /&gt;&lt;br /&gt;The problem was in the :if clause on the validates_presence_of validation, password_required?.  It was causing the validation not to occur.&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    def password_required?&lt;br /&gt;      crypted_password.blank? || !password.blank?&lt;br /&gt;    end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;This code is saying that a password is required in two situations:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;when the crypted_password is blank -- that situation happens when creating a new user, &lt;span style="font-weight:bold;"&gt;OR&lt;/span&gt; &lt;br /&gt;&lt;li&gt;when the class instance variable 'password' is not blank -- this can only happen when the variable has been accessed, such as when attempting to update a password.&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The bug is in the test for &lt;font face="courier"&gt;!password.blank?&lt;/font&gt; because it's assuming that the user will enter something as a new password.  To resolve that, I changed the code to this:&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    def password_required?&lt;br /&gt;      crypted_password.blank? || !password.nil?&lt;br /&gt;    end&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;and now the validation is called (and fails) properly.  More about this issue can be found in the last few posts on &lt;a href="http://technoweenie.stikipad.com/plugins/show/Change+Password"&gt;this page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-6867011779483389925?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/6867011779483389925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=6867011779483389925' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6867011779483389925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6867011779483389925'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/fixing-blank-password-bug-in-acts-as.html' title='Fixing a Blank Password Bug in Acts As Authenticated'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-6919608868151962053</id><published>2007-10-10T09:59:00.001-07:00</published><updated>2007-10-10T10:08:20.263-07:00</updated><title type='text'>How To Make the Debugger Work with RadRails</title><content type='html'>I've finally got the debugger working with Aptana's RadRails.&lt;br /&gt;&lt;br /&gt;I've had the debugger working for awhile, but I was experiencing a problem where the current line, i.e. the current execution line, wasn't being highlighted.  Actually, the source file of the current line wasn't being even opened.&lt;br /&gt;&lt;br /&gt;After trolling around various messages boards, etc., I learned that the bug has been fixed in the latest beta version of RadRails.  Here’s a post on how to do that: http://www.aptana.com/forums/viewtopic.php?t=2939&lt;br /&gt;&lt;br /&gt;Personally, I had to manually add the update site in order to get it to work, although you might not have that experience.  Of course, it took me awhile to figure out how to do this...here you go:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Go to Help &gt; Software Updates &gt; Find and Install&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select "Search for new features to install" and click "Next"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the button on the right for "New Remote Site"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enter:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Name: RadRails Beta&lt;/li&gt;&lt;br /&gt;&lt;li&gt;URL: http://update.aptana.com/update/rails/beta/3.2/site.xml&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;li&gt;Click 'OK'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Check the box next to "RadRails Beta"&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the "Finish" button.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Now the update should download and install.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-6919608868151962053?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/6919608868151962053/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=6919608868151962053' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6919608868151962053'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6919608868151962053'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/how-to-make-debugger-work-with-radrails.html' title='How To Make the Debugger Work with RadRails'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-8201178770184169455</id><published>2007-10-04T01:59:00.000-07:00</published><updated>2007-10-04T02:20:03.322-07:00</updated><title type='text'>Where to put/store/save/keep your modules and files containing modules?</title><content type='html'>To a Rails newbie, sometimes the simplest things are hard to figure out.  Here's what you need to know:&lt;br /&gt;&lt;blockquote&gt;&lt;br /&gt;&lt;strong&gt;When you create a module, you save it to your lib/ directory.&lt;/strong&gt;&lt;/blockquote&gt;&lt;br /&gt;All the modules in the lib/ directory are auto-loaded by Rails.  That is, Rails does something like this:&lt;br /&gt;&lt;blockquote&gt;&lt;code&gt;&lt;pre&gt;for file in lib/&lt;br /&gt;   require file&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;/blockquote&gt;Also, I think there is some magic to this, but I'm not 100% sure.  If you have a module called MiscUtils then your file needs to be named misc_utils.rb in order for Rails to auto-load it.&lt;br /&gt;&lt;br /&gt;Additionally, Ruby does this super-sweet thing where you can re-open any class or module and add to it at any time.  In other words, you can declare a class or module in two locations, and Ruby will merge them together and treat them as one class.  My experience has been that when you do this, then you need to explicitly require the files even if they're in the lib directory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-8201178770184169455?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/8201178770184169455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=8201178770184169455' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8201178770184169455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/8201178770184169455'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/where-to-putstoresavekeep-your-modules.html' title='Where to put/store/save/keep your modules and files containing modules?'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-5411765216448960404</id><published>2007-10-03T11:36:00.000-07:00</published><updated>2007-10-03T11:58:02.934-07:00</updated><title type='text'>What is that hyphen right before the closing of an ERb block?</title><content type='html'>Periodically, I see some ERb code in a view like this:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;% form_tag '/posts' do -%&gt;     &lt;/code&gt;&lt;br /&gt;    &lt;%= submit_tag 'Save' %&gt;&lt;br /&gt;&lt;% end -%&gt;&lt;/pre&gt;&lt;br /&gt;In fact, that code was culled right from the Rails docs at for &lt;a href="http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#M000601"&gt;form_tag&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;As you can see, in those two ERb tags, there is this syntax at close of the tag:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;blockquote&gt;-%&amp;gt;&lt;/blockquote&gt;Today I was wondering what the hyphen (-) was for before the percentage symbol (%).  It turns out that the hyphen means that when the HTML output is generated there is no line return after the close of the ERb tag.&lt;br /&gt;&lt;br /&gt;For example, the ERb code above produces this HTML:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&amp;lt;form action="/posts" method="post"&amp;gt;    &amp;lt;div&gt;&amp;lt;input name="commit" type="submit" value="Save" /&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/pre&gt;&lt;br /&gt;whereas this ERb code:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&lt;% form_tag '/posts' do %&gt;    &lt;br /&gt;    &lt;%= submit_tag 'Save' %&gt;&lt;br /&gt;&lt;% end %&gt;&lt;/pre&gt;&lt;br /&gt;produces this HTML:&lt;br /&gt;&lt;code&gt;&lt;/code&gt;&lt;pre&gt;&amp;lt;form action="/posts" method="post"&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&amp;lt;input name="commit" type="submit" value="Save" /&amp;gt;&amp;lt;/div&gt;&lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-5411765216448960404?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/5411765216448960404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=5411765216448960404' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5411765216448960404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5411765216448960404'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/what-is-that-hyphen-right-before.html' title='What is that hyphen right before the closing of an ERb block?'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-4999220631227498354</id><published>2007-10-01T20:53:00.000-07:00</published><updated>2007-10-01T21:05:26.256-07:00</updated><title type='text'>How Mixins, Include and Extend Work</title><content type='html'>I was a little puzzled tonight by this chunk of code that I found in the acts_as_authenticated plug-in module:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    def self.included(base)&lt;br /&gt;      base.send :helper_method, :current_user, :logged_in?&lt;br /&gt;    end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;It comes down to some Ruby magic: when a module is included by a class the self.included method on the module is called.  Likewise, when a class extends a module the self.extended method is called.&lt;br /&gt;&lt;br /&gt;"base" is the class that includes/extends the module.  "send" is calling the method ":helper_method" and passing ":current_user" and ":logged_in?" as parameters.&lt;br /&gt;&lt;br /&gt;Special thanks to &lt;a href="http://www.juixe.com/techknow/index.php/2006/06/15/mixins-in-ruby/"&gt;Juixe&lt;/a&gt; for an excellent article that helped me figure this out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-4999220631227498354?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/4999220631227498354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=4999220631227498354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4999220631227498354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4999220631227498354'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/10/how-mixins-include-and-extend-work.html' title='How Mixins, Include and Extend Work'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-7952152000874830161</id><published>2007-09-28T17:43:00.000-07:00</published><updated>2007-09-28T17:49:45.905-07:00</updated><title type='text'>DRY Migrations (aka reverting or undoing earlier migrations)</title><content type='html'>I have a case where I made some database changes in migration 001 and now I want to undo them in migration 005.  This is different that actually rolling back to version 001 (i.e. rake db:migrate version=1)...I actually want to undo or revert what I did in 001.  The obvious thing to do would be to simply have 005 do the opposite of 001, but that isn't very DRY.  &lt;br /&gt;&lt;br /&gt;Using a simple example, let's say my migrations were:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;001_create_books.rb&lt;br /&gt;&lt;li&gt;002_create_libraries.rb&lt;br /&gt;&lt;li&gt;003_create_librarians.rb&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;and now my library is going electronic, so I do this:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;004_create_e_books.rb&lt;br /&gt;&lt;li&gt;005_destroy_books.rb&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;In 005 I want to do the exact opposite of 001, so I did this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;class DestroyBooks &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    CreateBooks::migrate(:down)&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    CreateBooks::migrate(:up)&lt;br /&gt;  end&lt;br /&gt;end&lt;/pre&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-7952152000874830161?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/7952152000874830161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=7952152000874830161' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7952152000874830161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7952152000874830161'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/dry-migrations-aka-reverting-or-undoing.html' title='DRY Migrations (aka reverting or undoing earlier migrations)'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-3340953658962184442</id><published>2007-09-27T13:39:00.000-07:00</published><updated>2007-09-28T17:55:02.878-07:00</updated><title type='text'>Custom Configurations and App Specific Settings</title><content type='html'>&lt;blockquote&gt;&lt;br /&gt;One not immediately obvious Ruby on Rails configuration issue I came across is how to structure application-specific config parameters, and in particular, how to make them configurable/overridable across different environments (dev, test, production). This has been solved repeatedly in different ways by the Rails community and there's info scattered around but assimilating it took a while, &lt;a href="http://lemurware.blogspot.com/2006/08/ruby-on-rails-configuration-and.html"&gt;here's what I've settled on&lt;/a&gt; for now.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;I couldn't have said it better myself.  I've now spent 4 hours researching the best way to do this...this is a basic feature of a web app, you'd think there would be a conventional way to create ..whatever you want to call them: custom configurations, application specific settings, application configs...in Rails.&lt;br /&gt;&lt;br /&gt;At present, I've found four solutions...the one suggested by the above blogger, and these three others:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;http://www.taknado.com/2007/7/25/custom-configuration-info-in-rails&lt;br /&gt;&lt;li&gt;http://jarmark.org/projects/app-config/&lt;br /&gt;&lt;li&gt;Use after_initialize method on the Rails::Configuration class.  (Note: this is only semi-well documented...it's documented, but not included at http://api.rubyonrails.org.  I found it here: http://edgedocs.planetargon.org/classes/Rails/Configuration.html#M002860)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;In addition, I found these blog posts useful:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;http://toolmantim.com/article/2006/12/27/environments_and_the_rails_initialisation_process&lt;br /&gt;&lt;li&gt;http://glu.ttono.us/articles/2006/05/22/guide-environments-in-rails-1-1&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I haven't decided how I'm going to do this yet, but I hope you find this helpful.&lt;br /&gt;&lt;br /&gt;UPDATE: I was exchanging e-mail from Jeff at &lt;a href="http://www.softiesonrails.com"&gt;softiesonrails.com&lt;/a&gt; who suggested this solution:&lt;br /&gt;&lt;blockquote&gt;What I usually do is add it to the bottom of environment.rb.  If I have RAILS_ENV-dependent data (like development mode vs. production mode), then just put the relevant Ruby code at the bottom of environments/development.rb, for example:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    module MyConstants&lt;br /&gt;      ALLOWED_NAMES = ['jeff', 'cookie monster']&lt;br /&gt;      IP_ALLOWED = '1.2.3.4'&lt;br /&gt;    end&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;and then you can access them anywhere in your Rails code as MyConstants::ALLOWED_NAMES, etc. &lt;br /&gt;&lt;br /&gt;If you prefer to move it to a file, you'd create a file named my_constants.rb in the /lib folder, and then explicitly require it from environment.rb:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;pre&gt;    require 'my_constants'&lt;/pre&gt;&lt;/code&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-3340953658962184442?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/3340953658962184442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=3340953658962184442' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3340953658962184442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3340953658962184442'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/custom-configurations-and-app-specific.html' title='Custom Configurations and App Specific Settings'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-1209669765160047708</id><published>2007-09-18T17:31:00.001-07:00</published><updated>2007-09-18T17:52:43.959-07:00</updated><title type='text'>Reverting Migrations (self.drop) Issue</title><content type='html'>I created an ran a migration today.  Here is how my database looked to begin:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mysql&gt; show tables;&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| Tables_in_books_development          |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| journals                             |&lt;br /&gt;| schema_info                          |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;2 rows in set (0.00 sec)&lt;br /&gt;&lt;br /&gt;mysql&gt; select * from schema_info;&lt;br /&gt;+---------+&lt;br /&gt;| version |&lt;br /&gt;+---------+&lt;br /&gt;|      19 |&lt;br /&gt;+---------+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then, I ran this migration:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class CreateThemes &lt; ActiveRecord::Migration&lt;br /&gt;  def self.up&lt;br /&gt;    create_table :themes do |t|&lt;br /&gt;      t.column :name, :string&lt;br /&gt;      t.column :stylesheet_path, :string&lt;br /&gt;      t.column :thumbnail_path, :string&lt;br /&gt;      t.column :journals_count, :integer, :default =&gt; 0&lt;br /&gt;    end&lt;br /&gt;    #add_column :journals, :theme_id, :integer&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def self.down&lt;br /&gt;    drop_table :themes&lt;br /&gt;    remove_column :journals, :theme_id&lt;br /&gt;  end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice how I have the add_column method commented out.  Running Rake yields this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\rails_apps\books&gt;rake db:migrate&lt;br /&gt;(in C:/rails_apps/books)&lt;br /&gt;== CreateThemes: migrating ====================================================&lt;br /&gt;-- create_table(:themes)&lt;br /&gt;   -&gt; 0.1200s&lt;br /&gt;== CreateThemes: migrated (0.1200s) ===========================================&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see, the column is not added to the journals table.  Here's what my database looks like now:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mysql&gt; show tables;&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| Tables_in_books_development          |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| journals                             |&lt;br /&gt;| schema_info                          |&lt;br /&gt;| themes                               |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;3 rows in set (0.00 sec)&lt;br /&gt;&lt;br /&gt;mysql&gt; select * from schema_info;&lt;br /&gt;+---------+&lt;br /&gt;| version |&lt;br /&gt;+---------+&lt;br /&gt;|      20 |&lt;br /&gt;+---------+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Well, I really need that column added to journals, so I better revert that migration via Rake, uncomment the add_column method, and re-Rake.  Here's what happens:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;C:\rails_apps\books&gt;rake db:migrate version=19&lt;br /&gt;(in C:/rails_apps/books)&lt;br /&gt;== CreateThemes: reverting ====================================================&lt;br /&gt;-- drop_table(:themes)&lt;br /&gt;   -&gt; 0.0500s&lt;br /&gt;-- remove_column(:journals, :theme_id)&lt;br /&gt;rake aborted!&lt;br /&gt;Mysql::Error: Can't DROP 'theme_id'; check that column/key exists: ALTER TABLE journals DROP `theme_id`&lt;br /&gt;&lt;br /&gt;(See full trace by running task with --trace)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Oops!  The self.down method is crapping out because there is no column in journals called theme_id.  (Of course, we knew that.)  Let's checkout the database now:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;mysql&gt; show tables;&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| Tables_in_books_development          |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;| journals                             |&lt;br /&gt;| schema_info                          |&lt;br /&gt;+--------------------------------------+&lt;br /&gt;2 rows in set (0.01 sec)&lt;br /&gt;&lt;br /&gt;mysql&gt; select * from schema_info;&lt;br /&gt;+---------+&lt;br /&gt;| version |&lt;br /&gt;+---------+&lt;br /&gt;|      20 |&lt;br /&gt;+---------+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Do you see that schema_info still says version 20.  I presume that the last thing a migration does is update the schema_info.version with the idea being that we don't modify the version until we sure that the migration has succeeded.  The problem with that is that migrations aren't transactional--that is, they can complete  or fail partially, yet the schema_info is updated as though it were a transaction.  I don't know how Rails fixes this, but it's something worth knowing about.&lt;br /&gt;&lt;br /&gt;Anyhow, at this point my database is in limbo...neither in version 19 nor 20.  When I run &lt;pre&gt;rake db:migrate&lt;/pre&gt; nothing happens because as far as Rake can tell, the DB is up-to-date.  But, I can't run &lt;pre&gt;rake db:migrate version=19&lt;/pre&gt; either because Rake will error out because there is no theme table to drop.&lt;br /&gt;&lt;br /&gt;Okay, so the short-term solution to this problem is to clean-up the database manually.  In my case, everything was actually reverted in the self.drop, but Rake doesn't know that.  In your case you may have more manual clean-up to do.  So, all I needed to do was update schema_info.version to 19.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-1209669765160047708?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/1209669765160047708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=1209669765160047708' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1209669765160047708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1209669765160047708'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/reverting-migrations-selfdrop-issue.html' title='Reverting Migrations (self.drop) Issue'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-2376009723721701332</id><published>2007-09-17T13:37:00.000-07:00</published><updated>2007-09-17T13:39:31.072-07:00</updated><title type='text'>Netscape Navigator 1.0</title><content type='html'>I'm not getting much work done today...my desk and office are a mess, so I'm working at cleaning up.&lt;br /&gt;&lt;br /&gt;While doing so, I found &lt;a href="http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&amp;item=290161888711"&gt;a bit of history&lt;/a&gt; in my desk, and &lt;a href="http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&amp;item=290161888711"&gt;you can have it&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-2376009723721701332?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/2376009723721701332/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=2376009723721701332' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2376009723721701332'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2376009723721701332'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/netscape-navigator-10.html' title='Netscape Navigator 1.0'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-1851107724804524294</id><published>2007-09-11T13:15:00.000-07:00</published><updated>2007-09-11T14:27:51.858-07:00</updated><title type='text'>Create Action Requires POST</title><content type='html'>UPDATE: I wrote the whole post below, and then I figured it out...oy, the risks of auto-generated code.  Typically, I use &lt;code&gt;script/generate scaffold&lt;/code&gt; to build my controllers and views, then I start modifying from there.  The risk of using auto-generated code is that you don't know every detail...and, if you're gonna own a program, you gotta know ever detail.&lt;br /&gt;&lt;br /&gt;Long story short: I started digging around at &lt;code&gt;.../verification.rb&lt;/code&gt; and I finally ended up back at my own controller and found this that scaffold sticks this bit of code in at the top of every controller:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;  # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)&lt;br /&gt;  verify :method =&gt; :post, :only =&gt; [ :destroy, :create, :update ],&lt;br /&gt;         :redirect_to =&gt; { :action =&gt; :list }&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;which is why I wasn't able call create with a GET.  Yikes!&lt;br /&gt;&lt;br /&gt;&lt;hr&gt;&lt;br /&gt;&lt;br /&gt;Boy, what a morning!  I found a "feature" of Rails that I don't quite understand yet, but it certainly caused me a lot of headache.  Maybe somebody else who is frustrated will benefit from this information.&lt;br /&gt;&lt;br /&gt;Long story short: if you are going to call the create action in a controller, then you can only do so via POST.  If you try to do so via GET you will get an error like the one below.  In other words:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Form with POST method --&amp;gt; works&lt;/span&gt;&lt;br /&gt; &amp;lt;form action="/books/create" method="post"&amp;gt;&lt;br /&gt;  &amp;lt;input type="submit" name="submit" value="submit"&amp;gt;&lt;br /&gt; &amp;lt;/form&amp;gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="font-weight:bold;"&gt;Form with GET method --&amp;gt; does not work&lt;/span&gt;&lt;br /&gt; &amp;lt;form action="/books/create" method="get"&amp;gt;&lt;br /&gt;  &amp;lt;input type="submit" name="submit" value="submit"&amp;gt;&lt;br /&gt; &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Apparently, Rails has some sort of before_filter that requires certain types of actions to be called via certain HTTP methods.  (Note: I am not using any of the Rails RESTful stuff, e.g. map.resources.)&lt;br /&gt;&lt;br /&gt;I have yet to figure out exactly what filter causes this requirement.  Also, I would be interested in knowing if there is a way to inspect all the before filters that will be run for a given action or controller.  If you know, please post in the comments.  &lt;br /&gt;&lt;br /&gt;Special thanks to &lt;a href="http://www.movesonrails.com/"&gt;Dirkjan&lt;/a&gt; for helping me debug this far.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;From development.log&lt;/h3&gt;&lt;code&gt;Processing BooksController#create (for 127.0.0.1 at 2007-09-11 10:53:22) [GET]&lt;br /&gt;  Session ID: e042ea5ba771fd5423d39369ec8e1227&lt;br /&gt;  Parameters: {"action"=&gt;"create", "controller"=&gt;"books", "journal_id"=&gt;"1"}&lt;br /&gt;Redirected to http://localhost:3005/books/list&lt;br /&gt;Filter chain halted as [#&amp;lt;ActionController::Filters::ClassMethods::ProcFilter:0x47e198c @filter=#&amp;lt;Proc:0x0391ce4c@C:/InstantRails-1.7-win/InstantRails/ruby/lib/ruby/gems/1.8/gems/actionpack-1.13.3/lib/action_controller/verification.rb:74&amp;gt;&amp;gt;] returned false.&lt;br /&gt;Completed in 0.01000 (100 reqs/sec) | DB: 0.00000 (0%) | 302 Found [http://localhost/books/create?journal_id=1]&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Processing BooksController#list (for 127.0.0.1 at 2007-09-11 10:53:22) [GET]&lt;br /&gt;  Session ID: e042ea5ba771fd5423d39369ec8e1227&lt;br /&gt;  Parameters: {"action"=&gt;"list", "controller"=&gt;"books"}&lt;br /&gt;  [4;36;1mBook Columns (0.010000)[0m   [0;1mSHOW FIELDS FROM books[0m&lt;br /&gt;  [4;35;1mSQL (0.000000)[0m   [0mSELECT count(*) AS count_all FROM books [0m&lt;br /&gt;  [4;36;1mBook Load (0.000000)[0m   [0;1mSELECT * FROM books LIMIT 0, 10[0m&lt;br /&gt;Rendering  within layouts/books&lt;br /&gt;Rendering books/list&lt;br /&gt;Completed in 0.03000 (33 reqs/sec) | Rendering: 0.01000 (33%) | DB: 0.01000 (33%) | 200 OK [http://localhost/books/list]&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-1851107724804524294?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/1851107724804524294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=1851107724804524294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1851107724804524294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/1851107724804524294'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/create-action-requires-post.html' title='Create Action Requires POST'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-4820586186070657947</id><published>2007-09-10T16:36:00.000-07:00</published><updated>2007-09-11T13:15:27.972-07:00</updated><title type='text'>How to use IRC for Ruby on Rails (#rubyonrails)</title><content type='html'>14 years ago I used IRC to chat with people online about the Grateful Dead and Phish, but haven't since, and basically forgot about 99% of how it works.  &lt;br /&gt;&lt;br /&gt;Then, recently I wanted to join the #rubyonrails IRC channel to get some instant information, so from http://www.rubyonrails.com/community I learned that #rubyonrails was hosted at irc.freenode.net.  I downloaded ChatZilla and tried to join.&lt;br /&gt;&lt;br /&gt;Frustration.  #rubyonrails requires some sort of nickname registration and it took me the &lt;span style="font-style:italic;"&gt;longest&lt;/span&gt; time to figure out how the heck it works.&lt;br /&gt;&lt;br /&gt;I searched for documentation and found all sorts, but what I was found was very dry and technical and full of details.  Typically, I like that type of stuff--bare bones, just the facts.  &lt;br /&gt;&lt;br /&gt;But, here I needed the dummies course, and I found it at http://www.zymic.com/irc.php.  I can't vouch for that site, but thank goodness they had some basic info...it wasn't 100% correct, but it got me close enough.&lt;br /&gt;&lt;br /&gt;In ChatZilla &gt; Preferences &gt; General there is a "nickname" setting.  When you connect to irc.freenode.net you need to register this nickname...obviously, it should be something sort of unique.  (How to connect? Open Firefox and visit the URL irc://irc.freenode.net ...which should launch ChatZilla.)&lt;br /&gt;&lt;br /&gt;After ChatZilla connects to irc.freenode.net, you will need to register your nickname, aka "nick".  To register the nick, type:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/msg nickserv register &lt;span style="font-style:italic;"&gt;&amp;lt;yourpassword&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;where &lt;span style="font-style:italic;"&gt;&amp;lt;yourpassword&amp;gt;&lt;/span&gt; is some password of your creation.  This will register your nickname with some sort of central registration database.&lt;br /&gt;&lt;br /&gt;Then, to enter the channel type:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/join #rubyonrails&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;On subsequent visits to IRC, ChatZilla will send your username to nickserv, but you will need to "identify" yourself this time.  To do so, type:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/msg nickserv identify &lt;span style="font-style:italic;"&gt;&amp;lt;yourpassword&amp;gt;&lt;/span&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then, join the channel like you did before:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/join #rubyonrails&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Personally, I think of it like this:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;register = create a login&lt;br /&gt;&lt;li&gt;identify = login&lt;br /&gt;&lt;li&gt;join = enter a chat room&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Hopefully, these instructions will help someone else out along the way.&lt;br /&gt;&lt;br /&gt;P.S.  By the way, the delay between posts is explained by the fact that I was out of town for a few weeks visiting family.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-4820586186070657947?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/4820586186070657947/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=4820586186070657947' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4820586186070657947'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4820586186070657947'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/09/how-to-use-irc-for-ruby-on-rails.html' title='How to use IRC for Ruby on Rails (#rubyonrails)'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-5445292046064101771</id><published>2007-08-20T21:51:00.001-07:00</published><updated>2007-08-20T21:53:32.773-07:00</updated><title type='text'>Incorporation</title><content type='html'>We incorporated our startup today...a small milestone on a long journey, so we took a picture to commemorate the moment.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-5445292046064101771?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/5445292046064101771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=5445292046064101771' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5445292046064101771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5445292046064101771'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/incorporation.html' title='Incorporation'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-5498738228275893611</id><published>2007-08-20T16:56:00.000-07:00</published><updated>2007-08-20T21:45:46.291-07:00</updated><title type='text'>HTML and Helpers</title><content type='html'>Look at all this code.  Yikes!&lt;br /&gt;&lt;br /&gt;Even though, in theory, you're supposed to be &lt;span style="font-style:italic;"&gt;allowed&lt;/span&gt; to put HTML in your helpers, the result is that you still end up mixing up all your presentation and business logic.  &lt;a href="http://darwinweb.net/article/Jeff_Crofts_Myth_Of_Contentpresentation_Separation"&gt;Some people&lt;/a&gt; would argue that &lt;a href="http://www2.jeffcroft.com/blog/2007/aug/09/myth-content-and-presentation-separation/"&gt;it's not possible to separate presentation and content&lt;/a&gt;.  I'm not arguing either way...just trying to point out that it's easy to get these things intermingled.&lt;br /&gt;&lt;br /&gt;Anyhow, what's going on here is that a document group has a bunch of document templates.  Users will have filled out some templates--in which case the "instances" of those templates become documents--and in other cases they won't have filled them out.  &lt;br /&gt;&lt;br /&gt;Originally, I was just going to do a condition based on the existence of the document or not, but then I realized this edge case that somehow a user may end up with two documents based on the same template.  I'm not sure how this would happen, but could happen easily, for example, if the user bookmarked the URL for the new document page for that document template.&lt;br /&gt;&lt;br /&gt;I suppose I could make the new action check for the existence of a document using said template for the current user, and that would almost ensure this problem wouldn't happen...from the UI.  What happens if data is added directly to the database?  In fact, that's how I found this case...I accidentally loaded some test data twice and my original code crapped out.&lt;br /&gt;&lt;br /&gt;Anyhow, in my view:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;% &lt;br /&gt;@document_group.document_templates.each do |child| &lt;br /&gt;    array_of_links_to_document_if_exists_from_template(child).each do |link| &lt;br /&gt;        %&gt;&amp;lt;li&amp;gt;&lt;%= link %&gt;&amp;lt;/li&amp;gt;&lt;%&lt;br /&gt;    end&lt;br /&gt;end&lt;br /&gt;%&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;And in my helper:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;&lt;br /&gt;  def array_of_links_to_document_if_exists_from_template(document_template)&lt;br /&gt;    links = []&lt;br /&gt;    documents = Document.find(:all, :conditions =&gt; { :journal_id =&gt; @journal, :document_template_id =&gt; document_template })&lt;br /&gt;    if (!documents.empty?)&lt;br /&gt;      documents.each do |document|&lt;br /&gt;        links.push(link_to_remote(document.name, { :update =&gt; "dvMainPane", :url =&gt; { :controller =&gt; :documents, :action =&gt; :edit, :id =&gt; document }}))&lt;br /&gt;      end&lt;br /&gt;    else&lt;br /&gt;      links.push(link_to_remote(document_template.name, { :update =&gt; "dvMainPane", :url =&gt; { :controller =&gt; :documents, :action =&gt; :new, :journal_id =&gt; @journal, :document_template_id =&gt; document_template.id }}))&lt;br /&gt;    end&lt;br /&gt;    links&lt;br /&gt;  end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Is the helper the right place for business logic?  I'm thinking right solution here isn't to put the logic in a helper...maybe helpers are really just rendering helpers...and that the logic should be in my model.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-5498738228275893611?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/5498738228275893611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=5498738228275893611' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5498738228275893611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/5498738228275893611'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/looping-within-helper.html' title='HTML and Helpers'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-9062502284389369749</id><published>2007-08-16T10:32:00.000-07:00</published><updated>2007-08-16T10:37:16.977-07:00</updated><title type='text'>Navigating Associations in Scaffolding with Toffee</title><content type='html'>My friend &lt;a href="http://www.kexplorer.com/listener/markpuck"&gt;Mark&lt;/a&gt; suggested &lt;a href="http://open.bluefountain.com/software/toffee/documentation/how-to/using-toffee-in-your-rails-application"&gt;Toffee&lt;/a&gt; for dealing with &lt;a href="http://progress-vs-perfection.blogspot.com/2007/08/navigating-associations-in-scaffolding.html"&gt;navigating scaffold associations&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Haven't tried it yet, but on the surface seems to solve some of what I was discussing.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-9062502284389369749?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/9062502284389369749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=9062502284389369749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/9062502284389369749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/9062502284389369749'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/navigating-associations-in-scaffolding_16.html' title='Navigating Associations in Scaffolding with Toffee'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-4132301605132557435</id><published>2007-08-14T16:19:00.000-07:00</published><updated>2007-08-14T16:46:16.675-07:00</updated><title type='text'>Creating Multiple Objects (of different Models) in one form.</title><content type='html'>Yikes!  Did I ever dig hole for myself, so let me tell you how I got out of it.&lt;br /&gt;&lt;br /&gt;Long story short: I have a model architecture like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;document&lt;br /&gt; |&lt;br /&gt; --&gt; document_content_groups[]&lt;br /&gt;     |&lt;br /&gt;     --&gt;document_contents&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;In other words, document_contents are name value pairs...think of them as questions (name) and answers (value).  one or more document_contents are grouped into a document_content_group...think of that as a chunk of questions.  in other words, a document_content_group has a collection of document_contents.  then, a document has a collection of document_content_groups.&lt;br /&gt;&lt;br /&gt;So, on a form where a user creates a new document really we're creating many things:&lt;br /&gt;&lt;br /&gt;1 new document object&lt;br /&gt;1 or more document_content_group objects&lt;br /&gt;1 or more document_content objects&lt;br /&gt;&lt;br /&gt;and, all of these must be associated with their parent properly.&lt;br /&gt;&lt;br /&gt;On p. 499 the Rails book (Agile Web Development with Rails) it is suggested that something like this be done:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;% for_tag do %&gt;&lt;br /&gt;  &lt;% for @product in @products %&gt;&lt;br /&gt;    &lt;%= text_field("product[]", 'image_url') %&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt;&lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and what this syntax is supposed to do is make the ID of the object be inserted into the form "name" field, e.g. name="product_ID[image_url]".  But (sharing this is the purpose of this post), &lt;b&gt;this syntax does not work with a newly created object, it only works with editing existing objects&lt;/b&gt;.  I solved the problem like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;@dcg_index = 0&lt;br /&gt;@dc_index = 0&lt;br /&gt;for document_content_group in @document_content_groups %&gt;&lt;br /&gt; &amp;lt;p&amp;gt;&lt;%= document_content_group.name %&gt;&amp;lt;br /&amp;gt;&lt;br /&gt; &lt;%= text_field("document_content_group", 'name', :index =&gt; @dcg_index) %&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;  &lt;% &lt;br /&gt;  for document_content in document_content_group.document_contents %&gt;&lt;br /&gt;   &amp;lt;p&amp;gt;&lt;%= document_content.name %&gt;&amp;lt;br /&amp;gt;&lt;br /&gt;   &lt;%= hidden_field ("document_content", "document_content_group", :value =&gt; @dcg_index.to_s, :index =&gt; @dc_index) %&gt;&lt;br /&gt;   &lt;%= hidden_field ("document_content", "name", :value =&gt; document_content.name, :index =&gt; @dc_index) %&gt;&lt;br /&gt;   &lt;%= text_field("document_content", "value", :index =&gt; @dc_index) %&gt;&amp;lt;/p&amp;gt;&lt;br /&gt;   &lt;% @dc_index += 1%&gt;&lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt; &lt;% @dcg_index += 1%&gt;&lt;br /&gt;&lt;% end %&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, the result is that when the form is posted I get two hashes in the params: document_content_groups and document_contents each of which contains hashes representing the objects I want to create.  &lt;br /&gt;&lt;br /&gt;I can easily create the document_content_groups by passing those hashes in to create, but I have to do some munging on the document_contents to prepare them:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;      @dcg_index = 0  # this must be the same initial index from the "new" form&lt;br /&gt;      for document_content_group_hash in params[:document_content_group].values do&lt;br /&gt;        document_content_group = @document.document_content_groups.create(document_content_group_hash)&lt;br /&gt;        for document_content_hash in params[:document_content].values do&lt;br /&gt;          if (document_content_hash["document_content_group"].to_i == @dcg_index)&lt;br /&gt;            # this is removed from the hash because it's not really the document_content_group_id...&lt;br /&gt;            # it's just a temporary ID that was used to group the items together from the _new form&lt;br /&gt;            document_content_hash.delete("document_content_group")&lt;br /&gt;            document_content_group.document_contents.create(document_content_hash)&lt;br /&gt;          end&lt;br /&gt;        end&lt;br /&gt;        @dcg_index += 1&lt;br /&gt;      end&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;Anyhow, not particularly pretty, but it gets the job done for now.  Suggestions on how to make it more graceful are welcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-4132301605132557435?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/4132301605132557435/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=4132301605132557435' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4132301605132557435'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/4132301605132557435'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/creating-multiple-objects-of-different.html' title='Creating Multiple Objects (of different Models) in one form.'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-6537822197132826406</id><published>2007-08-08T23:14:00.001-07:00</published><updated>2007-08-09T09:19:23.733-07:00</updated><title type='text'>Navigating Associations in Scaffolding</title><content type='html'>In a scaffold generated list.rhtml only the content_columns are displayed.  I modified that to show all columns, but the drawback is that for foreign keys you only see the ID, not any thing descriptive.  That is, if I have books which belong_to authors, then what I see from the list.rhtml is author_id, not author_name.&lt;br /&gt;&lt;br /&gt;I’ve been working to get around that because I can save a lot of time if the joins work magically.  So, I wrote some code that basically looks at a column, if it’s an “id column”, then it walks the association to find the object.  Once found, it looks for some logical text to display, and if none is found then defaults to the ID.&lt;br /&gt;&lt;br /&gt;I've put the code below, but I can’t believe Rails doesn’t provide a way to do this automagically...it seems like something that would be used so often.  Anyone?&lt;br /&gt;&lt;br /&gt;Anyhow Scaffold makes this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&lt;% for document_content_template in @ document_content_templates %&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;  &lt;% for column in DocumentContentTemplate.content_columns %&gt;&lt;br /&gt;    &lt;td&gt;&lt;%=h document_content_template.send(column.name) %&gt;&lt;/td&gt;&lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt;  [... snipped show-edit-destroy ]&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Which I’ve changed to this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&lt;% for document_content_template in @document_content_templates %&gt;&lt;br /&gt;  &lt;tr&gt;&lt;br /&gt;  &lt;% for column in DocumentContentTemplate.columns %&gt;&lt;br /&gt;    &lt;td&gt;&lt;%=h display_column_text(column, document_content_template) %&gt;&lt;/td&gt;&lt;br /&gt;  &lt;% end %&gt;&lt;br /&gt;  [... snipped show-edit-destroy ]&lt;br /&gt;  &lt;/tr&gt;&lt;br /&gt;&lt;% end %&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;With these helpers:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;1  def display_column_text(column, object)&lt;br /&gt;2    if column.name[-3, 3] != "_id" &lt;br /&gt;3      object.send(column.name)&lt;br /&gt;4    else&lt;br /&gt;5      value_from_join(column, object)&lt;br /&gt;6    end&lt;br /&gt;7  end&lt;br /&gt;8&lt;br /&gt;9  def value_from_join(column, object)&lt;br /&gt;10   h = column.name.sub(/_id/, '')       # strip off the id&lt;br /&gt;11   r = object.send(h)                   # get the object&lt;br /&gt;12&lt;br /&gt;13   if (defined? r.name != nil) &lt;br /&gt;14     r.name&lt;br /&gt;15   elsif (defined? r.description != nil)&lt;br /&gt;16     r.description&lt;br /&gt;17   else&lt;br /&gt;18     r.id&lt;br /&gt;19   end&lt;br /&gt;20 end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;P.S.  Yes, I realize there might be a bug on line 10.&lt;br /&gt;P.P.S  There’s actually a potentail bug on line 11 as well…what happens if you have a controller that’s like this:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;belongs_to :model_name, :foreign_key =&gt; "some_other_id"&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;which will throw this error:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;undefined method `some_other' for #&amp;lt;ModelName:0x47a8650&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;UPDATE:&lt;/span&gt; the bug on line 11 can easily be handled like so:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;begin                               # get the object&lt;br /&gt;  r = object.send(h)                   &lt;br /&gt;rescue&lt;br /&gt;  return object.send(column.name)&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Again, I can’t believe Rails doesn’t the magic to navigate around these objects more gracefully.  Thoughts or comments anyone???&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-6537822197132826406?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/6537822197132826406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=6537822197132826406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6537822197132826406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/6537822197132826406'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/navigating-associations-in-scaffolding.html' title='Navigating Associations in Scaffolding'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-3304483683350727384</id><published>2007-08-08T10:29:00.000-07:00</published><updated>2007-08-08T11:54:28.305-07:00</updated><title type='text'>Perfection, Not Progress</title><content type='html'>I wasted an entire day yesterday on &lt;code&gt;:counter_cache =&gt; true&lt;/code&gt;.  (Why was it wasted?  Because I didn't need a counter cache yesterday, but knew that I would need it in a few weeks or months...progress versus perfection rears its ugly head again.)&lt;br /&gt;&lt;br /&gt;Anyhow the problem ultimately had nothing to do with counter caching, but the error message didn't help too much, and there wasn't much in Google about the error message, so I spent a lot of time looking for the problem in the wrong place.  Hopefully this post will help others in the future if you're getting this error message:&lt;br /&gt;&lt;blockquote&gt;&lt;code style="font-size:12px"&gt;NoMethodError in Document content templateController#create &lt;br /&gt;undefined method `increment_counter' for Class:Class&lt;/code&gt;&lt;/blockquote&gt;&lt;br /&gt;Yesterday I was creating entities called &lt;code&gt;DocumentTemplate&lt;/code&gt; and &lt;code&gt;DocumentContentTemplate&lt;/code&gt;:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;class DocumentTemplate &lt; ActiveRecord::Base&lt;br /&gt;  has_many :DocumentContentTemplates&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class DocumentContentTemplate &lt; ActiveRecord::Base&lt;br /&gt;  belongs_to :DocumentTemplate&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Then, I ran a quick &lt;code&gt;script/generate scaffold&lt;/code&gt; on both of these, and modified the &lt;code&gt;_form.rhmtl&lt;/code&gt; for &lt;code&gt;DocumentContentTemplate&lt;/code&gt; in order to add the association to &lt;code&gt;DocumentTemplate&lt;/code&gt;.  Everything is working fine.&lt;br /&gt;&lt;br /&gt;Next, I decide that I'm going to need a counter cache on the &lt;code&gt;DocumentTemplate&lt;/code&gt;, so I modify the &lt;code&gt;DocumentContentTemplate&lt;/code&gt; model and added the &lt;code&gt;document_content_templates_count&lt;/code&gt; column to the &lt;code&gt;document_templates&lt;/code&gt; table via migration:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;class DocumentContentTemplate &lt; ActiveRecord::Base&lt;br /&gt;  belongs_to :DocumentTemplate, :counter_cache =&gt; true&lt;br /&gt;end&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;Now, when I create a new &lt;code&gt;DocumentContentTemplate&lt;/code&gt; the method &lt;code&gt;DocumentContentTemplate#create&lt;/code&gt; should automatically increment the &lt;code&gt;document_content_templates_count&lt;/code&gt; column in the &lt;code&gt;document_templates&lt;/code&gt; table.  But, when I submit the form that calls the create method I get this error:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;NoMethodError in Document content templateController#create &lt;br /&gt;undefined method `increment_counter' for Class:Class&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;I spent hours debugging and investigating all the things related to counter cache, but it turns out that wasn't the problem.  Go way back to the has_many and belongs_to declarations:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;has_many :DocumentContentTemplates&lt;br /&gt;belongs_to :DocumentTemplate&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;which, if you look carefully, should really be:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;has_many :document_content_templates&lt;br /&gt;belongs_to :document_template&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;So, if you're seeing that error, that's how to fix it.  But, this raises two issues that I want to bring up:&lt;br /&gt;&lt;br /&gt;1.  My understanding is that the camel-case of a class name is supposed to be used when referring to the class, not an instance of it.  For example, camelcase is used in a class definition or when the class is being used:&lt;br /&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code style="font-size:12px"&gt;class DocumentTemplate &lt; ActiveRecord::Base&lt;br /&gt;&lt;br /&gt;DocumentTemplate.find(:all)&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;br /&gt;With that in mind, aren't the has_* and belongs_to methods referring to classes?  Why don't they use the camelcase?&lt;br /&gt;&lt;br /&gt;2.  Regardless of the answer to #1, why does Rails handle this error gracefully?  Why does &lt;code&gt;has_*|belongs_to :ClassName&lt;/code&gt; not throw an error when it should be &lt;code&gt;has_*|belongs :class_name&lt;/code&gt;?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-3304483683350727384?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/3304483683350727384/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=3304483683350727384' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3304483683350727384'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/3304483683350727384'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/08/perfection-not-progress.html' title='Perfection, Not Progress'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-7598301940174601712</id><published>2007-07-24T12:44:00.001-07:00</published><updated>2007-07-24T12:51:58.378-07:00</updated><title type='text'>REST</title><content type='html'>Started designing my app last night.  I had most of it in mind, so I just started hammering it out.  I know, not the best way to do it, but sometimes you just have to get into the code.&lt;br /&gt;&lt;br /&gt;A few days ago, I wanted to get more in sync with Rails and REST before, so I did some reading online.  Something I enjoyed was &lt;a href="http://www.softiesonrails.com/2007/3/28/rest-101-part-1-understanding-resources"&gt;this article&lt;/a&gt; (and the subequent parts) from SoftiesOnRails.com.&lt;br /&gt;&lt;br /&gt;With REST fresh in mind, design goes really smoothly.  There's only one place (yet) in my app where I'm feeling like I can't use one of the seven basic actions provided by a RESTful conroller.&lt;br /&gt;&lt;br /&gt;It has to do with a "wizard" model where when a user is creating a new Widget we break it up into a few steps.  So, I'm using the create action for the first page of the wizard, and then I guess I need to do some sort of update for the subequent pages.  I'm not sure...haven't really researched it yet, but there must be a right way to do this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-7598301940174601712?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/7598301940174601712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=7598301940174601712' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7598301940174601712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/7598301940174601712'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/07/rest.html' title='REST'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-2166598643436391211</id><published>2007-07-22T23:31:00.001-07:00</published><updated>2007-07-23T00:06:52.405-07:00</updated><title type='text'>RadRails and Scaffold-Migration Best Practice</title><content type='html'>So, started tinkering again with Ruby on Rails tonight.  It's been about a year since I last worked with RoR, so I wanted to familiarize myself with it again.&lt;br /&gt;&lt;br /&gt;Fired up RadRails.  Let me say that this has undergone &lt;span style="font-style: italic;"&gt;vast improvement&lt;/span&gt; since I used it a year ago, and I would feel totally comfortable recommending it to anyone.  I have been able to manage the entire development process from within the IDE: create and empty application, generate models, views, controllers, and migrations; instantiate, start and stopp servers; rake tasks, database management...so far, I can do everything through the IDE.  I'm very impressed.&lt;br /&gt;&lt;br /&gt;Then, I spent an hour or so screwing around with a little test app to re-familiarize myself with how the whole thing worked.  An issue here and there, but generally speaking it all worked out well.&lt;br /&gt;&lt;br /&gt;I'm still trying to get my head around the whole &lt;span style=";font-family:courier new;font-size:85%;"  &gt;script/generate scaffold&lt;/span&gt; thing in relation to migrations.  You have to setup the DB table before you can run &lt;span style=";font-family:courier new;font-size:85%;"  &gt;script/generate scaffold&lt;/span&gt;.  But, you have to run &lt;span style=";font-family:courier new;font-size:85%;"  &gt;script/generate model&lt;/span&gt; to setup the migration and then run &lt;span style=";font-family:courier new;font-size:85%;"  &gt;rake db:migrate&lt;/span&gt;.  This seems feels like I'm doing something wrong because I thought &lt;span style=";font-family:courier new;font-size:85%;"  &gt;script/generate scaffold&lt;/span&gt; is supposed to setup the model too.  That's how it was a year ago, in pre-migration days.  I have to figure out the best practice now...suggestions are welcome in the comments.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-2166598643436391211?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/2166598643436391211/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=2166598643436391211' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2166598643436391211'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2166598643436391211'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/07/radrails-and-formhtml.html' title='RadRails and Scaffold-Migration Best Practice'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-2716385326736070024</id><published>2007-07-20T08:36:00.001-07:00</published><updated>2007-09-29T08:01:49.314-07:00</updated><title type='text'>Aptana RadRails IDE and InstantRails</title><content type='html'>&lt;div&gt;&lt;span style="font-size:100%;"&gt;So, I'm doing this new startup thing--can't tell you just yet what the thing is--from the very scratch and &lt;a href="http://www.avogen.com/"&gt;Mark&lt;/a&gt; asked me keep a blog about it.  Here goes...&lt;/span&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;div&gt;&lt;span style="font-size:100%;"&gt;Yesterday was spent setting up my development environment.  In short, this is composed of two things:&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;InstantRails&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Aptana IDE with RadRails Plug-In&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:100%;"&gt;And the key is figuring out how to get the them to play nicely together.  So far, I ran into only two glitches:&lt;br /&gt;&lt;/span&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Installed InstantRails, then installed Aptana IDE, then installed RadRails Plug-In.  But, the plug-in wasn't working which I could tell because it's configuration options weren't appearing in the preferences.  From reading &lt;a href="http://www.aptana.com/forums/viewtopic.php?t=1782"&gt;this post&lt;/a&gt; I learned that it turns out I needed to upgrade my Java JDK to 1.5+.  Yay.  Also, turns out you can't just easily upgrade from within the JDK 1.4 (what I had) Control Panel tool to the latest version.  You have to uninstall, find the new package, install, blah...yay.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Got the RR Plug-In working, started reading the RR help documentation and it says there's some configurations that I need to setup.  Even though the RR configs are appearing in the Aptana IDE prefs, the specific configs they mention are not to be found in the location where the screenshot in the docs say to look for them.  Ug.   Maybe the install didn't work...so, uninstall, re-install...everything.  No luck.  Some posts I read say don't install one sub-package of the RR plug-in (the Ruby Development Tools, RDT)...okay, uninstall, re-install without package...no luck.&lt;br /&gt;&lt;br /&gt;Turns out, this was a bug in the documentation.  The configurations had been moved to a new area of the preferences, but the documentation hadn't been updated.  Oy! &lt;/span&gt;&lt;/li&gt;  &lt;br /&gt;&lt;li&gt;Finally, &lt;a href="http://instantrails.rubyforge.org/wiki/wiki.pl?RadRails"&gt;This article&lt;/a&gt; on the InstantRails wiki describes how to configure RadRails so that they play nicely together.  I set the configs and was all set.  Hooray!  &lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;br /&gt;Note on the title: Progress vs. Perfection...what's it mean?&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;Some could interpret it as a form of saying quantity is preferable to quality, but that's not what it means to me.  In my view, it's about staying focused on the goal while demonstrating respect for the &lt;a href="http://www.google.com/search?q=Law+of+Diminishing+Returns"&gt;Law of Diminishing Returns&lt;/a&gt;.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-2716385326736070024?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/2716385326736070024/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=2716385326736070024' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2716385326736070024'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/2716385326736070024'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2007/07/aptana-radrails-ide-and-instantrails.html' title='Aptana RadRails IDE and InstantRails'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-30954145.post-115260128288438294</id><published>2006-07-11T00:00:00.000-07:00</published><updated>2007-07-20T10:46:34.208-07:00</updated><title type='text'>Just Do It!</title><content type='html'>Which template should I use?  Hmmm...don't know...doesn't matter.  That's the whole point of this blog...to make decisions, and move on...without worrying about making a mistake.&lt;br /&gt;&lt;br /&gt;Update, July 20, 2007: Just changed the theme...I wanted a serif font...easier on the eyes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/30954145-115260128288438294?l=progress-vs-perfection.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://progress-vs-perfection.blogspot.com/feeds/115260128288438294/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=30954145&amp;postID=115260128288438294' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/115260128288438294'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/30954145/posts/default/115260128288438294'/><link rel='alternate' type='text/html' href='http://progress-vs-perfection.blogspot.com/2006/07/just-do-it.html' title='Just Do It!'/><author><name>Scott</name><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
