humanize_fraction 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e0beddb356fa1d63e5658dd2e25fb4916414fbd0
4
- data.tar.gz: 520506910e547967f3f5f485c51c8d8bb75fe6eb
3
+ metadata.gz: 71e2420b7a27230601ab8ae89e38f3097908f13f
4
+ data.tar.gz: 80455bea8b7ae37f41a686570ced33c3ffa78914
5
5
  SHA512:
6
- metadata.gz: 07e78cdf965891de22a42f8b92b41e366ac6f18dd58dccadd8783b8ec46b9b2114a1d1cb9fd68429c526d711eebd74f58232ba45ab2f8cbde533c4cc48c79198
7
- data.tar.gz: 8b4c46ebc18c7ae1f57c26a748c7599769fb82c05336c8bd553667cd6d4c16a8a5dd236fa8aac23a021ead71d4f1a790c58fc7ac773e4cce4de9f7979f58cda9
6
+ metadata.gz: 47ecefd1c758ef9de3c81505d16f6312ff3d339f42929feb7c5f4a992c4056ff430d05c30f599b7b85bc784a9bab666fd75250306ee77d624f75c71b119bf942
7
+ data.tar.gz: 8a3d6b9e0fd2337dadbf331ad8d17f386d46adc450ca0c4bee112810e458b2acc497fce5cbc300dc47a2b7d4fe50cce8166979283b065bcf218a073aab5ae9da
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # humanize_fraction [![CircleCI](https://circleci.com/gh/6/humanize_fraction.svg?style=svg)](https://circleci.com/gh/6/humanize_fraction)
1
+ # humanize_fraction [![CircleCI](https://circleci.com/gh/6/humanize_fraction.svg?style=svg)](https://circleci.com/gh/6/humanize_fraction) [![Gem Version](https://badge.fury.io/rb/humanize_fraction.svg)](https://rubygems.org/gems/humanize_fraction)
2
2
 
3
3
  Rubygem to convert fraction to words, like 1 ⅓ => one and a third. Examples:
4
4
 
@@ -15,6 +15,28 @@ Rubygem to convert fraction to words, like 1 ⅓ => one and a third. Examples:
15
15
  #=> "a millionth"
16
16
  "222/333".humanize_fraction
17
17
  #=> "two hundred and twenty-two three hundred thirty-thirds"
18
+ "1/1000000000000000000000000000".humanize_fraction(shorthand: true)
19
+ #=> "an octillionth"
20
+ ```
21
+
22
+ If you don't want to monkey patch `String`, you can also use the Humanizer class directly:
23
+
24
+ ```ruby
25
+ # From a string:
26
+ fraction = HumanizeFraction::Humanizer.from_string("2 1/4")
27
+
28
+ # From integers:
29
+ fraction = HumanizeFraction::Humanizer.new(
30
+ whole_part: 2,
31
+ numerator: 1,
32
+ denominator: 4,
33
+ )
34
+
35
+ fraction.to_s
36
+ # => "two and one fourth"
37
+
38
+ fraction.to_s(shorthand: true, quarter: true)
39
+ # => "two and a quarter"
18
40
  ```
19
41
 
20
42
  ## Installation
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.add_runtime_dependency "activesupport", ">= 4"
26
26
  spec.add_runtime_dependency "humanize", "~> 1.4"
27
- spec.add_runtime_dependency "twitter_cldr", "~> 4.4"
27
+ spec.add_runtime_dependency "numbers_and_words", "~> 0.11"
28
28
 
29
29
  spec.add_development_dependency "bundler", "~> 1.14"
30
30
  spec.add_development_dependency "rake", "~> 10.0"
@@ -2,7 +2,7 @@ module CoreExtensions
2
2
  module String
3
3
  module HumanizeFraction
4
4
  def humanize_fraction(options = {})
5
- ::HumanizeFraction::Humanizer.from_string(self, options).to_s
5
+ ::HumanizeFraction::Humanizer.from_string(self).to_s(options)
6
6
  end
7
7
  end
8
8
  end
@@ -1,34 +1,37 @@
1
1
  module HumanizeFraction
2
2
  class Humanizer
3
3
  # From: https://github.com/thechrisoshow/fractional/blob/master/lib/fractional.rb
4
- SINGLE_FRACTION = /^\s*(\-?\d+)\/(\-?\d+)\s*$/
5
- MIXED_FRACTION = /^\s*(\-?\d*)\s+(\d+)\/(\d+)\s*$/
4
+ SINGLE_FRACTION = /\A\s*(\-?\d+)\/(\-?\d+)\s*\z/
5
+ MIXED_FRACTION = /\A\s*(\-?\d*)\s+(\d+)\/(\d+)\s*\z/
6
6
 
7
- attr_reader :numerator, :denominator, :integer_part, :quarter, :shorthand
7
+ # Numbers that should be prefixed with `a` instead of `an` even though they
8
+ # start with a vowel.
9
+ NUMBERS_STARTING_WITH_SILENT_VOWEL = [
10
+ "one",
11
+ ]
8
12
 
9
- def initialize(numerator:, denominator:, integer_part: nil, shorthand: false, quarter: false)
13
+ attr_reader :numerator, :denominator, :whole_part
14
+
15
+ def initialize(numerator:, denominator:, whole_part: nil)
10
16
  [numerator, denominator].each do |number|
11
17
  if !number.is_a?(Integer)
12
18
  raise ArgumentError, "Expected Integers for numerator/denominator but got #{number.class.name}"
13
19
  end
14
20
  end
15
- if !integer_part.nil? && !integer_part.is_a?(Integer)
16
- raise ArgumentError, "Expected Integer or NilClass for integer_part but got #{integer_part.class.name}"
21
+ if !whole_part.nil? && !whole_part.is_a?(Integer)
22
+ raise ArgumentError, "Expected Integer or NilClass for whole_part but got #{whole_part.class.name}"
17
23
  end
18
- @integer_part = integer_part
24
+ @whole_part = whole_part
19
25
  @numerator = numerator
20
26
  @denominator = denominator
21
- @shorthand = shorthand
22
- @quarter = quarter
23
27
  end
24
- alias_method :quarter?, :quarter
25
- alias_method :shorthand?, :shorthand
26
28
 
27
- def to_s
29
+ def to_s(shorthand: false, quarter: false)
30
+ humanized_denominator = humanize_denominator(shorthand: shorthand, quarter: quarter)
28
31
  words = []
29
- words << humanize_integer_part if !integer_part.nil?
30
- words << humanize_numerator
31
- words << humanize_denominator
32
+ words << humanize_whole_part if !whole_part.nil?
33
+ words << humanize_numerator(humanized_denominator, shorthand: shorthand)
34
+ words << humanized_denominator
32
35
  words.join(" ")
33
36
  end
34
37
 
@@ -38,7 +41,7 @@ module HumanizeFraction
38
41
  end
39
42
  if string_is_mixed_fraction?(string)
40
43
  whole, numerator, denominator = string.scan(MIXED_FRACTION).flatten.map(&:to_i)
41
- new(integer_part: whole, numerator: numerator, denominator: denominator, **options)
44
+ new(whole_part: whole, numerator: numerator, denominator: denominator, **options)
42
45
  elsif string_is_single_fraction?(string)
43
46
  numerator, denominator = string.split("/").map(&:to_i)
44
47
  new(numerator: numerator, denominator: denominator, **options)
@@ -49,32 +52,31 @@ module HumanizeFraction
49
52
 
50
53
  private
51
54
 
52
- def humanize_integer_part
53
- "#{integer_part.humanize} and"
55
+ def humanize_whole_part
56
+ "#{whole_part.humanize} and"
54
57
  end
55
58
 
56
- def humanize_numerator
57
- number = if numerator == 1 && shorthand?
58
- # 8 is the only(?) case where you want to prefix with `an` instead of `a`.
59
- first_digit(denominator) == 8 ? "an" : "a"
59
+ def humanize_numerator(humanized_denominator, shorthand:)
60
+ number = if numerator == 1 && shorthand
61
+ first_number = humanized_denominator.split(" ").first
62
+ indefinite_article(first_number)
60
63
  else
61
64
  numerator.humanize
62
65
  end
63
66
  number
64
67
  end
65
68
 
66
- def humanize_denominator
69
+ def humanize_denominator(shorthand:, quarter:)
67
70
  number = case denominator
68
71
  when 2
69
72
  "half"
70
73
  when 4
71
- quarter? ? "quarter" : "fourth"
74
+ quarter ? "quarter" : "fourth"
72
75
  else
73
- denominator.localize(:en).to_rbnf_s("SpelloutRules", "spellout-ordinal")
76
+ I18n.with_locale(:en) { denominator.to_words(ordinal: true) }
74
77
  end
75
78
  # Handle case of `a millionth`, `a thousandth`, etc.
76
- if shorthand? && denominator >= 100 &&
77
- first_digit(denominator) == 1 && remaining_digits_zeros?(denominator)
79
+ if shorthand && denominator >= 100 && one_followed_by_zeros?(denominator)
78
80
  number.sub!(/\Aone\s/, "")
79
81
  end
80
82
  if numerator != 1
@@ -83,15 +85,20 @@ module HumanizeFraction
83
85
  number
84
86
  end
85
87
 
86
- def first_digit(number)
87
- number.to_s.split("").first.to_i
88
+ # Checks number is a 1 followed by only zeros, e.g. 10 or 10000000
89
+ def one_followed_by_zeros?(number)
90
+ digits = number.to_s.split("")
91
+ first_digit = digits.shift
92
+ first_digit.to_i == 1 && digits.size > 0 && digits.map(&:to_i).all?(&:zero?)
88
93
  end
89
94
 
90
- # Checks if everything after first digit are zeros.
91
- def remaining_digits_zeros?(number)
92
- numbers = number.to_s.split("")
93
- numbers.shift
94
- numbers.size > 0 && numbers.map(&:to_i).all?(&:zero?)
95
+ def indefinite_article(humanized_number)
96
+ if humanized_number.match(/\A[aeiou]/) &&
97
+ !NUMBERS_STARTING_WITH_SILENT_VOWEL.include?(humanized_number)
98
+ "an"
99
+ else
100
+ "a"
101
+ end
95
102
  end
96
103
 
97
104
  def self.string_is_mixed_fraction?(value)
@@ -1,3 +1,3 @@
1
1
  module HumanizeFraction
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -1,6 +1,7 @@
1
1
  require "active_support/inflector"
2
2
  require "humanize"
3
- require "twitter_cldr"
3
+ # TODO: figure out how to use this library without the monkey patching it does.
4
+ require "numbers_and_words"
4
5
 
5
6
  require "humanize_fraction/humanizer"
6
7
  require "humanize_fraction/version"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: humanize_fraction
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Graham
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.4'
41
41
  - !ruby/object:Gem::Dependency
42
- name: twitter_cldr
42
+ name: numbers_and_words
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '4.4'
47
+ version: '0.11'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '4.4'
54
+ version: '0.11'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement