views:

106

answers:

2

I have a class hierarchy looks like this:

class Post < ActiveRecord::Base; end
class Project < Post; end
class ProjectDesignWall < Project; end

There's a controller that fetches data like so:

@projects = Project.find(:all, :include => [:project_image_photos,:user])

In development, this runs the following query, straight from the logs:

SELECT * FROM `posts` WHERE ( (`posts`.`type` = 'Project' ) ) ORDER BY originally_created_at DESC

However, as soon as it's run in production mode, even with the same database and data, it results in the following query:

SELECT * FROM `posts` WHERE ( (`posts`.`type` = 'Project' OR `posts`.`type` = 'ProjectDesignWall' ) ) ORDER BY originally_created_at DESC

Does anyone know why this is happening, and is there any way to get it to at least behave consistantly, if not outright fix the problem?

+4  A: 

Because in production all your classes are loaded at once. When all the classes are loading it realises that ProjectDesignWall is a subclass of Project thus gathers all of them.

Ryan Bigg
Is there a way to force this to happen in development, without caching the classes (ie. don't need to restart the server to reload classes)?
Luke
On each reload it'll load the classes that you need, I cannot think of a way to do it.
Ryan Bigg
+1  A: 

There is an open ticket for this bug here: https://rails.lighthouseapp.com/projects/8994/tickets/188-single-table-inheritance-bug-only-in-production-environment

The solution is listed at the bottom of this ticket: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2389-sti-changes-behavior-depending-on-environment

To quote:

You must explicitly name subclasses in the parent class

class ProjectFeedEvent < FeedEvent

def self.subclasses
  [ProjectAddedEvent]
end

end

Part of the reason this issue has been around for a while and has not received much attention is that STI is not commonly necessary in Rails. Most contributors to Rails have decided not to use it in their own projects and therefore do not put time into making sure that it is well supported. Here's a blurb that briefly explains why you should not use it and suggests an alternative: http://www.matthewpaulmoore.com/ruby-on-rails-code-quality-checklist#sti

My own personal experiences using STI at my company was that is seemed very useful at first, but as time went on we determined that we simply didn't need it enough to warrant the complexity. Since then, our project has grown dramatically and we have not missed it at all.

Gdeglin
This works perfectly, thanks! I've been rethinking the use of STI as well, but in my case I think it works well (common data structure, but different business rules for subclasses).
Luke