Ruby on rails 什么类型的Rails模型关系最适合聚合键+多个外键?

Ruby on rails 什么类型的Rails模型关系最适合聚合键+多个外键?,ruby-on-rails,model,Ruby On Rails,Model,我正在考虑以下数据库结构,但我不确定哪种类型的Rails模型关系将支持我定义的数据库键。有人能建议这在Rails中如何工作吗 Posts id post_type -- must be 'Q' or 'A' author date content UNIQUE KEY (post_id, post_type) -- to support foreign keys Questions id post_id post_type -- must be 'Q' FOREIGN KEY (post_id

我正在考虑以下数据库结构,但我不确定哪种类型的Rails模型关系将支持我定义的数据库键。有人能建议这在Rails中如何工作吗

Posts
id
post_type -- must be 'Q' or 'A'
author
date
content
UNIQUE KEY (post_id, post_type) -- to support foreign keys

Questions
id
post_id
post_type -- must be 'Q'
FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)

Answers    
id
post_id
post_type -- must be 'A'
question_id
FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)
FOREIGN KEY (question_id) REFERENCES Questions(post_id)

Comments    
id
post_id
author
date
content
FOREIGN KEY (post_id) REFERENCES Posts(post_id)
上述草图将转换为以下实现:

CREATE TABLE Posts (
  post_id     SERIAL PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'Q' or 'A'
  -- other columns common to both types of Post
  UNIQUE KEY (post_id, post_type) -- to support foreign keys
) ENGINE=InnoDB;

CREATE TABLE Comments (
  comment_id  SERIAL PRIMARY KEY, 
  post_id     BIGINT UNSIGNED NOT NULL,
  -- other columns for comments (e.g. date, who, text)
  FOREIGN KEY (post_id) REFERENCES Posts(post_id)
) ENGINE=InnoDB; 

CREATE TABLE Questions (
  post_id     BIGINT UNSIGNED PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'Q'
  -- other columns specific to Questions
  FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)
) ENGINE=InnoDB;

CREATE TABLE Answers (
  post_id     BIGINT UNSIGNED PRIMARY KEY,
  post_type   CHAR(1),              -- must be 'A'
  question_id BIGINT UNSIGNED NOT NULL,
  -- other columns specific to Answers
  FOREIGN KEY (post_id, post_type) REFERENCES Posts(post_id, post_type)
  FOREIGN KEY (question_id) REFERENCES Questions(post_id)
) ENGINE=InnoDB;

关于如何在rails中对此进行建模,您有多种选择,但是我建议的第一件事是,为了节省您的时间和以后的麻烦,您应该从不同的角度来处理您的问题

为了充分利用Rails,您不应该从数据库设计开始。您应该从一个数据模型开始,然后看看如何将这个数据模型映射到数据库结构,而不是反过来。这是一个微妙的区别,但涉及到一种不同的心态,即您将数据库视为模型的次要考虑因素,而不是相反。从长远来看,这将使问题更容易理解

在这个场景中可以使用两种ActiveRecord结构,它们是单表继承和多态继承

单表继承

单表继承STI在同一基础数据库表中存储具有许多共享功能的模型。在您的示例中,问题和答案以及在较小程度上的注释都是类似的对象。它们有一些内容、作者、一些日期时间字段,用于在创建时和更新时等。问题和答案之间的唯一区别是,问题属于答案。注释要稍微复杂一些,因为您可以对问题和答案进行注释,也可以对注释进行注释,尽管您的数据库模式没有反映出这是可能的

使用STI,您的问答模型不会存储在单独的表中,而是存储在单个表中,并用类名进行标记。然后,在您的案例文章中,实际的问答类继承自基类。有很多关于STI的资源,但可能会有所帮助

多态遗传

这是在rails中模拟类似行为的第二种方法。在您的例子中,这使用一个表来存储两个类之间的公共数据。此表包含引用基本对象的类名和id实例的列。然后,特定于对象的数据将存储在每个模型的单独表中

使用STI实现

要使用STI对数据建模,您需要创建一个基本的帖子模型,如下所示

  class CreatePosts < ActiveRecord::Migration  
    def self.up  
      create_table :posts do |t|  
        t.string :type 
        t.string :author   
        t.text :content  
        t.integer :parent_id   
        t.timestamps  
      end  
    end  


    def self.down  
      drop_table :posts  
    end  
end  
class Post < ActiveRecord::Base  
end  

class Question < Post  
  has_many :answers, :foreign_key => :parent_id  
  has_many :comments, :foreign_key => :parent_id  
end  

class Answer < Post  
  belongs_to :question, :foreign_key => :parent_id  
  has_many :comments, :foreign_key => :parent_id  
end  

class Comment < Post  
  belongs_to :question, :foreign_key => :parent_id  
  belongs_to :answer, :foreign_key => :parent_id  
end  
此代码生成以下结果

Steve asked What is 2 + 2 Malcolm commented Good question, i'd been wondering that myself John answered with 2+2 = 5 Chris commented Sorry John it should be 4 Phil answered with 2+2 is a sum Steve commented Hi Phil thanks for stating the obvious! 示例后的数据内容如下:-

1|Question|Steve|What is 2 + 2||2009-06-13 09:52:20|2009-06-13 09:52:20 2|Answer|John|2+2 = 5|1|2009-06-13 09:52:20|2009-06-13 09:52:20 3|Comment|Chris|Sorry John it should be 4|2|2009-06-13 09:52:20|2009-06-13 09:52:20 4|Answer|Phil|2+2 is a sum|1|2009-06-13 09:52:20|2009-06-13 09:52:20 5|Comment|Steve|Hi Phil thanks for stating the obvious!|4|2009-06-13 09:52:20|2009-06-13 09:52:20 6|Comment|Malcolm|Good question, i'd been wondering that myself|1|2009-06-13 09:52:20|2009-06-13 09:52:20
您可能会发现将评论模型分为提问评论和回答评论更容易。这将使直接sql变得更容易。

此解决方案是否也可以在has\u和\u-belish\u-to\u-many之间使用,例如:

运动员和教练

s1 = Sportsmen.new(:name=> “Günter”)
t1 = Trainer.new(:name=> „Hans“)
t2 = Trainer.new(:name=> „Joachim“)

is this correct ?
S1t1 = s1.t1
S1t2 = s1.t2

这太棒了。谢谢你花时间写这么全面的答案。尽管我喜欢您建议使用STI而不是多态方法,但是STI与类表继承everything2.com/title/…相比的一个缺点是,您最终会在派生自Post的类中使用一些未使用的列。例如,一个问题可能有与其关联的标签,这可能是问题表中的一列,但在STI下,它应该是Posts表中的一列,然后答案和评论也会以标签列结束。。。。但是,由于Rails只提供STI和多态关联,因此即使在这种方法中使用了额外的未使用列,STI似乎也是更好的选择。不过,总的来说你是对的——我需要从Rails的角度而不是从数据库的角度来解决这个问题。恐怕这需要一些时间来适应。嗨,查理,我会对此发表评论,但我已经出去喝酒好几个小时了,所以现在不是时候。明天我会写一些评论和/或多态解决方案。没有问题,史蒂夫。保持水分充足。顺便说一句,这是我在前面关于类表继承的评论中试图包含的链接: 1|Question|Steve|What is 2 + 2||2009-06-13 09:52:20|2009-06-13 09:52:20 2|Answer|John|2+2 = 5|1|2009-06-13 09:52:20|2009-06-13 09:52:20 3|Comment|Chris|Sorry John it should be 4|2|2009-06-13 09:52:20|2009-06-13 09:52:20 4|Answer|Phil|2+2 is a sum|1|2009-06-13 09:52:20|2009-06-13 09:52:20 5|Comment|Steve|Hi Phil thanks for stating the obvious!|4|2009-06-13 09:52:20|2009-06-13 09:52:20 6|Comment|Malcolm|Good question, i'd been wondering that myself|1|2009-06-13 09:52:20|2009-06-13 09:52:20
s1 = Sportsmen.new(:name=> “Günter”)
t1 = Trainer.new(:name=> „Hans“)
t2 = Trainer.new(:name=> „Joachim“)

is this correct ?
S1t1 = s1.t1
S1t2 = s1.t2