web-dev-qa-db-fra.com

Ruby on Rails 3: "discordance de superclasse pour la classe ..."

Plateforme: Mac OSX 10.6

Dans mon terminal, je démarre la console Ruby avec "Rails c"

Tout en suivant le Ruby on Rails 3 tutoriel pour construire une classe:

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

je reçois le message d'erreur:

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>'

Le tutoriel montre qu'il n'a pas de problème et je sais que le code est correct; J'ai cherché d'autres questions connexes, mais elles impliquaient toutes la migration de Ruby 2 à 3 ou erb vs eruby.

56
Matthew Chan

Vous avez déjà une classe Word définie ailleurs. J'ai essayé dans une application Rails 3 mais je n'ai pas pu répliquer.

Si vous n'avez pas créé vous-même une deuxième classe Word, il est probable qu'un de vos Gems ou plugins la définisse déjà.

71

Cela peut également se produire en tant que tel:

# /models/document/geocoder.rb
class Document
  module Geocoder
  end
end

# /models/document.rb
require 'document/geocoder'

class Document < ActiveRecord::Base
  include Geocoder
end

Le besoin charge Document (qui a une super-classe d'Object) avant Document < ActiveRecord::Base (qui a une superclasse différente).

Je dois noter que dans un environnement Rails, le require n'est généralement pas nécessaire car il a un chargement automatique de classe.

24
Kris

J'ai eu le problème avec une application Rails 4. J'ai utilisé des problèmes sous l'espace de noms utilisateur.

class User
  module SomeConcern
  end
end

En développement, tout a bien fonctionné mais en production (je suppose à cause de preload_app true) j'ai eu l'erreur de non-concordance. La solution était assez simple. Je viens d'ajouter un initialiseur:

require "user"

À votre santé!

17
2called-chaos

J'ai eu ce même problème en ce moment. Fondamentalement, cela signifie que Word est défini comme une classe ailleurs et je suppose que c'est sur le joyau des liaisons ferroviaires. Modifiez simplement Word en Word2 et cela devrait fonctionner correctement dans le didacticiel.

6
RebelWarrior

Parfois, nous "ouvrons la classe" sans que nous le sachions. Par exemple, avec une imbrication profonde de module:

# space_gun.rb
class SpaceGun << Weapon
  def fire
    Trigger.fire
  end
end

# space_gun/trigger.rb
class SpaceGun
  class Trigger
  end
end

Lorsque nous définissons le déclencheur, nous ouvrons la classe SpaceGun existante. Cela marche. Cependant, si nous chargeons les deux fichiers dans l'ordre inverse, l'erreur serait déclenchée, car nous définirions d'abord une classe SpaceGun, mais ce n'est pas une arme.

Parfois, nous faisons cette erreur parce que nous avons explicitement besoin d'un sous-module (par exemple, un déclencheur) de la classe parente. Ce qui signifie que la définition de classe se fera dans l'ordre inverse, ce qui provoque ce problème.

# 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

Non plus

  1. compter sur le chargement automatique
  2. toujours mettre l'héritage à chaque occurrence de classe ouverte.
3
lulalala