inflection 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +35 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/VERSION +1 -0
- data/inflection.gemspec +20 -0
- data/lib/inflection.rb +358 -0
- data/spec/inflection_extras_spec.rb +111 -0
- data/spec/string_spec.rb +222 -0
- data/test/setup.rb +15 -0
- data/test/suite/lib/inflection +189 -0
- data/test/suite/lib/inflection.rb +40 -0
- data/test/suite/lib/injective +4 -0
- metadata +76 -0
data/.gitignore
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## Rubinius
|
17
|
+
*.rbc
|
18
|
+
|
19
|
+
## PROJECT::GENERAL
|
20
|
+
*.gem
|
21
|
+
coverage
|
22
|
+
rdoc
|
23
|
+
pkg
|
24
|
+
tmp
|
25
|
+
doc
|
26
|
+
log
|
27
|
+
.yardoc
|
28
|
+
measurements
|
29
|
+
|
30
|
+
## BUNDLER
|
31
|
+
.bundle
|
32
|
+
Gemfile.local
|
33
|
+
Gemfile.lock
|
34
|
+
|
35
|
+
## PROJECT::SPECIFIC
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Dan Kubb
|
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.
|
data/README.rdoc
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
= inflection
|
2
|
+
|
3
|
+
Support library that provies english inflection.
|
4
|
+
|
5
|
+
== Note on Patches/Pull Requests
|
6
|
+
|
7
|
+
* Fork the project.
|
8
|
+
* Make your feature addition or bug fix.
|
9
|
+
* Add tests for it. This is important so I don't break it in a
|
10
|
+
future version unintentionally.
|
11
|
+
* Commit, do not mess with rakefile, version, or history.
|
12
|
+
(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)
|
13
|
+
* Send me a pull request. Bonus points for topic branches.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2010 Simon Hafner. See LICENSE for details.
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/inflection.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{inflection}
|
5
|
+
s.version = "0.1"
|
6
|
+
|
7
|
+
s.authors = ["Dan Kubb", "Simon Hafner"]
|
8
|
+
s.description = %q{Support library for inflections}
|
9
|
+
s.extra_rdoc_files = [
|
10
|
+
"LICENSE",
|
11
|
+
"README.rdoc"
|
12
|
+
]
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.homepage = %q{http://github.com/Tass/extlib}
|
15
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubygems_version = %q{1.3.7}
|
18
|
+
s.summary = %q{Provies english inflection.}
|
19
|
+
end
|
20
|
+
|
data/lib/inflection.rb
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
# = English Nouns Number Inflection.
|
4
|
+
#
|
5
|
+
# This module provides english singular <-> plural noun inflections.
|
6
|
+
module Inflection
|
7
|
+
|
8
|
+
@singular_of = {}
|
9
|
+
@plural_of = {}
|
10
|
+
|
11
|
+
@singular_rules = []
|
12
|
+
@plural_rules = []
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# Defines a general inflection exception case.
|
16
|
+
#
|
17
|
+
# ==== Parameters
|
18
|
+
# singular<String>::
|
19
|
+
# singular form of the word
|
20
|
+
# plural<String>::
|
21
|
+
# plural form of the word
|
22
|
+
#
|
23
|
+
# ==== Examples
|
24
|
+
#
|
25
|
+
# Here we define erratum/errata exception case:
|
26
|
+
#
|
27
|
+
# English::Inflect.word "erratum", "errata"
|
28
|
+
#
|
29
|
+
# In case singular and plural forms are the same omit
|
30
|
+
# second argument on call:
|
31
|
+
#
|
32
|
+
# English::Inflect.word 'information'
|
33
|
+
def word(singular, plural=nil)
|
34
|
+
plural = singular unless plural
|
35
|
+
singular_word(singular, plural)
|
36
|
+
plural_word(singular, plural)
|
37
|
+
end
|
38
|
+
|
39
|
+
def clear(type = :all)
|
40
|
+
if type == :singular || type == :all
|
41
|
+
@singular_of = {}
|
42
|
+
@singular_rules = []
|
43
|
+
@singularization_rules, @singularization_regex = nil, nil
|
44
|
+
end
|
45
|
+
if type == :plural || type == :all
|
46
|
+
@singular_of = {}
|
47
|
+
@singular_rules = []
|
48
|
+
@singularization_rules, @singularization_regex = nil, nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Define a singularization exception.
|
54
|
+
#
|
55
|
+
# ==== Parameters
|
56
|
+
# singular<String>::
|
57
|
+
# singular form of the word
|
58
|
+
# plural<String>::
|
59
|
+
# plural form of the word
|
60
|
+
def singular_word(singular, plural)
|
61
|
+
@singular_of[plural] = singular
|
62
|
+
@singular_of[plural.capitalize] = singular.capitalize
|
63
|
+
end
|
64
|
+
|
65
|
+
# Define a pluralization exception.
|
66
|
+
#
|
67
|
+
# ==== Parameters
|
68
|
+
# singular<String>::
|
69
|
+
# singular form of the word
|
70
|
+
# plural<String>::
|
71
|
+
# plural form of the word
|
72
|
+
def plural_word(singular, plural)
|
73
|
+
@plural_of[singular] = plural
|
74
|
+
@plural_of[singular.capitalize] = plural.capitalize
|
75
|
+
end
|
76
|
+
|
77
|
+
# Define a general rule.
|
78
|
+
#
|
79
|
+
# ==== Parameters
|
80
|
+
# singular<String>::
|
81
|
+
# ending of the word in singular form
|
82
|
+
# plural<String>::
|
83
|
+
# ending of the word in plural form
|
84
|
+
# whole_word<Boolean>::
|
85
|
+
# for capitalization, since words can be
|
86
|
+
# capitalized (Man => Men) #
|
87
|
+
# ==== Examples
|
88
|
+
# Once the following rule is defined:
|
89
|
+
# English::Inflect.rule 'y', 'ies'
|
90
|
+
#
|
91
|
+
# You can see the following results:
|
92
|
+
# irb> "fly".plural
|
93
|
+
# => flies
|
94
|
+
# irb> "cry".plural
|
95
|
+
# => cries
|
96
|
+
# Define a general rule.
|
97
|
+
|
98
|
+
def rule(singular, plural, whole_word = false)
|
99
|
+
singular_rule(singular, plural)
|
100
|
+
plural_rule(singular, plural)
|
101
|
+
word(singular, plural) if whole_word
|
102
|
+
end
|
103
|
+
|
104
|
+
# Define a singularization rule.
|
105
|
+
#
|
106
|
+
# ==== Parameters
|
107
|
+
# singular<String>::
|
108
|
+
# ending of the word in singular form
|
109
|
+
# plural<String>::
|
110
|
+
# ending of the word in plural form
|
111
|
+
#
|
112
|
+
# ==== Examples
|
113
|
+
# Once the following rule is defined:
|
114
|
+
# English::Inflect.singular_rule 'o', 'oes'
|
115
|
+
#
|
116
|
+
# You can see the following results:
|
117
|
+
# irb> "heroes".singular
|
118
|
+
# => hero
|
119
|
+
def singular_rule(singular, plural)
|
120
|
+
@singular_rules << [singular, plural]
|
121
|
+
end
|
122
|
+
|
123
|
+
# Define a plurualization rule.
|
124
|
+
#
|
125
|
+
# ==== Parameters
|
126
|
+
# singular<String>::
|
127
|
+
# ending of the word in singular form
|
128
|
+
# plural<String>::
|
129
|
+
# ending of the word in plural form
|
130
|
+
#
|
131
|
+
# ==== Examples
|
132
|
+
# Once the following rule is defined:
|
133
|
+
# English::Inflect.singular_rule 'fe', 'ves'
|
134
|
+
#
|
135
|
+
# You can see the following results:
|
136
|
+
# irb> "wife".plural
|
137
|
+
# => wives
|
138
|
+
def plural_rule(singular, plural)
|
139
|
+
@plural_rules << [singular, plural]
|
140
|
+
end
|
141
|
+
|
142
|
+
# Read prepared singularization rules.
|
143
|
+
def singularization_rules
|
144
|
+
if defined?(@singularization_regex) && @singularization_regex
|
145
|
+
return [@singularization_regex, @singularization_hash]
|
146
|
+
end
|
147
|
+
# No sorting needed: Regexen match on longest string
|
148
|
+
@singularization_regex = Regexp.new("(" + @singular_rules.map {|s,p| p}.join("|") + ")$", "i")
|
149
|
+
@singularization_hash = Hash[*@singular_rules.flatten].invert
|
150
|
+
[@singularization_regex, @singularization_hash]
|
151
|
+
end
|
152
|
+
|
153
|
+
# Read prepared pluralization rules.
|
154
|
+
def pluralization_rules
|
155
|
+
if defined?(@pluralization_regex) && @pluralization_regex
|
156
|
+
return [@pluralization_regex, @pluralization_hash]
|
157
|
+
end
|
158
|
+
@pluralization_regex = Regexp.new("(" + @plural_rules.map {|s,p| s}.join("|") + ")$", "i")
|
159
|
+
@pluralization_hash = Hash[*@plural_rules.flatten]
|
160
|
+
[@pluralization_regex, @pluralization_hash]
|
161
|
+
end
|
162
|
+
|
163
|
+
attr_reader :singular_of, :plural_of
|
164
|
+
|
165
|
+
# Convert an English word from plural to singular.
|
166
|
+
#
|
167
|
+
# "boys".singular #=> boy
|
168
|
+
# "tomatoes".singular #=> tomato
|
169
|
+
#
|
170
|
+
# ==== Parameters
|
171
|
+
# word<String>:: word to singularize
|
172
|
+
#
|
173
|
+
# ==== Returns
|
174
|
+
# <String>:: singularized form of word
|
175
|
+
#
|
176
|
+
# ==== Notes
|
177
|
+
# Aliased as singularize (a Railism)
|
178
|
+
def singular(word)
|
179
|
+
if result = singular_of[word]
|
180
|
+
return result.dup
|
181
|
+
end
|
182
|
+
result = word.dup
|
183
|
+
regex, hash = singularization_rules
|
184
|
+
result.sub!(regex) {|m| hash[m]}
|
185
|
+
singular_of[word] = result
|
186
|
+
return result
|
187
|
+
end
|
188
|
+
|
189
|
+
# Alias for #singular (a Railism).
|
190
|
+
#
|
191
|
+
alias_method(:singularize, :singular)
|
192
|
+
|
193
|
+
# Convert an English word from singular to plural.
|
194
|
+
#
|
195
|
+
# "boy".plural #=> boys
|
196
|
+
# "tomato".plural #=> tomatoes
|
197
|
+
#
|
198
|
+
# ==== Parameters
|
199
|
+
# word<String>:: word to pluralize
|
200
|
+
#
|
201
|
+
# ==== Returns
|
202
|
+
# <String>:: pluralized form of word
|
203
|
+
#
|
204
|
+
# ==== Notes
|
205
|
+
# Aliased as pluralize (a Railism)
|
206
|
+
def plural(word)
|
207
|
+
# special exceptions
|
208
|
+
return "" if word == ""
|
209
|
+
if result = plural_of[word]
|
210
|
+
return result.dup
|
211
|
+
end
|
212
|
+
result = word.dup
|
213
|
+
regex, hash = pluralization_rules
|
214
|
+
result.sub!(regex) {|m| hash[m]}
|
215
|
+
plural_of[word] = result
|
216
|
+
return result
|
217
|
+
end
|
218
|
+
|
219
|
+
# Alias for #plural (a Railism).
|
220
|
+
alias_method(:pluralize, :plural)
|
221
|
+
end
|
222
|
+
|
223
|
+
# One argument means singular and plural are the same.
|
224
|
+
|
225
|
+
word 'equipment'
|
226
|
+
word 'fish'
|
227
|
+
word 'grass'
|
228
|
+
word 'hovercraft'
|
229
|
+
word 'information'
|
230
|
+
word 'milk'
|
231
|
+
word 'money'
|
232
|
+
word 'moose'
|
233
|
+
word 'plurals'
|
234
|
+
word 'postgres'
|
235
|
+
word 'rain'
|
236
|
+
word 'rice'
|
237
|
+
word 'series'
|
238
|
+
word 'sheep'
|
239
|
+
word 'species'
|
240
|
+
word 'status'
|
241
|
+
word 'pokemon'
|
242
|
+
word 'pokémon'
|
243
|
+
word 'mysql'
|
244
|
+
|
245
|
+
# Two arguments defines a singular and plural exception.
|
246
|
+
word 'alias' , 'aliases'
|
247
|
+
word 'analysis' , 'analyses'
|
248
|
+
word 'axis' , 'axes'
|
249
|
+
word 'basis' , 'bases'
|
250
|
+
word 'buffalo' , 'buffaloes'
|
251
|
+
word 'cactus' , 'cacti'
|
252
|
+
word 'crisis' , 'crises'
|
253
|
+
word 'criterion' , 'criteria'
|
254
|
+
word 'cross' , 'crosses'
|
255
|
+
word 'datum' , 'data'
|
256
|
+
word 'diagnosis' , 'diagnoses'
|
257
|
+
word 'drive' , 'drives'
|
258
|
+
word 'erratum' , 'errata'
|
259
|
+
word 'goose' , 'geese'
|
260
|
+
word 'index' , 'indices'
|
261
|
+
word 'life' , 'lives'
|
262
|
+
word 'louse' , 'lice'
|
263
|
+
word 'matrix' , 'matrices'
|
264
|
+
word 'medium' , 'media'
|
265
|
+
word 'mouse' , 'mice'
|
266
|
+
word 'movie' , 'movies'
|
267
|
+
word 'octopus' , 'octopi'
|
268
|
+
word 'ox' , 'oxen'
|
269
|
+
word 'phenomenon' , 'phenomena'
|
270
|
+
word 'plus' , 'plusses'
|
271
|
+
word 'potato' , 'potatoes'
|
272
|
+
word 'quiz' , 'quizzes'
|
273
|
+
word 'status' , 'status'
|
274
|
+
word 'status' , 'statuses'
|
275
|
+
word 'Swiss' , 'Swiss'
|
276
|
+
word 'testis' , 'testes'
|
277
|
+
word 'thesaurus' , 'thesauri'
|
278
|
+
word 'thesis' , 'theses'
|
279
|
+
word 'thief' , 'thieves'
|
280
|
+
word 'tomato' , 'tomatoes'
|
281
|
+
word 'torpedo' , 'torpedoes'
|
282
|
+
word 'vertex' , 'vertices'
|
283
|
+
word 'wife' , 'wives'
|
284
|
+
word 'tooth' , 'teeth'
|
285
|
+
word 'penis' , 'penises'
|
286
|
+
word 'stimulus' , 'stimuli'
|
287
|
+
word 'shaman' , 'shamans'
|
288
|
+
word 'rookie' , 'rookies'
|
289
|
+
word 'radius' , 'radii'
|
290
|
+
word 'talisman' , 'talismans'
|
291
|
+
word 'syllabus' , 'syllabi'
|
292
|
+
word 'move' , 'moves'
|
293
|
+
word 'human' , 'humans'
|
294
|
+
word 'hippopotamus', 'hippopotami'
|
295
|
+
word 'german' , 'germans'
|
296
|
+
word 'fungus' , 'fungi'
|
297
|
+
word 'focus' , 'foci'
|
298
|
+
word 'die' , 'dice'
|
299
|
+
word 'alumnus' , 'alumni'
|
300
|
+
word 'appendix' , 'appendices'
|
301
|
+
word 'arena' , 'arenas'
|
302
|
+
|
303
|
+
# One-way singularization exception (convert plural to singular).
|
304
|
+
|
305
|
+
# General rules.
|
306
|
+
rule 'person' , 'people', true
|
307
|
+
rule 'shoe' , 'shoes', true
|
308
|
+
rule 'hive' , 'hives', true
|
309
|
+
rule 'man' , 'men', true
|
310
|
+
rule 'child' , 'children', true
|
311
|
+
rule 'news' , 'news', true
|
312
|
+
rule 'rf' , 'rves'
|
313
|
+
rule 'af' , 'aves'
|
314
|
+
rule 'ero' , 'eroes'
|
315
|
+
rule 'man' , 'men'
|
316
|
+
rule 'ch' , 'ches'
|
317
|
+
rule 'sh' , 'shes'
|
318
|
+
rule 'ss' , 'sses'
|
319
|
+
#rule 'ta' , 'tum'
|
320
|
+
#rule 'ia' , 'ium'
|
321
|
+
#rule 'ra' , 'rum'
|
322
|
+
rule 'ay' , 'ays'
|
323
|
+
rule 'ey' , 'eys'
|
324
|
+
rule 'oy' , 'oys'
|
325
|
+
rule 'uy' , 'uys'
|
326
|
+
rule 'y' , 'ies'
|
327
|
+
rule 'x' , 'xes'
|
328
|
+
rule 'lf' , 'lves'
|
329
|
+
rule 'ffe' , 'ffes'
|
330
|
+
rule 'afe' , 'aves'
|
331
|
+
rule 'ouse' , 'ouses'
|
332
|
+
rule 'ive' , 'ives' # don't want to snag wife
|
333
|
+
# more cases of words ending in -oses not being singularized properly
|
334
|
+
# than cases of words ending in -osis
|
335
|
+
# rule 'osis' , 'oses'
|
336
|
+
rule 'ox' , 'oxes'
|
337
|
+
rule 'us' , 'uses'
|
338
|
+
rule '' , 's'
|
339
|
+
|
340
|
+
# Some latin words
|
341
|
+
rule 'a' , 'ae'
|
342
|
+
rule 'um' , 'a'
|
343
|
+
|
344
|
+
# cookie / bookie
|
345
|
+
rule 'ookie' , 'ookies'
|
346
|
+
# One-way singular rules.
|
347
|
+
|
348
|
+
singular_rule 'of' , 'ofs' # proof
|
349
|
+
singular_rule 'o' , 'oes' # hero, heroes
|
350
|
+
singular_rule 'f' , 'ves'
|
351
|
+
|
352
|
+
# One-way plural rules.
|
353
|
+
|
354
|
+
#plural_rule 'fe' , 'ves' # safe, wife
|
355
|
+
plural_rule 's' , 'ses'
|
356
|
+
plural_rule 'fe' , 'ves' # don't want to snag perspectives
|
357
|
+
|
358
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'extlib/inflection'
|
3
|
+
|
4
|
+
describe Extlib::Inflection do
|
5
|
+
describe "#classify" do
|
6
|
+
it 'classifies data_mapper as DataMapper' do
|
7
|
+
Extlib::Inflection.classify('data_mapper').should == 'DataMapper'
|
8
|
+
end
|
9
|
+
|
10
|
+
it "classifies enlarged_testes as EnlargedTestis" do
|
11
|
+
Extlib::Inflection.classify('enlarged_testes').should == 'EnlargedTestis'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "singularizes string first: classifies data_mappers as egg_and_hams as EggAndHam" do
|
15
|
+
Extlib::Inflection.classify('egg_and_hams').should == 'EggAndHam'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#camelize" do
|
20
|
+
it 'camelizes data_mapper as DataMapper' do
|
21
|
+
Extlib::Inflection.camelize('data_mapper').should == 'DataMapper'
|
22
|
+
end
|
23
|
+
|
24
|
+
it "camelizes merb as Merb" do
|
25
|
+
Extlib::Inflection.camelize('merb').should == 'Merb'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "camelizes data_mapper/resource as DataMapper::Resource" do
|
29
|
+
Extlib::Inflection.camelize('data_mapper/resource').should == 'DataMapper::Resource'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "camelizes data_mapper/associations/one_to_many as DataMapper::Associations::OneToMany" do
|
33
|
+
Extlib::Inflection.camelize('data_mapper/associations/one_to_many').should == 'DataMapper::Associations::OneToMany'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#underscore" do
|
38
|
+
it 'underscores DataMapper as data_mapper' do
|
39
|
+
Extlib::Inflection.underscore('DataMapper').should == 'data_mapper'
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'underscores Merb as merb' do
|
43
|
+
Extlib::Inflection.underscore('Merb').should == 'merb'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'underscores DataMapper::Resource as data_mapper/resource' do
|
47
|
+
Extlib::Inflection.underscore('DataMapper::Resource').should == 'data_mapper/resource'
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'underscores Merb::BootLoader::Rackup as merb/boot_loader/rackup' do
|
51
|
+
Extlib::Inflection.underscore('Merb::BootLoader::Rackup').should == 'merb/boot_loader/rackup'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "#humanize" do
|
56
|
+
it 'replaces _ with space: humanizes employee_salary as Employee salary' do
|
57
|
+
Extlib::Inflection.humanize('employee_salary').should == 'Employee salary'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "strips _id endings: humanizes author_id as Author" do
|
61
|
+
Extlib::Inflection.humanize('author_id').should == 'Author'
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#demodulize" do
|
66
|
+
it 'demodulizes module name: DataMapper::Inflector => Inflector' do
|
67
|
+
Extlib::Inflection.demodulize('DataMapper::Inflector').should == 'Inflector'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'demodulizes module name: A::B::C::D::E => E' do
|
71
|
+
Extlib::Inflection.demodulize('A::B::C::D::E').should == 'E'
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe "#tableize" do
|
76
|
+
it 'pluralizes last word in snake_case strings: fancy_category => fancy_categories' do
|
77
|
+
Extlib::Inflection.tableize('fancy_category').should == 'fancy_categories'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'underscores CamelCase strings before pluralization: enlarged_testis => enlarged_testes' do
|
81
|
+
Extlib::Inflection.tableize('enlarged_testis').should == 'enlarged_testes'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'underscores CamelCase strings before pluralization: FancyCategory => fancy_categories' do
|
85
|
+
Extlib::Inflection.tableize('FancyCategory').should == 'fancy_categories'
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'underscores CamelCase strings before pluralization: EnlargedTestis => enlarged_testes' do
|
89
|
+
Extlib::Inflection.tableize('EnlargedTestis').should == 'enlarged_testes'
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'replaces :: with underscores: Fancy::Category => fancy_categories' do
|
93
|
+
Extlib::Inflection.tableize('Fancy::Category').should == 'fancy_categories'
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'underscores CamelCase strings before pluralization: Enlarged::Testis => enlarged_testes' do
|
97
|
+
Extlib::Inflection.tableize('Enlarged::Testis').should == 'enlarged_testes'
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
describe "#foreign_key" do
|
103
|
+
it 'adds _id to downcased string: Message => message_id' do
|
104
|
+
Extlib::Inflection.foreign_key('Message').should == 'message_id'
|
105
|
+
end
|
106
|
+
|
107
|
+
it "demodulizes string first: Admin::Post => post_id" do
|
108
|
+
Extlib::Inflection.foreign_key('Admin::Post').should == 'post_id'
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
data/spec/string_spec.rb
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'extlib/string'
|
3
|
+
|
4
|
+
describe String, "#to_const_string" do
|
5
|
+
it "swaps slashes with ::" do
|
6
|
+
"foo/bar".to_const_string.should == "Foo::Bar"
|
7
|
+
end
|
8
|
+
|
9
|
+
it "replaces snake_case with CamelCase" do
|
10
|
+
"foo/bar/baz_bat".to_const_string.should == "Foo::Bar::BazBat"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "leaves constant string as is" do
|
14
|
+
"Merb::Test".to_const_string.should == "Merb::Test"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
describe String, "#to_const_path" do
|
21
|
+
it "swaps :: with slash" do
|
22
|
+
"Foo::Bar".to_const_path.should == "foo/bar"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "snake_cases string" do
|
26
|
+
"Merb::Test::ViewHelper".to_const_path.should == "merb/test/view_helper"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "leaves slash-separated snake case string as is" do
|
30
|
+
"merb/test/view_helper".to_const_path.should == "merb/test/view_helper"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
describe String, "#camel_case" do
|
37
|
+
it "handles lowercase without underscore" do
|
38
|
+
"merb".camel_case.should == "Merb"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "handles lowercase with 1 underscore" do
|
42
|
+
"merb_core".camel_case.should == "MerbCore"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "handles lowercase with more than 1 underscore" do
|
46
|
+
"so_you_want_contribute_to_merb_core".camel_case.should == "SoYouWantContributeToMerbCore"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "handles lowercase with more than 1 underscore in a row" do
|
50
|
+
"__python__is__like__this".camel_case.should == "PythonIsLikeThis"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "handle first capital letter with underscores" do
|
54
|
+
"Python__Is__Like__This".camel_case.should == "PythonIsLikeThis"
|
55
|
+
end
|
56
|
+
|
57
|
+
it "leaves CamelCase as is" do
|
58
|
+
"TestController".camel_case.should == "TestController"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
describe String, "#snake_case" do
|
65
|
+
it "lowercases one word CamelCase" do
|
66
|
+
"Merb".snake_case.should == "merb"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "makes one underscore snake_case two word CamelCase" do
|
70
|
+
"MerbCore".snake_case.should == "merb_core"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "handles CamelCase with more than 2 words" do
|
74
|
+
"SoYouWantContributeToMerbCore".snake_case.should == "so_you_want_contribute_to_merb_core"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "handles CamelCase with more than 2 capital letter in a row" do
|
78
|
+
"CNN".snake_case.should == "cnn"
|
79
|
+
"CNNNews".snake_case.should == "cnn_news"
|
80
|
+
"HeadlineCNNNews".snake_case.should == "headline_cnn_news"
|
81
|
+
"NameACRONYM".snake_case.should == "name_acronym"
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does NOT change one word lowercase" do
|
85
|
+
"merb".snake_case.should == "merb"
|
86
|
+
end
|
87
|
+
|
88
|
+
it "leaves snake_case as is" do
|
89
|
+
"merb_core".snake_case.should == "merb_core"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
describe String, "#escape_regexp" do
|
96
|
+
it "escapes all * in a string" do
|
97
|
+
"*and*".escape_regexp.should == "\\*and\\*"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "escapes all ? in a string" do
|
101
|
+
"?and?".escape_regexp.should == "\\?and\\?"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "escapes all { in a string" do
|
105
|
+
"{and{".escape_regexp.should == "\\{and\\{"
|
106
|
+
end
|
107
|
+
|
108
|
+
it "escapes all } in a string" do
|
109
|
+
"}and}".escape_regexp.should == "\\}and\\}"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "escapes all . in a string" do
|
113
|
+
".and.".escape_regexp.should == "\\.and\\."
|
114
|
+
end
|
115
|
+
|
116
|
+
it "escapes all regexp special characters used in a string" do
|
117
|
+
"*?{}.".escape_regexp.should == "\\*\\?\\{\\}\\."
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
describe String, "#unescape_regexp" do
|
124
|
+
it "unescapes all \\* in a string" do
|
125
|
+
"\\*and\\*".unescape_regexp.should == "*and*"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "unescapes all \\? in a string" do
|
129
|
+
"\\?and\\?".unescape_regexp.should == "?and?"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "unescapes all \\{ in a string" do
|
133
|
+
"\\{and\\{".unescape_regexp.should == "{and{"
|
134
|
+
end
|
135
|
+
|
136
|
+
it "unescapes all \\} in a string" do
|
137
|
+
"\\}and\\}".unescape_regexp.should == "}and}"
|
138
|
+
end
|
139
|
+
|
140
|
+
it "unescapes all \\. in a string" do
|
141
|
+
"\\.and\\.".unescape_regexp.should == ".and."
|
142
|
+
end
|
143
|
+
|
144
|
+
it "unescapes all regexp special characters used in a string" do
|
145
|
+
"\\*\\?\\{\\}\\.".unescape_regexp.should == "*?{}."
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
|
151
|
+
describe String, "#/" do
|
152
|
+
it "concanates operands with File::SEPARATOR" do
|
153
|
+
("merb" / "core").should == "merb#{File::SEPARATOR}core"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
require 'rbconfig'
|
159
|
+
describe String, "#relative_path_from" do
|
160
|
+
it "uses other operand as base for path calculation" do
|
161
|
+
site_dir = Config::CONFIG["sitedir"]
|
162
|
+
|
163
|
+
two_levels_up = site_dir.split(File::SEPARATOR)
|
164
|
+
2.times { two_levels_up.pop } # remove two deepest directories
|
165
|
+
two_levels_up = two_levels_up.join(File::SEPARATOR)
|
166
|
+
|
167
|
+
two_levels_up.relative_path_from(site_dir).should == "../.."
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
describe String, ".translate" do
|
173
|
+
before(:each) do
|
174
|
+
String.stub!(:translations).and_return({ "on snakes and rubies" => "a serpenti e rubini" })
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'looks up for translation in translations dictionary' do
|
178
|
+
String.translate("on snakes and rubies").should == "a serpenti e rubini"
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'returns string that has no translations as it is' do
|
182
|
+
String.translate("shapes").should == "shapes"
|
183
|
+
String.translate("kalopsia").should == "kalopsia"
|
184
|
+
String.translate("holding on to nothing").should == "holding on to nothing"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe String, ".t" do
|
189
|
+
before(:each) do
|
190
|
+
String.stub!(:translations).and_return({ '%s must not be blank' => "%s moet ingevuld worden",
|
191
|
+
'username' => 'gebruikersnaam',
|
192
|
+
'%s must be between %s and %s characters long' => '%s moet tussen %s en %s tekens lang zijn'})
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'looks up for translation in translations dictionary and translates parameters as well' do
|
196
|
+
"%s must not be blank".t(:username).should == "gebruikersnaam moet ingevuld worden"
|
197
|
+
"%s must not be blank".t('username').should == "gebruikersnaam moet ingevuld worden"
|
198
|
+
"%s must be between %s and %s characters long".t(:password, 5, 9).should == "password moet tussen 5 en 9 tekens lang zijn"
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'returns string that has no translations as it is' do
|
202
|
+
"password".t.should == "password"
|
203
|
+
end
|
204
|
+
|
205
|
+
it 'should not translate when freezed' do
|
206
|
+
"%s must not be blank".t('username'.freeze).should == "username moet ingevuld worden"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe String, ".translations" do
|
211
|
+
before(:each) do
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'returns empty hash by default' do
|
216
|
+
String.translations.should == {}
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'returns @translations if set' do
|
220
|
+
pending "is it @translations on metaclass or @@translations? leaving it out for now"
|
221
|
+
end
|
222
|
+
end
|
data/test/setup.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Add PROJECT/lib to $LOAD_PATH
|
2
|
+
$LOAD_PATH.unshift(File.expand_path("#{__FILE__}/../../lib"))
|
3
|
+
|
4
|
+
# Ensure baretest is required
|
5
|
+
require 'baretest'
|
6
|
+
|
7
|
+
# Some defaults on BareTest (see Kernel#BareTest)
|
8
|
+
BareTest do
|
9
|
+
require_baretest "0.5.0" # minimum baretest version to run these tests
|
10
|
+
require_ruby "1.8.7" # minimum ruby version to run these tests
|
11
|
+
use :support # Use :support in all suites
|
12
|
+
use :basic_verifications
|
13
|
+
end
|
14
|
+
|
15
|
+
require 'ruby-debug'
|
@@ -0,0 +1,189 @@
|
|
1
|
+
@singular | @plural
|
2
|
+
'ability' | 'abilities'
|
3
|
+
'account' | 'accounts'
|
4
|
+
'address' | 'addresses'
|
5
|
+
'agency' | 'agencies'
|
6
|
+
'alga' | 'algae'
|
7
|
+
'alias' | 'aliases'
|
8
|
+
'alumna' | 'alumnae'
|
9
|
+
'alumnus' | 'alumni'
|
10
|
+
'analysis' | 'analyses'
|
11
|
+
'appendix' | 'appendices'
|
12
|
+
'archive' | 'archives'
|
13
|
+
'arena' | 'arenas'
|
14
|
+
'article' | 'articles'
|
15
|
+
'asset' | 'assets'
|
16
|
+
'athlete' | 'athletes'
|
17
|
+
'attachment' | 'attachments'
|
18
|
+
'axis' | 'axes'
|
19
|
+
'basis' | 'bases'
|
20
|
+
'book' | 'books'
|
21
|
+
'bookie' | 'bookies'
|
22
|
+
'box' | 'boxes'
|
23
|
+
'branch' | 'branches'
|
24
|
+
'buffalo' | 'buffaloes'
|
25
|
+
'bus' | 'buses'
|
26
|
+
'buy' | 'buys'
|
27
|
+
'case' | 'cases'
|
28
|
+
'cactus' | 'cacti'
|
29
|
+
'cat' | 'cats'
|
30
|
+
'category' | 'categories'
|
31
|
+
'child' | 'children'
|
32
|
+
'city' | 'cities'
|
33
|
+
'comment' | 'comments'
|
34
|
+
'commit' | 'commits'
|
35
|
+
'cookie' | 'cookies'
|
36
|
+
'cow' | 'cows'
|
37
|
+
'crisis' | 'crises'
|
38
|
+
'criterion' | 'criteria'
|
39
|
+
'cross' | 'crosses'
|
40
|
+
'crunch' | 'crunches'
|
41
|
+
'cry' | 'cries'
|
42
|
+
'date' | 'dates'
|
43
|
+
'datum' | 'data'
|
44
|
+
'day' | 'days'
|
45
|
+
'diagnosis' | 'diagnoses'
|
46
|
+
'die' | 'dice'
|
47
|
+
'document' | 'documents'
|
48
|
+
'download' | 'downloads'
|
49
|
+
'drive' | 'drives'
|
50
|
+
'dwarf' | 'dwarves'
|
51
|
+
'edge' | 'edges'
|
52
|
+
'edition' | 'editions'
|
53
|
+
'elf' | 'elves'
|
54
|
+
'equipment' | 'equipment'
|
55
|
+
'erratum' | 'errata'
|
56
|
+
'event' | 'events'
|
57
|
+
'experience' | 'experiences'
|
58
|
+
'fish' | 'fish'
|
59
|
+
'fix' | 'fixes'
|
60
|
+
'fly' | 'flies'
|
61
|
+
'focus' | 'foci'
|
62
|
+
'foobar' | 'foobars'
|
63
|
+
'formula' | 'formulae'
|
64
|
+
'forum' | 'fora'
|
65
|
+
'fox' | 'foxes'
|
66
|
+
'friend' | 'friends'
|
67
|
+
'fruit' | 'fruits'
|
68
|
+
'fungus' | 'fungi'
|
69
|
+
'game' | 'games'
|
70
|
+
'german' | 'germans'
|
71
|
+
'goose' | 'geese'
|
72
|
+
'grass' | 'grass'
|
73
|
+
'guy' | 'guys'
|
74
|
+
'half' | 'halves'
|
75
|
+
'hero' | 'heroes'
|
76
|
+
'hippopotamus' | 'hippopotami'
|
77
|
+
'hive' | 'hives'
|
78
|
+
'horse' | 'horses'
|
79
|
+
'house' | 'houses'
|
80
|
+
'hovercraft' | 'hovercraft'
|
81
|
+
'human' | 'humans'
|
82
|
+
'income' | 'incomes'
|
83
|
+
'index' | 'indices'
|
84
|
+
'information' | 'information'
|
85
|
+
'installation' | 'installations'
|
86
|
+
'invoice' | 'invoices'
|
87
|
+
'job' | 'jobs'
|
88
|
+
'joy' | 'joys'
|
89
|
+
'life' | 'lives'
|
90
|
+
'link' | 'links'
|
91
|
+
'location' | 'locations'
|
92
|
+
'louse' | 'lice'
|
93
|
+
'man' | 'men'
|
94
|
+
'map' | 'maps'
|
95
|
+
'mash' | 'mashes'
|
96
|
+
'matrix_fu' | 'matrix_fus'
|
97
|
+
'matrix' | 'matrices'
|
98
|
+
'medium' | 'media'
|
99
|
+
'memorandum' | 'memoranda'
|
100
|
+
'milk' | 'milk'
|
101
|
+
'money' | 'money'
|
102
|
+
'moose' | 'moose'
|
103
|
+
'mouse' | 'mice'
|
104
|
+
'move' | 'moves'
|
105
|
+
'movie' | 'movies'
|
106
|
+
'mysql' | 'mysql'
|
107
|
+
'nebula' | 'nebulae'
|
108
|
+
'newsletter' | 'newsletters'
|
109
|
+
'news' | 'news'
|
110
|
+
'node_child' | 'node_children'
|
111
|
+
'octopus' | 'octopi'
|
112
|
+
'old_news' | 'old_news'
|
113
|
+
'ox' | 'oxen'
|
114
|
+
'package' | 'packages'
|
115
|
+
'penis' | 'penises'
|
116
|
+
'person' | 'people'
|
117
|
+
'perspective' 'perspectives'
|
118
|
+
'phenomenon' | 'phenomena'
|
119
|
+
'photo' | 'photos'
|
120
|
+
'ping' | 'pings'
|
121
|
+
'plus' | 'plusses'
|
122
|
+
'pokemon' | 'pokemon'
|
123
|
+
'pokémon' | 'pokémon'
|
124
|
+
'portfolio' | 'portfolios'
|
125
|
+
'postgres' | 'postgres'
|
126
|
+
'post' | 'posts'
|
127
|
+
'potato' | 'potatoes'
|
128
|
+
'prey' | 'preys'
|
129
|
+
'price' | 'prices'
|
130
|
+
'prize' | 'prizes'
|
131
|
+
'process' | 'processes'
|
132
|
+
'product' | 'products'
|
133
|
+
'project' | 'projects'
|
134
|
+
'proof' | 'proofs'
|
135
|
+
'query' | 'queries'
|
136
|
+
'quiz' | 'quizzes'
|
137
|
+
'radius' | 'radii'
|
138
|
+
'rain' | 'rain'
|
139
|
+
'rat' | 'rats'
|
140
|
+
'ray' | 'rays'
|
141
|
+
'rice' | 'rice'
|
142
|
+
'rookie' | 'rookies'
|
143
|
+
'rose' | 'roses'
|
144
|
+
'safe' | 'saves'
|
145
|
+
'salesperson' 'salespeople'
|
146
|
+
'schedule' | 'schedules'
|
147
|
+
'search' | 'searches'
|
148
|
+
'series' | 'series'
|
149
|
+
'server' | 'servers'
|
150
|
+
'shaman' | 'shamans'
|
151
|
+
'sheep' | 'sheep'
|
152
|
+
'shelf' | 'shelves'
|
153
|
+
'shoe' | 'shoes'
|
154
|
+
'song' | 'songs'
|
155
|
+
'spam' | 'spams'
|
156
|
+
'species' | 'species'
|
157
|
+
'spokesman' | 'spokesmen'
|
158
|
+
'sportsman' | 'sportsmen'
|
159
|
+
'spray' | 'sprays'
|
160
|
+
'stack' | 'stacks'
|
161
|
+
'status_code' 'status_codes'
|
162
|
+
'status' | 'statuses'
|
163
|
+
'stimulus' | 'stimuli'
|
164
|
+
'Swiss' | 'Swiss'
|
165
|
+
'switch' | 'switches'
|
166
|
+
'syllabus' | 'syllabi'
|
167
|
+
'talisman' | 'talismans'
|
168
|
+
'testis' | 'testes'
|
169
|
+
'thesaurus' | 'thesauri'
|
170
|
+
'thesis' | 'theses'
|
171
|
+
'thief' | 'thieves'
|
172
|
+
'ticket' | 'tickets'
|
173
|
+
'tomato' | 'tomatoes'
|
174
|
+
'tooth' | 'teeth'
|
175
|
+
'torpedo' | 'torpedoes'
|
176
|
+
'tournament' | 'tournaments'
|
177
|
+
'toy' | 'toys'
|
178
|
+
'trash' | 'trashes'
|
179
|
+
'typo' | 'typos'
|
180
|
+
'url' | 'urls'
|
181
|
+
'version' | 'versions'
|
182
|
+
'vertebra' | 'vertebrae'
|
183
|
+
'vertex' | 'vertices'
|
184
|
+
'virus' | 'viruses'
|
185
|
+
'vita' | 'vitae'
|
186
|
+
'wife' | 'wives'
|
187
|
+
'wish' | 'wishes'
|
188
|
+
'woman' | 'women'
|
189
|
+
'zero' | 'zeroes'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# So we can test with all provided solutions
|
2
|
+
#BareTest.new_component :inflection do
|
3
|
+
require 'inflection'
|
4
|
+
suite 'Inflection', :use => :tabular_data do
|
5
|
+
suite 'bijective' do
|
6
|
+
setup.tabular_data <<-TABLE
|
7
|
+
@from | @to
|
8
|
+
:singular | :plural
|
9
|
+
:plural | :singular
|
10
|
+
TABLE
|
11
|
+
|
12
|
+
setup.tabular_data(File.read(File.expand_path('../inflection', __FILE__)))
|
13
|
+
|
14
|
+
setup do
|
15
|
+
class << self
|
16
|
+
attr_reader :singular, :plural
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
exercise "converting :singular <=> :plural from :from" do
|
21
|
+
::Inflection.send(@to, send(@from))
|
22
|
+
end
|
23
|
+
verify "returns :to" do
|
24
|
+
returns(send(@to))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
suite 'injective singular -> plural' do
|
29
|
+
|
30
|
+
setup.tabular_data(File.read(File.expand_path('../injective', __FILE__)))
|
31
|
+
|
32
|
+
exercise "converting :plural" do
|
33
|
+
::Inflection.singular(@plural)
|
34
|
+
end
|
35
|
+
verify "returns :singular" do
|
36
|
+
returns(@singular)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: inflection
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
version: "0.1"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Dan Kubb
|
12
|
+
- Simon Hafner
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-07 00:00:00 +02:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Support library for inflections
|
22
|
+
email:
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .gitignore
|
32
|
+
- LICENSE
|
33
|
+
- README.rdoc
|
34
|
+
- VERSION
|
35
|
+
- inflection.gemspec
|
36
|
+
- lib/inflection.rb
|
37
|
+
- spec/inflection_extras_spec.rb
|
38
|
+
- spec/string_spec.rb
|
39
|
+
- test/setup.rb
|
40
|
+
- test/suite/lib/inflection
|
41
|
+
- test/suite/lib/inflection.rb
|
42
|
+
- test/suite/lib/injective
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/Tass/extlib
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options:
|
49
|
+
- --charset=UTF-8
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
segments:
|
66
|
+
- 0
|
67
|
+
version: "0"
|
68
|
+
requirements: []
|
69
|
+
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 1.3.7
|
72
|
+
signing_key:
|
73
|
+
specification_version: 3
|
74
|
+
summary: Provies english inflection.
|
75
|
+
test_files: []
|
76
|
+
|