У меня особенно сложная модель с определенными проверками и обратными вызовами. Теперь бизнес нуждается в конкретном сценарии, когда добавление новой записи требует пропуска валидации и обратных вызовов. Какой лучший способ сделать это?
Rails 3 пропускает проверки и обратные вызовы
Ответ 1
Это работает в Rails 3:
Model.skip_callback(:create)
model.save(:validate => false)
Model.set_callback(:create)
Ответ 2
Используйте ActiveRecord:: Persistence # update_column, например:
Model.update_column(field, value)
Ответ 3
Если целью является просто вставить или обновить запись без обратных вызовов или проверок, и вы хотели бы сделать это, не прибегая к дополнительным драгоценным камням, добавляя условные проверки, используя RAW SQL, или futzing с вашим выходным кодом каким-либо образом, может быть возможно использовать "теневой объект", который указывает на вашу существующую таблицу db. Например:
class ImportedUser < ActiveRecord::Base
# To import users with no validations or callbacks
self.table_name = 'users'
end
Это работает с каждой версией Rails, является потокобезопасным и полностью исключает все проверки и обратные вызовы без каких-либо изменений в вашем существующем коде. Просто не забудьте использовать свой новый класс для вставки объекта, например:
ImportedUser.new( person_attributes )
Ответ 4
Мой выбор был таким (примечание: это отключает обратные вызовы при создании, обновлении, удалении и других, которые вам нужно добавить в массив).
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
Ответ 5
Как насчет добавления метода в вашу модель, позволяющего пропустить обратные вызовы?
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, который выглядит красиво, здесь
Ответ 6
Я написал простую жемчужину для пропусков проверки adhoc, но ее, вероятно, можно было бы обновить, включив также пропущенные обратные вызовы.
https://github.com/npearson72/validation_skipper
Вы можете взять can_skip_validation_for
в драгоценном камне и добавить функциональность, чтобы также пропускать обратные вызовы. Возможно, вызовите метод can_skip_validation_and_callbacks_for
Все остальное будет работать одинаково. Если вы хотите помочь в этом, сообщите мне.
Ответ 7
Я бы рекомендовал НЕ использовать метод 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!
Ответ 8
Этот хак работал у меня наконец (переопределил метод _notify_comment_observer_for_after_create
для объекта):
if no_after_create_callback
def object._notify_comment_observer_for_after_create; nil; end
end
Ответ 9
Ни одно из них не будет работать, если ваши проверки будут записаны в базу данных.
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------------------------+--------------------------------------------------+------+-----+--------------------+----------------+
| status | enum('Big','Small','Ugly','Stupid','Apologetic') | NO | | Stupid | |