Skip to content

Commit 4f75840

Browse files
committed
Add Inflection rules for String#humanize. [#535 state:resolved] [dcmanges]
Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
1 parent 3a95ee7 commit 4f75840

File tree

3 files changed

+51
-8
lines changed

3 files changed

+51
-8
lines changed

activesupport/CHANGELOG

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
*Edge*
22

3+
* Add Inflection rules for String#humanize. #535 [dcmanges]
4+
5+
ActiveSupport::Inflector.inflections do |inflect|
6+
inflect.human(/_cnt$/i, '\1_count')
7+
end
8+
9+
'jargon_cnt'.humanize # => 'Jargon count'
10+
311
* TimeWithZone: when crossing DST boundary, treat Durations of days, months or years as variable-length, and all other values as absolute length. A time + 24.hours will advance exactly 24 hours, but a time + 1.day will advance 23-25 hours, depending on the day. Ensure consistent behavior across all advancing methods [Geoff Buesing]
412

513
* Added TimeZone #=~, to support matching zones by regex in time_zone_select. #195 [Ernie Miller]

activesupport/lib/active_support/inflector.rb

+18-4
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ module Inflector
3030
class Inflections
3131
include Singleton
3232

33-
attr_reader :plurals, :singulars, :uncountables
33+
attr_reader :plurals, :singulars, :uncountables, :humans
3434

3535
def initialize
36-
@plurals, @singulars, @uncountables = [], [], []
36+
@plurals, @singulars, @uncountables, @humans = [], [], [], []
3737
end
3838

3939
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
@@ -76,9 +76,20 @@ def uncountable(*words)
7676
(@uncountables << words).flatten!
7777
end
7878

79+
# Specifies a humanized form of a string by a regular expression rule or by a string mapping.
80+
# When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
81+
# When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
82+
#
83+
# Examples:
84+
# human /_cnt$/i, '\1_count'
85+
# human "legacy_col_person_name", "Name"
86+
def human(rule, replacement)
87+
@humans.insert(0, [rule, replacement])
88+
end
89+
7990
# Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
8091
# Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
81-
# <tt>:singulars</tt>, <tt>:uncountables</tt>.
92+
# <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
8293
#
8394
# Examples:
8495
# clear :all
@@ -209,7 +220,10 @@ def dasherize(underscored_word)
209220
# "employee_salary" # => "Employee salary"
210221
# "author_id" # => "Author"
211222
def humanize(lower_case_and_underscored_word)
212-
lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
223+
result = lower_case_and_underscored_word.to_s.dup
224+
225+
inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
226+
result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
213227
end
214228

215229
# Removes the module part from the expression in the string.

activesupport/test/inflector_test.rb

+25-4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,23 @@ def test_humanize
110110
end
111111
end
112112

113+
def test_humanize_by_rule
114+
ActiveSupport::Inflector.inflections do |inflect|
115+
inflect.human(/_cnt$/i, '\1_count')
116+
inflect.human(/^prefx_/i, '\1')
117+
end
118+
assert_equal("Jargon count", ActiveSupport::Inflector.humanize("jargon_cnt"))
119+
assert_equal("Request", ActiveSupport::Inflector.humanize("prefx_request"))
120+
end
121+
122+
def test_humanize_by_string
123+
ActiveSupport::Inflector.inflections do |inflect|
124+
inflect.human("col_rpted_bugs", "Reported bugs")
125+
end
126+
assert_equal("Reported bugs", ActiveSupport::Inflector.humanize("col_rpted_bugs"))
127+
assert_equal("Col rpted bugs", ActiveSupport::Inflector.humanize("COL_rpted_bugs"))
128+
end
129+
113130
def test_constantize
114131
assert_nothing_raised { assert_equal Ace::Base::Case, ActiveSupport::Inflector.constantize("Ace::Base::Case") }
115132
assert_nothing_raised { assert_equal Ace::Base::Case, ActiveSupport::Inflector.constantize("::Ace::Base::Case") }
@@ -148,7 +165,7 @@ def test_underscore_to_lower_camel
148165
end
149166
end
150167

151-
%w{plurals singulars uncountables}.each do |inflection_type|
168+
%w{plurals singulars uncountables humans}.each do |inflection_type|
152169
class_eval "
153170
def test_clear_#{inflection_type}
154171
cached_values = ActiveSupport::Inflector.inflections.#{inflection_type}
@@ -160,25 +177,29 @@ def test_clear_#{inflection_type}
160177
end
161178

162179
def test_clear_all
163-
cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables
180+
cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables, ActiveSupport::Inflector.inflections.humans
164181
ActiveSupport::Inflector.inflections.clear :all
165182
assert ActiveSupport::Inflector.inflections.plurals.empty?
166183
assert ActiveSupport::Inflector.inflections.singulars.empty?
167184
assert ActiveSupport::Inflector.inflections.uncountables.empty?
185+
assert ActiveSupport::Inflector.inflections.humans.empty?
168186
ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0]
169187
ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1]
170188
ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2]
189+
ActiveSupport::Inflector.inflections.instance_variable_set :@humans, cached_values[3]
171190
end
172191

173192
def test_clear_with_default
174-
cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables
193+
cached_values = ActiveSupport::Inflector.inflections.plurals, ActiveSupport::Inflector.inflections.singulars, ActiveSupport::Inflector.inflections.uncountables, ActiveSupport::Inflector.inflections.humans
175194
ActiveSupport::Inflector.inflections.clear
176195
assert ActiveSupport::Inflector.inflections.plurals.empty?
177196
assert ActiveSupport::Inflector.inflections.singulars.empty?
178197
assert ActiveSupport::Inflector.inflections.uncountables.empty?
198+
assert ActiveSupport::Inflector.inflections.humans.empty?
179199
ActiveSupport::Inflector.inflections.instance_variable_set :@plurals, cached_values[0]
180200
ActiveSupport::Inflector.inflections.instance_variable_set :@singulars, cached_values[1]
181201
ActiveSupport::Inflector.inflections.instance_variable_set :@uncountables, cached_values[2]
202+
ActiveSupport::Inflector.inflections.instance_variable_set :@humans, cached_values[3]
182203
end
183204

184205
Irregularities.each do |irregularity|
@@ -217,7 +238,7 @@ def test_clear_with_default
217238
end
218239
end
219240

220-
{ :singulars => :singular, :plurals => :plural, :uncountables => :uncountable }.each do |scope, method|
241+
{ :singulars => :singular, :plurals => :plural, :uncountables => :uncountable, :humans => :human }.each do |scope, method|
221242
ActiveSupport::Inflector.inflections do |inflect|
222243
define_method("test_clear_inflections_with_#{scope}") do
223244
# save the inflections

0 commit comments

Comments
 (0)