roda-tags 0.1.1 → 0.2.0

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.
@@ -1,6 +1,8 @@
1
- # The inflector extension adds inflection instance methods to String, which allows the easy
1
+ # frozen_string_literal: false
2
+
3
+ # The inflector extension adds inflection instance methods to String, which allows the easy
2
4
  # transformation of words from singular to plural, class names to table names, modularized class
3
- # names to ones without, and class names to foreign keys. It exists for
5
+ # names to ones without, and class names to foreign keys. It exists for
4
6
  # backwards compatibility to legacy Sequel code.
5
7
  #
6
8
  # To load the extension:
@@ -17,16 +19,21 @@ class String
17
19
  # inflect.uncountable "equipment"
18
20
  # end
19
21
  #
20
- # New rules are added at the top. So in the example above, the irregular rule for octopus will
21
- # now be the first of the pluralization and singularization rules that is runs. This guarantees
22
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will
23
+ # now be the first of the pluralization and singularization rules that is runs. This guarantees
22
24
  # that your rules run before any of the rules that may already have been loaded.
25
+ #
23
26
  module Inflections
27
+ # Array to store plural inflection rules
24
28
  @plurals = []
29
+ # Array to store singular inflection rules
25
30
  @singulars = []
31
+ # Array to store words that are the same in singular and plural forms
26
32
  @uncountables = []
27
-
33
+
28
34
  # Proc that is instance evaled to create the default inflections for both the
29
35
  # model inflector and the inflector extension.
36
+ # rubocop:disable Metrics/BlockLength
30
37
  DEFAULT_INFLECTIONS_PROC = proc do
31
38
  plural(/$/, 's')
32
39
  plural(/s$/i, 's')
@@ -66,29 +73,45 @@ class String
66
73
  irregular('quiz', 'quizzes')
67
74
  irregular('testis', 'testes')
68
75
 
69
- uncountable(%w(equipment information rice money species series fish sheep news))
76
+ uncountable(%w[equipment information rice money species series fish sheep news])
70
77
  end
71
-
72
-
78
+ # rubocop:enable Metrics/BlockLength
79
+
73
80
  class << self
74
- # Array of 2 element arrays, first containing a regex, and the second containing a
75
- # substitution pattern, used for plurization.
81
+ # An Array that stores the pluralization rules.
82
+ # Each rule is a 2-element array containing:
83
+ # - A regular expression pattern for matching words to pluralize
84
+ # - A substitution pattern (e.g. '\1es') for transforming the match into plural form
85
+ # Rules are processed in reverse order, so newer rules take precedence.
76
86
  attr_reader :plurals
77
87
 
78
- # Array of 2 element arrays, first containing a regex, and the second containing a
79
- # substitution pattern, used for singularization.
88
+ # An Array that stores the singularization rules.
89
+ # Each rule is a 2-element array containing:
90
+ # - A regular expression pattern for matching plural words
91
+ # - A substitution pattern (e.g. '\1y') for transforming the match into singular form
92
+ # Rules are processed in reverse order, so newer rules take precedence.
80
93
  attr_reader :singulars
81
94
 
82
- # Array of strings for words were the singular form is the same as the plural form
95
+ # An Array of uncountable word strings that should not be inflected.
96
+ # These words have the same form in both singular and plural.
97
+ # Examples: 'fish', 'money', 'species'
83
98
  attr_reader :uncountables
84
99
  end
85
100
 
86
- # Clears the loaded inflections within a given scope (default is :all). Give the scope as a
87
- # symbol of the inflection type, the options are: :plurals, :singulars, :uncountables
101
+ # Clear inflection rules in a given scope.
102
+ # If scope is not specified, all inflection rules will be cleared.
103
+ # Passing :plurals, :singulars, or :uncountables will clear only that specific type of rule.
104
+ #
105
+ # @param scope [Symbol] The scope of rules to clear. Can be :all (default),
106
+ # :plurals, :singulars, or :uncountables
107
+ # @return [Array] An empty array
108
+ #
109
+ # @example Clear all inflection rules
110
+ # String.inflections.clear
111
+ #
112
+ # @example Clear only plural rules
113
+ # String.inflections.clear(:plurals)
88
114
  #
89
- # Examples:
90
- # clear :all
91
- # clear :plurals
92
115
  def self.clear(scope = :all)
93
116
  case scope
94
117
  when :all
@@ -96,219 +119,370 @@ class String
96
119
  @singulars = []
97
120
  @uncountables = []
98
121
  else
99
- instance_variable_set("@#{scope}", [])
122
+ instance_variable_set(:"@#{scope}", [])
100
123
  end
101
124
  end
102
125
 
103
- # Specifies a new irregular that applies to both pluralization and singularization at the same
104
- # time. This can only be used for strings, not regular expressions. You simply pass the
105
- # irregular in singular and plural form.
126
+ # Specifies a new irregular inflection rule that transforms between singular and plural forms.
127
+ # This method creates rules for both pluralization and singularization simultaneously.
128
+ # Unlike regular inflection rules, this only works with literal strings, not regexp.
129
+ #
130
+ # @param singular [String] The singular form of the word
131
+ # @param plural [String] The plural form of the word
132
+ #
133
+ # @example
134
+ # irregular('person', 'people') # Creates rules to transform person <-> people
135
+ # irregular('child', 'children') # Creates rules to transform child <-> children
106
136
  #
107
- # Examples:
108
- # irregular 'octopus', 'octopi'
109
- # irregular 'person', 'people'
110
137
  def self.irregular(singular, plural)
111
- plural(Regexp.new("(#{singular[0, 1]})#{singular[1..-1]}$", 'i'), '\1' + plural[1..-1])
112
- singular(Regexp.new("(#{plural[0, 1]})#{plural[1..-1]}$", 'i'), '\1' + singular[1..-1])
138
+ plural(Regexp.new("(#{singular[0, 1]})#{singular[1..]}$", 'i'), "\\1#{plural[1..]}")
139
+ singular(Regexp.new("(#{plural[0, 1]})#{plural[1..]}$", 'i'), "\\1#{singular[1..]}")
113
140
  end
114
141
 
115
- # Specifies a new pluralization rule and its replacement. The rule can either be a string or a
116
- # regular expression. The replacement should always be a string that may include references to
117
- # the matched data from the rule.
142
+ # Specifies a new pluralization rule to transform singular words into plural forms.
143
+ # Adds the rule to the beginning of the rules array so it takes precedence over existing rules.
144
+ #
145
+ # @param rule [Regexp, String] Pattern to match words that should be pluralized
146
+ # @param replacement [String] Template for constructing the plural form, can reference
147
+ # captured groups from the rule pattern using \1, \2 etc.
148
+ # @return [Array] The updated array of plural rules
149
+ #
150
+ # @example Add rule to pluralize words ending in 'y'
151
+ # plural(/([^aeiou])y$/i, '\1ies') # changes 'fly' to 'flies'
118
152
  #
119
- # Example:
120
- # plural(/(x|ch|ss|sh)$/i, '\1es')
121
153
  def self.plural(rule, replacement)
122
154
  @plurals.insert(0, [rule, replacement])
123
155
  end
124
156
 
125
- # Specifies a new singularization rule and its replacement. The rule can either be a string or
126
- # a regular expression. The replacement should always be a string that may include references
127
- # to the matched data from the rule.
157
+ # Specifies a new singularization rule to transform plural words into singular forms.
158
+ # Adds the rule to the beginning of the rules array so it takes precedence over existing rules.
159
+ #
160
+ # @param rule [Regexp, String] Pattern to match words that should be singularized
161
+ # @param replacement [String] Template for constructing the singular form, can reference
162
+ # captured groups from the rule pattern using \1, \2 etc.
163
+ #
164
+ # @return [Array] The updated array of singular rules
165
+ #
166
+ # @example Add rule to singularize words ending in 'ies'
167
+ # singular(/([^aeiou])ies$/i, '\1y') # changes 'flies' to 'fly'
128
168
  #
129
- # Example:
130
- # singular(/([^aeiouy]|qu)ies$/i, '\1y')
131
169
  def self.singular(rule, replacement)
132
170
  @singulars.insert(0, [rule, replacement])
133
171
  end
134
172
 
135
- # Add uncountable words that shouldn't be attempted inflected.
173
+ # Adds words that have the same singular and plural form to the uncountables list.
174
+ # These words will be skipped by the inflector and returned unchanged.
175
+ #
176
+ # @param words [Array<String>] One or more words to mark as uncountable
177
+ # @return [Array] The flattened array of all uncountable words
178
+ #
179
+ # @example Add a single uncountable word
180
+ # uncountable "fish"
181
+ #
182
+ # @example Add multiple uncountable words
183
+ # uncountable "rice", "equipment"
184
+ #
185
+ # @example Add an array of uncountable words
186
+ # uncountable %w(sheep species)
136
187
  #
137
- # Examples:
138
- # uncountable "money"
139
- # uncountable "money", "information"
140
- # uncountable %w( money information rice )
141
188
  def self.uncountable(*words)
142
189
  (@uncountables << words).flatten!
143
190
  end
144
191
 
145
- # Sequel.require('default_inflections', 'model')
146
- # instance_eval(&Sequel::DEFAULT_INFLECTIONS_PROC)
147
- # Sequel.require('default_inflections', 'model')
148
- instance_eval(&DEFAULT_INFLECTIONS_PROC)
192
+ # Execute the default inflection rules defined in DEFAULT_INFLECTIONS_PROC
193
+ # This sets up the basic plural/singular transformations and irregular/uncountable words
194
+ # that the inflector will use by default
195
+ instance_exec(&DEFAULT_INFLECTIONS_PROC)
149
196
  end
150
197
 
151
- # Yield the Inflections module if a block is given, and return
152
- # the Inflections module.
198
+ # Provides access to the Inflections module for defining custom inflection rules.
199
+ # If a block is given, yields the Inflections module to the block.
200
+ # Always returns the Inflections module.
201
+ #
202
+ # @yield [Inflections] The Inflections module if a block is given
203
+ #
204
+ # @return [Inflections] The Inflections module
205
+ #
206
+ # @example Define custom inflection rules
207
+ # String.inflections do |inflect|
208
+ # inflect.plural /^(ox)$/i, '\1\2en'
209
+ # inflect.singular /^(ox)en/i, '\1'
210
+ # end
211
+ #
153
212
  def self.inflections
154
- yield Inflections if block_given?
213
+ yield Inflections if defined?(yield)
155
214
  Inflections
156
215
  end
157
216
 
158
- # By default, camelize converts the string to UpperCamelCase. If the argument to camelize
159
- # is set to :lower then camelize produces lowerCamelCase.
217
+ # Converts the string to CamelCase format.
218
+ # - Replaces forward slashes with double colons (e.g. 'foo/bar' -> 'Foo::Bar')
219
+ # - Converts underscores to camelized format (e.g. 'foo_bar' -> 'FooBar')
160
220
  #
161
- # camelize will also convert '/' to '::' which is useful for converting paths to namespaces
221
+ # @param first_letter_in_uppercase [Symbol] Whether first letter should be
222
+ # uppercase (:upper) or lowercase (:lower)
162
223
  #
163
- # Examples
224
+ # @return [String] The camelized string
225
+ #
226
+ # @example Convert to UpperCamelCase
164
227
  # "active_record".camelize #=> "ActiveRecord"
228
+ #
229
+ # @example Convert to lowerCamelCase
165
230
  # "active_record".camelize(:lower) #=> "activeRecord"
231
+ #
232
+ # @example Convert path to namespace
166
233
  # "active_record/errors".camelize #=> "ActiveRecord::Errors"
167
- # "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
234
+ #
168
235
  def camelize(first_letter_in_uppercase = :upper)
169
- s = gsub(%r{/(.?)}) { |x| "::#{x[-1..-1].upcase unless x == '/'}" }
170
- .gsub(/(^|_)(.)/) { |x| x[-1..-1].upcase }
236
+ s = gsub(%r{/(.?)}) { |x| "::#{x[-1..].upcase unless x == "/"}" }
237
+ .gsub(/(^|_)(.)/) { |x| x[-1..].upcase }
171
238
  s[0...1] = s[0...1].downcase unless first_letter_in_uppercase == :upper
172
239
  s
173
240
  end
174
- alias_method :camelcase, :camelize
241
+ alias camelcase camelize
175
242
 
176
- # Singularizes and camelizes the string. Also strips out all characters preceding
177
- # and including a period (".").
243
+ # Converts a string into a class name by removing any non-final period and subsequent characters,
244
+ # converting to singular form, and camelizing.
245
+ # Commonly used to obtain class name from table or file names.
246
+ #
247
+ # @return [String] A camelized singular form suitable for a class name
178
248
  #
179
- # Examples
249
+ # @example Convert database table name to class name
180
250
  # "egg_and_hams".classify #=> "EggAndHam"
181
- # "post".classify #=> "Post"
251
+ #
252
+ # @example Remove schema prefix
182
253
  # "schema.post".classify #=> "Post"
254
+ #
255
+ # @example Basic conversion
256
+ # "post".classify #=> "Post"
257
+ #
183
258
  def classify
184
259
  sub(/.*\./, '').singularize.camelize
185
260
  end
186
261
 
187
- # Constantize tries to find a declared constant with the name specified
188
- # in the string. It raises a NameError when the name is not in CamelCase
189
- # or is not initialized.
262
+ # Finds and returns a Ruby constant from a string name.
263
+ # The string must be a valid constant name in CamelCase format.
264
+ # Can handle namespaced constants using double colons (::).
265
+ # Raises NameError if the constant name is invalid or not defined.
190
266
  #
191
- # Examples
267
+ # @return [Object] The Ruby constant corresponding to the string name
268
+ #
269
+ # @raise [NameError] If string is not a valid constant name or constant is not defined
270
+ #
271
+ # @example Get Module class
192
272
  # "Module".constantize #=> Module
193
- # "Class".constantize #=> Class
273
+ #
274
+ # @example Get namespaced constant
275
+ # "ActiveRecord::Base".constantize #=> ActiveRecord::Base
276
+ #
277
+ # @example Invalid constant name
278
+ # "invalid_name".constantize #=> NameError: invalid_name is not a valid constant name!
279
+ #
194
280
  def constantize
195
- unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(self)
196
- raise(NameError, "#{inspect} is not a valid constant name!")
281
+ unless (m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(self))
282
+ raise(NameError, "#{inspect} is not a valid constant name!")
197
283
  end
198
- Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
284
+
285
+ # rubcop:disable Style/DocumentDynamicEvalDefinition
286
+ Object.module_eval("::#{m[1]}", __FILE__, __LINE__) # ::Post
287
+ # rubcop:enable Style/DocumentDynamicEvalDefinition
199
288
  end
200
289
 
201
- # Replaces underscores with dashes in the string.
290
+ # Replaces underscores (_) in a string with dashes (-).
291
+ # A helper method commonly used for URL slugs and CSS class names.
292
+ #
293
+ # @return [String] The string with underscores replaced by dashes
294
+ #
295
+ # @example
296
+ # "hello_world".dasherize #=> "hello-world"
297
+ # "foo_bar_baz".dasherize #=> "foo-bar-baz"
202
298
  #
203
- # Example
204
- # "puni_puni".dasherize #=> "puni-puni"
205
299
  def dasherize
206
300
  tr('_', '-')
207
301
  end
208
302
 
209
- # Removes the module part from the expression in the string
303
+ # Removes the module part from a fully-qualified Ruby constant name,
304
+ # returning just the rightmost portion after the last double colon (::).
305
+ #
306
+ # @return [String] The final constant name without any module namespacing
307
+ #
308
+ # @example Remove module namespace from fully-qualified name
309
+ # "ActiveRecord::Base::Table".demodulize #=> "Table"
310
+ #
311
+ # @example No change when no modules present
312
+ # "String".demodulize #=> "String"
210
313
  #
211
- # Examples
212
- # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
213
- # "Inflections".demodulize #=> "Inflections"
214
314
  def demodulize
215
315
  gsub(/^.*::/, '')
216
316
  end
217
317
 
218
- # Creates a foreign key name from a class name.
219
- # +use_underscore+ sets whether the method should put '_' between the name and 'id'.
318
+ # Creates a foreign key name from a class name by removing any module namespacing,
319
+ # underscoring the remaining name, and appending 'id'. The underscore before 'id'
320
+ # is optional.
321
+ #
322
+ # @param use_underscore [Boolean] Whether to include an underscore before 'id'
323
+ #
324
+ # @return [String] The foreign key name
220
325
  #
221
- # Examples
326
+ # @example Basic usage
222
327
  # "Message".foreign_key #=> "message_id"
223
- # "Message".foreign_key(false) #=> "messageid"
328
+ #
329
+ # @example Without underscore
330
+ # "Message".foreign_key(use_underscore: false) #=> "messageid"
331
+ #
332
+ # @example With namespaced class
224
333
  # "Admin::Post".foreign_key #=> "post_id"
225
- def foreign_key(use_underscore = true)
226
- "#{demodulize.underscore}#{'_' if use_underscore}id"
334
+ #
335
+ def foreign_key(use_underscore: true)
336
+ "#{demodulize.underscore}#{"_" if use_underscore}id"
227
337
  end
228
338
 
229
- # Capitalizes the first word and turns underscores into spaces and strips _id.
230
- # Like titleize, this is meant for creating pretty output.
339
+ # Converts a string into a more human-readable format by:
340
+ # - Removing any trailing '_id'
341
+ # - Converting underscores to spaces
342
+ # - Capitalizing the first letter
343
+ #
344
+ # @return [String] A human-friendly version of the string
345
+ #
346
+ # @example Convert a database column name
347
+ # "employee_salary".humanize #=> "Employee salary"
348
+ #
349
+ # @example Remove ID suffix
350
+ # "user_id".humanize #=> "User"
351
+ #
352
+ # @example Basic conversion
353
+ # "hello_world".humanize #=> "Hello world"
231
354
  #
232
- # Examples
233
- # "employee_salary" #=> "Employee salary"
234
- # "author_id" #=> "Author"
235
355
  def humanize
236
356
  gsub(/_id$/, '').tr('_', ' ').capitalize
237
357
  end
238
358
 
239
- # Returns the plural form of the word in the string.
359
+ # Transforms a word into its plural form according to standard English language rules
360
+ # and any custom rules defined through String.inflections.
240
361
  #
241
- # Examples
362
+ # If the word is in the uncountable list (e.g. "sheep", "fish"), returns it unchanged.
363
+ # Otherwise applies plural transformation rules in order until one matches.
364
+ #
365
+ # @return [String] The plural form of the word
366
+ #
367
+ # @example Basic pluralization
242
368
  # "post".pluralize #=> "posts"
243
369
  # "octopus".pluralize #=> "octopi"
244
- # "sheep".pluralize #=> "sheep"
245
- # "words".pluralize #=> "words"
370
+ #
371
+ # @example Uncountable words
372
+ # "fish".pluralize #=> "fish"
373
+ #
374
+ # @example Complex phrases
246
375
  # "the blue mailman".pluralize #=> "the blue mailmen"
247
376
  # "CamelOctopus".pluralize #=> "CamelOctopi"
377
+ #
248
378
  def pluralize
249
379
  result = dup
250
380
  unless Inflections.uncountables.include?(downcase)
251
- Inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
381
+ Inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
252
382
  end
253
383
  result
254
384
  end
255
385
 
256
- # The reverse of pluralize, returns the singular form of a word in a string.
386
+ # Transforms a word into its singular form according to standard English language rules
387
+ # and any custom rules defined through String.inflections.
257
388
  #
258
- # Examples
389
+ # If the word is in the uncountable list (e.g. "sheep", "fish"), returns it unchanged.
390
+ # Otherwise applies singular transformation rules in order until one matches.
391
+ #
392
+ # @return [String] The singular form of the word
393
+ #
394
+ # @example Basic singularization
259
395
  # "posts".singularize #=> "post"
260
- # "octopi".singularize #=> "octopus"
261
- # "sheep".singluarize #=> "sheep"
262
- # "word".singluarize #=> "word"
396
+ # "matrices".singularize #=> "matrix"
397
+ #
398
+ # @example Uncountable words
399
+ # "fish".singularize #=> "fish"
400
+ #
401
+ # @example Complex phrases
263
402
  # "the blue mailmen".singularize #=> "the blue mailman"
264
403
  # "CamelOctopi".singularize #=> "CamelOctopus"
404
+ #
265
405
  def singularize
266
406
  result = dup
267
407
  unless Inflections.uncountables.include?(downcase)
268
- Inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
408
+ Inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
269
409
  end
270
410
  result
271
411
  end
272
412
 
273
- # Underscores and pluralizes the string.
413
+ # Converts a class name or CamelCase word to a suitable database table name
414
+ # by underscoring and pluralizing it. Namespaces are converted to paths.
415
+ # Used to derive table names from model class names.
274
416
  #
275
- # Examples
417
+ # @return [String] The table name (underscored, pluralized form)
418
+ #
419
+ # @example Convert class name to table name
276
420
  # "RawScaledScorer".tableize #=> "raw_scaled_scorers"
277
- # "egg_and_ham".tableize #=> "egg_and_hams"
421
+ #
422
+ # @example Handle namespaces
423
+ # "Admin::Post".tableize #=> "admin/posts"
424
+ #
425
+ # @example Basic conversion
278
426
  # "fancyCategory".tableize #=> "fancy_categories"
427
+ #
279
428
  def tableize
280
429
  underscore.pluralize
281
430
  end
282
431
 
283
- # Capitalizes all the words and replaces some characters in the string to create
284
- # a nicer looking title. Titleize is meant for creating pretty output.
432
+ # Converts a string into a more human-readable title format by:
433
+ # - Converting underscores and dashes to spaces
434
+ # - Capitalizing each word
435
+ # - Applying human-friendly formatting
285
436
  #
286
437
  # titleize is also aliased as as titlecase
287
438
  #
288
- # Examples
289
- # "man from the boondocks".titleize #=> "Man From The Boondocks"
439
+ # @return [String] A titleized version of the string
440
+ #
441
+ # @example Convert basic string to title
442
+ # "hello_world".titleize #=> "Hello World"
443
+ #
444
+ # @example Convert with special characters
290
445
  # "x-men: the last stand".titleize #=> "X Men: The Last Stand"
446
+ #
447
+ # @example Convert camelCase to title
448
+ # "camelCase".titleize #=> "Camel Case"
449
+ #
291
450
  def titleize
292
- underscore.humanize.gsub(/\b([a-z])/) { |x| x[-1..-1].upcase }
451
+ underscore.humanize.gsub(/\b([a-z])/) { |x| x[-1..].upcase }
293
452
  end
294
- alias_method :titlecase, :titleize
453
+ alias titlecase titleize
295
454
 
296
- # The reverse of camelize. Makes an underscored form from the expression in the string.
297
- # Also changes '::' to '/' to convert namespaces to paths.
455
+ # Converts a CamelCase or camelCase string into an underscored format.
456
+ # - Replaces '::' with '/' for namespace/path conversion
457
+ # - Adds underscores between words including:
458
+ # - Between runs of capital letters: 'ABC' -> 'a_b_c'
459
+ # - Before first lowercase letter after capitals: 'HTMLParser' -> 'html_parser'
460
+ # - Before capitals after lowercase/numbers: 'fooBar' -> 'foo_bar'
461
+ # - Converts all dashes to underscores
462
+ # - Converts everything to lowercase
298
463
  #
299
- # Examples
464
+ # @return [String] The underscored version of the string
465
+ #
466
+ # @example Convert camelCase
467
+ # "camelCase".underscore #=> "camel_case"
300
468
  # "ActiveRecord".underscore #=> "active_record"
301
- # "ActiveRecord::Errors".underscore #=> active_record/errors
469
+ #
470
+ # @example Convert namespace
471
+ # "ActiveRecord::Errors".underscore #=> 'active_record/errors'
472
+ #
473
+ # @example Convert complex CamelCase
474
+ # "HTMLParser".underscore #=> "html_parser"
475
+ #
302
476
  def underscore
303
- gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
304
- .gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
477
+ gsub('::', '/').gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
478
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2').tr('-', '_').downcase
305
479
  end
306
480
  end
307
481
 
308
-
309
482
  # Ripped from the Sequel gem by Jeremy Evans
310
- #
311
- #
483
+ # https://github.com/jeremyevans/sequel/blob/master/lib/sequel/extensions/inflector.rb
484
+ #
485
+ #
312
486
  # Copyright (c) 2007-2008 Sharon Rosner
313
487
  # Copyright (c) 2008-2015 Jeremy Evans
314
488
  #