Number formatting + subscriptions

Hi all,

I want to make strings like this:

$100.00 plus $22.00 per month
$100.00
$22.00 per week
free (I want this when both numbers are zero)

Generally: [one off fee] plus [fee per billing cycle] per [billing cycle length]

Based on this input:

per_license_cost (= one off fee)
per_cycle_cost (= fee per cycle)
currency_symbol (=$)
cycle_length (= a string: 'day' | 'week' | 'month' | 'year')

I have working code, and in any other language I'd take the uglyness
for granted, but in Ruby I still have hope. So, what would be a better
way to write this? I've put the code I put together at the bottom.

Thanks,
Douglas

The code:

  def human_price
    if per_license_cost.zero? and per_cycle_cost.zero?
      'free'
    elsif per_cycle_cost.zero?
      human_per_license_cost
    elsif per_license_cost.zero?
      human_per_cycle_cost
    else
      human_per_license_cost + ' plus ' + human_per_cycle_cost
    end
  end
  
  def currency_symbol
    '$' # fine for now... should I think about a Money class to manage this?
  end

  private

  def human_cost(number)
    human = number.to_s
    number = if number.abs.to_s.length > 2
               human[-2, 0] = '.'
               human
             elsif number.abs.to_s.length == 2
               '0.' + human
             elsif number.abs.to_s.length == 1
               '0.0' + human
             else
               '0.00'
       end
    return currency_symbol + number
  end
  
  def human_per_license_cost
    human_cost(per_license_cost)
  end

  def human_per_cycle_cost
    human_cost(per_cycle_cost) + ' per ' + cycle_length
  end

Douglas Livingstone wrote:

I want to make strings like this:

$100.00 plus $22.00 per month
$100.00
$22.00 per week
free (I want this when both numbers are zero)

Generally: [one off fee] plus [fee per billing cycle] per [billing cycle length]

I have working code, and in any other language I'd take the uglyness
for granted, but in Ruby I still have hope. So, what would be a better
way to write this? I've put the code I put together at the bottom.

I'll try to start from scratch so please point any errors I might have introduced:

# Note that this is not designed to work properly with Floats as it
# directly compares to 0 -- use a delta if it also should work with
# Floats.
def human_price(currency, base_fee, cycle_fee, cycle_length)
   has_base_fee = base_fee != 0
   has_cycle_fee = cycle_fee != 0
   result = ""

   result << "%s%.2f" % [currency, base_fee] if has_base_fee

   if has_cycle_fee then
     result << " plus " if has_base_fee
     result << "%s%.2f per %s" % [currency, cycle_fee, cycle_length]
   end

   result = "free" if result.empty?

   return result
end

The formating of a single price could be out-factored, but I think in this simple case it is still reasonable to just have the logic two times in the method...

Yes, you're right; when I was looking for string formatting, I didn't
see the % operator so my logic was bloated, so I factored it out. But
with your much neater logic it doesn't need that,so thanks very much!

Douglas

···

On Fri, 1 Apr 2005 09:07:02 +0900, Florian Groß <florgro@gmail.com> wrote:

The formating of a single price could be out-factored, but I think in
this simple case it is still reasonable to just have the logic two times
in the method...