Skip to content

piotrmurach/strings-numeral

Repository files navigation

strings logo

Strings::Numeral

Gem Version Actions CI Build status Maintainability Coverage Status Inline docs

Express numbers as string numerals.

Strings::Numeral provides conversions of numbers to numerals component for Strings.

Features

  • No monkey-patching String class
  • Functional API that can be easily wrapped by other objects
  • Instance based configuration
  • Highly performant

Installation

Add this line to your application's Gemfile:

gem 'strings-numeral'

And then execute:

$ bundle

Or install it yourself as:

$ gem install strings-numeral

Contents

1. Usage

Strings::Numeral helps to express any number as a numeral in words. It exposes few methods to achieve this. For example, you can express a number as a cardinal numeral using cardinalize:

Strings::Numeral.cardinalize(1234)
# => "one thousand, two hundred thirty four"

But you're not limited to converting integers only. It can handle decimals as well:

Strings::Numeral.cardinalize(1234.567)
# => "one thousand, two hundred thirty four and five hundred sixty seven thousandths"

For more options on how to customize formatting see configuration section.

Similarly, you can convert a number to a ordinal numeral with ordinalize:

Strings::Numeral.ordinalize(1234)
# => "one thousand, two hundred thirty fourth"

You can also convert a number to a short ordinal:

Strings::Numeral.ordinalize(1234, short: true)
# => "1234th"

Using monetize you can convert any number into a monetary numeral:

Strings::Numeral.monetize(1234.567)
# => "one thousand, two hundred thirty four dollars and fifty seven cents",

To turn a number into a roman numeral use romanize:

Strings::Numeral.romanize(2020)
# => "MMXX"

2. API

2.1 numeralize

The normalize is a wrapping method for the cardinalize and ordinalize methods. By default it converts a number to cardinal numeral:

Strings::Numeral.numeralize(1234.567)
# => "one thousand, two hundred thirty four and five hundred sixty seven thousandths"

You can also make it convert to ordinal numerals using :term option:

Strings::Numeral.numeralize(1234.567, term: :ord)
# => "one thousand, two hundred thirty fourth and five hundred sixty seven thousandths"

2.2 cardinalize

To express a number as a cardinal numeral use cardinalize or cardinalise.

Strings::Numeral.cardinalize(1234)
# => "one thousand, two hundred thirty four"

You're not limited to integers only. You can also express decimal numbers as well:

Strings::Numeral.cardinalize(123.456)
# => "one hundred twenty three and four hundred fifty six thousandths"

By default the fractional part of a decimal number is expressed as a fraction. If you wish to spell out fractional part digit by digit use :decimal option with :digit value:

Strings::Numeral.cardinalize(123.456, decimal: :digit)
# => "one hundred twenty three point four five six"

You may prefer to use a different delimiter for thousand's. You can do use by passing the :delimiter option:

Strings::Numeral.cardinalize(1_234_567, delimiter: " and ")
# => "one million and two hundred thirty four thousand and five hundred sixty seven"

To change word that splits integer from factional part use :separator option:

Strings::Numeral.cardinalize(1_234.567, separator: "dot")
# => "one thousand, two hundred thirty four dot five hundred sixty seven thousandths"

2.3 ordinalize

To express a number as a cardinal numeral use ordinalize or ordinalise.

Strings::Numeral.ordinalize(1234)
# => "one thousand, two hundred thirty fourth"

You're not limited to integers only. You can also express decimal numbers as well:

Strings::Numeral.ordinalize(123.456)
# => "one hundred twenty third and four hundred fifty six thousandths"

By default the fractional part of a decimal number is expressed as a fraction. If you wish to spell out fractional part digit by digit use :decimal option with :digit value:

Strings::Numeral.ordinalize(123.456, decimal: :digit)
# => "one hundred twenty third point four five six"

You may prefer to use a different delimiter for thousand's. You can do use by passing the :delimiter option:

Strings::Numeral.ordinalize(1_234_567, delimiter: " and ")
# => "one million and two hundred thirty four thousand and five hundred sixty seventh"

To change word that splits integer from factional part use :separator option:

Strings::Numeral.ordinalize(1_234.567, separator: "dot")
# => "one thousand, two hundred thirty fourth dot five hundred sixty seven thousandths"

2.4 monetize

To express a number as a monetary numeral use monetize or monetise.

Strings::Numeral.monetize(123.456)
# => "one hundred twenty three dollars and forty six cents",

By default monetize displays money using USD currency. You can change this with the :currency option that as value accepts internationally recognised symbols. Currently support currencies are: EUR, GBP, JPY, PLN and USD.

Strings::Numeral.monetize(123.456, currency: :jpy)
# => "one hundred twenty three yen and forty six sen"

2.5 romanize

To convert a number into a Roman numeral use romanize:

Strings::Numeral.romanize(2020)
# => "MMXX"

2.6 configuration

All available configuration settings are:

  • currency - Adds currency words for integer and fractional parts. Supports EUR, GBP, JPY, PLN and USD. Defaults to USD.
  • decimal - Formats fractional part of a number. The :digit value spells out every digit and the :fraction appends divider word. Defaults to :fraction.
  • delimiter - Sets the thousands delimiter. Defaults to ", ".
  • separator - Sets the separator between the fractional and integer parts. Defaults to "and" for :fraction and "point" for :digit option.
  • strict - Enables number validation for the input parameter. Defaults to false.
  • trailing_zeros - If true keeps trailing zeros at the end of the fractional part. Defaults to false.

The above settings can be passed as keyword arguments:

Strings::Numeral.cardinalize("12.100", trailing_zeros: true, decimal: :digit)
# => "twelve point one zero zero"

Or you can configure the settings for an instance during initialisation:

numeral = Strings::Numeral.new(delimiter: "; ", separator: "dot")

After initialisation, you can use configure to change settings inside a block:

numeral.configure do |config|
  config.delimiter "; "
  config.separator "dot"
  config.decimal :digit
  config.trailing_zeros true
end

Once configured, you can use the instance like so:

numeral.cardinalize("1234.56700")
# => "one thousand; two hundred thirty four dot five six seven zero zero"

3. Extending Core Classes

Though it is highly discouraged to pollute core Ruby classes, you can add the required methods to String, Float and Integer classes using refinements.

For example, if you wish to only extend Float class with cardinalize method do:

module MyFloatExt
  refine Float do
    def cardinalize(**options)
      Strings::Numeral.cardinalize(self, **options)
    end
  end
end

Then cardinalize method will be available for any float number where refinement is applied:

using MyFloatExt

12.34.cardinalize
# => "twelve and thirty four"

However, if you want to include all the Strings::Numeral methods in Float, Integer and String classes, you can use provided extensions file:

require "strings/numeral/extensions"

using Strings::Numeral::Extensions

Alternatively, you can choose what class you wish to refine with all the methods:

require "bigdecimal"
require "strings/numeral/extensions"

module MyBigDecimalExt
  refine BigDecimal do
    include Strings::Numeral::Extensions::Methods
  end
end

using MyBigDecimalExt

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/strings-numeral. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.

License

The gem is available as open source under the terms of the MIT License.

Code of Conduct

Everyone interacting in the Strings::Numeral project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

Copyright

Copyright (c) 2019 Piotr Murach. See LICENSE for further details.