Supposing you have a Rails 4.2 application with a
Book model, and there's a record of who has read that book, so it
has_many :readings. If you start a new console, reopen the class, and try to use that association, you might be surprised by the result:
What? Where did my associations go?
This puzzled me for a while until I realized that the first line of code in that irb session is not reopening the class. Instead, it's defining it for the first time, and once Rails has a class definition in place it won't attempt to load the definition that's in
This bit me recently on a Rails 4.1 to 4.2 upgrade. I was running the test suite and getting errors as if fixtures were not working - i.e., errors like
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'readings' in 'field list':. But it was because I was reopening model classes in
test_helper to add some methods, and those reopenings didn't have the full class definitions with all the associations and module inclusions and whatnot. Yup, I know, bad practice, hey, reasons. So I "fixed" it by adding
Book (thanks to Michael Cohen for noting that
Book.first did an unnecessary query) just before my
class Book < ActiveRecord::Base in
test_helper; with that in place the
app/models/book.rb class definition was loaded first and then my reopening code was actually reopening as I intended.
Joe Rafaniello had an even better idea. Rather than using autoloading by referencing the constant, just do a plain old
require 'book'; that explicitly shows that we're loading the class rather than trying to fool autoloading.
More generally, Michael Cohen also pointed to Justin Weiss's article on monkeypatching and suggested putting these test-related monkeypatches in a module rather than just slapping them into