Matthew
Matthew

Reputation: 2135

Ruby on Rails 3 : "superclass mismatch for class ..."

Platform: Mac OSX 10.6

In my terminal, i start the Ruby console with "rails c"

While following the Ruby on Rails 3 tutorial to build a class:

class Word < String 
  def palindrome? #check if a string is a palindrome
    self == self.reverse
  end
end

i get the error message:

TypeError: superclass mismatch for class Word
    from (irb):33
    from /Users/matthew/.rvm/gems/ruby-1.9.2-p180@rails3tutorial/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start'
    from /Users/matthew/.rvm/gems/ruby-1.9.2-p180@rails3tutorial/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start'
    from /Users/matthew/.rvm/gems/ruby-1.9.2-p180@rails3tutorial/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'

The tutorial shows that it has no problem and i know the code is fine; I've searched other related questions, but they all involved migrating from Ruby 2 to 3 or erb vs eruby.

Upvotes: 75

Views: 89639

Answers (6)

Benjamin Bouchet
Benjamin Bouchet

Reputation: 13181

Depending on your specific case, any of the already-provided answers could be your solution.

To find out quickly and easily, temporarily set config.eager_load = true and start your rails console. It should immediately fail with a more explicit error message, pointing at the right file and line number.

Don't forget to set config.eager_load back to its original value after.

Upvotes: 1

lulalala
lulalala

Reputation: 17981

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

  1. rely on auto loading
  2. always put inheritance to every open class occurrence.

Upvotes: 8

2called-chaos
2called-chaos

Reputation: 3078

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!

Upvotes: 23

Kris
Kris

Reputation: 19948

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.

Upvotes: 28

RebelWarrior
RebelWarrior

Reputation: 59

I had this same problem right now. Basically that means that Word is defined as a class elsewhere and my guess is that it's on the rail-ties gem. Just change Word to Word2 and it should work fine on the tutorial.

Upvotes: 5

Douglas F Shearer
Douglas F Shearer

Reputation: 26488

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.

Upvotes: 95

Related Questions