Tuesday, June 10, 2008

invalidates_format_of

Have you ever found yourself wanting an invalidates_format_of or validates_format_not method. For example, maybe you want to make sure a name field doesn't have 2 or more consecutive spaces, there's not regular expression that I can come up with that will positively match a string that does NOT have 2 consecutive spaces.

Even if there is a regular expression that does that, let's assume for the sake of this article that you have a situation where you can't easily come up with a regular expression that describes what you want but you CAN come up with a regular expression that describes what you don't want. In that case, you'd really like something like:


# too bad this doesn't work...
invalidates_format_of :name, :with => /\s{2,}/, :message => "can't have consecutive spaces"

Unfortunately, invalidates_format_of doesn't exist but validates_each comes to the rescue. The validates_each method allows you to build just about any type of validator you could ever want. To build the equivalent of invalidates_format_of, all you have to do is this:

# invalidates_format_of
validates_each :name, :on => :create do |model, attr, value|
if value =~ /\s{2,}/
model.errors.add(attr, "can't have consecutive spaces")
end
end

This technique could certainly be used to create your own validates_absence_of, validates_non_uniquess_of or any other method that doesn't quiet meet your requirements. For example, if you want a method that validates uniqueness of a name but only if it's not nil (i.e. nil is allowed but name must be unique if it's not nil), then try this:

# validates_nil_or_uniqueness_of
validates_each :name, :on => :create do |model, attr, value|
if model.name != nil && model.class.find_by_name(value)
model.errors.add(attr, "is already taken")
end
end

Piece of cake... I hope that helps someone out there on the interwebs.

Monday, April 21, 2008

spawn plugin - now works with nginx

The latest version (0.6) of the spawn plugin for rails, now works with nginx. Go get it... now!

Monday, March 03, 2008

sort_like - Sort One Array Like Another

Every so often, you find that you can write something in Ruby that's so cool that you have to share. Today, I had 2 arrays that had similar objects and I wanted the 2nd array to be sorted like the first array. For example, what if you have an array of sorted IDs and you want to get a bunch of model objects using the list of IDs.


sorted_ids = [1, 3, 5, 4, 2]
unsorted = Model.find_all_by_id(sorted_ids)
The problem is, the model objects won't necessarily come back in the same order as the array of IDs. Ruby to the rescue... sort those results with one line of code!

sorted = unsorted.sort_by{|model| sorted_ids.index(model.id)}
How cool is that?

homework


Write the same functionality in Java without scratching your eyes out.

Hint: wear goggles.