$: << File.dirname(__FILE__)
require "connect"
require "logger"

#ActiveRecord::Base.logger = Logger.new(STDERR)

require "rubygems"
require "active_record"


ActiveRecord::Schema.define do 
  # START:migration
  create_table :accounts, :force => true do |t|
    t.string  :number
    t.decimal :balance, :precision => 10, :scale => 2, :default => 0
  end
  # END:migration
end


#START:class_account
#START:transfer
class Account < ActiveRecord::Base
  validate :price_must_be_at_least_a_cent
#END:class_account

  def self.transfer(from, to, amount)
    transaction(from, to) do
      from.withdraw(amount)
      to.deposit(amount)
    end
  end
#END:transfer
#START:class_account

  def withdraw(amount)
    adjust_balance_and_save(-amount)
  end

  def deposit(amount)
    adjust_balance_and_save(amount)
  end

  private

  def adjust_balance_and_save(amount)
    self.balance += amount
    save!
  end

  def price_must_be_at_least_a_cent
    errors.add(:balance, "is negative") if balance < 0
  end
#START:transfer
end
#END:transfer
#END:class_account

#START:fixed
  def adjust_balance_and_save(amount)
    self.balance += amount
  end
#END:fixed

#START:setup
peter = Account.create(:balance => 100, :number => "12345")
paul  = Account.create(:balance => 200, :number => "54321")
#END:setup

case ARGV[0] || "1"

when "1"
  #START:xfer1
  Account.transaction do
    paul.deposit(10)
    peter.withdraw(10)
  end
  #END:xfer1

when "2"
  #START:xfer2
  Account.transaction do
    paul.deposit(350)
    peter.withdraw(350)
  end
  #END:xfer2

when "3"
  #START:xfer3
  begin
    Account.transaction do
      paul.deposit(350)
      peter.withdraw(350)
    end
  rescue
    puts "Transfer aborted"
  end
  
  puts "Paul has #{paul.balance}"
  puts "Peter has #{peter.balance}"
  #END:xfer3

when "4"
  #START:xfer4
  begin
    Account.transaction(peter, paul) do
      paul.deposit(350)
      peter.withdraw(350)
    end
  rescue
    puts "Transfer aborted"
  end
  
  puts "Paul has #{paul.balance}"
  puts "Peter has #{peter.balance}"
  #END:xfer4
  
when "5"
  #START:xfer5
  Account.transfer(peter, paul, 350) rescue  puts "Transfer aborted"
  
  puts "Paul has #{paul.balance}"
  puts "Peter has #{peter.balance}"
  #END:xfer5

end



