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])
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?
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
You must explicitly name subclasses in the parent class
class ProjectFeedEvent < FeedEvent
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.
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.