消除 Rails 中 HasMany 关系中的联接表

发布于 2024-08-22 10:07:11 字数 1963 浏览 9 评论 0原文

我正在考虑如何在 Rails 中创建基于角色的访问控制系统。我也见过这些伟大的项目(除其他外):

我的问题是,真的有必要吗有一个用于所有内容的连接表吗?如果关系中的一个表只有几个值(比如小于 100),我不能将连接表与那个小表合并吗?)这就是我的意思...这就是我需要的:

< strong>模型

  • 用户
  • 角色
  • 权限
  • UserRoles/RolesUsers
  • GroupRoles
  • 成员资格 (GroupUsers)
  • RolePermissions

类似的东西...

方式 RoleRequirement 的工作原理是创建一个 roles 表和一个 roles_users 连接表。这意味着,如果我在应用程序中总共有 20 个可能的角色,则我的

  • 角色表有 20 行,
  • RolesUsers 表有 n 行。

这意味着每次我想按角色查找用户时,我都必须进行联接。但我想知道,由于应用程序中只有几个角色,为什么不直接替换此迁移:

create_table "roles", :force => true do |t|
  t.string "name"
end

create_table "roles_users", :id => false, :force => true do |t|
  t.integer "role_id"
  t.integer "user_id"
end

用这个...

create_table "roles", :force => true do |t|
  t.string "name"
  t.integer "user_id" # or some polymorphic form
end

这会导致重复(例如大量名为“admin”的角色),但由于空间很便宜,我们可以创建一个像 Role.unique 这样的方法来查找所有唯一的角色(以摆脱那个 20 行表),为什么人们要创建连接表?

权限也是如此:我可能只有 4 个启动权限:创建、读取、更新、删除。所以我不需要权限表和roles_permissions 表,我只需复制CRUD 权限并在权限表中包含role_id 即可。与组相同,如果我的 roles 表中有多态列,则不需要组角色。

推荐的方法是什么?

以下是建议迁移的片段

I am thinking about ways to create a Role Based Access Control system in Rails. I have seen these great projects too (among others):

My question is, is it really necessary to have a join table for everything? If I one of the tables in the relationship only has a few values (say less than 100), can't I just merge the join table with that small table?) This is what I mean... Here's what I need:

Models

  • User
  • Group
  • Role
  • Permission
  • UserRoles/RolesUsers
  • GroupRoles
  • Memberships (GroupUsers)
  • RolePermissions

Something like that...

The way RoleRequirement works is by creating a roles table and a roles_users join table. This means that if I have 20 total possible Roles in an application, I have

  • Role table with 20 rows
  • RolesUsers table with n rows.

Which means every time I want to find a user by role, I have to do a join. I'm wondering though, since there will only be a few Roles in an application, why not just replace this migration:

create_table "roles", :force => true do |t|
  t.string "name"
end

create_table "roles_users", :id => false, :force => true do |t|
  t.integer "role_id"
  t.integer "user_id"
end

with this one...

create_table "roles", :force => true do |t|
  t.string "name"
  t.integer "user_id" # or some polymorphic form
end

That would cause duplication (tons of roles named "admin" for example), but since space is cheap, and we could create a method like Role.unique to find all unique Roles (to get rid of that 20-row table), why do people create the join table?

Same thing with Permissions: I only will likely have 4 permissions to start: create read update delete. So I don't need a permissions table and a roles_permissions table, I could just duplicate the CRUD permissions and have the role_id in the permissions table. Same with Group, I don't need Group Roles if I had polymorphic columns in my roles table.

What is the recommended way to do this?

Here is a snippet of the proposed migration.

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

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

发布评论

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

评论(1

甜中书 2024-08-29 10:07:11

我不建议你这样做。您所描述的称为非规范化

非规范化会给许多应用程序带来问题,只有在您有明确的需要时才应该这样做。我通常仅出于报告目的而对表进行非规范化。

您的问题并不表明您需要非规范化。相反,它显示了对拥有“额外”表的误导性厌恶,并避免简单的联接。重复数据不仅会消耗空间,还会消耗性能(unique 并不是免费的)。现代 RDBMS 非常擅长处理连接。

我建议通过谷歌搜索并搜索有关非规范化的信息。没有黄金法则,但你的情况似乎没有任何充分的理由。

如果您正在寻求性能提升,请将 ActiveRecord 扔进垃圾桶。有很多替代方案,您可以编写自己的替代方案。

I would not suggest you do this. What you describe is called denormalization.

Denormalization introduces problems for many applications and should only be done if you have a clear need for it. I typically only denormalize tables for reporting purposes.

Your question doesn't show that you have any need to denormalize. Rather, it shows a misguided aversion to having "extra" tables, and avoiding a simple join. Having duplicated data costs more than just space, it also costs performance (unique isn't a freebie). Modern RDBMS are quite adept at handling joins.

I'd suggest googling and searching SO for information on denormalization. There is no golden rule, but your case doesn't seem to have any good reason to.

If you're looking for performance gains, throw ActiveRecord in the trash. There are many alternatives, and you can write your own.

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