After_create callback called twice in test env when using fi

All,

I’ve been trying to figure out a strange bug in one of my applications
that I think I’ve narrowed down to a problem with rails fixtures. It
seems as though the after_create callback is being run twice when I
save a record. This is only happening a) in the test environment, and
b) when there is a fixture file for that table.

The test below only prints “Doing stuff” one time if I remove the
‘fixtures’ line. Likewise, saving the item through ./script/console
in development mode also does not call the do_stuff method twice.

I’m inclined to think that this is a bug in the handling of fixtures,
but I’d love to be proven wrong. I couldn’t find this in trac, but if
there’s an open ticket, then I’d like to know about it. If not, and
if everyone agrees that this is a likely bug, then I’ll open one.

The model:

class Item < ActiveRecord::Base
after_create :do_stuff
def do_stuff
puts “Doing stuff”
end
end

The test:

require File.dirname(FILE) + ‘/…/test_helper’
require ‘item’

class ItemTest < Test::Unit::TestCase
fixtures :items

def test_callback
  @item = Item.new
  puts "========================"
  @item.save
  puts "========================"
end

end

The fixture file:

one:
id: 1
two:
id: 2

The rake run:

rake test:units

(in /Users/tsaleh/Documents/Programming/svn/bug/trunk)
/opt/local/bin/ruby -Ilib:test “/opt/local/lib/ruby/gems/1.8/gems/
rake-0.7.3/lib/rake/rake_test_loader.rb” “test/unit/item_test.rb”
Loaded suite /opt/local/lib/ruby/gems/1.8/gems/rake-0.7.3/lib/rake/
rake_test_loader
Started

Doing stuff
Doing stuff

.
Finished in 0.051473 seconds.

1 tests, 0 assertions, 0 failures, 0 errors

Thanks for the help,
Tammer

[email protected]
(626) 841-0708
Usually online via Google Talk

Tammer Saleh wrote:

All,

I’ve been trying to figure out a strange bug in one of my applications
that I think I’ve narrowed down to a problem with rails fixtures. It

Try this in your environment.rb:

module ActiveRecord
module Callbacks
def callbacks_for(method)
(self.class.read_inheritable_attribute(method.to_sym) or []).uniq
end
end
end

  • OR -

Use the alternate form of defining a callback:

def after_create

end

From what I understand, the problem seems to be that the ‘after_create
:foo, :bar’ syntax appends those symbols to an array without doing a
‘uniq’. It seems that if you happen to load the class twice, you’ll get
double entries in the callback list. This can happen easily because the
Ruby ‘require’ method doesn’t seem to convert paths to absolute paths,
e.g the following will cause the file ‘/lib/foo.rb’ to be loaded twice:

In \app\models\bar.rb

require File.join(RAILS_ROOT, ‘lib’, ‘foo’)
require ‘…/…/lib/foo’
class Bar < ActiveRecord::Base

end

Brian H. wrote:

Tammer Saleh wrote:

All,

I’ve been trying to figure out a strange bug in one of my applications

Or, perhaps more cleanly:

module Callbacks
def callbacks_for_with_uniq(method)
callbacks_for_without_uniq(method).uniq
end

alias_method_chain :callbacks_for, :uniq
end