ruby-on-rails - 为什么我在“has_many”关系中对“所有者”的调用不起作用?
问题描述
我正在使用 Rails 5.0.7.1,我在文档中看到我的 CollectionProxy 实例应该有权访问“@owner”实例变量:
Active Record 中的关联代理是持有关联的对象(称为@owner)和实际关联的对象(称为@target)之间的中间人。@reflection 中提供了任何代理所涉及的关联类型。这是 ActiveRecord::Reflection::AssociationReflection 类的一个实例。
blog.posts 中的关联代理将 blog 中的对象作为@owner,将其帖子的集合作为@target,@reflection 对象表示一个 :has_many 宏。
此类通过 method_missing 将未知方法委托给 @target。
在我的 Rails 应用程序中,我有以下(相当不切实际的)测试代码:
class Post < ApplicationRecord
has_many :comments do
def number_five
if owner.is_a? Post
Comment.where(id: 5, post_id: self.id)
end
end
end
end
class Comment < ApplicationRecord
belongs_to :post
end
当我打电话时Post.last.commments.number_five
,我收到以下错误:
NameError (undefined local variable or method `owner' for #
<Comment::ActiveRecord_Associations_CollectionProxy:0x00007fcbb9106120>)
当我添加byebug
到 and 之间的行def number_five
并owner.is_a? Post
检查 的值时self
,我看到它是ActiveRecord::Associations::CollectionProxy
,所以我认为我owner
在应该定义它的范围内调用。
我试过了Post.last.comments.instance_variables
,我没有看到:@owner
,只有以下内容:
[:@association, :@klass, :@table, :@values, :@offsets,
:@loaded, :@predicate_builder, :@scope]
我还尝试了以下方法:
comments = Post.last.comments
def comments.get_owner
self.owner
end
这返回与NameError
上面相同。
对于它的价值,当我跑步时Post.last.comments.class
,我看到了它Comment::ActiveRecord_Associations_CollectionProxy
。
鉴于文档的阅读方式,我希望能够从内部调用Post.last.comments.owner
或@owner
从内部调用Post.last.comments
(我都尝试过),并让它返回Post.last
. 我的期望是错误的,还是我的代码错误,或者完全是别的什么?
解决方案
文档有点混乱。我记得当我第一次需要从扩展方法中脱离关联时,我不得不花几个小时猜测、阅读 Rails 源代码并尝试弄清楚这一点。
owner
是您所追求的,但这是关联的一种方法,您可以通过以下方式获得关联proxy_association
(这只是 的访问器方法@association
):
has_many :comments do
def number_five
if proxy_association.owner.is_a? Post
#...
end
end
end
我不确定这是否是“正确”或“官方”的方式,但这是我自 Rails 4 以来一直在做的事情。
推荐阅读
- c# - 当我尝试将 SaveChanges() 保存到上下文时,EF 中的“更新条目时发生错误”
- c++ - 如何让 if() 由 && 而不是 || 分割
- java - spring boot 跟踪更新值
- go - nano 上的 golang 格式搞砸了,而在 vscode 上还可以。nano 格式被推送到 git
- google-maps - 向数据层添加几何图形 - 如何在添加过程中设置特征样式?
- php - 在 localhost laravel 上安装新的 Laravel 源
- sql - ActiveRecord 多对多我应该制作另一个表来保存关系信息吗?
- sql - 在 postgres 中合并查询
- ffmpeg - 高效的命令行来裁剪视频,覆盖另一个裁剪并使用 ffmpeg 缩放结果
- reactjs - 从 fetch 调用变量到 React 渲染函数