Skip to main content

Benjamin Oakes

Photo of Ben Oakes

Hi, I'm Ben Oakes and this is my geek blog. Currently, I'm a Ruby/JavaScript Developer at Liaison. Previously, I was a Developer at Continuity and Hedgeye, a Research Assistant in the Early Social Cognition Lab at Yale University and a student at the University of Iowa. I also organize TechCorridor.io, ICRuby, OpenHack Iowa City, and previously organized NewHaven.rb. I have an amazing wife named Danielle Oakes.

Filtering for the month May, 2010. Clear

Politeness

by Ben

Sometimes Rubyists can be a little rude. To help fix that problem, I did what I do best: I wrote a Ruby script.

From the GitHub repository:

Require your Ruby code to be more polite: require ‘politeness’

Inspired by INTERCAL, this library makes Ruby programmers say “please” more often. If Ruby doesn’t like how brash or cocky you’re being, it will stop in the middle of your code and tell you so:

"Not polite enough!"

However, you can say please too much. In that case, Ruby will throw its hands up and tell you that you’re:

"Too polite!"

Most libraries are very rude, so be sure to require politeness after including them (unless you intend to make them a little more well-mannered).

Rails validations should be instance level, not class level

by Ben

I recently ran into a problem where I needed to use validates_uniqueness_of with more than one scope. Basically, I have resources that users can either share or keep to themselves. Each resource has a description that should be unique. However, the scope of the uniqueness depends on the situation. In pseudo-code, I wanted something like:

if shared?
  validates_uniqueness_of :description, :scope => :shared
else
  validates_uniqueness_of :description, :scope => :user_id
end

(That is, if you share, the description should be unique across all the shared resources. Otherwise, it should just be unique within your stuff.)

That seems straightforward, but it’s complicated by the fact that Rails validations are at the class-level rather than the instance-level. To me, it makes more sense to execute validations at the instance-level.

Specifically because they’re not executed at the instance-level, validations like validates_uniqueness_of need “smelly” option keys like :if and :unless. If the validations were executed in the proper context (i.e., in the context of the instance that’s being validated), Rails wouldn’t need any of that hackery. The real if and unless could be used directly.

The Hashrocket folks said something similar in their Rails 3 Blog Club – Week 1 video. As far as I know, the situation is staying the same in Rails 3, even with all the validation refactoring. Even so, I think there’s a strong argument for moving validations to the instance level.

For example, if validations were executed in the context of the model instance, the above would have translated directly to something like this:

class MyModel < ActiveRecord::Base
  # [...]

  def validate
    if shared?
      validate_uniqueness_of :description, :scope => :shared
    else
      validate_uniqueness_of :description, :scope => :user_id
    end
  end
end

(Note for blog skimmers, the above code does NOT work.)

Instead, I ended up with the following:

class MyModel < ActiveRecord::Base
  validates_uniqueness_of :description, :scope => :shared, :if => :shared?
  validates_uniqueness_of :description, :scope => :user_id, :unless => :shared?
end

The :if / :unless keys still feel like a hack to me. (I’m scared they will break in non-obvious ways, to be honest — I think I’ve already found a couple of corner cases.)

Am I missing something when it comes to why validations were designed this way? If so, how would you approach this problem?

Obama chooses Elena Kagan for Supreme Court

by Ben

It’s great the Supreme Court is starting to reflect the population a little better.  If anyone has an argument against that, I’m guessing it’s almost certainly BS.

Obama chooses Elena Kagan for Supreme Court – CNN.com.