【问题标题】:Rails - how do I avoid having to trigger the create action in one controller from the create action in another controllerRails - 如何避免必须从另一个控制器中的创建操作触发一个控制器中的创建操作
【发布时间】:2012-09-05 22:03:41
【问题描述】:

在这里原谅一个基本问题。

通过阅读,我了解到从另一个控制器触发创建操作不是最佳实践 - 我正在寻找有关在以下情况下应该如何组织代码的建议:

我有两个控制器:案例和通知。

创建新案例时,我希望它也创建一个新案例 通知。

通知创建操作在其模型中创建一个新实例, 并发送电子邮件。

我认为我不应该只从我的案例控制器调用 Notification#create 是否正确?我应该将其提取到帮助程序或模块中吗?如果是这样,它会是什么样子?关于这个主题的其他大致相似的帖子不再详细说明。

谢谢。

【问题讨论】:

  • 你可以使用 Rails 观察者来创建通知api.rubyonrails.org/classes/ActiveRecord/Observer.html
  • 谢谢,我设法设置了一个观察者,以便在创建新通知时发送通知电子邮件 - 您是否建议在这种情况下使用观察者而不是下面的回调解决方案?
  • 查看我的回答了解更多详情

标签: ruby-on-rails model-view-controller controller action


【解决方案1】:

您只需要在您的案例控制器操作中编写 Notification.create 即可。

您可以根据需要编写尽可能多的代码,在控制器操作中创建尽可能多的模型。

【讨论】:

  • 这有点导致另一个问题,如果我只是调用 .create 它不会执行通知控制器中的所有代码,即发送电子邮件......我想触发控制器创建操作完整的。
【解决方案2】:

由于 create 是一种 POST 方法,我认为没有办法从案例控制器调用通知控制器的创建。我的建议是将通知实例的创建和发送邮件逻辑移动到您的案例模型的保存之前。这将在每次创建案例时创建一个通知,并且还会处理邮件发送机制。由于这是您业务需求的一部分,因此最好将业务逻辑移到您的模型中。

【讨论】:

  • 很好的建议,非常感谢 - 我一直对从另一个控制器触发创建操作的可能性感到困惑。使用这样的过滤器从创建操作中删除其他附加功能是关键。
【解决方案3】:

这个逻辑应该在你的模型中。好的解决方案是使用 ActiveRecord 回调。

# app/models/case.rb
class Case < ActiveRecord:Base
  after_create :create_notification

private        # <--- bottom of your model
  def create_notification
    Notification.create!(some_options_for_notification)
  end
end

# app/models/notification.rb
class Notification < ActiveRecord:Base
  after_create :send_notification

def send(opts)
  ...          # <--- some logic to send notification here
end


private        # <--- bottom of your model
  def send_notification
    send(some_options_for_sending)
  end
end

【讨论】:

  • 感谢尼克。在这两种情况下,使用观察者会更好吗?它们似乎也是一个不错的解决方案。
  • 是的,observer 是适合您情况的完美模式,但是当我的模型逻辑更复杂时,我更喜欢使用它。
【解决方案4】:

作为选项之一,您可以使用 rails 观察者来创建通知 http://api.rubyonrails.org/classes/ActiveRecord/Observer.html

观察者和回调之间几乎没有区别,例如观察者不能取消任何模型动作,但在你的情况下,我认为不管用什么。

但观察者也曾经坚持单一职责原则。

例子

class CaseObserver < ActiveRecord::Observer
 def after_create(case)
    #create notification
 end
end

应该保存到/app/models/case_observer.rb.

在你的config/application.rb

config.active_record.observers = :case_observer

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多