2011-09-27 117 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    |    |