RoR:has_one“或另一个”? (或者,没有继承的多态性。)

发布于 2024-07-11 05:54:40 字数 1055 浏览 11 评论 0原文

大家好,我的项目有一个有趣的要求。 我需要一种 has_one 关系,其中它可以是一个类,也可以是另一个类,但没有继承。 如果这是唯一的方法,我可以摆脱继承,但是两个关联记录具有完全不同的数据并且根本不相关。

我需要弄清楚的是类似以下内容。

# 1. Foo never belongs to anything.
# 2. Foo MUST have one assigned sub-record for validity.
# 3. Foo can only have either Bar or Baz assigned.
# 4. Bar and Baz have only ONE common property, and aren't
#    related in either data or implementation.

class Foo < ActiveRecord::Base
  # Attributes: id, name, value
  has_one :assignment, :foreign_key => 'assigned_to', :readonly => true
          # Could really use an :object_type for has_one here...
end

class Bar < ActiveRecord::Base
  # Attributes: name,...
end

class Baz < ActiveRecord::Base
  # Attributes: name,...
end

其中 Foo 有一个赋值,类型为 BarBaz; 它们只共享一个公共列,所以也许我可以从中创建一个父对象。 但是,如果我让它们继承一个公共对象(当它们包含的数据实际上是橙子和苹果时),我必须制作一个表格进行记录吗? 如果记录是抽象记录,但孩子们不是,我也许可以逃脱惩罚吗?

我想现在你已经看到我的困难了。 我对 RoR 还很陌生,但到目前为止我很喜欢它。 我确信有办法解决这个问题,但如果我不知道它是什么,那我就该死了。

Hey all, I have something of an interesting requirement for my project. I need a has_one relationship where it is either one class or the other, but without inheritance. I could get away with inheritance if it is the only way, but the two associate records have completely different data and aren't related at all.

What I need to figure out is something like the following.

# 1. Foo never belongs to anything.
# 2. Foo MUST have one assigned sub-record for validity.
# 3. Foo can only have either Bar or Baz assigned.
# 4. Bar and Baz have only ONE common property, and aren't
#    related in either data or implementation.

class Foo < ActiveRecord::Base
  # Attributes: id, name, value
  has_one :assignment, :foreign_key => 'assigned_to', :readonly => true
          # Could really use an :object_type for has_one here...
end

class Bar < ActiveRecord::Base
  # Attributes: name,...
end

class Baz < ActiveRecord::Base
  # Attributes: name,...
end

Where Foo has one assignment, of type either Bar or Baz; they only share one common column, so perhaps I can make a parent object from that. However, if I make them inherit from a common object (when the data they contain really is oranges and apples) must I make a table for the record? Can I perhaps get away with it if the record is an abstract record, but the children aren't?

I suppose by now you can see my difficulty. I'm rather new to RoR but loving it so far. I'm sure there's a way around this, but I'll be darned if I can't figure out what it is.

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

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

发布评论

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

评论(2

白芷 2024-07-18 05:54:40

您正在尝试对不适合关系数据库范例的事物进行建模。 SQL 中的所有引用都有一个来源和一个目标。

FWIW,多态关联也是一种反模式,因为它打破了这条规则。 当文档说您必须放弃引用完整性约束才能使其正常工作时,这应该是一个线索,表明这是一个损坏的设计!

您需要 Foo 拥有两种 has_one 关系:一种与 Bar,一种与 Baz。 然后实现一些类逻辑以尝试确保在 Foo 的任何实例中仅填充一个引用。 也就是说,在对 Bar 和 Baz 的引用中,一个必须有值,另一个必须为零,但这是您的代码需要检查和强制执行的内容。

You're trying to model something that doesn't fit the relational database paradigm. All references in SQL have one origin and one target.

FWIW, Polymorphic Associations is also an anti-pattern because it breaks this rule. It should be a clue that it's a broken design when the documentation says you must forgo a referential integrity constraint to make it work!

You need Foo to have two has_one relationships: one to Bar and one to Baz. Then implement some class logic to try to ensure only one reference is populated in any instance of Foo. That is, of the references to Bar and Baz, one must have a value and the other must be nil, but this is something for your code to check for and enforce.

隔纱相望 2024-07-18 05:54:40

也许实现此目的的一种方法是在 Foo 中为 Bar 和 Baz 创建一元关联。 然后创建一个名为“赋值”和“赋值=”的方法,这可以是访问 Bar 和 Baz 的唯一方法。 您可以在 get 方法中检查两个 has_one 中哪一个不是 nil 并返回那个。 在赋值方法中,您可以检查传入的变量的类型是什么,并设置与该对象的正确的“has-one”关系,并将另一个设置为 nil。 这应该涵盖您的所有基础,但又不会太复杂。

Perhaps one way to do this, is to create to has-one associations in Foo, for Bar and Baz. Then create a method called assignment and assignment= which can be the sole way to access Bar and Baz. You can check which of the two has_ones is not nil in the get method and return that one. In the assignment method, you can-check what is the type of the variable passed in and set the correct has-one relationship to that object and set the other to nil. That ought to cover all your bases without being too complicated.

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