2011-09-27 67 views
66

我有一个特别复杂的模型,其中包含验证和回调定义。业务需求现在需要添加新记录的特定场景需要跳过验证和回调。什么是最好的方法来做到这一点?Rails 3跳过验证和回调

回答

116

这个工作在Rails的3:

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

API docsrelated question

+5

难道你不需要再使用'''set_callback(:create)'''?我的印象是'''skip_callback'''禁用它,直到重新启用。 –

+1

我想是的,我从来没有使用这种方法,更多信息http://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html#method-i-skip_callback – Dinatih

+19

这不能是线程安全的?这将是很好的能够在实例级别上设置它.. –

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 

如果你最终使用这样的事情,我会建议使用自己的方法,而不是型号名称,以避免名称的connascence。

我也跑过从埃里克森福克斯一个要点,看起来不错,这是here

+1

我喜欢这种方法,但'skip_callback'显示为一个类方法,而'update_attributes'是一个实例方法,是你想要的吗?嗯,我不明白,API文档说'skip_callback'是实例方法,但它不是在Rails控制台,奇怪。 –

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 
+0

Upvoted,但它不适用于我的3.2.6应用程序。我打电话给Model.skip_callback(:create,:after) – TuteC

+0

这是3.0+的解决方案它不能在2.x上工作 - 但我记得当我正在寻找解决方案时,我偶然发现了解决方案2 .x不适用于3.x –

29

使用ActiveRecord::Persistence#update_column,像这样:

Model.update_column(field, value) 
+0

根据您链接的文档:“调用回调。” – eggie5

+5

我想你看过'update_attribute'的文档,而不是'update_column'。如果您查看'update_column'的文档,它相当于单个列的'update_columns'。 'update_columns'的文档明确指出验证和回调被跳过。 – bowsersenior

+0

拯救我的生命!我试过skip_callback和其他方法,没有运气。这工作! –

0

这个技巧在最后为我工作(重新定义了对象_notify_comment_observer_for_after_create法):

if no_after_create_callback 
    def object._notify_comment_observer_for_after_create; nil; end 
end 
1

我写了一个简单的宝石跳过验证adhoc,但它可能会更新,以包括跳过回调。

https://github.com/npearson72/validation_skipper

你可以采取在创业板上市的can_skip_validation_for,并且还用于跳过回调添加功能。也许调用方法can_skip_validation_and_callbacks_for

其他一切工作都是一样的。如果你需要帮助,请告诉我。

1

我会建议不要使用skip_callback方法,因为它不是线程安全的。然而,sneaky save gem是因为它只是直接运行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! 
7

如果目标是简单地插入或更新不进行回调或验证的记录,你想做到这一点,而不诉诸额外的宝石,加入条件使用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

这太聪明了。救了我头痛! –

0

如果你的验证写入数据库本身,这些都不会工作。

+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ 
| Field        | Type            | Null | Key | Default   | Extra   | 
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+ 
| status        | enum('Big','Small','Ugly','Stupid','Apologetic') | NO |  | Stupid    |    |