lotus-utils 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64d787540b5ba2d1447be4ca787761da010c880b
4
- data.tar.gz: a8346f11b65e9500e7a260b53d077bf344e2c00b
3
+ metadata.gz: 3582ab69182aac292556f21c4a1021c09a9a4d50
4
+ data.tar.gz: 0f0e3a5561dee1797652203eb4fd6bdf75d01189
5
5
  SHA512:
6
- metadata.gz: b41336646647d1afd5280133b27fab60b88c267693aaef772ad43cc8fb460366be9ee80e04b16ff636a0b92382cb06287df8b2472815a87a3a6ed1d74731f1de
7
- data.tar.gz: d7da2e60819e1c78de89b3b880ad7793475224b6647e5420d0446856aecff7dcdfa55fb621fc66ec1e1b0db16538d8052f8c9aef69336e98b66eca8482173e62
6
+ metadata.gz: efcbf3a494ad1c10a1fd9f76dfbccc181af68eb001035633c603cf19bc01e4f66832c97169269b7af35f276cec245bc375a01166cdfd94dd6225a5f186855a89
7
+ data.tar.gz: 7f6ec20ba5908141c698eb3d1893b0e894621ee8c4e21f1a01e1bc22206da2eaa78f3bf86a8059ae9e81e84916bebd573ee1df63cce2496a9b4077ee9e603f20
data/CHANGELOG.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # Lotus::Utils
2
2
  Ruby core extentions and class utilities for Lotus
3
3
 
4
+ ## v0.4.1 - 2015-05-15
5
+ ### Added
6
+ - [Luca Guidi & Alfonso Uceda Pompa] Introduced `Lotus::Utils::Inflector`, `Lotus::Utils::String#pluralize` and `#singularize`
7
+
8
+ ### Fixed
9
+ - [Luca Guidi] Ensure `Lotus::Utils::Attributes#to_h` to safely return nested `::Hash` instances for complex data structures.
10
+ - [Luca Guidi] Let `Lotus::Interactor#error` to return a falsey value for control flow. (eg. `check_permissions or error "You can't access"`)
11
+
4
12
  ## v0.4.0 - 2015-03-23
5
13
  ### Added
6
14
  - [Luca Guidi] Introduced `Lotus::Utils::Escape`. It implements OWASP/ESAPI suggestions for HTML, HTML attribute and URL escape utilities.
@@ -176,6 +176,8 @@ module Lotus
176
176
  # require 'lotus/interactor'
177
177
  #
178
178
  # class Signup
179
+ # include Lotus::Interactor
180
+ #
179
181
  # def initialize(params)
180
182
  # @params = params
181
183
  # @user = User.new(@params)
@@ -198,6 +200,8 @@ module Lotus
198
200
  # require 'lotus/interactor'
199
201
  #
200
202
  # class Signup
203
+ # include Lotus::Interactor
204
+ #
201
205
  # def initialize(params)
202
206
  # @params = params
203
207
  # @user = User.new(@params)
@@ -293,6 +297,8 @@ module Lotus
293
297
  #
294
298
  # @param message [String] the error message
295
299
  #
300
+ # @return false
301
+ #
296
302
  # @since 0.3.5
297
303
  #
298
304
  # @see Lotus::Interactor#error!
@@ -336,6 +342,7 @@ module Lotus
336
342
  # result.logger # => [:prepare_data!, :persist!, :sync!]
337
343
  def error(message)
338
344
  @_errors << message
345
+ false
339
346
  end
340
347
 
341
348
  # Log an error AND interrupting the flow.
@@ -110,7 +110,24 @@ module Lotus
110
110
  #
111
111
  # @see Lotus::Utils::Hash
112
112
  def to_h
113
- @attributes.deep_dup
113
+ Utils::Hash.new.tap do |result|
114
+ @attributes.each do |k, v|
115
+ result[k] = _read_value(v)
116
+ end
117
+ end
118
+ end
119
+
120
+ private
121
+
122
+ # @since 0.4.1
123
+ # @api private
124
+ def _read_value(value)
125
+ case val = value
126
+ when ::Hash, ::Lotus::Utils::Hash, ->(v) { v.respond_to?(:lotus_nested_attributes?) }
127
+ val.to_h
128
+ else
129
+ val
130
+ end
114
131
  end
115
132
  end
116
133
  end
@@ -0,0 +1,586 @@
1
+ module Lotus
2
+ module Utils
3
+ # String inflector
4
+ #
5
+ # @since 0.4.1
6
+ # @api private
7
+ module Inflector
8
+ # Rule for irregular plural
9
+ #
10
+ # @since 0.4.1
11
+ # @api private
12
+ class IrregularRule
13
+ # @since 0.4.1
14
+ # @api private
15
+ def initialize(rules)
16
+ @rules = rules
17
+ @rules.freeze
18
+ end
19
+
20
+ # @since 0.4.1
21
+ # @api private
22
+ def ===(other)
23
+ key = other.downcase
24
+ @rules.key?(key) || @rules.value?(key)
25
+ end
26
+
27
+ # @since 0.4.1
28
+ # @api private
29
+ def apply(string)
30
+ key = string.downcase
31
+ result = @rules[key] || @rules.rassoc(key).last
32
+
33
+ string[0] + result[1..-1]
34
+ end
35
+ end
36
+
37
+ # Rule for irregular plural, that uses a suffix.
38
+ #
39
+ # @since 0.4.1
40
+ # @api private
41
+ class SuffixRule < IrregularRule
42
+ def initialize(matcher, replacement, rules)
43
+ super(rules)
44
+ @matcher = matcher
45
+ @replacement = replacement
46
+ end
47
+
48
+ # @since 0.4.1
49
+ # @api private
50
+ def ===(other)
51
+ @rules.key?(other.downcase)
52
+ end
53
+
54
+ # @since 0.4.1
55
+ # @api private
56
+ def apply(string)
57
+ string.sub(@matcher, @replacement)
58
+ end
59
+ end
60
+
61
+ # Matcher for blank strings
62
+ #
63
+ # @since 0.4.1
64
+ # @api private
65
+ BLANK_STRING_MATCHER = /\A[[:space:]]*\z/.freeze
66
+
67
+ # @since 0.4.1
68
+ # @api private
69
+ A = 'a'.freeze
70
+
71
+ # @since 0.4.1
72
+ # @api private
73
+ CH = 'ch'.freeze
74
+
75
+ # @since 0.4.1
76
+ # @api private
77
+ CHES = 'ches'.freeze
78
+
79
+ # @since 0.4.1
80
+ # @api private
81
+ EAUX = 'eaux'.freeze
82
+
83
+ # @since 0.4.1
84
+ # @api private
85
+ F = 'f'.freeze
86
+
87
+ # @since 0.4.1
88
+ # @api private
89
+ I = 'i'.freeze
90
+
91
+ # @since 0.4.1
92
+ # @api private
93
+ ICE = 'ice'.freeze
94
+
95
+ # @since 0.4.1
96
+ # @api private
97
+ ICES = 'ices'.freeze
98
+
99
+ # @since 0.4.1
100
+ # @api private
101
+ IDES = 'ides'.freeze
102
+
103
+ # @since 0.4.1
104
+ # @api private
105
+ IES = 'ies'.freeze
106
+
107
+ # @since 0.4.1
108
+ # @api private
109
+ IFE = 'ife'.freeze
110
+
111
+ # @since 0.4.1
112
+ # @api private
113
+ INA = 'ina'.freeze
114
+
115
+ # @since 0.4.1
116
+ # @api private
117
+ IS = 'is'.freeze
118
+
119
+ # @since 0.4.1
120
+ # @api private
121
+ IVES = 'ives'.freeze
122
+
123
+ # @since 0.4.1
124
+ # @api private
125
+ MA = 'ma'.freeze
126
+
127
+ # @since 0.4.1
128
+ # @api private
129
+ MATA = 'mata'.freeze
130
+
131
+ # @since 0.4.1
132
+ # @api private
133
+ MEN = 'men'.freeze
134
+
135
+ # @since 0.4.1
136
+ # @api private
137
+ MINA = 'mina'.freeze
138
+
139
+ # @since 0.4.1
140
+ # @api private
141
+ O = 'o'.freeze
142
+
143
+ # @since 0.4.1
144
+ # @api private
145
+ OES = 'oes'.freeze
146
+
147
+ # @since 0.4.1
148
+ # @api private
149
+ OUSE = 'ouse'.freeze
150
+
151
+ # @since 0.4.1
152
+ # @api private
153
+ S = 's'.freeze
154
+
155
+ # @since 0.4.1
156
+ # @api private
157
+ SES = 'ses'.freeze
158
+
159
+ # @since 0.4.1
160
+ # @api private
161
+ SSES = 'sses'.freeze
162
+
163
+ # @since 0.4.1
164
+ # @api private
165
+ UM = 'um'.freeze
166
+
167
+ # @since 0.4.1
168
+ # @api private
169
+ US = 'us'.freeze
170
+
171
+ # @since 0.4.1
172
+ # @api private
173
+ USES = 'uses'.freeze
174
+
175
+ # @since 0.4.1
176
+ # @api private
177
+ VES = 'ves'.freeze
178
+
179
+ # @since 0.4.1
180
+ # @api private
181
+ X = 'x'.freeze
182
+
183
+ # @since 0.4.1
184
+ # @api private
185
+ XES = 'xes'.freeze
186
+
187
+ # @since 0.4.1
188
+ # @api private
189
+ Y = 'y'.freeze
190
+
191
+ # Plural rule "is" => "es"
192
+ #
193
+ # @since 0.4.1
194
+ # @api private
195
+ PLURAL_IS_ES = SuffixRule.new( /is\z/, 'es', {
196
+ 'analysis' => true,
197
+ 'axis' => true,
198
+ 'basis' => true,
199
+ 'crisis' => true,
200
+ 'diagnosis' => true,
201
+ 'ellipsis' => true,
202
+ 'hypothesis' => true,
203
+ 'oasis' => true,
204
+ 'paralysis' => true,
205
+ 'parenthesis' => true,
206
+ 'synopsis' => true,
207
+ 'synthesis' => true,
208
+ 'thesis' => true,
209
+ })
210
+
211
+ # Plural rule "is" => "ides"
212
+ #
213
+ # @since 0.4.1
214
+ # @api private
215
+ PLURAL_IS_IDES = SuffixRule.new( /is\z/, 'ides', {
216
+ 'clitoris' => true,
217
+ 'iris' => true,
218
+ })
219
+
220
+ # Plural rule "f" => "s"
221
+ #
222
+ # @since 0.4.1
223
+ # @api private
224
+ PLURAL_F_S = SuffixRule.new( /\z/, 's', {
225
+ 'chief' => true,
226
+ 'spoof' => true,
227
+ })
228
+
229
+ # Plural rule "o" => "oes"
230
+ #
231
+ # @since 0.4.1
232
+ # @api private
233
+ PLURAL_O_OES = SuffixRule.new( /\z/, 'es', {
234
+ 'buffalo' => true,
235
+ 'domino' => true,
236
+ 'echo' => true,
237
+ 'embargo' => true,
238
+ 'hero' => true,
239
+ 'mosquito' => true,
240
+ 'potato' => true,
241
+ 'tomato' => true,
242
+ 'torpedo' => true,
243
+ 'veto' => true,
244
+ })
245
+
246
+ # Irregular rules
247
+ #
248
+ # @since 0.4.1
249
+ # @api private
250
+ PLURAL_IRREGULAR = IrregularRule.new({
251
+ # irregular
252
+ 'cactus' => 'cacti',
253
+ 'child' => 'children',
254
+ 'corpus' => 'corpora',
255
+ 'foot' => 'feet',
256
+ 'genus' => 'genera',
257
+ 'goose' => 'geese',
258
+ 'man' => 'men',
259
+ 'ox' => 'oxen',
260
+ 'person' => 'people',
261
+ 'quiz' => 'quizzes',
262
+ 'sex' => 'sexes',
263
+ 'testis' => 'testes',
264
+ 'tooth' => 'teeth',
265
+ 'woman' => 'women',
266
+ # uncountable
267
+ 'deer' => 'deer',
268
+ 'equipment' => 'equipment',
269
+ 'fish' => 'fish',
270
+ 'information' => 'information',
271
+ 'means' => 'means',
272
+ 'money' => 'money',
273
+ 'news' => 'news',
274
+ 'offspring' => 'offspring',
275
+ 'rice' => 'rice',
276
+ 'series' => 'series',
277
+ 'sheep' => 'sheep',
278
+ 'species' => 'species',
279
+ # a => ae
280
+ 'alumna' => 'alumnae',
281
+ 'alga' => 'algae',
282
+ 'vertebra' => 'vertebrae',
283
+ 'persona' => 'personae',
284
+ 'antenna' => 'antennae',
285
+ 'formula' => 'formulae',
286
+ 'nebula' => 'nebulae',
287
+ 'vita' => 'vitae',
288
+ # on => a
289
+ 'criterion' => 'criteria',
290
+ 'perihelion' => 'perihelia',
291
+ 'aphelion' => 'aphelia',
292
+ 'phenomenon' => 'phenomena',
293
+ 'prolegomenon' => 'prolegomena',
294
+ 'noumenon' => 'noumena',
295
+ 'organon' => 'organa',
296
+ 'asyndeton' => 'asyndeta',
297
+ 'hyperbaton' => 'hyperbata',
298
+ # us => i
299
+ 'alumnus' => 'alumni',
300
+ 'alveolus' => 'alveoli',
301
+ 'bacillus' => 'bacilli',
302
+ 'bronchus' => 'bronchi',
303
+ 'locus' => 'loci',
304
+ 'nucleus' => 'nuclei',
305
+ 'stimulus' => 'stimuli',
306
+ 'meniscus' => 'menisci',
307
+ 'thesaurus' => 'thesauri',
308
+ # a => ata
309
+ 'anathema' => 'anathemata',
310
+ 'enema' => 'enemata',
311
+ 'oedema' => 'oedemata',
312
+ 'bema' => 'bemata',
313
+ 'enigma' => 'enigmata',
314
+ 'sarcoma' => 'sarcomata',
315
+ 'carcinoma' => 'carcinomata',
316
+ 'gumma' => 'gummata',
317
+ 'schema' => 'schemata',
318
+ 'charisma' => 'charismata',
319
+ 'lemma' => 'lemmata',
320
+ 'soma' => 'somata',
321
+ 'diploma' => 'diplomata',
322
+ 'lymphoma' => 'lymphomata',
323
+ 'stigma' => 'stigmata',
324
+ 'dogma' => 'dogmata',
325
+ 'magma' => 'magmata',
326
+ 'stoma' => 'stomata',
327
+ 'drama' => 'dramata',
328
+ 'melisma' => 'melismata',
329
+ 'trauma' => 'traumata',
330
+ 'edema' => 'edemata',
331
+ 'miasma' => 'miasmata',
332
+ # s => es
333
+ 'acropolis' => 'acropolises',
334
+ 'chaos' => 'chaoses',
335
+ 'lens' => 'lenses',
336
+ 'aegis' => 'aegises',
337
+ 'cosmos' => 'cosmoses',
338
+ 'mantis' => 'mantises',
339
+ 'alias' => 'aliases',
340
+ 'dais' => 'daises',
341
+ 'marquis' => 'marquises',
342
+ 'asbestos' => 'asbestoses',
343
+ 'digitalis' => 'digitalises',
344
+ 'metropolis' => 'metropolises',
345
+ 'atlas' => 'atlases',
346
+ 'epidermis' => 'epidermises',
347
+ 'pathos' => 'pathoses',
348
+ 'bathos' => 'bathoses',
349
+ 'ethos' => 'ethoses',
350
+ 'pelvis' => 'pelvises',
351
+ 'bias' => 'biases',
352
+ 'gas' => 'gases',
353
+ 'polis' => 'polises',
354
+ 'caddis' => 'caddises',
355
+ 'rhinoceros' => 'rhinoceroses',
356
+ 'cannabis' => 'cannabises',
357
+ 'glottis' => 'glottises',
358
+ 'sassafras' => 'sassafrases',
359
+ 'canvas' => 'canvases',
360
+ 'ibis' => 'ibises',
361
+ 'trellis' => 'trellises',
362
+ })
363
+
364
+ # Irregular rules
365
+ #
366
+ # @since 0.4.1
367
+ # @api private
368
+ SINGULAR_IRREGULAR = IrregularRule.new({
369
+ # irregular
370
+ 'cacti' => 'cactus',
371
+ 'children'=> 'child',
372
+ 'corpora' => 'corpus',
373
+ 'feet' => 'foot',
374
+ 'genera' => 'genus',
375
+ 'geese' => 'goose',
376
+ 'men' => 'man',
377
+ 'oxen' => 'ox',
378
+ 'people' => 'person',
379
+ 'quizzes' => 'quiz',
380
+ 'sexes' => 'sex',
381
+ 'testes' => 'testis',
382
+ 'teeth' => 'tooth',
383
+ 'women' => 'woman',
384
+ # uncountable
385
+ 'deer' => 'deer',
386
+ 'equipment' => 'equipment',
387
+ 'fish' => 'fish',
388
+ 'information' => 'information',
389
+ 'means' => 'means',
390
+ 'money' => 'money',
391
+ 'news' => 'news',
392
+ 'offspring' => 'offspring',
393
+ 'rice' => 'rice',
394
+ 'series' => 'series',
395
+ 'sheep' => 'sheep',
396
+ 'species' => 'species',
397
+ 'police' => 'police',
398
+ # ae => a
399
+ 'alumnae' => 'alumna',
400
+ 'algae' => 'alga',
401
+ 'vertebrae' => 'vertebra',
402
+ 'personae' => 'persona',
403
+ 'antennae' => 'antenna',
404
+ 'formulae' => 'formula',
405
+ 'nebulae' => 'nebula',
406
+ 'vitae' => 'vita',
407
+ # a = on
408
+ 'criteria' => 'criterion',
409
+ 'perihelia' => 'perihelion',
410
+ 'aphelia' => 'aphelion',
411
+ 'phenomena' => 'phenomenon',
412
+ 'prolegomena' => 'prolegomenon',
413
+ 'noumena' => 'noumenon',
414
+ 'organa' => 'organon',
415
+ 'asyndeta' => 'asyndeton',
416
+ 'hyperbata' => 'hyperbaton',
417
+ # ses => s
418
+ 'acropolises' => 'acropolis',
419
+ 'chaoses' => 'chaos',
420
+ 'lenses' => 'lens',
421
+ 'aegises' => 'aegis',
422
+ 'cosmoses' => 'cosmos',
423
+ 'mantises' => 'mantis',
424
+ 'aliases' => 'alias',
425
+ 'daises' => 'dais',
426
+ 'marquises' => 'marquis',
427
+ 'asbestoses' => 'asbestos',
428
+ 'digitalises' => 'digitalis',
429
+ 'metropolises' => 'metropolis',
430
+ 'atlases' => 'atlas',
431
+ 'epidermises' => 'epidermis',
432
+ 'pathoses' => 'pathos',
433
+ 'bathoses' => 'bathos',
434
+ 'ethoses' => 'ethos',
435
+ 'pelvises' => 'pelvis',
436
+ 'biases' => 'bias',
437
+ 'gases' => 'gas',
438
+ 'polises' => 'polis',
439
+ 'caddises' => 'caddis',
440
+ 'rhinoceroses' => 'rhinoceros',
441
+ 'cannabises' => 'cannabis',
442
+ 'glottises' => 'glottis',
443
+ 'sassafrases' => 'sassafras',
444
+ 'canvases' => 'canvas',
445
+ 'ibises' => 'ibis',
446
+ 'trellises' => 'trellis',
447
+ # fallback
448
+ 'hives' => 'hive',
449
+ # ices => ex
450
+ "codices" => "codex",
451
+ "murices" => "murex",
452
+ "silices" => "silex",
453
+ "apices" => "apex",
454
+ "latices" => "latex",
455
+ "vertices" => "vertex",
456
+ "cortices" => "cortex",
457
+ "pontifices" => "pontifex",
458
+ "vortices" => "vortex",
459
+ "indices" => "index",
460
+ "simplices" => "simplex",
461
+ # ices => ix
462
+ "radices" => "radix",
463
+ "helices" => "helix",
464
+ "appendices" => "appendix",
465
+ # es => is
466
+ "axes" => "axis",
467
+ "analyses" => "analysis",
468
+ "bases" => "basis",
469
+ "crises" => "crisis",
470
+ "diagnoses" => "diagnosis",
471
+ "ellipses" => "ellipsis",
472
+ "hypotheses" => "hypothesis",
473
+ "oases" => "oasis",
474
+ "paralyses" => "paralysis",
475
+ "parentheses" => "parenthesis",
476
+ "syntheses" => "synthesis",
477
+ "synopses" => "synopsis",
478
+ "theses" => "thesis",
479
+ })
480
+
481
+ # Pluralize the given string
482
+ #
483
+ # @param string [String] a string to pluralize
484
+ #
485
+ # @return [String,NilClass] the pluralized string, if present
486
+ #
487
+ # @api private
488
+ # @since 0.4.1
489
+ def self.pluralize(string)
490
+ return string if string.nil? || string.match(BLANK_STRING_MATCHER)
491
+
492
+ case string
493
+ when PLURAL_IRREGULAR
494
+ PLURAL_IRREGULAR.apply(string)
495
+ when /\A((.*)[^aeiou])ch\z/
496
+ $1 + CHES
497
+ when /\A((.*)[^aeiou])y\z/
498
+ $1 + IES
499
+ when /\A(.*)(ex|ix)\z/
500
+ $1 + ICES
501
+ when /\A(.*)(eau|#{ EAUX })\z/
502
+ $1 + EAUX
503
+ when /\A(.*)x\z/
504
+ $1 + XES
505
+ when /\A(.*)(um|#{ A })\z/
506
+ $1 + A
507
+ when /\A(.*)(ouse|#{ ICE })\z/
508
+ $1 + ICE
509
+ when PLURAL_O_OES
510
+ PLURAL_O_OES.apply(string)
511
+ when /\A(.*)(en|#{ INA })\z/
512
+ $1 + INA
513
+ when PLURAL_F_S
514
+ PLURAL_F_S.apply(string)
515
+ when /\A(.*)(?:([^f]))f[e]*\z/
516
+ $1 + $2 + VES
517
+ when /\A(.*)us\z/
518
+ $1 + USES
519
+ when PLURAL_IS_ES
520
+ PLURAL_IS_ES.apply(string)
521
+ when PLURAL_IS_IDES
522
+ PLURAL_IS_IDES.apply(string)
523
+ when /\A(.*)ss\z/
524
+ $1 + SSES
525
+ when /s\z/
526
+ string
527
+ else
528
+ string + S
529
+ end
530
+ end
531
+
532
+ # Singularize the given string
533
+ #
534
+ # @param string [String] a string to singularize
535
+ #
536
+ # @return [String,NilClass] the singularized string, if present
537
+ #
538
+ # @api private
539
+ # @since 0.4.1
540
+ def self.singularize(string)
541
+ return string if string.nil? || string.match(BLANK_STRING_MATCHER)
542
+
543
+ case string
544
+ when SINGULAR_IRREGULAR
545
+ SINGULAR_IRREGULAR.apply(string)
546
+ when /\A.*[^aeiou]#{CHES}\z/
547
+ string.sub(CHES, CH)
548
+ when /\A.*[^aeiou]#{IES}\z/
549
+ string.sub(IES, Y)
550
+ when /\A(.*)#{ICE}\z/
551
+ $1 + OUSE
552
+ when /\A.*#{EAUX}\z/
553
+ string.chop
554
+ when /\A(.*)#{IDES}\z/
555
+ $1 + IS
556
+ when /\A(.*)#{US}\z/
557
+ $1 + I
558
+ when /\A(.*)#{SES}\z/
559
+ $1 + S
560
+ when /\A(.*)#{OUSE}\z/
561
+ $1 + ICE
562
+ when /\A(.*)#{MATA}\z/
563
+ $1 + MA
564
+ when /\A(.*)#{OES}\z/
565
+ $1 + O
566
+ when /\A(.*)#{MINA}\z/
567
+ $1 + MEN
568
+ when /\A(.*)#{XES}\z/
569
+ $1 + X
570
+ when /\A(.*)#{IVES}\z/
571
+ $1 + IFE
572
+ when /\A(.*)#{VES}\z/
573
+ $1 + F
574
+ when /\A(.*)#{I}\z/
575
+ $1 + US
576
+ when /\A(.*)#{A}\z/
577
+ $1 + UM
578
+ when /[^s]\z/
579
+ string
580
+ else
581
+ string.chop
582
+ end
583
+ end
584
+ end
585
+ end
586
+ end
@@ -1,3 +1,5 @@
1
+ require 'lotus/utils/inflector'
2
+
1
3
  module Lotus
2
4
  module Utils
3
5
  # String on steroids
@@ -220,6 +222,30 @@ module Lotus
220
222
  nil
221
223
  end
222
224
 
225
+ # Return a pluralized version of self.
226
+ #
227
+ # @return [Lotus::Utils::String] the pluralized string.
228
+ #
229
+ # @api private
230
+ # @since 0.4.1
231
+ #
232
+ # @see Lotus::Utils::Inflector
233
+ def pluralize
234
+ self.class.new Inflector.pluralize(self)
235
+ end
236
+
237
+ # Return a singularized version of self.
238
+ #
239
+ # @return [Lotus::Utils::String] the singularized string.
240
+ #
241
+ # @api private
242
+ # @since 0.4.1
243
+ #
244
+ # @see Lotus::Utils::Inflector
245
+ def singularize
246
+ self.class.new Inflector.singularize(self)
247
+ end
248
+
223
249
  # Returns the hash of the internal string
224
250
  #
225
251
  # @return [Fixnum]
@@ -3,6 +3,6 @@ module Lotus
3
3
  # Defines the version
4
4
  #
5
5
  # @since 0.1.0
6
- VERSION = '0.4.0'.freeze
6
+ VERSION = '0.4.1'.freeze
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lotus-utils
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-23 00:00:00.000000000 Z
12
+ date: 2015-05-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -74,6 +74,7 @@ files:
74
74
  - lib/lotus/utils/deprecation.rb
75
75
  - lib/lotus/utils/escape.rb
76
76
  - lib/lotus/utils/hash.rb
77
+ - lib/lotus/utils/inflector.rb
77
78
  - lib/lotus/utils/io.rb
78
79
  - lib/lotus/utils/kernel.rb
79
80
  - lib/lotus/utils/load_paths.rb