<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/bank/no_exchange_bank.rb</filename>
    </added>
    <added>
      <filename>lib/bank/variable_exchange_bank.rb</filename>
    </added>
    <added>
      <filename>lib/money/core_extensions.rb</filename>
    </added>
    <added>
      <filename>lib/money/money.rb</filename>
    </added>
    <added>
      <filename>lib/support/cattr_accessor.rb</filename>
    </added>
    <added>
      <filename>tests/core_extensions_test.rb</filename>
    </added>
    <added>
      <filename>tests/money_test.rb</filename>
    </added>
    <added>
      <filename>tests/no_exchange_bank_test.rb</filename>
    </added>
    <added>
      <filename>tests/variable_exchange_bank_test.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,4 +1,4 @@
-Copyright (c) 2005 Tobias Luetke
+Copyright (c) 2005 Tobias Lutke
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the</diff>
      <filename>MIT-LICENSE</filename>
    </modified>
    <modified>
      <diff>@@ -14,18 +14,13 @@ exporting.
 
 == Download
 
-
 Preferred method of installation is gem: 
 
-gem install -s http://dist.leetsoft.com money 
+  gem install --source http://dist.leetsoft.com money 
 
 Alternatively you can get the library packed
-http://dist.leetsoft.com/pkg/
-
-If you plan to enhance this class please get a copy from svn so that
-you can easily submit patches
-
-svn: svn://leetsoft.com/money/trunk
+  
+  http://dist.leetsoft.com/pkg/
 
 == Useage
 
@@ -34,7 +29,7 @@ object in your models. The following example requires a cents and a currency fie
 
   class ProductUnit &lt; ActiveRecord::Base
     belongs_to :product
-    composed_of :price, :class_name =&gt; &quot;Money&quot;, :mapping =&gt; %w(cents currency)
+    composed_of :price, :class_name =&gt; &quot;Money&quot;, :mapping =&gt; [%w(cents cents) %(currency currency)]
 
     private        
       validate :cents_not_zero
@@ -47,6 +42,33 @@ object in your models. The following example requires a cents and a currency fie
       validates_uniqueness_of :sku        
   end
   
+== Class configuration
+
+Two const class variables are available to tailor Money to your needs. 
+If you don't need currency exchange at all, just ignore those.
+
+=== Default Currency
+
+By default Money defaults to USD as its currency. This can be overwritten using
+
+  Money.default_currency = &quot;CAD&quot;
+  
+If you use rails, the environment.rb is a very good place to put this. 
+
+=== Currency Exchange
+
+The second parameter is a bit more complex. It lets you provide your own implementation of the 
+currency exchange service. By default Money throws an exception when trying to call .exchange_to. 
+
+A second minimalist implementation is provided which lets you supply custom exchange rates:
+
+  Money.bank = VariableExchangeBank.new 
+  Money.bank.add_rate(&quot;USD&quot;, &quot;CAD&quot;, 1.24515)
+  Money.bank.add_rate(&quot;CAD&quot;, &quot;USD&quot;, 0.803115)
+  Money.us_dollar(100).exchange_to(&quot;CAD&quot;) =&gt; Money.ca_dollar(124)
+  Money.ca_dollar(100).exchange_to(&quot;USD&quot;) =&gt; Money.us_dollar(80)
+
+There is nothing stopping you from creating bank objects which scrape www.xe.com for the current rates or just return rand(2)
   
 == Code
 </diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -5,12 +5,16 @@ require 'rake/rdoctask'
 require 'rake/gempackagetask'
 require 'rake/contrib/rubyforgepublisher'
 
-PKG_VERSION = &quot;1.0.0&quot;
+PKG_VERSION = &quot;1.3.2&quot;
 PKG_NAME = &quot;money&quot;
 PKG_FILE_NAME = &quot;#{PKG_NAME}-#{PKG_VERSION}&quot;
 
+RUBY_FORGE_PROJECT = 'money'
+RUBY_FORGE_USER = 'xal'
+RELEASE_NAME  = &quot;REL #{PKG_VERSION}&quot;
+
 PKG_FILES = FileList[
-    &quot;lib/**/*&quot;, &quot;test/*&quot;, &quot;[A-Z]*&quot;, &quot;rakefile&quot;
+    &quot;lib/**/*&quot;, &quot;tests/*&quot;, &quot;[A-Z]*&quot;, &quot;rakefile&quot;
 ].exclude(/\bCVS\b|~$/)
 
 desc &quot;Default Task&quot;
@@ -22,11 +26,15 @@ task :cleanup =&gt; [ :rm_packages, :clobber_rdoc ]
 # Run the unit tests
 
 Rake::TestTask.new(&quot;test&quot;) { |t|
-#  t.libs &lt;&lt; &quot;test&quot;
-  t.pattern = 'test/*_test.rb'
-  t.verbose = true
+  t.libs &lt;&lt; &quot;test&quot;
+  t.pattern = 'tests/*_test.rb'
+  t.verbose = false
 }
 
+task :install =&gt; [:package] do
+  `gem install pkg/#{PKG_FILE_NAME}.gem`
+end
+
 # Genereate the RDoc documentation
 
 Rake::RDocTask.new { |rdoc|
@@ -66,6 +74,8 @@ task :publish =&gt; [:rdoc, :package] do
   `ssh tobi@leetsoft.com &quot;mkdir -p dist/api/#{PKG_NAME}&quot;`
   Rake::SshDirPublisher.new(&quot;leetsoft.com&quot;, &quot;dist/api/#{PKG_NAME}&quot;, &quot;doc&quot;).upload
   `ssh tobi@leetsoft.com './gemupdate'`
+  `rm -rf pkg/`
+  `rm -rf doc/`
 end
 
 
@@ -91,25 +101,124 @@ Rake::GemPackageTask.new(spec) do |p|
   p.need_zip = true
 end
 
+# --- Ruby forge release manager by florian gross -------------------------------------------------
 
-=begin
-desc &quot;Packing generator to tgz&quot;
-task :package =&gt; [:cleanup] do
-  system %{ tar -czvf ../#{PKG_NAME}.tar.gz #{PKG_FILES} }
-#  system %{ cd ..; zip -r #{PKG_NAME}.zip #{PKG_NAME} }
-end
+RUBY_FORGE_PROJECT = 'money'
+RUBY_FORGE_USER = 'xal'
+RELEASE_NAME  = &quot;REL #{PKG_VERSION}&quot;
 
-desc &quot;Sending package to server&quot;
-task :upload =&gt; [:package, :rdoc] do
-  publisher = Rake::CompositePublisher.new
-  publisher.add Rake::SshFilePublisher.new(&quot;leetsoft.com&quot;, &quot;leetsoft.com/htdocs/rails/money&quot;, &quot;..&quot;, &quot;#{PKG_NAME}.tar.gz&quot;)
-#  publisher.add Rake::SshFilePublisher.new(&quot;leetsoft.com&quot;, &quot;leetsoft.com/htdocs/rails/money&quot;, &quot;..&quot;, &quot;#{PKG_NAME}.zip&quot;)
-  publisher.add Rake::SshDirPublisher.new(&quot;leetsoft.com&quot;, &quot;leetsoft.com/htdocs/rails/money&quot;, &quot;doc&quot;)
-  publisher.upload
-end
 
-task :rm_packages do
-  system %{ cd ..; rm #{PKG_NAME}.tar.gz }
-#  system %{ cd ..; rm #{PKG_NAME}.zip }
+desc &quot;Publish the release files to RubyForge.&quot;
+task :release =&gt; [:gem] do
+  files = [&quot;gem&quot;].map { |ext| &quot;pkg/#{PKG_FILE_NAME}.#{ext}&quot; }
+
+  if RUBY_FORGE_PROJECT then
+    require 'net/http'
+    require 'open-uri'
+
+    project_uri = &quot;http://rubyforge.org/projects/#{RUBY_FORGE_PROJECT}/&quot;
+    project_data = open(project_uri) { |data| data.read }
+    group_id = project_data[/[?&amp;]group_id=(\d+)/, 1]
+    raise &quot;Couldn't get group id&quot; unless group_id
+
+    # This echos password to shell which is a bit sucky
+    if ENV[&quot;RUBY_FORGE_PASSWORD&quot;]
+      password = ENV[&quot;RUBY_FORGE_PASSWORD&quot;]
+    else
+      print &quot;#{RUBY_FORGE_USER}@rubyforge.org's password: &quot;
+      password = STDIN.gets.chomp
+    end
+
+    login_response = Net::HTTP.start(&quot;rubyforge.org&quot;, 80) do |http|
+      data = [
+        &quot;login=1&quot;,
+        &quot;form_loginname=#{RUBY_FORGE_USER}&quot;,
+        &quot;form_pw=#{password}&quot;
+      ].join(&quot;&amp;&quot;)
+      http.post(&quot;/account/login.php&quot;, data)
+    end
+
+    cookie = login_response[&quot;set-cookie&quot;]
+    raise &quot;Login failed&quot; unless cookie
+    headers = { &quot;Cookie&quot; =&gt; cookie }
+
+    release_uri = &quot;http://rubyforge.org/frs/admin/?group_id=#{group_id}&quot;
+    release_data = open(release_uri, headers) { |data| data.read }
+    package_id = release_data[/[?&amp;]package_id=(\d+)/, 1]
+    raise &quot;Couldn't get package id&quot; unless package_id
+
+    first_file = true
+    release_id = &quot;&quot;
+
+    files.each do |filename|
+      basename  = File.basename(filename)
+      file_ext  = File.extname(filename)
+      file_data = File.open(filename, &quot;rb&quot;) { |file| file.read }
+
+      puts &quot;Releasing #{basename}...&quot;
+
+      release_response = Net::HTTP.start(&quot;rubyforge.org&quot;, 80) do |http|
+        release_date = Time.now.strftime(&quot;%Y-%m-%d %H:%M&quot;)
+        type_map = {
+          &quot;.zip&quot;    =&gt; &quot;3000&quot;,
+          &quot;.tgz&quot;    =&gt; &quot;3110&quot;,
+          &quot;.gz&quot;     =&gt; &quot;3110&quot;,
+          &quot;.gem&quot;    =&gt; &quot;1400&quot;
+        }; type_map.default = &quot;9999&quot;
+        type = type_map[file_ext]
+        boundary = &quot;rubyqMY6QN9bp6e4kS21H4y0zxcvoor&quot;
+
+        query_hash = if first_file then
+          {
+            &quot;group_id&quot; =&gt; group_id,
+            &quot;package_id&quot; =&gt; package_id,
+            &quot;release_name&quot; =&gt; RELEASE_NAME,
+            &quot;release_date&quot; =&gt; release_date,
+            &quot;type_id&quot; =&gt; type,
+            &quot;processor_id&quot; =&gt; &quot;8000&quot;, # Any
+            &quot;release_notes&quot; =&gt; &quot;&quot;,
+            &quot;release_changes&quot; =&gt; &quot;&quot;,
+            &quot;preformatted&quot; =&gt; &quot;1&quot;,
+            &quot;submit&quot; =&gt; &quot;1&quot;
+          }
+        else
+          {
+            &quot;group_id&quot; =&gt; group_id,
+            &quot;release_id&quot; =&gt; release_id,
+            &quot;package_id&quot; =&gt; package_id,
+            &quot;step2&quot; =&gt; &quot;1&quot;,
+            &quot;type_id&quot; =&gt; type,
+            &quot;processor_id&quot; =&gt; &quot;8000&quot;, # Any
+            &quot;submit&quot; =&gt; &quot;Add This File&quot;
+          }
+        end
+
+        query = &quot;?&quot; + query_hash.map do |(name, value)|
+          [name, URI.encode(value)].join(&quot;=&quot;)
+        end.join(&quot;&amp;&quot;)
+
+        data = [
+          &quot;--&quot; + boundary,
+          &quot;Content-Disposition: form-data; name=\&quot;userfile\&quot;; filename=\&quot;#{basename}\&quot;&quot;,
+          &quot;Content-Type: application/octet-stream&quot;,
+          &quot;Content-Transfer-Encoding: binary&quot;,
+          &quot;&quot;, file_data, &quot;&quot;
+          ].join(&quot;\x0D\x0A&quot;)
+
+        release_headers = headers.merge(
+          &quot;Content-Type&quot; =&gt; &quot;multipart/form-data; boundary=#{boundary}&quot;
+        )
+
+        target = first_file ? &quot;/frs/admin/qrs.php&quot; : &quot;/frs/admin/editrelease.php&quot;
+        http.post(target + query, data, release_headers)
+      end
+
+      if first_file then
+        release_id = release_response.body[/release_id=(\d+)/, 1]
+        raise(&quot;Couldn't get release id&quot;) unless release_id
+      end
+
+      first_file = false
+    end
+  end
 end
-=end</diff>
      <filename>Rakefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,181 +1,29 @@
-# === Usage with ActiveRecord
-# 
-# Use the compose_of helper to let active record deal with embedding the money
-# object in your models. The following example requires a cents and a currency field.
-# 
-#   class ProductUnit &lt; ActiveRecord::Base
-#     belongs_to :product
-#     composed_of :price, :class_name =&gt; &quot;Money&quot;, :mapping =&gt; %w(cents currency)
-# 
-#     private        
-#       validate :cents_not_zero
-#     
-#       def cents_not_zero
-#         errors.add(&quot;cents&quot;, &quot;cannot be zero or less&quot;) unless cents &gt; 0
-#       end
-#     
-#       validates_presence_of :sku, :currency
-#       validates_uniqueness_of :sku        
-#   end
-#   
-class Money
-  include Comparable
-  attr_reader :cents, :currency
-
-  DEFAULT = &quot;CAD&quot;
-
-  EXCHANGE_RATES = { 
-    &quot;CAD_TO_USD&quot; =&gt; 0.85,  
-    &quot;USD_TO_CAD&quot; =&gt; 1.15,
-  }
-
-  # Creates a new money object. 
-  #  Money.new(100) 
-  # 
-  # Alternativly you can use the convinience methods like 
-  # Money.ca_dollar and Money.us_dollar 
-  def initialize(cents, currency = DEFAULT)
-    @cents, @currency = cents, currency
-  end
-
-  # Do two money objects equal? Only works if both objects are of the same currency
-  def eql?(other_money)
-    cents == other_money.cents &amp;&amp; currency == other_money.currency
-  end
-
-  def &lt;=&gt;(other_money)
-    if currency == other_money.currency
-      cents &lt;=&gt; other_money.cents
-    else
-      cents &lt;=&gt; other_money.exchange_to(currency).cents
-    end
-  end
-  
-  def +(other_money)
-    if currency == other_money.currency
-      Money.new(cents + other_money.cents,currency)
-    else
-      Money.new(cents + other_money.exchange_to(currency).cents,currency)
-    end   
-  end
-
-  def -(other_money)
-    if currency == other_money.currency
-      Money.new(cents - other_money.cents, currency)
-    else
-      Money.new(cents - other_money.exchange_to(currency).cents, currency)
-    end   
-  end
-    
-  # get the cents value of the object
-  def cents
-    @cents.to_i
-  end
-  
-  # multiply money by fixnum
-  def *(fixnum)
-    Money.new(cents * fixnum, currency)    
-  end
-
-  # divide money by fixnum
-  def /(fixnum)
-    Money.new(cents / fixnum, currency)    
-  end
-  
-  
-  # Format the price according to several rules
-  # Currently supported are :with_currency, :no_cents and :html
-  #
-  # with_currency: 
-  #
-  #  Money.ca_dollar(0).format =&gt; &quot;free&quot;
-  #  Money.ca_dollar(100).format =&gt; &quot;$1.00&quot;
-  #  Money.ca_dollar(100).format(:with_currency) =&gt; &quot;$1.00 CAD&quot;
-  #  Money.us_dollar(85).format(:with_currency) =&gt; &quot;$0.85 USD&quot;
-  #
-  # no_cents:  
-  #
-  #  Money.ca_dollar(100).format(:no_cents) =&gt; &quot;$1&quot;
-  #  Money.ca_dollar(599).format(:no_cents) =&gt; &quot;$5&quot;
-  #  
-  #  Money.ca_dollar(570).format([:no_cents, :with_currency]) =&gt; &quot;$5 CAD&quot;
-  #  Money.ca_dollar(39000).format(:no_cents) =&gt; &quot;$390&quot;
-  #
-  # html:
-  #
-  #  Money.ca_dollar(570).format([:html, :with_currency]) =&gt;  &quot;$5.70 &lt;span class=\&quot;currency\&quot;&gt;CAD&lt;/span&gt;&quot;
-  def format(rules = [])
-    return &quot;free&quot; if cents == 0
-    
-    rules = [rules].flatten
-        
-    if rules.include?(:no_cents)
-      formatted = sprintf(&quot;$%d&quot;, cents.to_f / 100  )          
-    else
-      formatted = sprintf(&quot;$%.2f&quot;, cents.to_f / 100  )      
-    end
-    
-    if rules.include?(:with_currency)
-      formatted &lt;&lt; &quot; &quot;
-      formatted &lt;&lt; '&lt;span class=&quot;currency&quot;&gt;' if rules.include?(:html)
-      formatted &lt;&lt; currency
-      formatted &lt;&lt; '&lt;/span&gt;' if rules.include?(:html)
-    end
-    formatted
-  end
-  
-  # Money.ca_dollar(100).to_s =&gt; &quot;$1.00 CAD&quot;
-  def to_s
-    format(:with_currency)
-  end
-  
-  # Recieve the amount of this money object in another currency   
-  def exchange_to(other_currency)
-    rate = EXCHANGE_RATES[&quot;#{currency}_TO_#{other_currency}&quot;] or raise &quot;Can't find required exchange rate&quot;
-    
-    exchanged_cents = (cents * rate).floor
-    Money.new(exchanged_cents, other_currency)
-  end  
-  
-  # Create a new money object with value 0
-  def self.empty(currency = DEFAULT)
-    Money.new(0, currency)
-  end
-
-  # Create a new money object using the Canadian dollar currency
-  def self.ca_dollar(num)
-    Money.new(num, &quot;CAD&quot;)
-  end
-
-  # Create a new money object using the American dollar currency
-  def self.us_dollar(num)
-    Money.new(num, &quot;USD&quot;)
-  end
-  
-  # Recieve a money object with the same amount as the current Money object
-  # in american dollar 
-  def as_us_dollar
-    exchange_to(&quot;USD&quot;)
-  end
- 
- # Recieve a money object with the same amount as the current Money object
- # in canadian dollar 
-  def as_ca_dollar
-    exchange_to(&quot;CAD&quot;)
-  end
-
-  # Export the money class
-  # This is useful if you want to export Orders as XML as a means to get 
-  # Them out of the dynamic DB and store them a bit more static 
-  # ( Otherwise your completed orders would change in value when you put 
-  # products on sale ) 
-  # 
-  #  xml = XmlExporter.new    
-  #  Money.ca_dollar(1000).export(xml)
-  #  xml.to_s =&gt; &lt;money currency='CAD'&gt;1000&lt;/money&gt;
-  def export(exporter)
-    exporter.add_text(&quot;money&quot;, cents)
-    exporter.add_attribute(&quot;currency&quot;, currency)
-  end
-  
-end
\ No newline at end of file
+#--
+# Copyright (c) 2005 Tobias Luetke
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# &quot;Software&quot;), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#++
+
+
+require File.dirname(__FILE__) + '/support/cattr_accessor'
+require File.dirname(__FILE__) + '/bank/no_exchange_bank'
+require File.dirname(__FILE__) + '/bank/variable_exchange_bank'
+require File.dirname(__FILE__) + '/money/money'
+require File.dirname(__FILE__) + '/money/core_extensions'
\ No newline at end of file</diff>
      <filename>lib/money.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>lib/exporter/xml.rb</filename>
    </removed>
    <removed>
      <filename>test/money_test.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>a580bd396d12abb445f01d2b3fe15f32cd806bcf</id>
    </parent>
  </parents>
  <author>
    <name>tobi</name>
    <email>tobi@da9ee5fb-4aef-0310-b2bf-b6c93f260786</email>
  </author>
  <url>http://github.com/aflatter/money/commit/0797e9da6b529cb5adf866e329b8ba960ea6ec77</url>
  <id>0797e9da6b529cb5adf866e329b8ba960ea6ec77</id>
  <committed-date>2005-06-08T12:35:42-07:00</committed-date>
  <authored-date>2005-06-08T12:35:42-07:00</authored-date>
  <message>some major updates. version bump to 1.3.1


git-svn-id: svn://leetsoft.com/money/trunk@8 da9ee5fb-4aef-0310-b2bf-b6c93f260786</message>
  <tree>8aee692f4a80cca2639e06c0dfa0aa45260f9561</tree>
  <committer>
    <name>tobi</name>
    <email>tobi@da9ee5fb-4aef-0310-b2bf-b6c93f260786</email>
  </committer>
</commit>
