Ruby on Rails 3 : "superclass mismatch for class ..."
Sometimes we 'open class' without us knowing. For example with some deep module nesting:
# space_gun.rb
class SpaceGun << Weapon
def fire
Trigger.fire
end
end
# space_gun/trigger.rb
class SpaceGun
class Trigger
end
end
When we define trigger, we open the existing SpaceGun class. This works. However if we load the two file in the reverse order, the error would be raised, because we would define a SpaceGun class first, but is not a Weapon.
Sometimes we make this mistake because we explicitly require sub module (e.g. trigger) from the parent class. Which means the class definition will be done the reverse order, causing this issue.
# surely nothing can go wrong if we require what we need first right?
require 'space_gun/trigger'
class SpaceGun << Weapon
def fire
Trigger.fire
end
end
# BOOM
Either
- rely on auto loading
- always put inheritance to every open class occurrence.
I had the problem with a Rails 4 application. I used concerns under the user namespace.
class User
module SomeConcern
end
end
In development everything worked fine but in production (I guess because of preload_app true) I got the mismatch error. The fix was pretty simple. I just added an initializer:
require "user"
Cheers!
This can also happen as such:
# /models/document/geocoder.rb
class Document
module Geocoder
end
end
# /models/document.rb
require 'document/geocoder'
class Document < ActiveRecord::Base
include Geocoder
end
The require loads Document
(which has a superclass of Object) before Document < ActiveRecord::Base
(which has a different superclass).
I should note that in a Rails environment the require is not usually needed since it has auto class loading.
You already have a Word
class defined elsewhere. I tried within a Rails 3 app but was not able to replicate.
If you have not created a second Word
class yourself, it is likely one of your Gems or plugins already defines it.