Close
Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

PIVOTAL LABS
Standup 09/23/2008: Disabling pre-rails-2.1 style :include

Interesting Things

  • If your HTTP header’s HTTP_CLIENT_IP is not equal to HTTP_X_FORWARDED_IP, then rails 2.1 and above will consider it an IP spoofing attack and throw an exception! This is bad news for some traditional Apache->Mongrel setups. Solution is probably to change the apache HTTP headers, but we’re wondering exactly why this is a security problem for rails (and why they would break compatibility with the default apache setup from way back when)?
  • Be careful when using validates_uniquess_of with :case_sensitive => true AND a unique index at the database level. If your database is case insenitive, then rails will approve the uniqueness, but the database will fail the insert. Solution: be sure to use a collation type for the unique column that is case sensitive (such as binary in mysql).
  • Rails 2.1+ :includes are way better than pre-2.1, but they are less compatible with conditions. Hence, rails falls back on the old style. Here’s when it might legitimately fall back:
User.find(:all, :include => :profile, :conditions => "profiles.gender = 'M'")

Because we reference the included table profiles in the :conditions, rails has no choice but to construct one giant query to fetch Users and their profiles, rather than a separate query. Here’s a case when it guesses wrong:

User.find(:all, :include => :profile,
  :joins => "INNER JOIN comments ON comments.user_id = users.id",
  :conditions => "comments.approved = 1")

Because the conditions references a table that is not users, rails thinks it has to fall back to the old include style… but it’s wrong! Here’s how we tricked ActiveRecord into always using rails 2.1+ includes (note that we had to fix up a few queries that were referencing :inlcuded tables in :conditions to make this work):

module ActiveRecord::Associations::ClassMethods
  private
  def references_eager_loaded_tables?(options)
    false
  end
end

Comments
  1. Tim Connor says:

    Vis a vis, the spoofing exceptions, we had the same problem at work. “I monkey-patched rails to turn off the ip spoofing check”:http://github.com/timocratic/rails/commit/f403857fc2ff7918b17dc315b45a1d55016d0fbb but I’d gladly submit a patch to make it a configuration setting to turn it on or off, if there is interest.

  2. John says:

    Could you explain (or provide a link to) the differences between pre-2.1 and 2.1+ :include behavior? It makes the difference between a really helpful post and a nudge below the threshold for keeping a feed in my reader.

  3. David Stevenson says:

    Examples of pre-2.1 and 2.1 includes I posted in the [next standup article](http://pivots.pivotallabs.com/users/stevend/blog/articles/515-standup-09-24-2008-why-does-my-jvm-crash-running-solr-)!

  4. Dan Manges says:

    The IP spoofing exception was fixed in Rails 2.1.1. There was some concern in the lighthouse ticket that the fix wasn’t sufficient, but I tested with Apache and Passenger and it fixed 100% of the occurrences for my site.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *