diff --git a/lib/money/money.rb b/lib/money/money.rb index ab3729c5bc..36f5be2841 100644 --- a/lib/money/money.rb +++ b/lib/money/money.rb @@ -987,11 +987,18 @@ def to_money self end + # Common inspect function + # + # @return [String] + def inspect + "#" + end + # Allocates money between different parties without loosing pennies. # After the mathmatically split has been performed, left over pennies will # be distributed round-robin amongst the parties. This means that parties # listed first will likely recieve more pennies then ones that are listed later - # + # # @param [0.50, 0.25, 0.25] to give 50% of the cash to party1, 25% ot party2, and 25% to party3. # # @return [Array] @@ -1004,7 +1011,7 @@ def allocate(splits) raise ArgumentError, "splits add to more then 100%" if allocations > 1.0 left_over = cents - + amounts = splits.collect do |ratio| fraction = (cents * ratio / allocations).floor left_over -= fraction @@ -1016,6 +1023,29 @@ def allocate(splits) return amounts.collect { |cents| Money.new(cents, currency) } end + # Split money amongst parties evenly without loosing pennies. + # + # @param [2] number of parties. + # + # @return [Array] + # + # @example + # Money.new(100, "USD").split(3) #=> [Money.new(34), Money.new(33), Money.new(33)] + def split(num) + raise ArgumentError, "need at least one party" if num < 1 + low = Money.new(cents / num) + high = Money.new(low.cents + 1) + + remainder = cents % num + result = [] + + num.times do |index| + result[index] = index < remainder ? high : low + end + + return result + end + private # Cleans up formatting rules. diff --git a/spec/money_spec.rb b/spec/money_spec.rb index db400b239e..383323fe5f 100644 --- a/spec/money_spec.rb +++ b/spec/money_spec.rb @@ -1061,7 +1061,34 @@ def to_money end end - describe "allocation"do + describe "split" do + specify "#split needs at least one party" do + lambda {Money.us_dollar(1).split(0)}.should raise_error(ArgumentError) + lambda {Money.us_dollar(1).split(-1)}.should raise_error(ArgumentError) + end + + + specify "#gives 1 cent to both people if we start with 2" do + Money.us_dollar(2).split(2).should == [Money.us_dollar(1), Money.us_dollar(1)] + end + + specify "#split may distribute no money to some parties if there isnt enough to go around" do + Money.us_dollar(2).split(3).should == [Money.us_dollar(1), Money.us_dollar(1), Money.us_dollar(0)] + end + + specify "#split does not lose pennies" do + Money.us_dollar(5).split(2).should == [Money.us_dollar(3), Money.us_dollar(2)] + end + + specify "#split a dollar" do + moneys = Money.us_dollar(100).split(3) + moneys[0].cents.should == 34 + moneys[1].cents.should == 33 + moneys[2].cents.should == 33 + end + end + + describe "allocation" do specify "#allocate takes no action when one gets all" do Money.us_dollar(005).allocate([1]).should == [Money.us_dollar(5)] end