STI und has_many Assoziation mit „Typ“ -Spalte als Key
-
05-07-2019 - |
Frage
Ich bin mit Single Table Inheritance für verschiedene Arten von Projekten zu verwalten. Ich beschloss, einige Informationen mit jedem Projekt Typ zugeordnet zu speichern. Also habe ich neue Tabelle „project_types“ mit „model_type“ Feld als Primärschlüssel. Primärschlüsselwerte sind Werte von „Typ“ Bereich „Projekte“ Tabelle. Problem : Wenn ich mit Project-Objekt ProjectTypes zugeordnet versuchen, erhalten Objekt, das es immer null zurück.
>> p = Project.find(:first)
=> #<SiteDesign id: 1, type: "SiteDesign", name: "1", description: "dddd", concept: "d", client_id: 40, created_at: "2009-10-15 08:17:45", updated_at: "2009-10-15 08:17:45">
>> p.project_type
=> nil
Erste Projekte im Zusammenhang mit ProjectTypes Projekt ist OK. Gibt es so funktioniert es richtig zu machen?
Modelle:
class Project < ActiveRecord::Base
belongs_to :project_type, :class_name => "ProjectTypes", :foreign_key => "model_name"
end
class SiteDesign < Project
end
class TechDesign < Project
end
class ProjectTypes < ActiveRecord::Base
self.primary_key = "model_name"
has_many :projects, :class_name => "Project", :foreign_key => "type"
end
Migrationen:
class CreateProjectTypes < ActiveRecord::Migration
def self.up
create_table :project_types, :id => false do |t|
t.string :model_name , :null => false
t.string :name, :null => false
t.text :description
t.timestamps
end
add_index :project_types, :model_name, :unique => true
#all project types that are used.
models_names = {"SiteDesign" => "Site design",
"TechDesign" => "Tech design"}
#key for model_name and value for name
models_names.each do |key,value|
p = ProjectTypes.new();
p.model_name = key
p.name = value
p.save
end
end
def self.down
drop_table :project_types
end
end
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :type
t.string :name
t.text :description
t.text :concept
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
Lösung
Kein Wunder, Sie bekommen Probleme. Durch die Bewegung von einem reinen STI-System zu Ihrem aktuellen System brechen Sie schrecklich die Muster, die Sie verwenden, um Teile eines mit Teilen eines anderen Verwirbelung.
ich persönlich für etwas gehen würde wie:
class Project < ActiveRecord::Base
attr_readonly(:project_type)
belongs_to :project_type
before_create :set_project_type
def set_project_type()
project_type = ProjectType.find_by_model_name(this.class)
end
end
class SiteProject < Project
end
class TechProject < Project
end
class ProjectType < ActiveRecord::Base
has_many :projects
end
mit Migrationen:
class CreateProjectTypes < ActiveRecord::Migration
def self.up
create_table :project_types do |t|
t.string :model_name , :null => false
t.string :name, :null => false
t.text :description
t.timestamps
end
add_index :project_types, :model_name, :unique => true
#all project types that are used.
models_names = {"SiteDesign" => "Site design",
"TechDesign" => "Tech design"}
#key for model_name and value for name
models_names.each do |key,value|
p = ProjectTypes.new();
p.model_name = key
p.name = value
p.save
end
end
def self.down
drop_table :project_types
end
end
class CreateProjects < ActiveRecord::Migration
def self.up
create_table :projects do |t|
t.string :type
t.references :project_type, :null => false
t.text :description
t.text :concept
t.integer :client_id
t.timestamps
end
end
def self.down
drop_table :projects
end
end
Es reinigt nur die Dinge, und es hilft auch zu klären, was Sie tun. Ihr 'Projecttisch rein für zusätzliche Daten ist, Ihr Vererbungsbaum noch existiert. Ich habe auch in einigen Prüfungen geworfen sicher, dass Ihr Projekt Typ immer gesetzt (und richtig, auf der Grundlage der Modellname) und stoppt Sie vom Projekttyp zu ändern, sobald es nur, indem sie das Attribut gelesen gespeichert worden ist.