dry-inflector 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c399013c00255e60a1adc6c44984238b5b331a9d8432489a189131ac0e7545b3
4
- data.tar.gz: a59e33a3ca433c23bd0248413374b21da91a43d2ac666b1e30033f1e04d144de
3
+ metadata.gz: 7cccc4cd092473c4c5dfefd8830e97c987fbb6cd6039b6253fd973a0b4d5b8ac
4
+ data.tar.gz: 6aca715e9ab5497c0f325691783e92a10035b27a3e6fdf483df38b7fb306d6ad
5
5
  SHA512:
6
- metadata.gz: 9e6ef7a7de2938808c7f01344335d370793a6d0cfa64d0afa42a6481f60cf84bc66ae8080f32706908421d3c13bb5650ab8368fe881bd5c268a3eaafcd9f1da6
7
- data.tar.gz: 30cf65fc5594d8352b1d43b113f98b37b0e01b88e20301c4d02e11116030fcc16acb174c730953876c7337ada68c57b882c3f061a36788511a2763041374585e
6
+ metadata.gz: 2c9c21e1611fe3bafd8cf7e303b5030c1ba3f777fd397a58f2dfba77f8be05b49fdece384e49d82d43043e388ca3fc1f1c6c84508fdfdac02ce9851edfee1dba
7
+ data.tar.gz: c83c9d597c611194642fe6aed04b3c5f6e37ec9fa212b3501a13c93010305f9c339875a09ba123b8a97fa89f567e90c110af9ac76317f4c16749a5e91601b57e
@@ -2,10 +2,20 @@
2
2
 
3
3
  Inflector for Ruby
4
4
 
5
+ ## v0.1.2 - to be released
6
+
7
+ ### Added
8
+
9
+ - [Gustavo Caso & Nikita Shilnikov] Added support for acronyms
10
+
11
+ [Compare v0.1.1...master](https://github.com/dry-rb/dry-inflector/compare/v0.1.1...master)
12
+
5
13
  ## v0.1.1 - 2017-11-18
6
14
  ### Fixed
7
15
  - [Luca Guidi & Abinoam P. Marques Jr.] Ensure `Dry::Inflector#ordinalize` to work for all the numbers from 0 to 100
8
16
 
17
+ [Compare v0.1.0...v0.1.1](https://github.com/dry-rb/dry-inflector/compare/v0.1.0...v0.1.1)
18
+
9
19
  ## v0.1.0 - 2017-11-17
10
20
  ### Added
11
21
  - [Luca Guidi] Introduced `Dry::Inflector#pluralize`
@@ -47,7 +47,15 @@ module Dry
47
47
  # inflector = Dry::Inflector.new
48
48
  # inflector.camelize("dry/inflector") # => "Dry::Inflector"
49
49
  def camelize(input)
50
- input.to_s.gsub(/\/(.?)/) { "::#{Regexp.last_match(1).upcase}" }.gsub(/(?:\A|_)(.)/) { Regexp.last_match(1).upcase }
50
+ input = input.to_s.dup
51
+ input.sub!(/^[a-z\d]*/) { |match| inflections.acronyms.apply_to(match) }
52
+ input.gsub!(%r{(?:_|(/))([a-z\d]*)}i) do
53
+ m1 = Regexp.last_match(1)
54
+ m2 = Regexp.last_match(2)
55
+ "#{m1}#{inflections.acronyms.apply_to(m2)}"
56
+ end
57
+ input.gsub!("/", "::")
58
+ input
51
59
  end
52
60
 
53
61
  # Find a constant with the name specified in the argument string
@@ -134,10 +142,13 @@ module Dry
134
142
  def humanize(input)
135
143
  input = input.to_s
136
144
  result = inflections.humans.apply_to(input)
137
- result.gsub!(/_id\z/, "")
145
+ result.chomp!("_id")
138
146
  result.tr!("_", " ")
139
- result.capitalize!
140
- result
147
+ match = /(?<separator>\W)/.match(result)
148
+ separator = match ? match[:separator] : DEFAULT_SEPARATOR
149
+ result.split(separator).map.with_index { |word, index|
150
+ inflections.acronyms.apply_to(word, index.zero?)
151
+ }.join(separator)
141
152
  end
142
153
 
143
154
  # Creates a foreign key name
@@ -151,7 +162,7 @@ module Dry
151
162
  # inflector = Dry::Inflector.new
152
163
  # inflector.foreign_key("Message") => "message_id"
153
164
  def foreign_key(input)
154
- "#{underscorize(demodulize(input))}_id"
165
+ "#{underscore(demodulize(input))}_id"
155
166
  end
156
167
 
157
168
  # Ordinalize a number
@@ -237,7 +248,7 @@ module Dry
237
248
  # inflector.tableize("Book") # => "books"
238
249
  def tableize(input)
239
250
  input = input.to_s.gsub(/::/, "_")
240
- pluralize(underscorize(input))
251
+ pluralize(underscore(input))
241
252
  end
242
253
 
243
254
  # Underscore a string
@@ -253,8 +264,17 @@ module Dry
253
264
  # inflector = Dry::Inflector.new
254
265
  # inflector.underscore("dry-inflector") # => "dry_inflector"
255
266
  def underscore(input)
256
- input = input.to_s.gsub(/::/, "/")
257
- underscorize(input)
267
+ input = input.to_s.gsub("::", "/")
268
+ input.gsub!(inflections.acronyms.regex) do
269
+ m1 = Regexp.last_match(1)
270
+ m2 = Regexp.last_match(2)
271
+ "#{m1 ? '_' : '' }#{m2.downcase}"
272
+ end
273
+ input.gsub!(/([A-Z\d]+)([A-Z][a-z])/, '\1_\2')
274
+ input.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
275
+ input.tr!("-", "_")
276
+ input.downcase!
277
+ input
258
278
  end
259
279
 
260
280
  # Check if the input is an uncountable word
@@ -274,18 +294,12 @@ module Dry
274
294
  # @api private
275
295
  ORDINALIZE_TH = (11..13).each_with_object({}) { |n, ret| ret[n] = true }.freeze
276
296
 
277
- # @since 0.1.0
297
+ # @since 0.1.2
278
298
  # @api private
279
- attr_reader :inflections
299
+ DEFAULT_SEPARATOR = " "
280
300
 
281
301
  # @since 0.1.0
282
302
  # @api private
283
- def underscorize(input)
284
- input.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
285
- input.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
286
- input.tr!("-", "_")
287
- input.downcase!
288
- input
289
- end
303
+ attr_reader :inflections
290
304
  end
291
305
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dry
4
+ class Inflector
5
+ # A set of acronyms
6
+ #
7
+ # @since 0.1.2
8
+ # @api private
9
+ class Acronyms
10
+ attr_reader :regex
11
+
12
+ # @since 0.1.2
13
+ # @api private
14
+ def initialize
15
+ @rules = {}
16
+ define_regex_patterns
17
+ end
18
+
19
+ # @since 0.1.2
20
+ # @api private
21
+ def apply_to(word, capitalize = true)
22
+ @rules[word.downcase] || (capitalize ? word.capitalize : word)
23
+ end
24
+
25
+ # @since 0.1.2
26
+ # @api private
27
+ def add(rule, replacement)
28
+ @rules[rule] = replacement
29
+ define_regex_patterns
30
+ end
31
+
32
+ private
33
+
34
+ # @since 0.1.2
35
+ # @api private
36
+ def define_regex_patterns
37
+ regex = @rules.empty? ? /(?=a)b/ : /#{@rules.values.join("|")}/
38
+ @regex = /(?:(?<=([A-Za-z\d]))|\b)(#{regex})(?=\b|[^a-z])/
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "set"
4
4
  require "dry/inflector/rules"
5
+ require "dry/inflector/acronyms"
5
6
 
6
7
  module Dry
7
8
  class Inflector
@@ -57,6 +58,14 @@ module Dry
57
58
  # @api private
58
59
  attr_reader :humans
59
60
 
61
+ # Acronyms
62
+ #
63
+ # @return [Dry::Inflector::Acronyms]
64
+ #
65
+ # @since 0.1.2
66
+ # @api private
67
+ attr_reader :acronyms
68
+
60
69
  # Instantiate the rules
61
70
  #
62
71
  # @return [Dry::Inflector::Inflections]
@@ -69,6 +78,7 @@ module Dry
69
78
  @singulars = Rules.new
70
79
  @humans = Rules.new
71
80
  @uncountables = Set[]
81
+ @acronyms = Acronyms.new
72
82
 
73
83
  yield(self) if block_given?
74
84
  end
@@ -160,6 +170,28 @@ module Dry
160
170
  uncountables.merge(words.flatten)
161
171
  end
162
172
 
173
+ # Add one or more acronyms
174
+ #
175
+ # Acronyms affect how basic operations are performed, such
176
+ # as camelize/underscore.
177
+ #
178
+ # @param words [Array<String>] a list of acronyms
179
+ #
180
+ # @since 0.1.2
181
+ #
182
+ # @example
183
+ # require "dry/inflector"
184
+ #
185
+ # inflector = Dry::Inflector.new do |inflections|
186
+ # inflections.acronym "HTML"
187
+ # end
188
+ #
189
+ # inflector.camelize("html") # => "HTML"
190
+ # inflector.underscore("HTMLIsFun") # => "html_is_fun"
191
+ def acronym(*words)
192
+ words.each { |word| @acronyms.add(word.downcase, word) }
193
+ end
194
+
163
195
  # Add a custom humanize rule
164
196
  #
165
197
  # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
@@ -18,6 +18,7 @@ module Dry
18
18
  singular(inflect)
19
19
  irregular(inflect)
20
20
  uncountable(inflect)
21
+ acronyms(inflect)
21
22
  end
22
23
 
23
24
  # @since 0.1.0
@@ -101,7 +102,13 @@ module Dry
101
102
  inflect.uncountable(%w[hovercraft moose deer milk rain Swiss grass equipment information rice money species series fish sheep jeans])
102
103
  end
103
104
 
104
- private_class_method :plural, :singular, :irregular, :uncountable
105
+ # @since 0.1.2
106
+ # @api private
107
+ def self.acronyms(inflect)
108
+ inflect.acronym(*%w[JSON HTTP OpenSSL HMAC])
109
+ end
110
+
111
+ private_class_method :plural, :singular, :irregular, :uncountable, :acronyms
105
112
  end
106
113
  # rubocop:enable Metrics/MethodLength
107
114
  # rubocop:enable Metrics/AbcSize
@@ -3,6 +3,6 @@
3
3
  module Dry
4
4
  class Inflector
5
5
  # @since 0.1.0
6
- VERSION = "0.1.1"
6
+ VERSION = "0.1.2"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-inflector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2017-11-18 00:00:00.000000000 Z
13
+ date: 2018-04-25 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - README.md
83
83
  - dry-inflector.gemspec
84
84
  - lib/dry/inflector.rb
85
+ - lib/dry/inflector/acronyms.rb
85
86
  - lib/dry/inflector/inflections.rb
86
87
  - lib/dry/inflector/inflections/defaults.rb
87
88
  - lib/dry/inflector/rules.rb
@@ -107,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
108
  version: '0'
108
109
  requirements: []
109
110
  rubyforge_project:
110
- rubygems_version: 2.7.1
111
+ rubygems_version: 2.7.6
111
112
  signing_key:
112
113
  specification_version: 4
113
114
  summary: DRY Inflector