Space Vatican

Ramblings of a curious coder

Validates_inclusion_of in Ruby 1.9

Range#include? changed in ruby 1.9 . In ruby 1.8, testing whether a value was included in a range meant testing that it was greater than the start of the range and smaller than the end. Ruby 1.9 will iterate through all values in the range, checking whether any of them are equal to the value being tested.

The justification is that this is needed for some special cases. The example given in the link above is a range of objects wrapping integers, where #succ is defined to add 2 to the wrapped integer and comparison is defined by comparing the wrapped integer. If we write f(x) for the object wrapping x then you would have f(1) <= f(2) and f(2) <= f(3), but f(2) is not in the sequence generated by calling #succ repeatedly on f(1), since that yields only objects wrapping odd numbers.

While more correct in this sense, this is obviously a lot slower. It’s also not immune from a different class of issues. As Xavier Noria pointed out on the rails-core list, it’s easy enough to construct ranges with an infinite amount of elements in them for example. Calling include on them would hang forever on 1.9.

In the real world, my main concern is the speed. In our app we had a validates_inclusion_of on dates with a 100 year date range. On 1.8 this was instant, but on 1.9 calling include? on that range was taking around 130ms (on a 2.66Ghz Core i7).

Luckily the old include? logic is available as cover?. As of 3.0.5 Rails will use cover? rather than include? for validates_inclusion_of, until then you could drop something like this in an initializer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
if RUBY_VERSION =~ /1\.9/
  module ActiveModel
    # == Active Model Inclusion Validator
    module Validations
      class InclusionValidator < EachValidator
        def validate_each(record, attribute, value)
          match = if options[:in].is_a?(Range)
            options[:in].cover?(value)
          else
            options[:in].include?(value)
          end

          unless match
            record.errors.add(attribute, :inclusion, options.except(:in).merge!(:value => value))
          end
        end
      end
    end
  end
end

A Sneaky Session Gotcha in Rails 2.3

A colleague and I recently updated an app to rails 2.3.4 and found ourselves with a slightly sticky performance problem - slow app response times, with time disappearing seemingly nowhere. New Relic also showed that requests were queueing inside mongrels which wasn’t shouldn’t have been a problem since there were plenty of mongrels for the traffic being received at the time

Our friendly Engineyard support engineer pointed us to a ticket on the Rails lighthouse describing a rather similar situation encountered during the RC phase of rails 2.3: Active record based sessions causing trouble because they weren’t returning their connection to the connection pool [1]. Connection pooling isn’t new in 2.3 but the move to rack changed the order in which things like sessions, query caching, connection pool are put up.

This ticket was mark as resolved, however looking at the fix it became clear why we were still experiencing the problem:

1
2
3
4
5
6
7
if ActionController::Base.session_store == ActiveRecord::SessionStore
  configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement
   configuration.middleware.insert_before :"ActiveRecord::SessionStore", ActiveRecord::QueryCache
else
  configuration.middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement
  configuration.middleware.use ActiveRecord::QueryCache
end

(Source here)

Since our session store isn’t ActiveRecord::SessionStore, the code to put the database related middleware in the right place in the chain isn’t executed. I’m not entirely sure what to do about this - the rails initializer cannot be expected to know the details of what the session store is doing (unless part of the session store interface was a uses_active_record? flag) but as it is this very sneaky and would have taken a while to find if we hadn’t been pointed in the right direction.


[1] As of Rails 2.2, Active Record has a concept of a connection pool: a given rails instance won’t use more than a certain number of connections (5 by default) even if that rails instance was a jruby based instance with hundreds or threads. If you need a connection from the pool and they are all in use then you have to wait until one becomes available. Normally you are blissfully unaware of this - rails marks your connection as no longer used when your action has finished processing.

Error Launching Remote Program: Security Policy Error

I created a new iPhone project today and got a rather vague error message from Xcode when I tried to run it on a device:

Error launching remote program: security policy error

After some digging it turns out that the problem was that I had two provisioning profiles on the device: - a wildcarded one (which had expired) that I use for quick hacks that don’t warrant going through the hassle of setting up new provision profiles - one created specifically for this application

The wildcarded profile had expired, and for some reason the iPhone was trying to launch the app with the expired profile even though it had a valid profile that it could have used. Deleting the expired profile from the device did the trick. If only that error message had been a bit more explicit …

My First Iphone App

After much toiling kgb’s first iPhone app is on sale! Get it now. Only in the US unfortunately.

For the record, we submitted two versions of the app: an earlier version that we didn’t expect to release (we wanted to see what the approval process was like and if apple was OK with the basic idea of our app) and the one that is on sale today. Both were approved in about 10 days - no approval horror stories here!