rext 0.3.4

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.
Files changed (55) hide show
  1. data/History.rdoc +97 -0
  2. data/Manifest +54 -0
  3. data/README.rdoc +136 -0
  4. data/Rakefile +16 -0
  5. data/benchmarks/enumerable.rb +14 -0
  6. data/benchmarks/proc.rb +24 -0
  7. data/lib/rext.rb +24 -0
  8. data/lib/rext/all.rb +18 -0
  9. data/lib/rext/array.rb +6 -0
  10. data/lib/rext/array/helpers.rb +64 -0
  11. data/lib/rext/date.rb +6 -0
  12. data/lib/rext/date/helpers.rb +11 -0
  13. data/lib/rext/enumerable.rb +6 -0
  14. data/lib/rext/enumerable/helpers.rb +88 -0
  15. data/lib/rext/hash.rb +6 -0
  16. data/lib/rext/hash/helpers.rb +42 -0
  17. data/lib/rext/integer.rb +6 -0
  18. data/lib/rext/integer/helpers.rb +29 -0
  19. data/lib/rext/module.rb +6 -0
  20. data/lib/rext/module/helpers.rb +85 -0
  21. data/lib/rext/numeric.rb +7 -0
  22. data/lib/rext/numeric/bytes.rb +16 -0
  23. data/lib/rext/numeric/time.rb +57 -0
  24. data/lib/rext/object.rb +7 -0
  25. data/lib/rext/object/helpers.rb +62 -0
  26. data/lib/rext/object/metaclass.rb +29 -0
  27. data/lib/rext/proc.rb +7 -0
  28. data/lib/rext/proc/helpers.rb +22 -0
  29. data/lib/rext/string.rb +7 -0
  30. data/lib/rext/string/encode.rb +82 -0
  31. data/lib/rext/string/helpers.rb +246 -0
  32. data/lib/rext/symbol.rb +6 -0
  33. data/lib/rext/symbol/helpers.rb +16 -0
  34. data/lib/rext/time.rb +6 -0
  35. data/lib/rext/time/helpers.rb +43 -0
  36. data/lib/rext/version.rb +4 -0
  37. data/rext.gemspec +30 -0
  38. data/spec/array_spec.rb +61 -0
  39. data/spec/date_spec.rb +14 -0
  40. data/spec/enumerable_spec.rb +55 -0
  41. data/spec/hash_spec.rb +36 -0
  42. data/spec/integer_spec.rb +19 -0
  43. data/spec/module_spec.rb +41 -0
  44. data/spec/numeric_spec.rb +31 -0
  45. data/spec/object_spec.rb +101 -0
  46. data/spec/spec.opts +1 -0
  47. data/spec/spec_helper.rb +5 -0
  48. data/spec/string_spec.rb +194 -0
  49. data/spec/symbol_spec.rb +14 -0
  50. data/spec/time_spec.rb +22 -0
  51. data/tasks/benchmark.rake +13 -0
  52. data/tasks/docs.rake +13 -0
  53. data/tasks/gemspec.rake +3 -0
  54. data/tasks/spec.rake +25 -0
  55. metadata +147 -0
@@ -0,0 +1,4 @@
1
+
2
+ module Rext
3
+ VERSION = '0.3.4'
4
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{rext}
5
+ s.version = "0.3.4"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["TJ Holowaychuk"]
9
+ s.date = %q{2009-10-08}
10
+ s.description = %q{Ruby extensions}
11
+ s.email = %q{tj@vision-media.ca}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/rext.rb", "lib/rext/all.rb", "lib/rext/array.rb", "lib/rext/array/helpers.rb", "lib/rext/date.rb", "lib/rext/date/helpers.rb", "lib/rext/enumerable.rb", "lib/rext/enumerable/helpers.rb", "lib/rext/hash.rb", "lib/rext/hash/helpers.rb", "lib/rext/integer.rb", "lib/rext/integer/helpers.rb", "lib/rext/module.rb", "lib/rext/module/helpers.rb", "lib/rext/numeric.rb", "lib/rext/numeric/bytes.rb", "lib/rext/numeric/time.rb", "lib/rext/object.rb", "lib/rext/object/helpers.rb", "lib/rext/object/metaclass.rb", "lib/rext/proc.rb", "lib/rext/proc/helpers.rb", "lib/rext/string.rb", "lib/rext/string/encode.rb", "lib/rext/string/helpers.rb", "lib/rext/symbol.rb", "lib/rext/symbol/helpers.rb", "lib/rext/time.rb", "lib/rext/time/helpers.rb", "lib/rext/version.rb", "tasks/benchmark.rake", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
13
+ s.files = ["History.rdoc", "Manifest", "README.rdoc", "Rakefile", "benchmarks/enumerable.rb", "benchmarks/proc.rb", "lib/rext.rb", "lib/rext/all.rb", "lib/rext/array.rb", "lib/rext/array/helpers.rb", "lib/rext/date.rb", "lib/rext/date/helpers.rb", "lib/rext/enumerable.rb", "lib/rext/enumerable/helpers.rb", "lib/rext/hash.rb", "lib/rext/hash/helpers.rb", "lib/rext/integer.rb", "lib/rext/integer/helpers.rb", "lib/rext/module.rb", "lib/rext/module/helpers.rb", "lib/rext/numeric.rb", "lib/rext/numeric/bytes.rb", "lib/rext/numeric/time.rb", "lib/rext/object.rb", "lib/rext/object/helpers.rb", "lib/rext/object/metaclass.rb", "lib/rext/proc.rb", "lib/rext/proc/helpers.rb", "lib/rext/string.rb", "lib/rext/string/encode.rb", "lib/rext/string/helpers.rb", "lib/rext/symbol.rb", "lib/rext/symbol/helpers.rb", "lib/rext/time.rb", "lib/rext/time/helpers.rb", "lib/rext/version.rb", "rext.gemspec", "spec/array_spec.rb", "spec/date_spec.rb", "spec/enumerable_spec.rb", "spec/hash_spec.rb", "spec/integer_spec.rb", "spec/module_spec.rb", "spec/numeric_spec.rb", "spec/object_spec.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/string_spec.rb", "spec/symbol_spec.rb", "spec/time_spec.rb", "tasks/benchmark.rake", "tasks/docs.rake", "tasks/gemspec.rake", "tasks/spec.rake"]
14
+ s.homepage = %q{http://github.com/visionmedia/rext}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Rext", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{rext}
18
+ s.rubygems_version = %q{1.3.5}
19
+ s.summary = %q{Ruby extensions}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
@@ -0,0 +1,61 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/array'
4
+
5
+ describe Array do
6
+ describe "helpers" do
7
+
8
+ before :each do
9
+ @items = %w( some foo bar )
10
+ end
11
+
12
+ describe "#from" do
13
+ it "should return elements after the position specified" do
14
+ @items.from(1).should == %w( foo bar )
15
+ end
16
+ end
17
+
18
+ describe "#to" do
19
+ it "should return elements up to position" do
20
+ @items.to(1).should == %w( some foo )
21
+ end
22
+ end
23
+
24
+ describe "#chunk" do
25
+ it "should split an array into several containing the length of n" do
26
+ (1..9).to_a.chunk(3).should == [[1,2,3], [4,5,6], [7,8,9]]
27
+ end
28
+
29
+ it "should accept a block, yielding each chunk" do
30
+ chunks = []
31
+ (1..9).to_a.in_groups_of(3) do |chunk|
32
+ chunks << chunk
33
+ end
34
+ chunks.should == [[1,2,3], [4,5,6], [7,8,9]]
35
+ end
36
+
37
+ it "should pad with nil by default" do
38
+ (1..5).to_a.in_groups_of(4).should == [[1,2,3,4], [5,nil,nil,nil]]
39
+ end
40
+
41
+ it "should not padd when pad_with is false" do
42
+ (1..6).to_a.in_groups_of(4, false).should == [[1,2,3,4], [5,6]]
43
+ end
44
+ end
45
+
46
+ describe "#pad" do
47
+ it "should pad with nil by default" do
48
+ [1,2].pad(4).should == [1, 2, nil, nil]
49
+ end
50
+
51
+ it "should pad an with an object" do
52
+ [1,2].pad(3 ,'x').should == [1, 2, 'x']
53
+ end
54
+
55
+ it "should do nothing when the array is of expected length" do
56
+ [1,2].pad(2).should == [1,2]
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,14 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/date'
4
+
5
+ describe Date do
6
+ describe "helpers" do
7
+ describe "#to_time" do
8
+ it "should convert to a Time instance" do
9
+ event = Date.parse('may 25th 1987')
10
+ event.to_time.should be_an_instance_of(Time)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,55 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/enumerable'
4
+
5
+ describe Enumerable do
6
+ describe "helpers" do
7
+ describe "#includes_all?" do
8
+ it "should return true when all arguments are present" do
9
+ [1,2,3].includes_all?(1,2).should be_true
10
+ end
11
+
12
+ it "should return true when not all arguments are present" do
13
+ [1,1,3,3,4].includes_all?(1,3,6).should be_false
14
+ [1,1,3,3,4].includes_all?(6,3,1).should be_false
15
+ end
16
+ end
17
+
18
+ describe "#group_by" do
19
+ before :each do
20
+ @enum = 'foo', :bar, 1, 2, 3
21
+ @results = {
22
+ String => ['foo'],
23
+ Symbol => [:bar],
24
+ Fixnum => [1, 2, 3]
25
+ }
26
+ end
27
+
28
+ it "should group an enum" do
29
+ @enum.group_by { |v| v.class }.should == @results
30
+ end
31
+
32
+ it "should group using instance evaluated block" do
33
+ @enum.group_by { self.class }.should == @results
34
+ end
35
+
36
+ it "should group by method call" do
37
+ @enum.group_by.class.should == @results
38
+ end
39
+ end
40
+
41
+ describe "#every" do
42
+ it "should map a method call" do
43
+ list = %w( cookies icecream sugar )
44
+ list.every.length.should == [7, 8 ,5]
45
+ end
46
+
47
+ it "should allow mapping shortcuts using a block" do
48
+ people = []
49
+ people << mock('Person', :name => 'TJ')
50
+ people << mock('Person', :name => 'Scott')
51
+ people.every { name.length }.should == [2, 5]
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,36 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/hash'
4
+
5
+ describe Hash do
6
+ describe "helpers" do
7
+ describe "#delete_at" do
8
+ it "should delete several keys, returning their values when present" do
9
+ options = { :foo => 1, :bar => 2 }
10
+ foo, bar, does_not_exist = options.delete_at :foo, :bar, :does_not_exist
11
+ foo.should == 1
12
+ bar.should == 2
13
+ does_not_exist.should be_nil
14
+ end
15
+ end
16
+
17
+ describe "#switchify" do
18
+ it "should work with bools" do
19
+ { :use_foobar => true }.switchify.should == ['--use-foobar']
20
+ { :use_foobar => false }.switchify.should be_empty
21
+ end
22
+
23
+ it "should stringify numbers and symbols" do
24
+ { :interval => 15, :icon => :jpeg }.switchify.sort.should == ['--icon', '--interval', '15', 'jpeg']
25
+ end
26
+
27
+ it "should work with little switches" do
28
+ { :T => true }.switchify.should == ['-T']
29
+ end
30
+
31
+ it "should add quotes around strings" do
32
+ { :glob => 'lib/**/*.rb' }.switchify.should == ['--glob', '"lib/**/*.rb"']
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/integer'
4
+
5
+ describe Integer do
6
+ describe "helpers" do
7
+ describe "#ordanalize" do
8
+ it "should convert integers to an ordanal string" do
9
+ 1.ordinalize.should == '1st'
10
+ 2.ordinalize.should == '2nd'
11
+ 3.ordinalize.should == '3rd'
12
+ 4.ordinalize.should == '4th'
13
+ 11.ordinalize.should == '11th'
14
+ 12.ordinalize.should == '12th'
15
+ 13.ordinalize.should == '13th'
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/module'
4
+
5
+ describe Module do
6
+ describe "helpers" do
7
+ describe "#proxy_method" do
8
+ it "should implement method_missing, passing regexp captures and arguments to the handler method" do
9
+ class FooBar
10
+ call_method :find, :if => /^find_by_(\w+)_(\w+)/
11
+ call_method :delete, :if => lambda { |meth, *args| meth.to_s =~ /^delete_by_(\w+)_(\w+)/ }
12
+ def find *args; args end
13
+ def delete *args; args; end
14
+ end
15
+ foo = FooBar.new
16
+ foo.find_by_user_email.should == ['user', 'email']
17
+ foo.find_by_user_name('foo').should == ['user', 'name', 'foo']
18
+ foo.delete_by_user_name('foo', 'bar').should == ['foo', 'bar']
19
+ lambda { foo.does_not_exist }.should raise_error(NoMethodError)
20
+ end
21
+ end
22
+
23
+ describe "#setup" do
24
+ it "should define included instance evaluated in context to the module passed" do
25
+ module BarFoo
26
+ setup do
27
+ include InstanceMethods
28
+ end
29
+
30
+ module InstanceMethods
31
+ def bar_foo
32
+ 'wahoo'
33
+ end
34
+ end
35
+ end
36
+ FooBar.send :include, BarFoo
37
+ FooBar.new.bar_foo.should == 'wahoo'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/numeric'
4
+
5
+ describe Numeric do
6
+ describe "time" do
7
+ describe "#ago / #before" do
8
+ it "should return the distance in time before now, or specified time" do
9
+ event = Time.mktime 1987, 5, 25
10
+ 15.days.before(event).should == Time.mktime(1987, 5, 10)
11
+ end
12
+ end
13
+
14
+ describe "#since / #from_now" do
15
+ it "should return the distance in time from now, or specified time" do
16
+ event = Time.mktime 1987, 5, 25
17
+ 5.days.since(event).should == Time.mktime(1987, 5, 30)
18
+ end
19
+ end
20
+ end
21
+
22
+ describe "bytes" do
23
+ it "should return bytes, kilobytes, megabytes, gigabytes, and terabytes" do
24
+ 5.bytes.should == 5
25
+ 5.kilobytes.should == 5120
26
+ 5.megabytes.should == 5242880
27
+ 5.gigabytes.should == 5368709120
28
+ 5.terabytes.should == 5497558138880
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,101 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/object'
4
+
5
+ describe Object do
6
+ describe "metaclass" do
7
+ describe "#metaclass" do
8
+ it "should return the anonymous 'virtual' class" do
9
+ 'foo'.metaclass.should be_an_instance_of(Class)
10
+ end
11
+ end
12
+
13
+ describe "#meta_eval" do
14
+ it "should evaluate a block in context to the metaclass" do
15
+ object = 'foo'
16
+ object.meta_eval do
17
+ define_method :foo do
18
+ 'bar'
19
+ end
20
+ end
21
+ object.foo.should == 'bar'
22
+ end
23
+
24
+ it "should accept a string to be evaluated" do
25
+ object = 'foo'
26
+ object.meta_eval <<-EOF
27
+ def foo
28
+ 'bar'
29
+ end
30
+ EOF
31
+ object.foo.should == 'bar'
32
+ end
33
+ end
34
+
35
+ describe "#meta_def" do
36
+ it "should define a method within the metaclass" do
37
+ object = 'foo'
38
+ object.meta_def(:foo) { |*args| "bar #{ args.join(', ') }" }
39
+ object.foo(1,2,3).should == 'bar 1, 2, 3'
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "helpers" do
45
+ describe "#indifferent_hash" do
46
+ it "should return a hash indifferent to symbols or strings for key access" do
47
+ hash = indifferent_hash
48
+ hash['foo'] = 'foo'
49
+ hash[:foo].should == 'foo'
50
+ hash['foo'].should == 'foo'
51
+ end
52
+ end
53
+ end
54
+
55
+ describe "#try" do
56
+ it "should try the block once with no args" do
57
+ times = 0
58
+ try { times += 1 }
59
+ times.should == 1
60
+ end
61
+
62
+ it "should try the block multiple times when failing" do
63
+ times = 0
64
+ try(3) { times += 1; raise 'foo' }
65
+ times.should == 3
66
+ end
67
+
68
+ it "should try the block one time when succesful" do
69
+ times = 0
70
+ try(3) { times += 1 }
71
+ times.should == 1
72
+ end
73
+
74
+ it "should return the value returned by the block" do
75
+ val = try(3) { 'test' }
76
+ val.should == 'test'
77
+ end
78
+
79
+ it "should allow specific exceptions to be rescued" do
80
+ lambda { try(3){ raise ArgumentError, 'foo' } }.should_not raise_error
81
+ lambda { try(3, :on => ArgumentError){ raise ArgumentError, 'foo' } }.should_not raise_error
82
+ lambda { try(3, :on => TypeError){ raise ArgumentError, 'foo' } }.should raise_error(ArgumentError)
83
+ end
84
+ end
85
+
86
+ describe "#returning" do
87
+ it "should return the value given to it" do
88
+ def frequency_of enum
89
+ returning Hash.new(0) do |hash|
90
+ enum.each do |value|
91
+ hash[value] += 1
92
+ end
93
+ end
94
+ end
95
+ frequency_of(%w( foo bar foo foo )).should == {
96
+ 'foo' => 3,
97
+ 'bar' => 1,
98
+ }
99
+ end
100
+ end
101
+ end
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,5 @@
1
+
2
+ $:.unshift File.dirname(__FILE__) + '/../lib'
3
+
4
+ require 'rubygems'
5
+ require 'rext/all'
@@ -0,0 +1,194 @@
1
+
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+ require 'rext/string'
4
+
5
+ describe String do
6
+ describe "encode" do
7
+ describe "#to_md5" do
8
+ it "should return an md5 hash" do
9
+ 'test'.to_md5.should == '098f6bcd4621d373cade4e832627b4f6'
10
+ 'test'.to_md5.should == 'test'.to_md5
11
+ 'test'.to_md5.should_not == 'tests'.to_md5
12
+ end
13
+ end
14
+
15
+ describe "#to_sha512" do
16
+ it "should return an md5 hash" do
17
+ 'test'.to_sha512.should == 'ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff'
18
+ 'test'.to_sha512.should == 'test'.to_sha512
19
+ 'test'.to_sha512.should_not == 'tests'.to_sha512
20
+ end
21
+ end
22
+
23
+ describe "#base64_encode" do
24
+ it "should base64 encode a string" do
25
+ 'tj'.base64_encode.should == 'dGo='
26
+ "foo \n bar\n\n".base64_encode.base64_decode.should == "foo \n bar\n\n"
27
+ end
28
+ end
29
+
30
+ describe "#base64_decode" do
31
+ it "should decode a base64 string" do
32
+ 'dGo='.base64_decode.should == 'tj'
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "helpers" do
38
+ describe "#word_frequency" do
39
+ it "should return a hash with word keys and count values" do
40
+ 'mm i love cookies mm'.word_frequency.
41
+ should == {
42
+ 'mm' => 2,
43
+ 'i' => 1,
44
+ 'love' => 1,
45
+ 'cookies' => 1,
46
+ }
47
+ end
48
+ end
49
+
50
+ describe "#frequency_of_word" do
51
+ it "should return the frequency of a word, or 0" do
52
+ 'yum yum ? yes'.frequency_of_word('yum').should == 2
53
+ 'yum yum ? yes'.frequency_of_word('yes').should == 1
54
+ 'yum yum ? yes'.frequency_of_word('no').should == 0
55
+ end
56
+ end
57
+
58
+ describe "#switchify" do
59
+ it "should return a switch version of the string" do
60
+ 'some_foo_bar'.switchify.should == '--some-foo-bar'
61
+ end
62
+
63
+ it "should return small switches when only a single char" do
64
+ 't'.switchify.should == '-t'
65
+ end
66
+
67
+ it "should raise an InvalidSwitchError when length 0" do
68
+ lambda { ''.switchify }.should raise_error(String::InvalidSwitchError)
69
+ end
70
+ end
71
+
72
+ describe "#path" do
73
+ it "should return an instance of a pathname" do
74
+ 'History.rdoc'.path.should be_an_instance_of(Pathname)
75
+ end
76
+ end
77
+
78
+ describe "#files" do
79
+ it "should return result of Dir glob" do
80
+ 'lib/*.*'.files.should be_an_instance_of(Array)
81
+ end
82
+ end
83
+
84
+ describe "#file" do
85
+ it "should return an instance of a file" do
86
+ 'History.rdoc'.file.should be_an_instance_of(File)
87
+ end
88
+ end
89
+
90
+ describe "#add_class" do
91
+ it "should add a word that does not exist" do
92
+ 'foo'.add_class('bar').should == 'foo bar'
93
+ end
94
+
95
+ it "should not add the same word twice" do
96
+ 'foo-bar bar'.add_class('bar').should == 'foo-bar bar'
97
+ end
98
+ end
99
+
100
+ describe "#wrap" do
101
+ it "should wrap a string" do
102
+ 'foo'.wrap('|').should == '|foo|'
103
+ end
104
+
105
+ it "should wrap with optional suffix" do
106
+ 'foo'.wrap('(', ')').should == '(foo)'
107
+ end
108
+ end
109
+
110
+ describe "#starts_with?" do
111
+ it "should check if a string starts with another" do
112
+ 'foo bar'.starts_with?('foo').should be_true
113
+ ' foo bar'.starts_with?('foo').should_not be_true
114
+ 'bar foo'.starts_with?('foo').should_not be_true
115
+ end
116
+ end
117
+
118
+ describe "#ends_with?" do
119
+ it "should check if a string ends with another" do
120
+ 'foo bar'.ends_with?('bar').should be_true
121
+ 'foo bar '.ends_with?('bar').should_not be_true
122
+ 'bar foo foo'.ends_with?('foo').should be_true
123
+ end
124
+ end
125
+
126
+ describe "#plural?" do
127
+ it "should check if a string is plural" do
128
+ 'cookies'.should be_plural
129
+ 'cookie'.should_not be_plural
130
+ end
131
+ end
132
+
133
+ describe "#singular?" do
134
+ it "should check if a string is singular" do
135
+ 'cookie'.should be_singular
136
+ 'cookies'.should_not be_singular
137
+ end
138
+ end
139
+
140
+ describe "#first" do
141
+ it "should return the first character" do
142
+ 'foo'.first.should == 'f'
143
+ end
144
+
145
+ it "should return n number of charcters" do
146
+ 'foo'.first(2).should == 'fo'
147
+ end
148
+ end
149
+
150
+ describe "#last" do
151
+ it "should return the last character" do
152
+ 'bar'.last.should == 'r'
153
+ end
154
+
155
+ it "should return the last n number of characters" do
156
+ 'bar'.last(2).should == 'ar'
157
+ end
158
+ end
159
+
160
+ describe "#from" do
161
+ it "should return all characters from n" do
162
+ 'cookies'.from(3).should == 'kies'
163
+ end
164
+ end
165
+
166
+ describe "#camelize" do
167
+ it "should camel-case a string, leaving the first character lower by default" do
168
+ 'some_foo_bar'.camelize.should == 'someFooBar'
169
+ end
170
+
171
+ it "should camel-case a string, with first character capitalized" do
172
+ 'some_foo_bar'.camelize(true).should == 'SomeFooBar'
173
+ end
174
+ end
175
+
176
+ describe "#constantize" do
177
+ it "should convert a string to a constant" do
178
+ 'Rext::VERSION'.constantize.should == Rext::VERSION
179
+ end
180
+
181
+ it "should raise an error when an invalid constant name is passed" do
182
+ lambda { 'foo bar'.constantize }.should raise_error(NameError)
183
+ end
184
+ end
185
+
186
+ describe "#digitize" do
187
+ it "should leave only numeric characters" do
188
+ '$100,000'.digitize.should == '100000'
189
+ '$100,000'.digitize.to_i.should == 100_000
190
+ end
191
+ end
192
+
193
+ end
194
+ end