首页 > 解决方案 > 如何找到 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。有一个更好的方法吗?

标签: ruby-on-rails

解决方案


如果它是一个真正的 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 方法。或者一个交互器


推荐阅读