Rails 3跳过验证和回调


Answers:


118

这适用于Rails 3:

Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)

API文档相关问题


5
您不再需要使用set_callback(:create)吗?我的印象是skip_callback禁用它,直到重新启用。
Caley Woods

1
我想是的,我从来不使用这个方法,更多信息api.rubyonrails.org/classes/ActiveSupport/Callbacks/...
Dinatih

20
这不是线程安全的吗?能够在实例级别上进行设置将非常好
。– Christopher Lindblom

1
以防万一有人遇到与我相同的问题:在rails 3中,这不会禁用观察者回调。为了做到这一点,我做了stackoverflow.com/questions/707615/…所说的
Alex Siri

最近,我们的项目遇到了问题。我们已经用相当简单的方法解决了这个问题。它对我们很好。该解决方案适用于任何版本的Rails。在我的博客文章中查看:railsguides.net/2014/03/25/skip-callbacks-in-tests
ka8725 2014年

29

使用ActiveRecord :: Persistence#update_column,如下所示:

Model.update_column(field, value)

根据链接的文档,“调用回调”。
eggie13年

5
我认为您查看的是文档update_attribute,而不是update_column。如果您查看的文档update_column,则相当于update_columns单列。的docsupdate_columns明确指出已跳过验证和回调。
bowsersenior

救我一命!我尝试过skip_callback和其他方法,没有运气。这可行!
Chihung Yu 2014年

10

如果目标是简单地插入或更新记录而没有回调或验证,而您想要这样做而又不求助于其他gem,添加条件检查,使用RAW SQL或以任何方式处理退出的代码,则可能是可以使用指向您现有数据库表的“影子对象”。像这样:

class ImportedUser < ActiveRecord::Base
  # To import users with no validations or callbacks
  self.table_name = 'users'
end

它适用于所有版本的Rails,是线程安全的,并且无需修改现有代码就可以完全消除所有验证和回调。只要记住要使用新类插入对象即可,例如:

ImportedUser.new( person_attributes )

1
这太聪明了。救了我头疼!
蒂姆·克雷奇默

2

我的看法是这样的(注意:这会在创建,更新,删除以及其他需要将其添加到数组的回调中禁用回调)。

    begin
      [:create, :save].each{|a| self.class.skip_callback(a) } # We disable callbacks on save and create

      # create new record here without callbacks, tou can also disable validations with 
      # .save(:validate => false)
    ensure
      [:create, :save].each{|a| self.class.set_callback(a) }  # and we ensure that callbacks are restored
    end

已投票,但后来不适用于我的3.2.6应用程序。我打电话给Model.skip_callback(:create,:after)
TuteC

这是适用于3.0+的解决方案,不适用于2.x-但我记得当我在寻找解决方案时,偶然发现了适用于3.x的2.x解决方案
Marcin Raczkowski

2

我建议不要使用skip_callback方法,因为它不是线程安全的。该偷偷摸摸保存宝石然而是因为它只是运行直接的SQL。请注意,这不会触发验证,因此您必须自己调用它们(例如:my_model.valid?)。

以下是他们文档中的一些示例:

# Update. Returns true on success, false otherwise.
existing_record.sneaky_save

# Insert. Returns true on success, false otherwise.
Model.new.sneaky_save

# Raise exception on failure.
record.sneaky_save!

1

如何在模型中添加一个使您跳过回调的方法呢?

class Foo < ActiveRecord::Base
  after_save :do_stuff

  def super_secret_create(attrs)
    self.skip_callback(:create)
    self.update_attributes(attrs)
    self.save(:validate => false)
    self.set_callback(:create)
  end
end

如果最终使用了类似的方法,我建议在方法中使用self而不是模型名称,以避免名称混淆。

我还碰到了Sven Fuchs的要点,看起来很不错,就在这里


1
我喜欢这种方法,但是skip_callback作为update_attributes实例方法显示为类方法,这是您想要的吗?嗯,我不明白,API文档说skip_callback是实例方法,但在Rails控制台中不是这样,很奇怪。
约翰尼·克拉西

1

我写了一个简单的gem来跳过adhoc验证,但是它可能会被更新为也包括跳过回调。

https://github.com/npearson72/validation_skipper

您可以使用can_skip_validation_forgem并添加功能以也跳过回调。也许叫方法can_skip_validation_and_callbacks_for

其他一切都一样。如果您需要帮助,请告诉我。


0

这个技巧终于为我工作了(_notify_comment_observer_for_after_create该对象的重新定义方法):

if no_after_create_callback
  def object._notify_comment_observer_for_after_create; nil; end
end

0

如果将您的验证写入数据库本身,则这些都不起作用。

+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| Field                              | Type                                             | Null | Key | Default            | Extra          |
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| status                             | enum('Big','Small','Ugly','Stupid','Apologetic') | NO   |     | Stupid             |                |
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.