ActiveRecord::Base#save! silently failing

Hello,

One of my AR models is failing to save (using rails 2.0.2 and
sqlite3). Both #save and #save return [] (sometimes other values),
but A) nothing ever hits the database, and B) #save! doesn't throw an
error, even if it's not a valid model. See the irb session below, as
well as my Order class and migration.

Has this happened to anyone else?

The most unusual thing I've done on this project so far is use the
decimal column type in the Order model. I'm going to change it to
float and see if that works, then try my hand at ruby-debug if it
doesn't.

Many thanks,
-Ed Brannin

t = Transaction.new

=> #<Transaction id: nil, order_id: nil, data: nil, txn_id: nil,
handshake: nil, created_at: nil, updated_at: nil>

t.valid?

=> false

t.save

=> false

t.save!

ActiveRecord::RecordInvalid: Validation failed: Handshake can't be
blank, Txn can't be blank, Data can't be blank
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/validations.rb:946:in `save_without_transactions!'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:112:in `save!'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/connection_adapters/abstract/database_statements.rb:
66:in `transaction'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:80:in `transaction'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:100:in `transaction'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:112:in `save!'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:120:in `rollback_active_record_state!'
  from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/
active_record/transactions.rb:112:in `save!'
  from (irb):4

o = Order.new

=> #<Order id: nil, name: "", email: "", company: "", gross: nil,
shipping: nil, handling: nil, address: "", status: "", created_at:
nil, updated_at: nil>

o.valid?

=> false

o.save

=> []

o.save!

=> []

class Order < ActiveRecord::Base
  validates_presence_of :name, :email, :address

validates_numericality_of :gross, :shipping, :handling, :greater_than_or_equal_to
=> 0

  has_many :transaction

  def total
    gross + shipping + handling
  end
end

...and its migration:
class CreateOrders < ActiveRecord::Migration
  def self.up
    create_table :orders do |t|
      t.string :name, :default => "", :null => false
      t.string :email, :default => "", :null => false
      t.string :company, :default => "", :null => false
      t.decimal :gross, :null => false
      t.decimal :shipping, :null => false
      t.decimal :handling, :null => false
      t.text :address, :default => "", :null => false
      t.string :status, :default => "", :null => false

      t.timestamps
    end
  end

  def self.down
    drop_table :orders
  end
end

Relevant gem versions:
action_profiler (1.0.0)
actionmailer (2.0.2, 2.0.1, 1.3.6, 1.3.3, 1.3.2, 1.3.1, 1.2.5, 1.2.3,
1.2.2, 1.2.1)
actionpack (2.0.2, 2.0.1, 1.13.6, 1.13.3, 1.13.2, 1.13.1, 1.12.5,
1.12.3, 1.12.2, 1.12.1)
actionwebservice (1.2.6, 1.2.3, 1.2.2, 1.2.1, 1.1.6, 1.1.4, 1.1.3,
1.1.2)
activerecord (2.0.2, 2.0.1, 1.15.6, 1.15.3, 1.15.2, 1.15.1, 1.14.4,
1.14.3, 1.14.2)
activeresource (2.0.2, 2.0.1)
activesupport (2.0.2, 2.0.1, 1.4.4, 1.4.2, 1.4.1, 1.4.0, 1.3.1)
acts_as_versioned (0.2.3)
json (1.1.2, 1.0.2, 0.4.3, 0.4.2)
mongrel (1.1.3, 1.1.2, 1.0.1, 1.0, 0.3.14, 0.3.13.4, 0.3.13.3)
mongrel_cluster (1.0.5, 0.2.1, 0.2.0)
rails (2.0.2, 2.0.1, 1.2.6, 1.2.3, 1.2.2, 1.2.1, 1.1.6, 1.1.4, 1.1.3,
1.1.2)
rails-app-installer (0.2.0, 0.1.5, 0.1.3)
rails_analyzer_tools (1.4.0, 1.1.0)
rspec (1.1.2, 1.1.1, 1.1.0, 1.0.5, 0.7.5.1, 0.7.5, 0.6.4, 0.6.3)
rubygems-update (1.0.1, 0.9.5, 0.9.4)
sqlite-ruby (2.2.3)
sqlite3-ruby (1.2.1, 1.2.0, 1.1.0.1, 1.1.0)
ZenTest (3.8.0, 3.7.2, 3.7.1, 3.6.1, 3.6.0)

Update:

Not surprisingly, the decimal vs float thing was a silly pipe-dream.
I then tried defining ALL the ActiveRecord callbacks to puts their
names and ran my specs. The 4 validation-related ones fire when I
call #valid?, but *none* of them fired on #save.

I'm stepping through ActiveRecord's #save! in rdebug now, but I don't
really expect to find my way through. Any help y'all can offer would
be most appreciated.

Thank you,
-Ed

Update:

Not surprisingly, the decimal vs float thing was a silly pipe-dream.
I then tried defining ALL the ActiveRecord callbacks to puts their
names and ran my specs. The 4 validation-related ones fire when I
call #valid?, but *none* of them fired on #save.

I'm stepping through ActiveRecord's #save! in rdebug now, but I don't
really expect to find my way through. Any help y'all can offer would
be most appreciated.

I'll guess that Order has_one :transaction. This unfortunately is a
bad thing.
AR::Base already has a transaction method, which executes the supplied
block in a transaction.
Paraphrasing wildly, at the end of the day, some the save methods boil
down to

transaction do
   #do some saving, invoke callbacks etc...
end

But on your order model, transaction is just an association accessor
and so the saving never gets done.

Fred

I'll guess that Order has_one :transaction. This unfortunately is a
bad thing.
AR::Base already has a transaction method, which executes the supplied
block in a transaction.

ack! I feel quite silly for not thinking of that.

Actually, it has_many :transaction, so when I changed it

Thank you!

-Ed