Archive for June, 2006

One of, a pocket case

Friday, June 30th, 2006

Another one of our snippets of code (all collected in a ‘private’ plugin called, surprisingly, ’snippets’) is one_of.

Suppose you have an html form, with a select that let your users specify the sort order for your index page. Said order can take a value of “name”, “name desc”, “date” or “date desc”. The more observant among you are probably yelling “SQL injection!!!, SQL injection!!!”, because even if your select only has those four options, nothing can prevent a malicious script kiddie to modify the request and ask for sort_order=your momma or perhaps sort_order=name; delete from users.

So smart web developers (or dumb web developers smart enough to remember when their sites got hacked because of a SQL injection) validate anything that comes from the outside world.

Our snippet, one_of, provides a simple way to do a very common validation: making sure a value is one of a given set of possible values.

class Object
  # Makes sure the value is "one of" the list given,
  # otherwise returns the first value from the list
  def one_of(*args)
    args = args[0] if args.size == 1 and args[0].kind_of? Array

    (args.include?(self) && self) || args[0]
  end
end

It’s use is exemplified, for example, in the following examples:

query[:sort] = params[:sort_order].one_of("name", "name desc",
                                                           "date", "date desc")
answer = answer.one_of("yes", "no")
answer = nil.one_of("yes", "no")  # => "yes"

This method serves it’s purpose well, so we haven’t had a need to enhance it. But I can easily think of a couple of improvements, making it more case-like.

class Object
  # Makes sure the value is "one of" the list given,
  # otherwise returns the first value from the list
  def one_of(*args)
    args = args[0] if args.size == 1 and args[0].kind_of? Array

    args.each do |arg|
      return (arg.kind_of?(Regexp) ? $1 : self) if arg === self
    end
    args.first
  end
end

See? Now you can do thinks like:

"abc".one_of(String, Numeric) # => "abc"
"abc".one_of("none", /([bc]+)/)  # => "bc"

It works almost like a pocket-sized version of case, with the default being first instead of last.

But be careful. Since the default value is the first one in the array, you might end up with a Class object, or a Regexp.

Do or do not… or maybe try?

Wednesday, June 28th, 2006

During RailsConf, _why presented the last two installment of his fabulous series: The Least Surprised. This time, they even were multimediatically animated, with sound and movement.

In one of them, Malsky (that’s his name) talks about exception handling and compares Java’s wimpy, tentative try (”uhm… let’s see, are we suppose to be doing this?”) and catch (”oh, oh, they threw a ball at me… don’t close your eyes… don’t close your eyes…”) with ruby’s assertive and daring begin (”we’re on a mission, here we go”) and rescue (”something went wrong, but it’s ok, we can deal with it”). And he finished with a “in ruby, there is no try” and a round of applause. I’m paraphrasing here, trying to fetch the memories behind a cloud of drunken stupor, but I’m sure it was pretty much like that, if not literally, at least in spirit.

So, anyway, after his totally and amazingly rocking performance, I approached him. Once I got the autograph out of the way, I showed him this little nugget of code we use at streeteasy.

module Kernel
  # Returns 'value' in case of an exception, otherwise returns the execution
  # of the given block
  def try(value = nil)
    yield if block_given?
  rescue Exception => exception
    value
  end
end

Which provides the simplest possible exception handling: in-line inside your expressions, with a default value in case of any exception. Some examples are in order:

try {params.join} || ""
try("") {params.join}
"User: #{user} (#{ try {user.group.name} || "no group" })"
user.group = try {Group.find(params[:id])}

See? a clean way of dealing with “minor” exceptions. And _why, after clarifying that it was Malsky’s opinion, not actually his, agreed that “it was tentative enough, and an apropriate use of trying”, and that the || syntax was prettier (we agree).

So now, our source code looks like this:

module Kernel
  # Returns 'value' in case of an exception, otherwise returns the execution
  # of the given block
  #
  # Now with the official stamp of approval of _why the lucky stiff
  #
  def try(value = nil)
    yield if block_given?
  rescue Exception => exception
    value
  end
end

Feel free to use it in your code, and try to give us credit (heh, see, a pun). Why not? (heh, another pun, I’m funny).

RailsConf Calendar

Tuesday, June 20th, 2006

I have made available an iCal file with the schedule for RailsConf 2006. I created it even before the official schedule was made public, but I have kept it up to date. The description even
includes a list of changes.

You can Subscribe in Apple iCal, or use the url above in any other program supporting the iCal format.

Hello world!

Tuesday, June 20th, 2006

It was about time for me to start blogging in english. I’ve been doing it in spanish for more than 5 years, and even had one or two false starts at the english blogging thing.

Now I’m starting for real. I’ll keep blogging in this site forever. That is, if you consider that “blogging forever” can include indefinitely long periods of silence.

So bear with me, bear with my ESL (that is English as a Second Language, for those of you gringos that have never had to deal with an immigrant) and please don’t call La Migra on me.