ruby-on-rails - 如何找到 has_many 关联的所有者
问题描述
我有一个模型用户
#/app/models/user.rb
class User < ApplicationRecord
has_many :posts, extend: PostsExtensions
def check_user
CheckPosts.new(posts).call
end
end
给定一组帖子,我有一个方法不仅取决于帖子,还取决于帖子所有者的状态,这是一个简化的示例
#app/services/check_post.rb
class CheckPosts
def initialize(posts)
@posts = posts
end
def call
case posts.process
...
end
private
attr_reader :posts
end
# app/models/concerns/posts_extensions.rb
module PostsExtensions
def user
first.user
end
def process
return 'not_ok' unless user.status_ok
if posts.empty?
return 'empty'
else
return 'not_empty'
end
end
结尾
如果帖子为空,则这不起作用,因为 first.user 会导致异常。我可以添加一个参数 user 来处理 iedef proces(user)
但这也会改变服务对象的 api。有一个更好的方法吗?
解决方案
如果它是一个真正的 CollectionProxy,你可以通过它的 Association 获得它的所有者。这具有甚至不必加载帖子的优点。
user = posts.proxy_association.owner
注意:这些方法没有记录。我会将它包装在一个扩展中并编写一个测试来警告您是否停止工作。
class User < ApplicationRecord
has_many :posts do
def user
proxy_association.owner
end
end
end
但是,您应该将用户传递到 CheckPosts。
# You're not just checking posts, you're checking a user's posts.
class CheckUserPosts
# No initialize, service objects have no state.
def call(user: user, posts: user.posts)
return 'not_ok' unless user.status_ok
if posts.empty?
return 'empty'
else
return 'not_empty'
end
end
end
通常你会这样做status = CheckUserPosts.call(user)
。但是,如果您只想查看某些帖子:
# Check only this week's posts by the user.
status = CheckUserPosts.call(
user: user,
posts: user.posts.this_week
)
鉴于 User 和 Posts 是有关系的,我也会质疑这是否只是一个 User 方法。或者一个交互器。
推荐阅读
- excel - 如何在 vba 中使用集合来更新另一个单元格与一个单元格的值进行比较
- visual-studio-2017 - 如何停止 resharper 删除空开关默认情况
- typescript - typescript - 在路径中包含类型,但不编译它们
- c - 在 shmget() C 中使用 IPC_CREAT 的数值等价物
- symfony - Symfony 4 不同用户类型的不同实体和安全组件
- r - dplyr:忽略函数输入的分组变量
- react-native - 如何在本机中将文本发送到屏幕末尾
- python - 无法加载json数据
- c# - C# 在 if/else 中使用构造函数
- python - 两个整数的二进制表示的统一重组