lib/papla.rb in papla-0.0.5 vs lib/papla.rb in papla-0.1.0
- old
+ new
@@ -1,11 +1,11 @@
-require 'bigdecimal'
-require 'bigdecimal/util'
-require 'papla/backend'
-require 'papla/version'
-
module Papla
+ autoload :Backend, 'papla/backend'
+ autoload :FixnumConverter, 'papla/fixnum_converter'
+ autoload :FloatConverter, 'papla/float_converter'
+ autoload :MoneyConverter, 'papla/money_converter'
+
# Converts a number to Polish or English words,
# capitalizing the first letter of the whole phrase.
#
# Localisation is provided by <tt>I18n</tt>, the language
# of the result depends on <tt>I18n.locale</tt>.
@@ -38,98 +38,37 @@
#
# Papla[1.0] # => "Jeden 00/100"
# Papla[87.654321] # => "Osiemdziesiąt siedem 65/100"
# Papla[2.999] # => "Trzy 00/100"
#
+ # If you're using the `money` gem, you can pass in an instance
+ # of `Money` to Papla. The returned string will contain the dollars
+ # part as words, the cents part as 'xx/100' and the currency
+ # string (e.g. `EUR`).
+ #
+ # Example:
+ #
+ # eleven_and_a_half_pounds = Money.new(1150, 'GBP')
+ # Papla[eleven_and_a_half_pounds] # => "Jedenaście 50/100 GBP"
+ #
+ # I18n.locale = :en
+ # discounted_price = Money.new(9999, 'PLN')
+ # Papla[discounted_price] # => "Ninety nine 99/100 PLN"
+ #
# @param [Fixnum] number the number to convert
# @return [String] the phrase in Polish or English
def self.[](number)
- validate!(number)
- number = prepare(number)
- basic_number = number.to_i
- basic_phrase = build_basic_phrase(basic_number)
-
- case number
- when Float; append_cents(basic_phrase, number)
- else basic_phrase
- end
+ converter = converter_for(number)
+ converter.new.convert(number)
end
private
- def self.prepare(number)
+ def self.converter_for(number)
case number
- when Float; number.round(2)
- else number
+ when defined?(Money) && Money then MoneyConverter
+ when Float then FloatConverter
+ when Fixnum then FixnumConverter
+ else raise ArgumentError, "Unsupported type: #{klass}"
end
end
-
- def self.build_basic_phrase(basic_number)
- if basic_number.zero?
- spell_zero
- else
- groups = group(basic_number)
- groups_as_words = convert_groups(groups)
- groups_as_words.flatten.join(' ')
- end.capitalize
- end
-
- def self.group(number)
- groups = []
-
- while number > 0
- number, group = number.divmod(1000)
- groups.unshift(group)
- end
-
- groups
- end
-
- def self.convert_groups(groups)
- bound = groups.count - 1
- result = []
-
- groups.each_with_index do |group, i|
- if group > 0
- result << convert_small_number(group)
- result << spell_rank(bound - i, group) if i < bound
- end
- end
-
- result
- end
-
- def self.convert_small_number(number)
- if number.zero?
- []
- elsif number < 20
- [spell_ones(number)]
- elsif number < 100
- tens, remainder = number.divmod(10)
- [spell_tens(tens), convert_small_number(remainder)]
- else
- hundreds, remainder = number.divmod(100)
- [spell_hundreds(hundreds), convert_small_number(remainder)]
- end
- end
-
- def self.validate!(number)
- max = 999_999_999
- raise ArgumentError, "#{number} is too big, only numbers up to #{max} are supported" if number > max
- end
-
- def self.append_cents(basic_phrase, number)
- cents = 100 * (number.to_d - number.to_i)
- spell_cents(basic_phrase, cents)
- end
-
- def self.backend
- @backend ||= Backend.new
- end
-
- def self.spell_zero; backend.zero; end
- def self.spell_ones(index); backend.ones(index); end
- def self.spell_tens(index); backend.tens(index); end
- def self.spell_hundreds(index); backend.hundreds(index); end
- def self.spell_rank(index, number); backend.rank(index, number); end
- def self.spell_cents(basic_phrase, cents); backend.cents(basic_phrase, cents); end
end