STI和has_many与“类型”关联列作为键
我正在使用单表继承来管理不同类型的项目。 我决定存储一些与每个项目类型相关的信息。所以我创建了新表“project_types”,其中“model_type”字段作为主键。主键值是“projects”表的“type”字段的值。 问题:当我尝试与 Project 对象 ProjectTypes 对象关联时,它总是返回 null。
>> 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
获取与 ProjectTypes 项目关联的项目就可以了。有办法让它正常工作吗?
型号:
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
迁移:
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
I am using Single Table Inheritance for managing different types of projects.
I decided to store some information associated with each project type. So i created new table "project_types" with "model_type" field as primary key. Primary key values are values of "type" field of "projects" table. Problem: When i trying to get associated with Project object ProjectTypes object it always returns null.
>> 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
Getting projects associated with ProjectTypes project is OK. Is there way to make it works properly?
Models:
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
Migrations:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你遇到问题并不奇怪。通过从纯粹的 STI 系统转移到当前系统,您将一个系统的一部分与另一个系统的一部分混合在一起,从而严重破坏了您正在使用的模式。
我个人会选择类似的方法:
通过迁移:
它只会清理事情,并且还有助于澄清您正在做什么。您的“ProjectType”表纯粹用于额外数据,您的继承树仍然存在。我还进行了一些检查,以确保您的项目类型始终设置(并且根据模型名称正确设置),并通过将属性设置为只读来阻止您在保存项目类型后更改项目类型。
Not surprising you're getting problems. By moving from a pure STI system to your current system you are horribly breaking the patterns you are using by intermingling parts of one with parts of another.
I'd personally go for something like:
with migrations:
It just cleans things up and it also helps clarify what you're doing. Your 'ProjectType' table is purely for extra data, your inheritance tree still exists. I've also thrown in some checks to make sure your project type is always set (and correctly, based on the model name) and stops you from changing project type once it's been saved by making the attribute read only.