单表继承与关系

时间:2012-02-06 02:12:25

标签: ruby-on-rails database ruby-on-rails-3 database-design

我正在尝试在Rails 3中构建学生门户网站,但我遇到了一些问题。

我们的想法是拥有一个包含给定人员所有基本数据的用户表。请参阅下面的UML / E-R,例如属性。

  • 用户可以同时是助手学生
  • 助理学生应继承自用户

这个想法是直接从用户继承,就像这样。

class User < ActiveRecord::Base
  # ...
  def awesome?
    [true, false].sample
  end
  # ...
end

class Student < User
  has_one :student
  has_many :registered_courses, through: :students
end

Student.new.awesome?

这使得学生模型中的关系非常奇怪。 has_many :registered_courses, through: :students

我希望最终能够做到这一点。

student.full_name
student.pin_code
student.registered_courses

一种解决方案是手动实施该方法,如此

class Student < User 
  has_one :student 
  def pin_number
    student.pin_number
  end
end

但是在学生模型中引用学生对象看起来很奇怪。

有更清晰,更好的方法吗?

以下是UML / E-R的示例。我试图通过删除不相关的属性来保持这个例子的清洁。这就是注册课程实体中属性如此之少的原因。

uml

2 个答案:

答案 0 :(得分:0)

STI不是一个很好的选择,因为你在这里阐述它,因为用户既可以是学生也可以是助手。在使用STI时,通常会添加一个类型列来指定记录真正属于哪个子类。如果学生和助理都从用户继承,那么这实际上不是一个选项,因为您将被迫为同​​时为助理和学生的人创建重复的用户记录。

我认为你最好只使用属于Student的Student和Assistant行,然后将User中包含的元素委托给User对象。

答案 1 :(得分:0)

我觉得继承在这里是一个糟糕的举动。如果你有这样的STI, HAS 就是其中之一。

而是将所有逻辑抛入User模型,无论如何你的所有数据都存在。加上Student&amp; Assistant不是互斥的,不应该有任何方法可以互相覆盖。

为什么不是STI?

STI主要用于包含相同数据的对象,但与它们做不同的事情。

例如,我有一个包含多个进程的规范(例如build和test)。所以我的order包含processes

process_1:
  order_id: 1
  specification: foo
  type: build

process_2:
  order_id: 1
  specification: foo
  type: test

在此示例中,数据中唯一发生变化的是类型,但由于类型更改,我知道要从规范中执行process

相关问题