inflecto 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +1 -0
  2. data/.rspec +1 -0
  3. data/.travis.yml +24 -0
  4. data/Changelog.md +7 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.devtools +66 -0
  7. data/Guardfile +18 -0
  8. data/LICENSE +20 -0
  9. data/README.md +46 -0
  10. data/Rakefile +5 -0
  11. data/TODO +1 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/roodi.yml +20 -0
  16. data/config/site.reek +95 -0
  17. data/config/yardstick.yml +2 -0
  18. data/inflecto.gemspec +16 -0
  19. data/lib/inflecto.rb +307 -0
  20. data/lib/inflecto/defaults.rb +58 -0
  21. data/lib/inflecto/inflections.rb +206 -0
  22. data/spec/integration/inflector_spec.rb +7 -0
  23. data/spec/rcov.opts +7 -0
  24. data/spec/shared/command_method_behavior.rb +7 -0
  25. data/spec/shared/each_method_behaviour.rb +15 -0
  26. data/spec/shared/hash_method_behavior.rb +17 -0
  27. data/spec/shared/idempotent_method_behavior.rb +7 -0
  28. data/spec/shared/invertible_method_behaviour.rb +9 -0
  29. data/spec/shared/mutator_behavior.rb +44 -0
  30. data/spec/spec_helper.rb +10 -0
  31. data/spec/unit/inflector/class_methods/camelize_spec.rb +21 -0
  32. data/spec/unit/inflector/class_methods/classify_spec.rb +15 -0
  33. data/spec/unit/inflector/class_methods/demodulize_spec.rb +13 -0
  34. data/spec/unit/inflector/class_methods/foreign_key_spec.rb +13 -0
  35. data/spec/unit/inflector/class_methods/humanize_spec.rb +14 -0
  36. data/spec/unit/inflector/class_methods/pluralize_spec.rb +194 -0
  37. data/spec/unit/inflector/class_methods/singularize_spec.rb +153 -0
  38. data/spec/unit/inflector/class_methods/tabelize_spec.rb +27 -0
  39. data/spec/unit/inflector/class_methods/underscore_spec.rb +21 -0
  40. metadata +99 -0
@@ -0,0 +1 @@
1
+ /Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,24 @@
1
+ language: ruby
2
+ bundler_args: --without guard metrics
3
+ script: "bundle exec rake spec"
4
+ rvm:
5
+ - 1.8.7
6
+ - ree
7
+ - 1.9.2
8
+ - 1.9.3
9
+ - 2.0.0
10
+ - jruby-18mode
11
+ - jruby-19mode
12
+ - rbx-18mode
13
+ - rbx-19mode
14
+ - ruby-head
15
+ matrix:
16
+ allow_failures:
17
+ - rvm: ruby-head
18
+ - rvm: rbx-18mode
19
+ - rvm: rbx-19mode
20
+ - rvm: jruby-head
21
+ - rvm: 2.0.0
22
+ notifications:
23
+ email:
24
+ - mbj@seonic.net
@@ -0,0 +1,7 @@
1
+ # v0.0.2 2013-01-20
2
+
3
+ [change] Do not depend on backports
4
+
5
+ # v0.0.1 2012-12-12
6
+
7
+ First public release!
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem 'inflecto', :path => '.'
6
+
7
+ gem 'devtools', :git => 'https://github.com/datamapper/devtools.git'
8
+ eval File.read('Gemfile.devtools')
@@ -0,0 +1,66 @@
1
+ # encoding: utf-8
2
+
3
+ group :development do
4
+ gem 'rake', '~> 10.0.3'
5
+ gem 'rspec', '~> 2.12.0'
6
+ gem 'yard', '~> 0.8.3'
7
+ end
8
+
9
+ group :yard do
10
+ gem 'redcarpet', '~> 2.2.2', :platforms => [ :mri, :rbx ]
11
+ end
12
+
13
+ group :guard do
14
+ gem 'guard', '~> 1.6.1'
15
+ gem 'guard-bundler', '~> 1.0.0'
16
+ gem 'guard-rspec', '~> 2.3.3'
17
+
18
+ # file system change event handling
19
+ gem 'rb-fchange', '~> 0.0.6', :require => false
20
+ gem 'rb-fsevent', '~> 0.9.3', :require => false
21
+ gem 'rb-inotify', '~> 0.9.0', :require => false
22
+
23
+ # Remove this one https://github.com/guard/listen/pull/78 is released
24
+ gem 'listen', '~> 0.7.2', :git => 'https://github.com/guard/listen'
25
+
26
+ # notification handling
27
+ gem 'libnotify', '~> 0.8.0', :require => false
28
+ gem 'rb-notifu', '~> 0.0.4', :require => false
29
+ gem 'terminal-notifier-guard', '~> 1.5.3', :require => false
30
+ end
31
+
32
+ group :metrics do
33
+ gem 'backports', '~> 2.7.0'
34
+ gem 'flay', '~> 1.4.3'
35
+ gem 'flog', '~> 2.5.3'
36
+ gem 'reek', '~> 1.2.13', :git => 'https://github.com/troessner/reek.git', :ref => 'ef77fcecaa21c9ebcbe4d9a79d41b0e70196bf18'
37
+ gem 'roodi', '~> 2.1.0'
38
+ gem 'yardstick', '~> 0.9.0'
39
+
40
+ platforms :ruby_18, :ruby_19 do
41
+ # this indirectly depends on ffi which does not build on ruby-head
42
+ gem 'yard-spellcheck', '~> 0.1.5'
43
+ end
44
+
45
+ platforms :mri_18 do
46
+ gem 'rcov', '~> 1.0.0'
47
+ end
48
+
49
+ platforms :mri_19 do
50
+ gem 'simplecov', '~> 0.7.1'
51
+ end
52
+
53
+ platforms :rbx do
54
+ gem 'pelusa', '~> 0.2.2'
55
+ end
56
+ end
57
+
58
+ group :benchmarks do
59
+ gem 'rbench', '~> 0.2.3'
60
+ end
61
+
62
+ platform :jruby do
63
+ group :jruby do
64
+ gem 'jruby-openssl', '~> 0.8.2'
65
+ end
66
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ guard :bundler do
4
+ watch('Gemfile')
5
+ end
6
+
7
+ guard :rspec do
8
+ # run all specs if the spec_helper or supporting files files are modified
9
+ watch('spec/spec_helper.rb') { 'spec' }
10
+ watch(%r{\Aspec/(?:lib|support|shared)/.+\.rb\z}) { 'spec' }
11
+
12
+ # run unit specs if associated lib code is modified
13
+ watch(%r{\Alib/(.+)\.rb\z}) { |m| Dir["spec/unit/#{m[1]}"] }
14
+ watch("lib/#{File.basename(File.expand_path('../', __FILE__))}.rb") { 'spec' }
15
+
16
+ # run a spec if it is modified
17
+ watch(%r{\Aspec/(?:unit|integration)/.+_spec\.rb\z})
18
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) The rails, merb & datamapper team
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,46 @@
1
+ inflecto
2
+ ========
3
+
4
+ [![Build Status](https://secure.travis-ci.org/mbj/inflecto.png)](http://travis-ci.org/mbj/inflecto)
5
+ [![Dependency Status](https://gemnasium.com/mbj/inflecto.png)](https://gemnasium.com/mbj/inflecto)
6
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/mbj/inflecto)
7
+
8
+ This is a standalone inflecto ripped out from [dm-core](https://github.com/datamapper/dm-core)
9
+
10
+ The dm-core inflecto originated from [extlib](https://github.com/datamapper/extlib)
11
+
12
+ The extlib inflecto originated from [active_support](https://github.com/rails/rails)
13
+
14
+ Installation
15
+ ------------
16
+
17
+ Install the gem ```inflecto``` via your preferred method.
18
+
19
+ Examples
20
+ --------
21
+
22
+ Soon.
23
+
24
+ Credits
25
+ -------
26
+
27
+ The rails, merb & datamapper team
28
+
29
+ The current maintainer is Markus Schirp ([mbj](https://github.com/mbj))
30
+
31
+ Contributing
32
+ -------------
33
+
34
+ * If you want your code merged into the mainline, please discuss the proposed changes with me before doing any work on it. This library is still in early development, and the direction it is going may not always be clear. Some features may not be appropriate yet, may need to be deferred until later when the foundation for them is laid, or may be more applicable in a plugin.
35
+ * Fork the project.
36
+ * Make your feature addition or bug fix.
37
+ * Follow this [style guide](https://github.com/dkubb/styleguide).
38
+ * Add specs for it. This is important so I don't break it in a future version unintentionally. Tests must cover all branches within the code, and code must be fully covered.
39
+ * Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
40
+ * Run "rake ci". This must pass and not show any regressions in the metrics for the code to be merged.
41
+ * Send me a pull request. Bonus points for topic branches.
42
+
43
+ License
44
+ -------
45
+
46
+ See LICENSE for details
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ require 'devtools'
4
+
5
+ Devtools.init
data/TODO ADDED
@@ -0,0 +1 @@
1
+ * Find the guys to mention in credits.
@@ -0,0 +1,3 @@
1
+ ---
2
+ threshold: 34
3
+ total_score: 164
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 143.4
@@ -0,0 +1,3 @@
1
+ ---
2
+ name: inflecto
3
+ namespace: Inflecto
@@ -0,0 +1,20 @@
1
+ ---
2
+ AbcMetricMethodCheck: { score: 70 }
3
+ AssignmentInConditionalCheck: { }
4
+ CaseMissingElseCheck: { }
5
+ ClassLineCountCheck: { line_count: 325 }
6
+ ClassNameCheck:
7
+ pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/
8
+ ClassVariableCheck: { }
9
+ CyclomaticComplexityBlockCheck: { complexity: 4 }
10
+ CyclomaticComplexityMethodCheck: { complexity: 4 }
11
+ EmptyRescueBodyCheck: { }
12
+ ForLoopCheck: { }
13
+ MethodLineCountCheck: { line_count: 16 }
14
+ MethodNameCheck:
15
+ pattern: !ruby/regexp /\A(?:[a-z\d](?:_?[a-z\d])+[?!=]?|\[\]=?|==|<=>|<<|[+*&|-])\z/
16
+ ModuleLineCountCheck: { line_count: 331 }
17
+ ModuleNameCheck:
18
+ pattern: !ruby/regexp /\A(?:[A-Z]+|[A-Z][a-z](?:[A-Z]?[a-z])+)\z/
19
+ # TODO: decrease parameter_count to 2 or less
20
+ ParameterNumberCheck: { parameter_count: 3 }
@@ -0,0 +1,95 @@
1
+ ---
2
+ UncommunicativeParameterName:
3
+ accept: []
4
+ exclude: []
5
+ enabled: true
6
+ reject:
7
+ - !ruby/regexp /^.$/
8
+ - !ruby/regexp /[0-9]$/
9
+ - !ruby/regexp /[A-Z]/
10
+ LargeClass:
11
+ max_methods: 14
12
+ exclude: []
13
+ enabled: true
14
+ max_instance_variables: 8
15
+ UncommunicativeMethodName:
16
+ accept: []
17
+ exclude: []
18
+ enabled: true
19
+ reject:
20
+ - !ruby/regexp /^[a-z]$/
21
+ - !ruby/regexp /[0-9]$/
22
+ - !ruby/regexp /[A-Z]/
23
+ LongParameterList:
24
+ max_params: 3
25
+ exclude: []
26
+ enabled: true
27
+ overrides: {}
28
+ FeatureEnvy:
29
+ exclude:
30
+ - Inflecto::Inflections#irregular
31
+ enabled: true
32
+ ClassVariable:
33
+ exclude: []
34
+ enabled: true
35
+ BooleanParameter:
36
+ exclude: []
37
+ enabled: true
38
+ IrresponsibleModule:
39
+ exclude: []
40
+ enabled: true
41
+ UncommunicativeModuleName:
42
+ accept: []
43
+ exclude: []
44
+ enabled: true
45
+ reject:
46
+ - !ruby/regexp /^.$/
47
+ - !ruby/regexp /[0-9]$/
48
+ NestedIterators:
49
+ ignore_iterators: []
50
+ exclude: []
51
+ enabled: true
52
+ max_allowed_nesting: 2
53
+ LongMethod:
54
+ max_statements: 8
55
+ exclude:
56
+ - Inflecto::Inflections#irregular
57
+ enabled: true
58
+ Duplication:
59
+ allow_calls: []
60
+ exclude:
61
+ - Inflecto::Inflections#irregular
62
+ enabled: true
63
+ max_calls: 2
64
+ UtilityFunction:
65
+ max_helper_calls: 1
66
+ exclude: []
67
+ enabled: true
68
+ Attribute:
69
+ exclude: []
70
+ enabled: false
71
+ UncommunicativeVariableName:
72
+ accept: []
73
+ exclude: []
74
+ enabled: true
75
+ reject:
76
+ - !ruby/regexp /^.$/
77
+ - !ruby/regexp /[0-9]$/
78
+ - !ruby/regexp /[A-Z]/
79
+ SimulatedPolymorphism:
80
+ exclude: []
81
+ enabled: true
82
+ max_ifs: 2
83
+ DataClump:
84
+ exclude:
85
+ - [replacement, rule]
86
+ enabled: true
87
+ max_copies: 2
88
+ min_clump_size: 2
89
+ ControlCouple:
90
+ exclude: []
91
+ enabled: true
92
+ LongYieldList:
93
+ max_params: 1
94
+ exclude: []
95
+ enabled: true
@@ -0,0 +1,2 @@
1
+ ---
2
+ threshold: 100.0
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'inflecto'
5
+ gem.version = '0.0.2'
6
+ gem.authors = ['The rails, merb & datamapper team', 'Markus Schirp']
7
+ gem.email = ['mbj@seonic.net']
8
+ gem.description = 'Inflector for strings'
9
+ gem.summary = gem.description
10
+ gem.homepage = 'https://github.com/mbj/inflecto'
11
+
12
+ gem.require_paths = %w[lib]
13
+ gem.files = `git ls-files`.split($/)
14
+ gem.test_files = `git ls-files spec/{unit,integration}`.split($/)
15
+ gem.extra_rdoc_files = %w[LICENSE README.md TODO]
16
+ end
@@ -0,0 +1,307 @@
1
+ # The Inflecto transforms words from singular to plural, class names to table names, modularized class names to ones without,
2
+ # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
3
+ # in inflections.rb.
4
+ #
5
+ # The Rails core team has stated patches for the inflections library will not be accepted
6
+ # in order to avoid breaking legacy applications which may be relying on errant inflections.
7
+ # If you discover an incorrect inflection and require it for your application, you'll need
8
+ # to correct it yourself (explained below).
9
+ module Inflecto
10
+
11
+ # Convert input to UpperCamelCase
12
+ #
13
+ # Will also convert '/' to '::' which is useful for converting paths to namespaces.
14
+ #
15
+ # @param [String] input
16
+ #
17
+ # @example
18
+ # Inflecto.camelize("data_mapper") # => "DataMapper"
19
+ # Inflecto.camelize("data_mapper/errors") # => "DataMApper::Errors"
20
+ #
21
+ # @return [String]
22
+ #
23
+ # @api public
24
+ #
25
+ def self.camelize(input)
26
+ input.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
27
+ end
28
+
29
+ # Convert input to underscored, lowercase string
30
+ #
31
+ # Changes '::' to '/' to convert namespaces to paths.
32
+ #
33
+ # @param [String] input
34
+ #
35
+ # @example
36
+ # Inflecto.underscore("DataMapper") # => "data_mapper"
37
+ # Inflecto.underscore("DataMapper::Errors") # => "data_mapper/errors"
38
+ #
39
+ # @return [String]
40
+ #
41
+ # @api public
42
+ #
43
+ def self.underscore(input)
44
+ word = input.to_s.dup
45
+ word.gsub!(/::/, '/')
46
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
47
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
48
+ word.tr!("-", "_")
49
+ word.downcase!
50
+ word
51
+ end
52
+
53
+ # Convert input underscores to dashes
54
+ #
55
+ # @param [String] input
56
+ #
57
+ # @example
58
+ # Inflecto.dasherize("foo_bar") # => "foo-bar"
59
+ #
60
+ # @return [String]
61
+ #
62
+ # @api public
63
+ #
64
+ def self.dasherize(input)
65
+ input.gsub(/_/, '-')
66
+ end
67
+
68
+ # Return unscoped constant name
69
+ #
70
+ # @param [String] input
71
+ #
72
+ # @example
73
+ #
74
+ # Inflecto.demodulize("DataMapper::Error") # => "Error"
75
+ # Inflecto.demodulize("DataMapper") # => "DataMapper"
76
+ #
77
+ # @return [String]
78
+ #
79
+ # @api public
80
+ #
81
+ def self.demodulize(input)
82
+ input.to_s.gsub(/^.*::/, '')
83
+ end
84
+
85
+ # Creates a foreign key name
86
+ #
87
+ # @param [String] input
88
+ #
89
+ # @example
90
+ #
91
+ # Inflecto.foreign_key("Message) => "message_id"
92
+ #
93
+ # @return [String]
94
+ #
95
+ # @api private
96
+ #
97
+ def self.foreign_key(input)
98
+ "#{underscore(demodulize(input))}_id"
99
+ end
100
+
101
+ # Find a constant with the name specified in the argument string
102
+ #
103
+ # The name is assumed to be the one of a top-level constant, constant scope of caller is igored
104
+ #
105
+ # @param [String] input
106
+ #
107
+ # @example
108
+ #
109
+ # Inflecto.constantize("Module") # => Module
110
+ # Inflecto.constantize("DataMapper::Error") # => Test::Unit
111
+ #
112
+ # @return [Class, Module]
113
+ #
114
+ # @api private
115
+ #
116
+ def self.constantize(input)
117
+ names = input.split('::')
118
+ names.shift if names.empty? || names.first.empty?
119
+
120
+ constant = Object
121
+ names.each do |name|
122
+ # Ruby 1.9 introduces an inherit argument for Module#const_get and
123
+ # #const_defined? and changes their default behavior.
124
+ if Module.method(:const_get).arity == 1
125
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
126
+ else
127
+ constant = constant.const_defined?(name, false) ? constant.const_get(name) : constant.const_missing(name)
128
+ end
129
+ end
130
+ constant
131
+ end
132
+
133
+ # Convert a number into an ordinal string
134
+ #
135
+ # @param [Fixnum] number
136
+ #
137
+ # @example
138
+ #
139
+ # ordinalize(1) # => "1st"
140
+ # ordinalize(2) # => "2nd"
141
+ # ordinalize(1002) # => "1002nd"
142
+ # ordinalize(1003) # => "1003rd"
143
+ #
144
+ # @return [String]
145
+ #
146
+ # @api private
147
+ #
148
+ def self.ordinalize(number)
149
+ if (11..13).include?(number.to_i % 100)
150
+ "#{number}th"
151
+ else
152
+ case number.to_i % 10
153
+ when 1; "#{number}st"
154
+ when 2; "#{number}nd"
155
+ when 3; "#{number}rd"
156
+ else "#{number}th"
157
+ end
158
+ end
159
+ end
160
+
161
+ # Yields a singleton instance of Inflecto::Inflections
162
+ #
163
+ # @example
164
+ #
165
+ # Inflecto.inflections do |inflect|
166
+ # inflect.uncountable "rails"
167
+ # end
168
+ #
169
+ # @return [Inflecto::Inflections]
170
+ #
171
+ # @api public
172
+ #
173
+ def self.inflections
174
+ if block_given?
175
+ yield Inflections.instance
176
+ else
177
+ Inflections.instance
178
+ end
179
+ end
180
+
181
+ # Convert input word string to plural
182
+ #
183
+ # @param [String] word
184
+ #
185
+ # @example
186
+ #
187
+ # Inflecto.pluralize("post") # => "posts"
188
+ # Inflecto.pluralize("octopus") # => "octopi"
189
+ # Inflecto.pluralize("sheep") # => "sheep"
190
+ # Inflecto.pluralize("words") # => "words"
191
+ # Inflecto.pluralize("CamelOctopus") # => "CamelOctopi"
192
+ #
193
+ # @return [String]
194
+ #
195
+ # @api public
196
+ #
197
+ def self.pluralize(word)
198
+ result = word.to_s.dup
199
+
200
+ if result.empty? || inflections.uncountables.include?(result.downcase)
201
+ result
202
+ else
203
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
204
+ result
205
+ end
206
+ end
207
+
208
+ # Convert word to singular
209
+ #
210
+ # @param [String] word
211
+ #
212
+ # @example
213
+ #
214
+ # Inflecto.singularize("posts") # => "post"
215
+ # Inflecto.singularize("octopi") # => "octopus"
216
+ # Inflecto.singularize("sheep") # => "sheep"
217
+ # Inflecto.singularize("word") # => "word"
218
+ # Inflecto.singularize("CamelOctopi") # => "CamelOctopus"
219
+ #
220
+ # @return [String]
221
+ #
222
+ # @api public
223
+ #
224
+ def self.singularize(word)
225
+ result = word.to_s.dup
226
+
227
+ if inflections.uncountables.any? { |inflection| result =~ /\b(#{inflection})\Z/i }
228
+ result
229
+ else
230
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
231
+ result
232
+ end
233
+ end
234
+
235
+ # Humanize string
236
+ #
237
+ # @param [String] input
238
+ #
239
+ # capitalizes the first word and turns underscores into spaces and strips a # trailing "_id", if any.
240
+ # Like +titleize+, this is meant for creating pretty output.
241
+ #
242
+ # @example
243
+ #
244
+ # Inflecto.humanize("employee_salary") # => "Employee salary"
245
+ # Inflecto.humanize("author_id") # => "Author"
246
+ #
247
+ # @return [String]
248
+ #
249
+ # @api private
250
+ #
251
+ def self.humanize(input)
252
+ result = input.to_s.dup
253
+
254
+ inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
255
+ result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
256
+ end
257
+
258
+
259
+ # Tabelize input string
260
+ #
261
+ # @param [String] input
262
+ #
263
+ # Create the name of a table like Rails does for models to table names.
264
+ # This method # uses the +pluralize+ method on the last word in the string.
265
+ #
266
+ # @example
267
+ #
268
+ # Inflecto.tabelize("RawScaledScorer") # => "raw_scaled_scorers"
269
+ # Inflecto.tabelize("egg_and_ham") # => "egg_and_hams"
270
+ # Inflecto.tabelize("fancyCategory") # => "fancy_categories"
271
+ #
272
+ # @return [String]
273
+ #
274
+ # @api private
275
+ #
276
+ def self.tableize(input)
277
+ pluralize(underscore(input).gsub('/','_'))
278
+ end
279
+
280
+ # Classify input
281
+ #
282
+ # Create a class name from a plural table name like Rails does for table names to models.
283
+ # Note that this returns a string and not a Class.
284
+ #
285
+ # To convert to an actual class # follow +classify+ with +constantize+.
286
+ #
287
+ # @examples:
288
+ #
289
+ # Inflecto.classify("egg_and_hams") # => "EggAndHam"
290
+ # Inflecto.classify("posts") # => "Post"
291
+ #
292
+ # # Singular names are not handled correctly:
293
+ # Inflecto.classify("business") # => "Busines"
294
+ #
295
+ # @return [String]
296
+ #
297
+ # @api private
298
+ #
299
+ def self.classify(table_name)
300
+ # strip out any leading schema name
301
+ camelize(singularize(table_name.to_s.sub(/.*\./, '')))
302
+ end
303
+
304
+ end
305
+
306
+ require 'inflecto/inflections'
307
+ require 'inflecto/defaults'