Rails-实现站点范围通知的方式

时间:2014-12-28 22:47:49

标签: ruby-on-rails ruby notifications

我对MVC并不陌生,但我是Rails的新手,而且我正努力尝试制作一切" Rails方式"。我想实施网站范围的通知,因此我创建了Notification模型并创建了UserNotification之间的多对多关系。

我面临的问题是在创建通知时,我有几个实体在我的代码中生成通知。当有人回复您关注的论坛帖子时,您会收到通知,收到新的私人消息,有人关注您,收到您的某个条目,等等。我真的不知道如何创建新通知。

在控制器中创建它们感觉很糟糕,它可以很容易地导致胖控制器。我知道Service Objects我喜欢他们,但我不确定在这种情况下是否应该使用它们。例如,我可以使用通知服务来处理所有通知。

我想到的另一件事是制作所有可以生成通知的模型a&#34; to_notification&#34;返回通知所拥有的消息的方法,例如,PrivateMessage模型将有一个返回to_notification的方法<a href="some_url">You've got a new private message from #{username}</a>

我考虑的第三个解决方案是在notify_user(user, message)模型中添加Notification方法。但我想Controller仍然需要管理很多逻辑,比如通知消息本身。

解决这个问题最有效的方法是什么?

编辑:我很清楚Mailboxer但我宁愿自己做。

更新

好的,所以我最终使用了一个服务对象。这是Notification模型

class Notification < ActiveRecord::Base
  validates :message, presence: true
  belongs_to :user
end

非常简单,然后我在NotifyUser中创建了一个名为app/actions/notify_user.rb的操作,负责发送通知

class NotifyUser
  def initialize(user, message)
    @user = user
    @message = message
  end

  def notify
    Notification.create(user: @user, message: @message)
  end
end

最后,要发送通知,我只需通过notify调用操作NotifyUser.new(user, message).notify方法即可。

通知消息的逻辑直接在控制器或操作中处理。例如:

def follow(user)
  success = current_user.follow user
  message = "You've got a new follower, #{view_context.link_to(current_user.username, current_user)}!"
  NotifyUser.new(user, message).notify if success
end

我仍然无法想出一种更优雅的方式来创建消息。我想这对我来说足够好了。

1 个答案:

答案 0 :(得分:1)

我更喜欢非平凡应用的服务对象。以下是我的个人意见。

假设您有一个典型的用例,其中用户向另一个用户发送消息,例如爱丽丝发送通知&#34;你好&#34;给鲍勃

这是一个在控制器中创建它们的例子,它是&#34; Rails方式&#34;。

  1. Alice访问了一个页面,例如&#34; www.example.com/notifications/" ;,写下她的消息,点击&#34;发送&#34;按钮。

  2. Rails使用NotificationsController创建新的Notification模型实例,即在数据库中记录。

  3. 当Bob登录时,应用程序会查询通知以查看是否有适用于Bob的通知。

  4. 以下是使用服务对象创建它们的示例:

    1. 您有一个文件,例如&#34; ./ app / services / notifier.rb&#34;暴露了一个普通的旧Ruby对象,例如&#34; Notifier&#34;。

    2. Notifier对象有一个&#34; send&#34;方法(或任何你想要的方法)。

    3. 该方法负责创建新的通知。

    4. 这是一个混合的例子:

      1. E.g。典型的NotificationsController有一些额外的代码:非用户可见的类级方法,例如&#34; def self.send&#34;。

      2. 控制器作为典型的REST资源CRUD管理器执行双重任务,并且还作为具有内部API方法的服务对象。

      3. 我对这种混合体验的个人经验是有效的,对于快速应用程序来说很容易,因为所有东西都在一个地方,但在真正的应用程序中,混合体往往会变成一个大的使用干净的分离,模拟和存根很难测试的代码球。

      4. 要向用户显示通知,并让用户与通知进行交互(例如编辑,删除),我建议使用典型的Rails控制器,因为通知本质上是资源。

          

        我想到的另一件事是制作所有可以生成通知的模型a&#34; to_notification&#34;方法

        如果您正在构建一个真正的应用,请不要这样做。我不得不清理这样的许多应用程序。当涉及国际化和本地化时,它也变得毛茸茸。

        • 我见过这种方式的唯一解决方案是DCI,它可以在您需要的时间点添加to_notifciation方法。这是一个很好的方法,除了DCI倾向于在Ruby中运行缓慢。
          

        我考虑在Notification模型中添加notify_user(用户,消息)方法。

        这实质上是一个混合类:它作为您的资源和服务对象实现双重任务。

        • 很好,但很难推理,因为它将与模型相关的概念(例如业务逻辑,记录持久性等)与控制器相关的概念混合在一起(例如创建新资源)。

        • 如上所述,它适用于快速应用,但往往会变成一个很难干净地测试的大代码球。