在 rake 任务期间关闭观察者的简单方法?

Posted

技术标签:

【中文标题】在 rake 任务期间关闭观察者的简单方法?【英文标题】:Simple way of turning off observers during rake task? 【发布时间】:2010-10-16 23:54:04 【问题描述】:

我在我的应用程序中使用了 restful_authentication。我正在使用 rake 任务创建一组默认用户,但是每次我运行该任务时,都会发送一封激活电子邮件,因为观察者与我的用户模型相关联。我在创建用户时设置了激活字段,因此不需要激活。

任何人都知道在运行 rake 任务时绕过观察者的简单方法,以便在我保存用户时不会发送电子邮件?

谢谢。

【问题讨论】:

【参考方案1】:

Rails 3.1 最终为此提供了 API: http://api.rubyonrails.org/v3.1.0/classes/ActiveModel/ObserverArray.html#method-i-disable

ORM.observers.disable :user_observer
  # => disables the UserObserver

User.observers.disable AuditTrail
  # => disables the AuditTrail observer for User notifications.
  #    Other models will still notify the AuditTrail observer.

ORM.observers.disable :observer_1, :observer_2
  # => disables Observer1 and Observer2 for all models.

ORM.observers.disable :all
  # => disables all observers for all models.

User.observers.disable :all do
  # all user observers are disabled for
  # just the duration of the block
end

例如ORM 可以是ActiveRecord::Base

【讨论】:

这是迄今为止最好的答案 :-) 这些都不适合我。我最终在 application.rb 中将它们用于 rake 任务 大多数人会用什么来代替ORM ORM 可以是 ActiveRecord::Base【参考方案2】:
User.skip_callback("create", :after, :send_confirmation_email)

....

User.set_callback("create", :after, :send_confirmation_email)

更多信息:

Disabling Callbacks in Rails 3

【讨论】:

【参考方案3】:

作为观察者的标志,我喜欢定义一个名为“disabled”的类访问器,所以它看起来像这样:

class ActivityObserver < ActiveRecord::Observer
  observe :user

  # used in tests to disable the observer on demand.
  cattr_accessor(:disabled)
end

我把它作为敏感回调的条件

def after_create(record)
       return if ActivityObserver.disabled
       # do_something
end

我只是在需要时打开标志

ActivityObserver.disabled=true

【讨论】:

【参考方案4】:

我来这里是为了寻找相同的答案...以上似乎都没有解决问题(或涉及向我的应用程序代码添加特定于迁移的逻辑 -- 嘘)。

这是我想出的(有点蹩脚,它需要在每个相关的迁移中进行,但是......)

class ChangeSomething < ActiveRecord::Migration

  # redefine...
  class MessageObserver < ActiveRecord::Observer
    def after_create(observed) ; end
    def after_update(observed) ; end
  end

  def self.up
    # Message create/update stuff...
  end
end

【讨论】:

【参考方案5】:

另一个你可以尝试的(rails 3)

config.active_record.observers = :my_model_observer unless File.basename($0) == 'rake'

【讨论】:

这也适用于我!但我想添加额外的 ARGV[0] == "db:migrate" 条件,因为您将来可能会编写一个利用你的观察者,你可能会忘记这条小线并拉扯你的头发试图弄清楚为什么你的观察者在你花哨的新 rake 任务期间不运行......【参考方案6】:

禁用 Rails 3 的观察者很简单:

Rails.configuration.active_record.observers = []

【讨论】:

【参考方案7】:

你可以把方法从观察者身上拿走;

MessageObserver.send(:remove_method, :after_create)

将通过删除它来停止 MessageObserver 上的 :after_create。

【讨论】:

【参考方案8】:

在我正在开发的应用上运行测试时,我使用以下内容:

Model.delete_observers

【讨论】:

【参考方案9】:

您可以向您的用户模型添加一个访问器,例如“skip_activation”,它不需要保存,但会在会话中持续存在,然后检查观察者中的标志。类似的东西

class User
  attr_accessor :skip_activation
  #whatever
end

然后,在观察者中:

def after_save(user)
  return if user.skip_activation
  #rest of stuff to send email
end

【讨论】:

【参考方案10】:

正如其他人所暗示的那样;我会用一个简单的 if 语句将不需要的逻辑包装在您的 Observer 中。

def after_create
  send_email if RAILS_ENV == "production"
end

【讨论】:

【参考方案11】:

一般来说,对于这些情况,您可以:

    设置一个模拟对象以“吸收”不需要的行为 有一个外部可访问的标志/开关,观察者尊重以抑制行为 向观察者添加逻辑以检测何时不需要行为一般(例如 dbarker 建议的内容) 有一个全局标志“测试”、“调试”、“启动”或任何改变低级行为的东西 自省并移除观察者 向您的模型添加一个方法,该方法执行替代的、未观察到的任务版本(尽可能与普通方法共享实现)。

在这种情况下,我会说#3 是你最好的选择。

【讨论】:

【参考方案12】:

据我所知,没有直接禁用观察者的方法,但听起来可以向观察者添加逻辑,以便在设置激活码时不发送电子邮件...

【讨论】:

以上是关于在 rake 任务期间关闭观察者的简单方法?的主要内容,如果未能解决你的问题,请参考以下文章

ruby fakeout.rake - 一个简单/可配置的rake任务,为应用程序(使用faker)生成各种大小的随机假数据

使用 rake 任务时检查电子邮件是不是发送一次的最佳方法是啥?

在 Elastic Beanstalk 环境中运行 Rails rake 任务

在“rake test”之后执行 rake 任务

Taskmgr 处理病毒的简单方法(需要继续观察)

rake 任务中的 Rails 异常通知器