2

If I define the following model...

class Foo
  include DataMapper::Resource
  property :name, String, :key => true

  before :save,  do
    puts 'save'
  end
  before :update,  do
    puts 'update'
  end
end

Why does the 2nd save also trigger the 'update' hook?

ruby :001 > f = Foo.new
 => #<Foo @name=nil> 
ruby :002 > f.name = 'Bob'
 => "Bob" 
ruby :003 > f.save
save
 => true 
ruby :004 > f.name = 'Joe'
 => "Joe" 
ruby :005 > f.save
save
update
 => true 

Of course I could dive into the source and answer the question of what code drives this behavior. More importantly, I want to understand the right way to use each of these hooks in practice.

tereško
  • 58,060
  • 25
  • 98
  • 150
Larsenal
  • 49,878
  • 43
  • 152
  • 220

1 Answers1

4
require 'rubygems'
require 'data_mapper'

class Foo
  include DataMapper::Resource

  property :name, String, :key => true

  before :create,  do
    puts 'Create: Only happens when saving a new object.'
  end

  before :update,  do
    puts 'Update: Only happens when saving an existing object.'
  end

  before :save,  do
    puts 'Save: Happens when either creating or updating an object.'
  end

  before :destroy,  do
    puts 'Destroy: Only happens when destroying an existing object.'
  end
end

DataMapper.setup :default, 'sqlite::memory:'
DataMapper.finalize
DataMapper.auto_migrate!

puts "New Foo:"
f = Foo.new :name => "Fighter"
f.save

puts "\nUpdate Foo:"
f.name = "Bar"
f.save

puts "\nUpdate Foo again:"
f.update :name => "Baz"

puts "\nDestroy Foo:"
f.destroy

Which returns:

New Foo:
Save: Happens when either creating or updating an object.
Create: Only happens when saving a new object.

Update Foo:
Save: Happens when either creating or updating an object.
Update: Only happens when saving an existing object.

Update Foo again:
Save: Happens when either creating or updating an object.
Update: Only happens when saving an existing object.

Destroy Foo:
Destroy: Only happens when destroying an existing object.

So as you can see you'd want to use :save hooks whenever something should happen after either a create or an update, and :create and/or :update when you want a finer level of control.

  • 2
    I've used this code to help me generate a nice diagram of common before and after hooks: https://www.lucidchart.com/documents/view#4307-531c-4f1f159f-ace0-1ca90a7a4df5?branch=9cd86b38-93fa-4432-ac0d-b351706819de – mltsy Jan 24 '12 at 21:14
  • @mltsy Don't forget that the object you're saving must be dirty before the hooks are called! Otherwise the hooks don't run at all. – Frank Nov 20 '12 at 22:37