after_create callback called twice in test env when using fixtures

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

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 Hartin 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