【问题标题】:Referencing several models from one model class- Bad practice?从一个模型类中引用多个模型 - 不好的做法?
【发布时间】:2016-05-27 09:19:11
【问题描述】:

我想使用此代码获取当前用户的所有通知:

current_user.follows.each do |follow|
    follow.followable.open_notifications.each do |notification|
        if !notification.reads.include?(current_user)
            @open_notifications += notification 
        end
    end
end

到目前为止,我的控制器中有这段代码,但是我知道这种逻辑应该放在模型类中。 移动代码后:

OpenNotification 控制器:

OpenNotification.fetch_unread(current_user) 

OpenNotification 模型:

def self.fetch_unread(user)
    @open_notifications = []
    user.follows.each do |follow|
        follow.followable.open_notifications.each do |notification|
            if !notification.reads.include?(user)
                @open_notifications += notification 
            end
        end
    end
    @open_notifications
end

编辑:

涉及的类:

  • 用户
  • 关注 - 谁(用户)关注什么(可关注)
  • Followable(多态 - 可以是用户、事件或地点)
  • OpenNotification - 存储跟随对象的变化信息
  • 读取 - 谁读取了哪个通知(user_id 和 open_notification_id)

用户:

has_many :follows, class_name: 'Follow',
                 source: :user

has_many :follows_as_fallowable, 
                class_name: 'Follow',
                as: :followable

has_many :followers, through: :follows_as_fallowable,
                   source: :user

事件:

has_many :follows, as: :followable
has_many :followers, through: :follows,
                         source: :user

has_many :open_notifications, as: :followable  

OpenNotification:

belongs_to :followable, polymorphic: true
has_many :reads

阅读:

belongs_to :user
belongs_to :open_notification

我的问题是,从负责一个特定资源的类中引用多个类是否是一种好习惯?
如果这不是一个好的做法,代码应该如何重构?

【问题讨论】:

  • 我不关心不同类的使用(在我看来只涉及两个类:User 和某种Follower)。但是嵌套的each 循环会导致性能下降,因为它会触发对数据库的许多查询(N+1 问题)。我会专注于优化它。如果不了解您的数据库模式和模型关联,就很难给出建议。您能否发布课程之间的联系方式?
  • 关系非常复杂,我已经添加了信息(见编辑)和简要说明。

标签: ruby-on-rails ruby design-patterns model refactoring


【解决方案1】:

从一个模型中引用多个模型是完全可以的,只要您有理由说您的通知模型应该知道用户模型(基本上大多数通知交互也与用户打交道?)。在你在这里展示的那一点上,我会说它确实如此,但是你必须在广泛的应用程序中考虑这个问题并重新评估它。如果您认为这可能有点牵强,我建议将此逻辑封装到一个单独的类中,以使您的代码更易于维护和可预测,如果有人要与您合作(想想服务对象)。此外,在您向@open_notifications 附加通知的地方,您应该考虑使用<<,因为这不会每次都重建@open_notifications 对象,而+= 将一遍又一遍地实例化它,为垃圾收集器留下更多工作。在大型操作中,您会在这里看到巨大的速度提升。

【讨论】:

    猜你喜欢
    • 2018-05-03
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 1970-01-01
    • 2012-08-05
    相关资源
    最近更新 更多