Archive for April, 2008

A case for methodizing your constants

Friday, April 4th, 2008

I was testing a bit of Rails code today and came across a spot where I wanted a unit test to make sure my method was going to properly handle an upper limit on associated objects. Think of it like this:

class Release < ActiveRecord::Base
  has_many :tags
  
  MAX_TAGS = 15
  
  def associate(tag)
    self.tags << tag unless self.tags.size == MAX_TAGS
  end
end

At 15 max tags, either I'm going to clutter up my tests with dummy data, or I'm going to drive myself insane creating needless fixtures. I use Mocha to stub out methods in my tests, so I immediately asked myself, "How can I stub a constant?" You can go ahead and alter the constant in your test case using const_set, but that requires that you set it back at the end of your test. Another option is to methodize the constant and stub it out like you would any other method:

class Release < ActiveRecord::Base
  has_many :tags
  
  MAX_TAGS = 15
  
  def self.max_tags
    MAX_TAGS
  end
  
  def associate(tag)
    self.tags << tag unless self.tags.size == Release.max_tags
  end
end

Now, in your test case, you can just stub out your new class method and, provided you're now accessing the constant in your original method through its new wrapper method, you're all set:

class ReleaseTest < ActiveSupport::TestCase
  def test_associate
    Release.stubs(:max_tags).returns(1)
    
    assert_no_difference 'release(:first).tags.reload.size' do
      release(:first).associate(tags(:new))
    end
  end
end

Start Simple, End With a Flourish

Thursday, April 3rd, 2008

As I continue developing new sites, I find myself falling into development patterns. I'm trying to foster some of them, but there's one habit in particular I'm trying to break: I realize that when I began my most recent project, it was littered with JavaScript-y goodness in an effort to get the "wow" factor from users. As time has worn on, however, I've found myself ripping out more and more of this chrome, to the point where the majority of my site now functions as a "normal" Web application.

One of the first pieces of AJAX I added to this project was the ability to edit a "media bar" while still browsing the page it was on. You'd click an "edit" link in a vertically floated DIV, and it would scale upwards in sort of a light box effect, while fading out its contents and fading in controls to edit those contents. Now, don't get me wrong. This control looked cool (take my word for it). I still have the code lying around in an old Subversion check-in, because I'm a bit proud of it, actually.

The problem with my editable media bar was that ultimately, it was too stylish for its own good. The novelty wore off after a few uses, and then I was stuck with a difficult-to-maintain piece of JavaScript that never seemed to fit with the rest of the site. But I had spent like three days on it! It was so cool! Which is why it had to go: I had spent so much time on it that I had tunnel vision, and when our designer actually got around to seeing it, he didn't even make a peep; it wasn't even a blip on his radar.

Something I had to realize was that if I really wanted this element on the site, I had to also be comfortable taking it away, and reevaluating it. It may come back in a similar form in the future, but for a version 1.0 release, it wasn't worth the time I spent creating it. I've reverted to a standard link to send users to the media bar edit page, and its functionality is as good, if not better, than my initial flashy solution.

So I'm going to be starting simple on my next project. JavaScript and AJAX can wait. It has its place on The Web, but for most everyday user interface patterns, it's just overkill, and the benefits do not outweigh the development time.