ruby-on-rails - 如何在 Rails 中使用多态的 belongs_to 关联设置 MTI?
问题描述
为了创建一个简短的、自包含的、正确的(可编译的)示例,假设我想做以下事情。
我有一个博客网站。有两种类型的帖子,TextPost
和LinkPost
。还有两种类型的用户,User
和Guest
。我想用and实现多表继承,我的意思是(希望我正确使用了这个术语):TextPost
LinkPost
- 在模型级别,我将拥有
Post
和。并将继承自.TextPost
LinkPost
TextPost
LinkPost
Post
- 在数据库级别,我将为 和 的“叶”模型提供表
TextPost
,LinkPost
但不为Post
.
每种类型都Post
可以属于 aUser
或 a Guest
。所以我们有一个多态的belongs_to
情况。
我的问题是如何实现这些目标。
我尝试了以下方法,但它不起作用。
class Post < ApplicationRecord
self.abstract_class = true
belongs_to :author, polymorphic: true # user or guest
validates :title, :author_id, :author_type, presence: true
end
class TextPost < Post
validates :content, presence: :true
end
class LinkPost < Post
validates :url, presence: :true
end
class User < ApplicationRecord
has_many :text_posts, as: :author
has_many :link_posts, as: :author
validates :name, presence: true
end
class Guest < ApplicationRecord
has_many :text_posts, as: :author
has_many :link_posts, as: :author
end
class CreateTextPosts < ActiveRecord::Migration[6.1]
def change
create_table :text_posts do |t|
t.string :title
t.string :content
t.references :author, polymorphic: true
t.timestamps
end
end
end
class CreateLinkPosts < ActiveRecord::Migration[6.1]
def change
create_table :link_posts do |t|
t.string :title
t.string :url
t.references :author, polymorphic: true
t.timestamps
end
end
end
class CreateUsers < ActiveRecord::Migration[6.1]
def change
create_table :users do |t|
t.string :name
t.timestamps
end
end
end
class CreateGuests < ActiveRecord::Migration[6.1]
def change
create_table :guests do |t|
t.timestamps
end
end
end
控制台输出:
:001 > user = User.create(name: 'alice')
(1.6ms) SELECT sqlite_version(*)
TRANSACTION (0.1ms) begin transaction
TRANSACTION (0.1ms) SAVEPOINT active_record_1
User Create (1.2ms) INSERT INTO "users" ("name", "created_at", "updated_at") VALUES (?, ?, ?) [["name", "alice"], ["created_at", "2021-06-11 23:33:38.445387"], ["updated_at", "2021-06-11 23:33:38.445387"]]
TRANSACTION (0.2ms) RELEASE SAVEPOINT active_record_1
:002'> text_post = TextPost.create(title: 'foo', content: 'lorem ipsum', author_id: 1, author_type:
'user')
Traceback (most recent call last):
1: from (irb):2:in `<main>'
NameError (wrong constant name user)
解决方案
常量的名称看起来像局部变量的名称,只是它们以大写字母开头。
所有内置类以及您定义的类都有一个对应的全局常量,其名称与名为 的类同名
class name
。
因此,在您的情况下,当您定义User
类时,有一个常量class name
: User
,但没有,这就是引发user
错误的原因。NameError (wrong constant name user)
尝试text_post = TextPost.create(title: 'foo', content: 'lorem ipsum', author_id: 1, author_type: 'User')
推荐阅读
- javascript - 本地机器与 travis.ci 为 `Date.toISOString()` 返回不同的结果
- javascript - 计算有或没有 string.slice 的字符串中的字符
- ruby-on-rails - 在 Rails 教程中,如何在没有'require_relative "application_record"' 的情况下从 ApplicationRecord 继承 Article?
- java - 确保特定用户只能看到自己的用户详细信息 - 使用 Spring
- python - 在 Python 中创建类抽象
- go - 什么会导致 go 在 runtime.pthread_cond_signal 上花费这么多时间
- node.js - 模式关系在填充后返回未定义
- macos - 终端:通过 MIME 选择 - 需要为每个文件添加扩展名
- c# - 读取来自 SslStream 的响应时不能信任 Content-Length?
- javascript - typescript parseInt() 导致编译错误