11 MarActiveRecord lifecycle

Thursday, 11 March 2010 — 16:24

Most rails developers know the language provides us with callbacks that allow us to run some logic before the ActiveRecord object is saved or updated. However, not everyone knows where to place this logic in the ActiveRecord cycle. This is the execution order and available callbacks, for a save/update instruction:

save
valid
(1) before_validation
(2) before_validation_on_create/ on_update
validate
validate_on_create/on_update
(3) after_validation
(4) after_validation_on_create/on_update
(5) before_save/before_update
(6) before_create

Very frequent bugs consist of making changes (that might break validations) on the model making use of before_save callback. If you do so, you might be filling your database with non valid records, as validations will not be run. Use before_validation in those cases

Ger

06 MarActiveRecord.save without callbacks

Saturday, 06 March 2010 — 09:59

You already know there is a way to avoid running validations when you save an ActiveRecord

project.save(false)

But, what if you want to skip validations?. There are some ways to achieve this. There are some metaprogramming options, such as adding and removing methods, or calling private methods with send (or send!)

project = Project.new(:name => 'ggomeze.com')
project.send(:create_without_callbacks)

project = Project.find(1)
project.send(:update_without_callbacks)

If these methods are private, it just because there should be a different way to do the same, no? :-). So here is my favorite:

# accessors
  attr_accessor :skip_callbacks

# callbacks
  with_options :unless => :skip_callbacks do |project|
    project.after_update :do_something
    project.after_save :do_other_thing
  end

Ah, just a note, you might be tempted to use this, instead of attr_accessor:

attr_accessor_with_default :skip_callbacks, false

but seems like attr_accessor_with_default creates a class attribute which might be problematic under some circumstances

Ger