我有一个特别复杂的模型,其中定义了验证和回调。现在,业务需要针对特定场景,其中添加新记录需要跳过验证和回调。最好的方法是什么?
我有一个特别复杂的模型,其中定义了验证和回调。现在,业务需要针对特定场景,其中添加新记录需要跳过验证和回调。最好的方法是什么?
Answers:
使用ActiveRecord :: Persistence#update_column,如下所示:
Model.update_column(field, value)
update_attribute
,而不是update_column
。如果您查看的文档update_column
,则相当于update_columns
单列。的docsupdate_columns
明确指出已跳过验证和回调。
如果目标是简单地插入或更新记录而没有回调或验证,而您想要这样做而又不求助于其他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 )
我的看法是这样的(注意:这会在创建,更新,删除以及其他需要将其添加到数组的回调中禁用回调)。
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
我建议不要使用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!
如何在模型中添加一个使您跳过回调的方法呢?
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的要点,看起来很不错,就在这里
skip_callback
作为update_attributes
实例方法显示为类方法,这是您想要的吗?嗯,我不明白,API文档说skip_callback
是实例方法,但在Rails控制台中不是这样,很奇怪。
我写了一个简单的gem来跳过adhoc验证,但是它可能会被更新为也包括跳过回调。
https://github.com/npearson72/validation_skipper
您可以使用can_skip_validation_for
gem并添加功能以也跳过回调。也许叫方法can_skip_validation_and_callbacks_for
其他一切都一样。如果您需要帮助,请告诉我。
如果将您的验证写入数据库本身,则这些都不起作用。
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| status | enum('Big','Small','Ugly','Stupid','Apologetic') | NO | | Stupid | |
set_callback(:create)
吗?我的印象是skip_callback
禁用它,直到重新启用。