ruby-on-rails – Rails关联的最佳代码结构
舞台
让我们谈谈我们遇到的最常见的关联类型. 我有一个用户:has_many Post(s) class User < ActiveRecord::Base has_many :posts end class Post < ActiveRecord::Base belongs_to :user end 问题陈述 我想在用户的所有帖子上做一些(非常轻快的)处理.我正在寻找构建我的代码来实现它的最佳方法.以下是几种方式以及它们工作或不工作的原因. 方法1 在User类本身中执行此操作. class User < ActiveRecord::Base has_many :posts def process_posts posts.each do |post| # code of whatever 'process' does to posts of this user end end end 邮政课程保持不变: class Post < ActiveRecord::Base belongs_to :user end 该方法称为: User.find(1).process_posts 为什么这看起来不是最好的方法 使用用户帖子做某事的逻辑应该属于Post类.在现实世界的场景中,用户可能还具有:与许多其他类的has_many关系,例如订单,评论,儿童等 如果我们开始向User类添加类似的process_orders,process_comments,process_children(yikes)方法,它将导致一个包含大量代码的巨型文件,其中很多代码可以(并且应该)分发到它所属的位置,即目标关联. 方法2 代理关联和范围 这两种结构都需要向User类添加方法/代码,这又使它变得臃肿.我宁愿将所有实现转移到目标类. 方法3 目标类的类方法 在目标类中创建类方法,并在User对象上调用这些方法. class User < ActiveRecord::Base has_many :comments # all target specific code in target classes end class Post < ActiveRecord::Base belongs_to :user # Class method def self.process Post.all.each do |post| # see Note 2 below # code of whatever 'process' does to posts of this user end end end 该方法称为: User.find(1).posts.process # See Note 1 below 现在,这看起来和感觉比方法1和2更好,因为: >用户模型仍然没有杂乱. 注1: 是的,您可以在关联上调用这样的类方法. Read why here. TL; DR是User.find(1).posts返回一个CollectionProxy对象,该对象可以访问目标(Post)类的类方法.它还方便地传递一个scope_attributes,它存储调用posts.process的用户的user_id.这很方便.见下面的注2. 笔记2: 对于那些在类方法中执行Post.all.each时不确定的人,它会返回调用此方法的用户的所有帖子,而不是数据库中的所有帖子. 所以当调用User.find(99).posts.process时,Post.all执行: SELECT "notes".* FROM "posts" WHERE "posts"."user_id" = $1 [["user_id",99]] 这是用户ID:99的所有帖子. Per @ Jesuspc的评论如下,Post.all.each可以简洁地写成all.each.它更具惯用性,并不会让我们看起来像是在查询数据库中的所有帖子. 我正在寻找的答案 >解释处理此类关联的最佳方式是什么.人们如何正常地做到这一点?如果方法3中有任何明显的设计缺陷. 解决方法
还有第四种选择.将此逻辑完全移出模型:
class PostProcessor def initialize(posts) @posts = posts end def process @posts.each do |post| # ... end end end PostProcessor.new(User.find(1).posts).process 这有时称为服务对象模式.这种方法的一个非常好的好处是它使这种逻辑的编写测试非常简单.这是关于这个和其他重构“胖”模型的方法的精彩博文:http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |