ruby-on-rails 多态性组合在铁轨上断裂6.1

zpjtge22  于 2022-11-19  发布在  Ruby
关注(0)|答案(2)|浏览(135)

我继承了一些遗留的Rails代码,这些代码在标准的多态关联周围有变通办法。这些代码过去一直工作到Rails 5。现在我试图升级到Rails 6. 1,它们坏了,我不知道如何修复它们。

**问题:**我们有以下2个表:

  • 职位
  • 标识符
  • 正文
  • ...
  • 注解
  • 标识符
  • 可注解标识
  • 可注解类型
  • ...

帖子有3种类型的评论-
1.管理员注解
1.匿名评论
1.用户注解
我们将其建模为多态关系,如下所示:
第一个
使用此设置,我可以通过执行以下操作获取所有注解-

p = Post.find(123)
p.comments

或按特定类型的用户获取注解-

p = Post.find(123)
p.user_comments
p.anonymous_comments

在rails 6.1中,此设置不起作用。当尝试运行rails console时,它失败并显示错误:
在“Assert有效密钥中的块”中:未知密钥::foreign_type。有效键为::类名,:匿名类,:主键,:外键,:从属,:验证,:反转,:严格加载,:自动保存,:添加前,:添加后,:删除前,:删除后,:扩展,:计数器缓存,:连接表,:索引错误,:确保所有者为(参数错误)
在网上寻找潜在的答案后,我能得到的最接近的答案是在每个关联中添加as: :commentable,如-

has_many :user_comments, -> { where commentable_type: "UserComment" },
    class_name: 'Comment', foreign_key: :commentable_id,
    foreign_type: :commentable_type, dependent: :destroy, inverse_of: :post, as: :commentable

但这并不能得到正确的结果集。它生成的sql如下所示-
SELECT注解.* FROM注解WHERE注解.可注解标识= 123 AND注解.可注解类型= 'Post' AND注解.可注解类型= 'UserComment'
如果没有as: :commentable,它将生成如下SQL:
SELECT注解.* FROM注解WHERE注解.可注解标识= 123 AND注解.可注解类型= '用户注解'
我有点迷路了,希望能得到任何帮助!
谢谢你!

n53p2ov0

n53p2ov01#

编辑仔细阅读文档后,这应该适用于has_one关联类型,而不适用于has_many
Rails 6.1增加了Delegated Types,可以用来实现你想要的。
请尝试以下操作
第一个

c3frrgcw

c3frrgcw2#

这看起来像是一个非常混乱和误导的尝试,试图将单表继承和多态关联组合在一起,而不了解两者是如何工作的,我怀疑代码实际上是按照早期版本的预期工作的。

短期内

在STI设置中,您使用类型继承列(默认类型)来指定ActiveRecord在从数据库检索行时加载的类。这意味着您的comments表应该有一个名为type的字符串列,其中包含UserCommentAdminComment之类的值。

class Comment < ActiveRecord::Base
  belongs_to :commentable, polymorphic: true
end

class UserComment < Comment 
end

class AdminComment < Comment 
end

# ...

当您设置指向STI模型的多个关联时,应在表的type列上设置条件,而不是commentable_type
第一个

多态关联

多态关联实际上只是一个肮脏的欺骗,以绕过对象关系障碍不匹配问题。通过使用一个整数列和一个varchar列,你可以创建一个指向任何表的单个关联-例如,这将是附加评论到帖子,视频,图片,甚至其他评论。这是commentable_type列实际上应该包含的内容。
要将上一个示例中的关联更改为多态,只需添加as:选项,告诉Rails要查找的belongs_to关联:

class Post < ActiveRecord::Base
  has_many :comments, as: :commentable
  has_many :user_comments, 
    -> { where(type: 'UserComment') }, 
    as: :commentable
  has_many :admin_comments, 
    -> { where(type: 'AdminComment') },  
    as: :commentable
end

否则,它只会假设您正在另一端查找名为 post 的关联-as:告诉ActiveRecord这是一个多态关联:
一个
您不必配置foreign_keyforeign_typeclass_name选项(这个选项完全错误),因为它们都可以从名称中派生出来。

相关问题