Schienen - Typensäule ohne STI verwenden?

81

Ich möchte eine Spalte verwenden, die aufgerufen wird, typeohne Single Table Inheritance (STI) aufzurufen. Ich möchte typenur eine normale Spalte sein, die a enthält String.

Wie kann ich dies tun, ohne dass Rails erwartet, dass ich eine einzelne Tabellenvererbung habe und eine Ausnahme von The single-table inheritance mechanism failed to locate the subclass...This error is raised because the column 'type' is reserved for storing the class in case of inheritance.auslöst?

Irgendwelche Ideen, wie das geht?

Kwas
quelle

Antworten:

134

In Rails 3.1 set_inheritance_columnist veraltet, auch können Sie einfach nilals Namen verwenden, wie folgt :

class Pancakes < ActiveRecord::Base
    self.inheritance_column = nil
    #...
end
Valentin Nemcev
quelle
Eigentlich sieht es so aus, als hätte sich das geändert rails 3.2. Laut apidock : 'Diese Methode ist in der neuesten stabilen Version veraltet oder verschoben. Die letzte vorhandene Version (v3.1.0) wird hier angezeigt. ' Danke für den Tipp!
Batkins
Es wurde in 3.1 veraltet und in 3.2 entfernt, glaube ich
Valentin Nemcev
2
@Batkins Der inheritance_columnLeser wird bewegt (daher "veraltet oder verschoben" Hinweis). Die Verwendung der inheritance_columndirekten Einstellung der Instanzvariablen ist beabsichtigt und nicht veraltet.
Lulalala
Arbeitete in Schienen 5.1
John Bachir
21

Sie können den STI-Spaltennamen überschreiben, indem Sie set_inheritance_column:

class Pancakes < ActiveRecord::Base
    set_inheritance_column 'something_you_will_not_use'
    #...
end

Wählen Sie also einen Spaltennamen aus, den Sie für nichts verwenden, und geben Sie ihn an set_inheritance_column.

mu ist zu kurz
quelle
2
Muss ich diese Spalte tatsächlich in meiner Datenbank erstellen?
Kwas
Danke, das hat funktioniert. Ein Framework sollte NIE !!!!! JE!!!! diktieren, was ein Tabellenfeld nicht benannt werden kann. Das ist schlecht für ältere Datensätze.
Jon
5
@ Jon: Rails kümmert sich nicht wirklich um Legacy-Daten oder spielt gut mit anderen, Rails hat zu viel Einstellung dafür. Sie können es mit einigem Aufwand dazu bringen, sich selbst zu verhalten, aber Sie kämpfen immer ein bisschen, wenn Sie etwas tun müssen, das Rails nicht geplant hat (was leider viele grundlegende Datenbankkonzepte enthält). OTOH, ich bin ein professioneller Ketzer, also werden andere Rails-Leute sicherlich sauer auf mich sein, wenn sie auf die ideologischen Probleme hinweisen :)
mu ist zu kurz
10
Ich denke, die Idee ist, dass Rails / Ruby die Konvention der Konfiguration vorziehen, also versuchen sie, sie für die Anwendungsfälle zu optimieren, die sie für richtig halten.
Ibrahim
21

Ich weiß, dass diese Frage ziemlich alt ist und ein wenig von der Frage abweicht, die Sie stellen, aber was ich immer mache, wenn ich den Drang verspüre, einen Spaltentyp oder etwas_Typ zu benennen, ist, dass ich nach einem Synonym für Typ suche und dieses stattdessen verwende:

Hier sind einige Alternativen: Art, Sorte, Sorte, Kategorie, Set, Genre, Art, Reihenfolge usw.

rii
quelle
10

Schienen 4.x.

Ich bin auf das Problem in einer Rails 4App gestoßen , aber in Rails 4 existiert die set_inheritance_columnMethode überhaupt nicht, sodass Sie sie nicht verwenden können.

Die Lösung, die für mich funktioniert hat, bestand darin, die Vererbung einzelner Tabellen durch Überschreiben ActiveRecordder folgenden inheritance_columnMethode zu deaktivieren :

class MyModel < ActiveRecord::Base

  private

  def self.inheritance_column
    nil
  end

end

Ich hoffe es hilft!

Itay Grudev
quelle
8
Einfachere Version : class MyModel < ActiveRecord::Base self.inheritance_column = nil end. Referenz: apidock.com/rails/ActiveRecord/ModelSchema/ClassMethods/…
Benj
1
Funktioniert für mich in Schienen 4.2.2. Vielleicht haben Sie den Server oder Spring nach der Änderung nicht neu gestartet?
Benj
1
Und andere Benutzer könnten die einfachere Version, die ich kommentiert habe, nützlich finden. Was das Problem des erneuten Ladens betrifft, bin ich kein Experte, aber es wäre für mich sinnvoll, eine Klasseneigenschaft nicht automatisch neu zu laden, ohne die Klassendefinition zu entladen und neu zu laden.
Benj
2
Ich verstehe Ihre Reaktion nicht, ich versuche nur, Ihre Antwort sinnvoll zu ergänzen. Warum fühlst du dich beleidigt? Ich komme in Frieden
Benj
2
@Benj Sieht so aus, als hätten sie alle Kommentare gelöscht, auf die Sie sich beziehen. Jetzt sieht es so aus, als würden Sie mit sich selbst streiten. ;)
Joshua Pinter
0

Wenn Sie dies für alle Modelle tun möchten, können Sie dies in einen Initialisierer stecken.

ActiveSupport.on_load(:active_record) do
  class ::ActiveRecord::Base
    # disable STI to allow columns named "type"
    self.inheritance_column = :_type_disabled
  end
end
Bill Lipa
quelle
Oder noch besser - in ApplicationRecord .
Alexander