带关系的单表继承

发布于 2025-01-02 22:31:40 字数 1021 浏览 1 评论 0原文

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

这个想法是拥有一个用户表,其中包含给定人员的所有基本数据。有关示例属性,请参阅下面的 UML/ER。

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

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

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/ER 示例。我试图通过删除不相关的属性来保持这个示例的干净。这就是注册课程实体中属性如此之少的原因。

uml

I'm trying to build a student portal in Rails 3, but I'm having some problem.

The idea is to have a users table that contains all basic data for a given person. See the UML/E-R below for example attributes.

  • A user can be both an Assistant and a Student at the same time.
  • Assistant and Student should inherit from User.

The idea was to inherit directly from the User, like this.

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?

This makes the relations in the student model very strange.
has_many :registered_courses, through: :students

I want to be able to do something like this in the end.

student.full_name
student.pin_code
student.registered_courses

One solution would be to implementing the method by hand, like this

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

But it looks really strange to refer to a student object inside the student model.

Is there a clearer, better way of doing this?

Here is an example UML/E-R. I've tried to keep this example clean by removing non relevant attributes. That is why there are so few attributes in the registered course entity.

uml

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

凶凌 2025-01-09 22:31:40

对于您在这里所阐述的方式,STI 并不是一个好的选择,因为用户既可以是学生,也可以是助手。当您使用 STI 时,通常会添加一个类型列来指定记录真正属于哪个子类。如果学生和助理都继承自用户,那么这确实不是一个选择,因为您将被迫为既是助理又是学生的人创建重复的用户记录。

我认为您最好只拥有属于学生的学生行和助理行,然后将用户中包含的元素委托回用户对象。

STI is not a good choice for this the way that you have articulated it here, since users can be both students and assistants. When you are using STI, you generally add a type column to specify which subclass the record really belongs to. If both Student and Assistant inherit from User, then that really isn't an option, since you'd be forced to create duplicate User records for someone who is both an Assistant and a Student.

I think you'd be better off simply having Student and Assistant rows that belong_to a Student, and then delegating the elements that are contained in User back to the User object.

昵称有卵用 2025-01-09 22:31:40

我觉得继承在这里是一个糟糕的举动。如果您将患上这样的性传播感染,那么它必须是其中之一。

相反,将所有逻辑都放入 User 模型中,无论如何,所有数据都在那里。再加上 Student & Assistant 并不相互排斥,不应该有任何方法会相互覆盖。

为什么不使用 STI?

STI 主要适用于包含相同数据但执行不同操作的对象。

例如,我有一个包含多个进程(例如构建和测试)的规范。所以我有一个包含流程订单

process_1:
  order_id: 1
  specification: foo
  type: build

process_2:
  order_id: 1
  specification: foo
  type: test

在此示例中,数据中唯一发生变化的是类型,但由于类型发生了变化,我知道要根据规范执行什么过程

I feel like Inheritance is a bad move here. If you're going to have STI like this it HAS to be one or the other.

Instead throw all your logic into the User model, all your data is there anyway. Plus since Student & Assistant aren't mutually exclusive there shouldn't be any methods that will override each other.

Why not STI?

STI is mainly meant for objects that contain the same data, but does different things with them.

For example, I have a specification that contains multiple processes(ex. build and test). So I have a order that contains processes.

process_1:
  order_id: 1
  specification: foo
  type: build

process_2:
  order_id: 1
  specification: foo
  type: test

In this example the only thing that changes in the data is the type, but because the type changes I know what process to perform from the specification.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文