Erstellen Single Table Inheritance Datensätze in Rails
-
05-07-2019 - |
Frage
Ich verwende einzelne Tabelle Vererbung für meine Anwendung. Mein polymorpher Typ ist Wartung mit nur einem Subtyp, gerade jetzt, genannt Ölwechseln. Ich laufe Probleme meine Aufzeichnungen in meiner create-Methode in der Steuerung zu schaffen. Hier ist der Code.
@log = Log.new(params[:log])
@log.maintenance = Maintenance.new(params[:maintenance])
Die params [: Wartung] Hash hat Tasten {: Name,: type}. Ich kann ihre Existenz und Werte überprüfen, indem sie den Ausdruck wie folgt
print params[:maintenance][:name]
print params[:maintenance][:type]
Wenn ich in „Ölwechsel“ für den Wert des übergeben: Typenschlüssels ist das Wartungsprotokoll vom Typ Wartung und nicht den von Ölwechseln. Ich kann das überprüfen, indem Sie den Datensatz in der REPL Konsole zu finden. Das Typ-Feld ist gleich Null. Ich kann es funktioniert, wie ich möchte, indem Sie die folgende Zeile hinzufügen.
@log.maintenance.type = params[:maintenance][:type]
Aber das ist hässlich. Was ich frage mich ist, warum das nicht schaffen Methode, um das Typ-Feld gesetzt, wie es der Name Feld tut nur finden?
Die beiden Typen, die Sie in meinem schema.rb so aussehen zu sehen
create_table "logs", :force => true do |t|
t.date "date"
t.text "description"
t.string "title"
t.string "summary"
t.integer "car_id"
t.datetime "created_at"
t.datetime "updated_at"
t.integer "maintenance_id"
t.integer "mileage"
end
create_table "maintenances", :force => true do |t|
t.string "name"
t.string "type"
t.datetime "created_at"
t.datetime "updated_at"
t.string "oil_brand"
t.string "oil_type"
t.string "oil_filter_type"
Meine Modelle wie folgt aussehen.
class Log < ActiveRecord::Base
belongs_to :car
has_and_belongs_to_many :tags
belongs_to :maintenance
end
class Maintenance < ActiveRecord::Base
has_one :log
end
class OilChange < Maintenance
end
TIA!
Lösung
Die spezifische Antwort ist, dass das type
Attribut, wie viele Rails des besonderen Eigenschaften von Massenzuordnung geschützt ist. (Look up :attr_protected
in der Dokumentation.)
Die Antwort auf das allgemeinere Problem ist, dass Sie nicht Ihre Modelle genug zu vertrauen. Wenn Sie einen Datensatz vom Typ Ölwechsel erstellen möchten, sollten Sie nicht Maintenance.new
oder Maintenance.create
nennen. Rufen Sie OilChange.new
oder OilChange.create
statt und Rails kümmert sich automatisch um die Art der Einstellung und tun all die Hintergrundarbeit für Sie.
Andere Tipps
Versuchen Sie, den folgenden Code:
begin
klass = Module.const_get(params[:maintenance][:type])
@log.maintenance = klass.new(params[:maintenance])
if ! @log.maintenance.is_a?(Maintenance)
@log.maintenance = Maintenance.new(params[:maintenance])
end
rescue NameError
@log.maintenance = Maintenance.new(params[:maintenance])
end
Wenn Sie nur Subklassen von Wartung in Ihrer Datenbank haben wollen, gehen Sie wie folgt in Ihrer Wartungsklasse:
class Maintenance < ActiveRecord::Base
validates_presence_of :type
# other stuff goes here
end
Dieser Code wird eine ungültige Wartungs Klasse erstellen, wenn die params die falsche Art enthalten. Wenn sie die richtige Art, eine Instanz der angegebenen Klasse enthalten wird erstellt.
Wenn Sie Ihre Modelle Namespaces verwenden können Sie diesem Artikel schauen in anstelle von Module.const_get
: