ordinalize_full 3.0.0 → 3.1.0

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
  SHA256:
3
- metadata.gz: 7174b3e018cd6b0f1b7b41a7d30fe3994726c81029d6c197e46184a58ed3e690
4
- data.tar.gz: d76be4c1a6205e4e5c62e4d32d776281cda48d120bf05d78778ccb3383d78ae8
3
+ metadata.gz: 141ca2978cba4542c3753808f1a4e7097c44b4c5d2baa6648a8a8f097c50e4d0
4
+ data.tar.gz: 1345bbea85ce31a8c67341003bad1ebe32695fbbb488d1d7528f36df1bd57b51
5
5
  SHA512:
6
- metadata.gz: a39b56d13c8026e98a2e08eec3fdc01152d60becd2942b1cb183bf56cf43524d1b5520e75cc9568948d371fc5e376ab61024c54d0ef903aa0a727b0ba0a184e1
7
- data.tar.gz: 672aed32b546b3346dd305008493d0665c83595ebb7b22f6ac9f1c20feffff0025928df0103fd8d12283da073e074a3ea8b4274ac60439b34f39add6c1e7222d
6
+ metadata.gz: d071d17ee79d77eb2254ab950867f27ed7a267ee3f26e108572ce85d9746e3433d2812cb0651e6a5b682617ae8da4dfa2e99da1f843d04a8f97005e9eed68b82
7
+ data.tar.gz: 7eafd8f37d55f00e8dba46ea12fc12ca8fd7ee99f18f6c54ec47d6cf0edd66a7b1949d1aae18bb92a124638b9765e57dee09a25a30c1e48e77cb829b6b143c08
data/.rubocop.yml CHANGED
@@ -6,32 +6,17 @@ AllCops:
6
6
  TargetRubyVersion: 3.0
7
7
  NewCops: enable
8
8
 
9
+ Gemspec/DevelopmentDependencies:
10
+ Enabled: false
11
+
9
12
  Metrics:
10
13
  Enabled: false
11
14
 
12
15
  Layout/AccessModifierIndentation:
13
16
  EnforcedStyle: outdent
14
17
 
15
- Layout/CaseIndentation:
16
- Enabled: false
17
-
18
- Layout/EndAlignment:
19
- Enabled: false
20
-
21
- Layout/EmptyLinesAroundArguments:
22
- Enabled: false
23
-
24
- Layout/LineLength:
25
- Enabled: false
26
-
27
18
  Style/Alias:
28
19
  EnforcedStyle: prefer_alias_method
29
20
 
30
- Style/Documentation:
31
- Enabled: false
32
-
33
21
  Style/StringLiterals:
34
22
  EnforcedStyle: double_quotes
35
-
36
- Style/SpecialGlobalVars:
37
- Enabled: false
data/README.md CHANGED
@@ -8,9 +8,8 @@ Like Rails' [ordinalize](http://api.rubyonrails.org/classes/ActiveSupport/Inflec
8
8
  Features:
9
9
 
10
10
  - i18n support
11
- - doesn't monkey-patch
11
+ - doesn't require monkey-patching
12
12
  - easy to integrate with Rails but doesn't require Rails
13
- - less than 50 lines of code
14
13
 
15
14
  ## Usage
16
15
 
@@ -49,6 +48,9 @@ MyIntegerLikeClass.new.ordinalize_in_full #=> "forty second"
49
48
 
50
49
  ## Limitations
51
50
 
52
- - only works up to 100 (for now)
51
+ - only works up to 100 for non-English languages
53
52
  - locales only available in English, French, Italian, Spanish, and Dutch (pull requests welcome!)
54
53
 
54
+ ## License
55
+
56
+ `SPDX-License-Identifier: MIT`
data/Rakefile CHANGED
@@ -10,11 +10,4 @@ end
10
10
  require "rubocop/rake_task"
11
11
  RuboCop::RakeTask.new
12
12
 
13
- require "cane/rake_task"
14
- Cane::RakeTask.new do |t|
15
- t.no_doc = true
16
- t.style_measure = 120
17
- t.abc_max = 20
18
- end
19
-
20
- task default: %i[spec rubocop cane]
13
+ task default: %i[spec rubocop]
@@ -1,102 +1,72 @@
1
1
  en:
2
- ordinalize_full:
3
- n_1: first
4
- n_2: second
5
- n_3: third
6
- n_4: fourth
7
- n_5: fifth
8
- n_6: sixth
9
- n_7: seventh
10
- n_8: eighth
11
- n_9: ninth
12
- n_10: tenth
13
- n_11: eleventh
14
- n_12: twelfth
15
- n_13: thirteenth
16
- n_14: fourteenth
17
- n_15: fifteenth
18
- n_16: sixteenth
19
- n_17: seventeenth
20
- n_18: eighteenth
21
- n_19: nineteenth
22
- n_20: twentieth
23
- n_21: twenty first
24
- n_22: twenty second
25
- n_23: twenty third
26
- n_24: twenty fourth
27
- n_25: twenty fifth
28
- n_26: twenty sixth
29
- n_27: twenty seventh
30
- n_28: twenty eighth
31
- n_29: twenty ninth
32
- n_30: thirtieth
33
- n_31: thirty first
34
- n_32: thirty second
35
- n_33: thirty third
36
- n_34: thirty fourth
37
- n_35: thirty fifth
38
- n_36: thirty sixth
39
- n_37: thirty seventh
40
- n_38: thirty eighth
41
- n_39: thirty ninth
42
- n_40: fortieth
43
- n_41: forty first
44
- n_42: forty second
45
- n_43: forty third
46
- n_44: forty fourth
47
- n_45: forty fifth
48
- n_46: forty sixth
49
- n_47: forty seventh
50
- n_48: forty eighth
51
- n_49: forty ninth
52
- n_50: fiftieth
53
- n_51: fifty first
54
- n_52: fifty second
55
- n_53: fifty third
56
- n_54: fifty fourth
57
- n_55: fifty fifth
58
- n_56: fifty sixth
59
- n_57: fifty seventh
60
- n_58: fifty eighth
61
- n_59: fifty ninth
62
- n_60: sixtieth
63
- n_61: sixty first
64
- n_62: sixty second
65
- n_63: sixty third
66
- n_64: sixty fourth
67
- n_65: sixty fifth
68
- n_66: sixty sixth
69
- n_67: sixty seventh
70
- n_68: sixty eighth
71
- n_69: sixty ninth
72
- n_70: seventieth
73
- n_71: seventy first
74
- n_72: seventy second
75
- n_73: seventy third
76
- n_74: seventy fourth
77
- n_75: seventy fifth
78
- n_76: seventy sixth
79
- n_77: seventy seventh
80
- n_78: seventy eighth
81
- n_79: seventy ninth
82
- n_80: eightieth
83
- n_81: eighty first
84
- n_82: eighty second
85
- n_83: eighty third
86
- n_84: eighty fourth
87
- n_85: eighty fifth
88
- n_86: eighty sixth
89
- n_87: eighty seventh
90
- n_88: eighty eighth
91
- n_89: eighty ninth
92
- n_90: ninetieth
93
- n_91: ninety first
94
- n_92: ninety second
95
- n_93: ninety third
96
- n_94: ninety fourth
97
- n_95: ninety fifth
98
- n_96: ninety sixth
99
- n_97: ninety seventh
100
- n_98: ninety eighth
101
- n_99: ninety ninth
102
- n_100: one hundredth
2
+ long_form:
3
+ negative: negative
4
+ simple:
5
+ ones:
6
+ n_0: zero
7
+ n_1: one
8
+ n_2: two
9
+ n_3: three
10
+ n_4: four
11
+ n_5: five
12
+ n_6: six
13
+ n_7: seven
14
+ n_8: eight
15
+ n_9: nine
16
+ n_10: ten
17
+ n_11: eleven
18
+ n_12: twelve
19
+ n_13: thirteen
20
+ n_14: fourteen
21
+ n_15: fifteen
22
+ n_16: sixteen
23
+ n_17: seventeen
24
+ n_18: eighteen
25
+ n_19: nineteen
26
+ tens:
27
+ n_2: twenty
28
+ n_3: thirty
29
+ n_4: forty
30
+ n_5: fifty
31
+ n_6: sixty
32
+ n_7: seventy
33
+ n_8: eighty
34
+ n_9: ninety
35
+ hundred: hundred
36
+ larger:
37
+ n_0: ""
38
+ n_1: thousand
39
+ n_2: million
40
+ n_3: billion
41
+ n_4: trillion
42
+ ordinal:
43
+ ones:
44
+ n_0: zeroth
45
+ n_1: first
46
+ n_2: second
47
+ n_3: third
48
+ n_4: fourth
49
+ n_5: fifth
50
+ n_6: sixth
51
+ n_7: seventh
52
+ n_8: eighth
53
+ n_9: ninth
54
+ n_10: tenth
55
+ n_11: eleventh
56
+ n_12: twelfth
57
+ n_13: thirteenth
58
+ n_14: fourteenth
59
+ n_15: fifteenth
60
+ n_16: sixteenth
61
+ n_17: seventeenth
62
+ n_18: eigthteenth
63
+ n_19: nineteenth
64
+ tens:
65
+ n_2: twentieth
66
+ n_3: thirtieth
67
+ n_4: fortieth
68
+ n_5: fiftieth
69
+ n_6: sixtieth
70
+ n_7: seventieth
71
+ n_8: eightieth
72
+ n_9: ninetieth
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "i18n"
4
4
 
5
+ # Main module
5
6
  module OrdinalizeFull
6
7
  I18n.load_path += Dir[File.join(__dir__, "ordinalize_full/locales/*.yml")]
7
8
 
@@ -35,7 +36,11 @@ module OrdinalizeFull
35
36
 
36
37
  value
37
38
  else
38
- I18n.t("ordinalize_full.n_#{self}", throw: true)
39
+ begin
40
+ integer_to_long_form_ordinal
41
+ rescue ArgumentError
42
+ I18n.t("ordinalize_full.n_#{self}", throw: true)
43
+ end
39
44
  end
40
45
  rescue ArgumentError
41
46
  raise NotImplementedError, "Unknown locale #{I18n.locale}"
@@ -47,40 +52,106 @@ private
47
52
 
48
53
  def ordinalize_in_short(gender: :masculine, plurality: :singular)
49
54
  abs_number = to_i.abs
50
- suffix = case I18n.locale
51
- when :en
52
- if (11..13).cover?(abs_number % 100)
53
- "th"
54
- else
55
- case abs_number % 10
56
- when 1 then "st"
57
- when 2 then "nd"
58
- when 3 then "rd"
59
- else "th"
55
+ suffix = \
56
+ case I18n.locale
57
+ when :en
58
+ if (11..13).cover?(abs_number % 100)
59
+ "th"
60
+ else
61
+ case abs_number % 10
62
+ when 1 then "st"
63
+ when 2 then "nd"
64
+ when 3 then "rd"
65
+ else "th"
66
+ end
67
+ end
68
+ when :fr
69
+ self == 1 ? "er" : "ème"
70
+ when :it
71
+ "°"
72
+ when :nl
73
+ [8, 1, 0].include?(self % 100) || self % 100 > 19 ? "ste" : "de"
74
+ when :es
75
+ value = ordinalize_in_full(gender: gender, plurality: plurality)
76
+
77
+ if value.end_with?("er")
78
+ ".ᵉʳ"
79
+ elsif value.end_with?("a")
80
+ ".ᵃ"
81
+ elsif value.end_with?("o")
82
+ ".ᵒ"
83
+ elsif value.end_with?("os")
84
+ ".ᵒˢ"
85
+ elsif value.end_with?("as")
86
+ ".ᵃˢ"
60
87
  end
61
88
  end
62
- when :fr
63
- self == 1 ? "er" : "ème"
64
- when :it
65
- "°"
66
- when :nl
67
- [8, 1, 0].include?(self % 100) || self % 100 > 19 ? "ste" : "de"
68
- when :es
69
- value = ordinalize_in_full(gender: gender, plurality: plurality)
70
-
71
- if value.end_with?("er")
72
- ".ᵉʳ"
73
- elsif value.end_with?("a")
74
- ".ᵃ"
75
- elsif value.end_with?("o")
76
- ".ᵒ"
77
- elsif value.end_with?("os")
78
- ".ᵒˢ"
79
- elsif value.end_with?("as")
80
- ".ᵃˢ"
89
+
90
+ [self, suffix].join
91
+ end
92
+
93
+ # Build the long form of a given number. In this context, it is used for every digit except the last two.
94
+ # @param number [Integer] - A number to write in long form
95
+ # @return [String] - The long form of a number
96
+ def number_to_word(number)
97
+ if number.zero?
98
+ I18n.t("long_form.simple.ones.n_0", throw: true)
99
+ elsif number < 20
100
+ I18n.t("long_form.simple.ones.n_#{number}", throw: true)
101
+ elsif number < 100
102
+ [
103
+ I18n.t("long_form.simple.tens.n_#{number / 10}", throw: true),
104
+ (number % 10).zero? ? "" : "-#{I18n.t("long_form.simple.ones.n_#{number % 10}", throw: true)}"
105
+ ].join
106
+ elsif number < 1000
107
+ [
108
+ I18n.t("long_form.simple.ones.n_#{number / 100}", throw: true),
109
+ " ",
110
+ I18n.t("long_form.simple.hundred", throw: true),
111
+ (number % 100).zero? ? "" : " and #{number_to_word(number % 100)}"
112
+ ].join
113
+ else
114
+ i = 0
115
+ meow = number
116
+ while meow >= 1000
117
+ meow /= 1000
118
+ i += 1
81
119
  end
120
+ the_one_tenth = number % ((10**(3 * i)))
121
+ [
122
+ number_to_word(meow),
123
+ " ",
124
+ i.positive? ? I18n.t("long_form.simple.larger.n_#{i}", throw: true) : "",
125
+ the_one_tenth.zero? ? "" : " #{number_to_word(the_one_tenth)}"
126
+ ].join
82
127
  end
128
+ end
83
129
 
84
- [self, suffix].join
130
+ # Builds the ordinalized version of a number. Specific to english. Really only the two least significant digits are
131
+ # ordinalized, and the rest are just in long format
132
+ # @param number [Integer] - A number to ordinalize in long form
133
+ # @return [String] - The long form of a number as an ordinal
134
+ def number_to_ordinal_word(number)
135
+ if number.zero?
136
+ I18n.t("long_form.ordinal.ones.n_0", throw: true)
137
+ elsif number < 20
138
+ I18n.t("long_form.ordinal.ones.n_#{number}", throw: true)
139
+ elsif number < 100 && (number % 10).zero?
140
+ I18n.t("long_form.ordinal.tens.n_#{number / 10}", throw: true)
141
+ elsif number < 100
142
+ "#{number_to_word(number - (number % 10))}-#{I18n.t("long_form.ordinal.ones.n_#{number % 10}", throw: true)}"
143
+ elsif number >= 100 && (number % 100).zero?
144
+ "#{number_to_word(number - (number % 100))}th"
145
+ else
146
+ "#{number_to_word(number - (number % 100))} and #{number_to_ordinal_word((number % 100))}"
147
+ end
148
+ end
149
+
150
+ # Builds the long form ordinal of an integer
151
+ # @return [String] - The long form ordinal of an integer (including negative)
152
+ def integer_to_long_form_ordinal
153
+ return "#{I18n.t('long_form.negative', throw: true)} #{number_to_ordinal_word(-self)}" if negative?
154
+
155
+ number_to_ordinal_word(self)
85
156
  end
86
157
  end
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ordinalize_full"
8
- spec.version = "3.0.0"
8
+ spec.version = "3.1.0"
9
9
  spec.authors = ["Cédric Félizard"]
10
10
  spec.email = ["cedric@felizard.fr"]
11
11
  spec.summary = "Turns a number into an ordinal string such as first, second, third or 1st, 2nd, 3rd."
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/infertux/ordinalize_full"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files`.split($/) # rubocop:disable Style/SpecialGlobalVars
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.require_paths = ["lib"]
19
19
 
@@ -22,7 +22,6 @@ Gem::Specification.new do |spec|
22
22
  spec.add_dependency "i18n", "~> 1.8"
23
23
 
24
24
  spec.add_development_dependency "bundler", ">= 1.5"
25
- spec.add_development_dependency "cane"
26
25
  spec.add_development_dependency "rake"
27
26
  spec.add_development_dependency "rspec", "~> 3"
28
27
  spec.add_development_dependency "rubocop"
@@ -8,10 +8,18 @@ describe OrdinalizeFull do
8
8
  before { I18n.locale = :en }
9
9
 
10
10
  specify { expect(1.ordinalize_in_full).to eq("first") }
11
- specify { expect(42.ordinalize_in_full).to eq("forty second") }
11
+ specify { expect(42.ordinalize_in_full).to eq("forty-second") }
12
+ specify { expect(2023.ordinalize_in_full).to eq("two thousand and twenty-third") }
13
+ specify { expect(2_147_483_647.ordinalize_in_full).to eq("two billion one hundred and forty-seven million four hundred and eighty-three thousand six hundred and forty-seventh") } # rubocop:disable Layout/LineLength
14
+
15
+ it "converts any number" do
16
+ 10.times do
17
+ expect { rand(1_000_000).ordinalize_in_full }.not_to raise_error
18
+ end
19
+ end
12
20
 
13
- it "raises with unknown numbers" do
14
- expect { 101.ordinalize_in_full }.to raise_error(NotImplementedError)
21
+ it "handles negatives too" do
22
+ expect(-273.ordinalize_in_full).to eq("negative two hundred and seventy-third")
15
23
  end
16
24
  end
17
25
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ordinalize_full
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cédric Félizard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-17 00:00:00.000000000 Z
11
+ date: 2023-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.5'
41
- - !ruby/object:Gem::Dependency
42
- name: cane
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: rake
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -167,7 +153,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
153
  - !ruby/object:Gem::Version
168
154
  version: '0'
169
155
  requirements: []
170
- rubygems_version: 3.3.26
156
+ rubygems_version: 3.4.10
171
157
  signing_key:
172
158
  specification_version: 4
173
159
  summary: Turns a number into an ordinal string such as first, second, third or 1st,