extlib 0.9.8 → 0.9.9

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.

Potentially problematic release.


This version of extlib might be problematic. Click here for more details.

Files changed (54) hide show
  1. data/History.txt +22 -0
  2. data/LICENSE +1 -1
  3. data/README +0 -0
  4. data/Rakefile +17 -12
  5. data/lib/extlib.rb +1 -1
  6. data/lib/extlib/blank.rb +51 -21
  7. data/lib/extlib/boolean.rb +1 -1
  8. data/lib/extlib/class.rb +12 -12
  9. data/lib/extlib/datetime.rb +20 -2
  10. data/lib/extlib/dictionary.rb +2 -2
  11. data/lib/extlib/hash.rb +57 -34
  12. data/lib/extlib/inflection.rb +0 -1
  13. data/lib/extlib/lazy_array.rb +327 -36
  14. data/lib/extlib/logger.rb +8 -8
  15. data/lib/extlib/mash.rb +45 -45
  16. data/lib/extlib/module.rb +1 -1
  17. data/lib/extlib/nil.rb +1 -1
  18. data/lib/extlib/numeric.rb +1 -1
  19. data/lib/extlib/object.rb +8 -21
  20. data/lib/extlib/object_space.rb +3 -3
  21. data/lib/extlib/pathname.rb +10 -0
  22. data/lib/extlib/pooling.rb +9 -17
  23. data/lib/extlib/rubygems.rb +7 -7
  24. data/lib/extlib/simple_set.rb +35 -8
  25. data/lib/extlib/string.rb +85 -42
  26. data/lib/extlib/struct.rb +10 -1
  27. data/lib/extlib/symbol.rb +11 -7
  28. data/lib/extlib/time.rb +31 -9
  29. data/lib/extlib/version.rb +1 -1
  30. data/lib/extlib/virtual_file.rb +1 -1
  31. data/spec/blank_spec.rb +85 -0
  32. data/spec/class_spec.rb +141 -0
  33. data/spec/datetime_spec.rb +22 -0
  34. data/spec/hash_spec.rb +537 -0
  35. data/spec/hook_spec.rb +1198 -0
  36. data/spec/inflection/plural_spec.rb +564 -0
  37. data/spec/inflection/singular_spec.rb +497 -0
  38. data/spec/inflection_extras_spec.rb +93 -0
  39. data/spec/lazy_array_spec.rb +1869 -0
  40. data/spec/mash_spec.rb +286 -0
  41. data/spec/module_spec.rb +58 -0
  42. data/spec/object_space_spec.rb +9 -0
  43. data/spec/object_spec.rb +114 -0
  44. data/spec/pooling_spec.rb +499 -0
  45. data/spec/simple_set_spec.rb +57 -0
  46. data/spec/spec_helper.rb +7 -0
  47. data/spec/string_spec.rb +220 -0
  48. data/spec/struct_spec.rb +12 -0
  49. data/spec/symbol_spec.rb +8 -0
  50. data/spec/time_spec.rb +22 -0
  51. data/spec/try_dup_spec.rb +45 -0
  52. data/spec/virtual_file_spec.rb +21 -0
  53. metadata +51 -26
  54. data/README.txt +0 -3
@@ -2,32 +2,39 @@ require "pathname"
2
2
 
3
3
  class String
4
4
  ##
5
- # @return <String> The string with all regexp special characters escaped.
5
+ # Escape all regexp special characters.
6
6
  #
7
- # @example
8
- # "*?{}.".escape_regexp #=> "\\*\\?\\{\\}\\."
7
+ # "*?{}.".escape_regexp #=> "\\*\\?\\{\\}\\."
8
+ #
9
+ # @return [String] Receiver with all regexp special characters escaped.
10
+ #
11
+ # @api public
9
12
  def escape_regexp
10
13
  Regexp.escape self
11
14
  end
12
-
15
+
13
16
  ##
14
- # @return String The string with all regexp special characters unescaped.
17
+ # Unescape all regexp special characters.
15
18
  #
16
- # @example
17
19
  # "\\*\\?\\{\\}\\.".unescape_regexp #=> "*?{}."
20
+ #
21
+ # @return [String] Receiver with all regexp special characters unescaped.
22
+ #
23
+ # @api public
18
24
  def unescape_regexp
19
25
  self.gsub(/\\([\.\?\|\(\)\[\]\{\}\^\$\*\+\-])/, '\1')
20
26
  end
21
-
27
+
22
28
  ##
23
- # @return <String> The string converted to snake case.
24
- #
25
- # @example
26
- # "FooBar".snake_case #=> "foo_bar"
27
- # @example
28
- # "HeadlineCNNNews".snake_case #=> "headline_cnn_news"
29
- # @example
30
- # "CNN".snake_case #=> "cnn"
29
+ # Convert to snake case.
30
+ #
31
+ # "FooBar".snake_case #=> "foo_bar"
32
+ # "HeadlineCNNNews".snake_case #=> "headline_cnn_news"
33
+ # "CNN".snake_case #=> "cnn"
34
+ #
35
+ # @return [String] Receiver converted to snake case.
36
+ #
37
+ # @api public
31
38
  def snake_case
32
39
  return self.downcase if self =~ /^[A-Z]+$/
33
40
  self.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/, '_\&') =~ /_*(.*)/
@@ -35,57 +42,71 @@ class String
35
42
  end
36
43
 
37
44
  ##
38
- # @return <String> The string converted to camel case.
45
+ # Convert to camel case.
39
46
  #
40
- # @example
41
- # "foo_bar".camel_case #=> "FooBar"
47
+ # "foo_bar".camel_case #=> "FooBar"
48
+ #
49
+ # @return [String] Receiver converted to camel case.
50
+ #
51
+ # @api public
42
52
  def camel_case
43
53
  return self if self !~ /_/ && self =~ /[A-Z]+.*/
44
54
  split('_').map{|e| e.capitalize}.join
45
55
  end
46
56
 
47
57
  ##
48
- # @return <String> The path string converted to a constant name.
58
+ # Convert a path string to a constant name.
49
59
  #
50
- # @example
51
60
  # "merb/core_ext/string".to_const_string #=> "Merb::CoreExt::String"
61
+ #
62
+ # @return [String] Receiver converted to a constant name.
63
+ #
64
+ # @api public
52
65
  def to_const_string
53
66
  gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
54
67
  end
55
68
 
56
69
  ##
57
- # @return <String>
58
- # The path that is associated with the constantized string, assuming a
59
- # conventional structure.
70
+ # Convert a constant name to a path, assuming a conventional structure.
60
71
  #
61
- # @example
62
72
  # "FooBar::Baz".to_const_path # => "foo_bar/baz"
73
+ #
74
+ # @return [String] Path to the file containing the constant named by receiver
75
+ # (constantized string), assuming a conventional structure.
76
+ #
77
+ # @api public
63
78
  def to_const_path
64
79
  snake_case.gsub(/::/, "/")
65
80
  end
66
81
 
67
82
  ##
68
- # @param o<String> The path component to join with the string.
69
- #
70
- # @return <String> The original path concatenated with o.
83
+ # Join with _o_ as a file path.
71
84
  #
72
- # @example
73
85
  # "merb"/"core_ext" #=> "merb/core_ext"
86
+ #
87
+ # @param [String] o Path component to join with receiver.
88
+ #
89
+ # @return [String] Receiver joined with o as a file path.
90
+ #
91
+ # @api public
74
92
  def /(o)
75
93
  File.join(self, o.to_s)
76
94
  end
77
95
 
78
96
  ##
79
- # @param other<String> Base path to calculate against
80
- #
81
- # @return <String> Relative path from between the two
97
+ # Calculate a relative path *from* _other_.
82
98
  #
83
- # @example
84
99
  # "/opt/local/lib".relative_path_from("/opt/local/lib/ruby/site_ruby") # => "../.."
100
+ #
101
+ # @param [String] other Base path to calculate *from*.
102
+ #
103
+ # @return [String] Relative path from _other_ to receiver.
104
+ #
105
+ # @api public
85
106
  def relative_path_from(other)
86
107
  Pathname.new(self).relative_path_from(Pathname.new(other)).to_s
87
108
  end
88
-
109
+
89
110
  # Overwrite this method to provide your own translations.
90
111
  def self.translate(value)
91
112
  translations[value] || value
@@ -95,19 +116,33 @@ class String
95
116
  @translations ||= {}
96
117
  end
97
118
 
98
- # Matches any whitespace (including newline) and replaces with a single space
119
+ ##
120
+ # Replace sequences of whitespace (including newlines) with either
121
+ # a single space or remove them entirely (according to param _spaced_)
99
122
  #
100
- # @example
101
123
  # <<QUERY.compress_lines
102
124
  # SELECT name
103
125
  # FROM users
104
- # QUERY
105
- # => "SELECT name FROM users"
126
+ # QUERY => "SELECT name FROM users"
127
+ #
128
+ # @param [TrueClass, FalseClass] spaced (default=true)
129
+ # Determines whether returned string has whitespace collapsed or removed
130
+ #
131
+ # @return [String] Receiver with whitespace (including newlines) replaced
132
+ #
133
+ # @api public
106
134
  def compress_lines(spaced = true)
107
135
  split($/).map { |line| line.strip }.join(spaced ? ' ' : '')
108
136
  end
109
137
 
110
- # Useful for heredocs - removes whitespace margin.
138
+ ##
139
+ # Remove whitespace margin.
140
+ #
141
+ # @param [Object] indicator ???
142
+ #
143
+ # @return [String] receiver with whitespace margin removed
144
+ #
145
+ # @api public
111
146
  def margin(indicator = nil)
112
147
  lines = self.dup.split($/)
113
148
 
@@ -120,12 +155,20 @@ class String
120
155
  lines.map { |line| line.sub(/^\s{#{min_margin}}/, '') }.join($/)
121
156
  end
122
157
 
123
- # Formats String for easy translation. Replaces an arbitrary number of
158
+ ##
159
+ # Formats String for easy translation. Replaces an arbitrary number of
124
160
  # values using numeric identifier replacement.
125
161
  #
126
- # @example
127
- # "%s %s %s" % %w(one two three) #=> "one two three"
128
- # "%3$s %2$s %1$s" % %w(one two three) #=> "three two one"
162
+ # "%s %s %s" % %w(one two three) #=> "one two three"
163
+ # "%3$s %2$s %1$s" % %w(one two three) #=> "three two one"
164
+ #
165
+ # @param [#to_s] values
166
+ # A list of values to translate and interpolate into receiver
167
+ #
168
+ # @return [String]
169
+ # Receiver translated with values translated and interpolated positionally
170
+ #
171
+ # @api public
129
172
  def t(*values)
130
173
  self.class::translate(self) % values.collect! { |value| value.frozen? ? value : self.class::translate(value.to_s) }
131
174
  end
@@ -1,5 +1,14 @@
1
1
  class Struct
2
- # Returns a hash containing the names and values for all instance variables in the Struct.
2
+ ##
3
+ # Get a hash with names and values of all instance variables.
4
+ #
5
+ # class Foo < Struct.new(:name, :age, :gender); end
6
+ # f = Foo.new("Jill", 50, :female)
7
+ # f.attributes #=> {:name => "Jill", :age => 50, :gender => :female}
8
+ #
9
+ # @return [Hash] Hash of instance variables in receiver, keyed by ivar name
10
+ #
11
+ # @api public
3
12
  def attributes
4
13
  h = {}
5
14
  each_pair { |k,v| h[k] = v }
@@ -1,17 +1,21 @@
1
1
  class Symbol
2
-
2
+
3
3
  def try_dup
4
4
  self
5
5
  end
6
-
6
+
7
7
  ##
8
- # @param o<String, Symbol> The path component to join with the string.
8
+ # Join with _o_ as a file path
9
9
  #
10
- # @return <String> The original path concatenated with o.
10
+ # :merb/"core_ext" #=> "merb/core_ext"
11
+ # :merb / :core_ext / :string #=> "merb/core_ext/string"
11
12
  #
12
- # @example
13
- # :merb/"core_ext" #=> "merb/core_ext"
13
+ # @param [#to_s] o The path component(s) to append.
14
+ #
15
+ # @return [String] The receiver (as path string), concatenated with _o_.
16
+ #
17
+ # @api public
14
18
  def /(o)
15
19
  File.join(self.to_s, o.to_s)
16
20
  end
17
- end
21
+ end
@@ -1,19 +1,41 @@
1
+ require "date"
2
+
1
3
  class Time
2
-
3
- # @return <String>
4
- # ISO 8601 compatible rendering of the Time object's properties.
5
- #
6
- # @example
7
- # Time.now.to_json # => "\"2008-03-28T17:54:20-05:00\""
4
+
5
+ ##
6
+ # Convert to ISO 8601 representation
7
+ #
8
+ # Time.now.to_json #=> "\"2008-03-28T17:54:20-05:00\""
9
+ #
10
+ # @return [String]
11
+ # ISO 8601 compatible representation of the Time object.
12
+ #
13
+ # @api public
8
14
  def to_json(*)
9
15
  self.xmlschema.to_json
10
16
  end
11
-
17
+
18
+ ##
19
+ # Return receiver (for DateTime/Time conversion protocol).
20
+ #
21
+ # Time.now.to_time #=> Wed Nov 19 20:08:28 -0800 2008
22
+ #
23
+ # @return [Time] Receiver
24
+ #
25
+ # @api public
12
26
  def to_time
13
27
  self
14
28
  end
15
-
29
+
30
+ ##
31
+ # Convert to DateTime (for DateTime/Time conversion protocol).
32
+ #
33
+ # Time.now.to_datetime #=> #<DateTime: 106046956823/43200,-1/3,2299161>
34
+ #
35
+ # @return [DateTime] DateTime object representing the same moment as receiver
36
+ #
37
+ # @api public
16
38
  def to_datetime
17
39
  DateTime.parse self.to_s
18
40
  end
19
- end
41
+ end
@@ -1,3 +1,3 @@
1
1
  module Extlib
2
- VERSION = "0.9.8"
2
+ VERSION = '0.9.9'
3
3
  end
@@ -7,4 +7,4 @@ class VirtualFile < StringIO
7
7
  super(string)
8
8
  @path = path
9
9
  end
10
- end
10
+ end
@@ -0,0 +1,85 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
+
3
+ describe Object do
4
+ it 'should provide blank?' do
5
+ Object.new.should respond_to(:blank?)
6
+ end
7
+
8
+ it 'should be blank if it is nil' do
9
+ object = Object.new
10
+ class << object
11
+ def nil?; true end
12
+ end
13
+ object.should be_blank
14
+ end
15
+
16
+ it 'should be blank if it is empty' do
17
+ {}.should be_blank
18
+ [].should be_blank
19
+ end
20
+
21
+ it 'should not be blank if not nil or empty' do
22
+ Object.new.should_not be_blank
23
+ [nil].should_not be_blank
24
+ { nil => 0 }.should_not be_blank
25
+ end
26
+ end
27
+
28
+ describe Numeric do
29
+ it 'should provide blank?' do
30
+ 1.should respond_to(:blank?)
31
+ end
32
+
33
+ it 'should never be blank' do
34
+ 1.should_not be_blank
35
+ end
36
+ end
37
+
38
+ describe NilClass do
39
+ it 'should provide blank?' do
40
+ nil.should respond_to(:blank?)
41
+ end
42
+
43
+ it 'should always be blank' do
44
+ nil.should be_blank
45
+ end
46
+ end
47
+
48
+ describe TrueClass do
49
+ it 'should provide blank?' do
50
+ true.should respond_to(:blank?)
51
+ end
52
+
53
+ it 'should never be blank' do
54
+ true.should_not be_blank
55
+ end
56
+ end
57
+
58
+ describe FalseClass do
59
+ it 'should provide blank?' do
60
+ false.should respond_to(:blank?)
61
+ end
62
+
63
+ it 'should always be blank' do
64
+ false.should be_blank
65
+ end
66
+ end
67
+
68
+ describe String do
69
+ it 'should provide blank?' do
70
+ 'string'.should respond_to(:blank?)
71
+ end
72
+
73
+ it 'should be blank if empty' do
74
+ ''.should be_blank
75
+ end
76
+
77
+ it 'should be blank if it only contains whitespace' do
78
+ ' '.should be_blank
79
+ " \r \n \t ".should be_blank
80
+ end
81
+
82
+ it 'should not be blank if it contains non-whitespace' do
83
+ ' a '.should_not be_blank
84
+ end
85
+ end
@@ -0,0 +1,141 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ class Grandparent
4
+ end
5
+
6
+ class Parent < Grandparent
7
+ end
8
+
9
+ class Child < Parent
10
+ end
11
+
12
+ class Parent
13
+ end
14
+
15
+ class Grandparent
16
+ class_inheritable_accessor :last_name, :_attribute
17
+
18
+ self._attribute = 1900
19
+ end
20
+
21
+ describe Class, "#inheritable_accessor" do
22
+
23
+ after :each do
24
+ Grandparent.send(:remove_instance_variable, "@last_name") rescue nil
25
+ Parent.send(:remove_instance_variable, "@last_name") rescue nil
26
+ Child.send(:remove_instance_variable, "@last_name") rescue nil
27
+ end
28
+
29
+ it 'inherits from parent unless overriden' do
30
+ Parent._attribute.should == 1900
31
+ Child._attribute.should == 1900
32
+ end
33
+
34
+ it 'inherits from grandparent unless overriden' do
35
+ Child._attribute.should == 1900
36
+ end
37
+
38
+ it "inherits even if the accessor is made after the inheritance" do
39
+ Grandparent.last_name = "Merb"
40
+ Parent.last_name.should == "Merb"
41
+ Child.last_name.should == "Merb"
42
+ end
43
+
44
+ it "supports ||= to change a child" do
45
+ Parent.last_name ||= "Merb"
46
+ Grandparent.last_name.should == nil
47
+ Parent.last_name.should == "Merb"
48
+ Child.last_name.should == "Merb"
49
+ end
50
+
51
+ it "supports << to change a child when the parent is an Array" do
52
+ Grandparent.last_name = ["Merb"]
53
+ Parent.last_name << "Core"
54
+ Grandparent.last_name.should == ["Merb"]
55
+ Parent.last_name.should == ["Merb", "Core"]
56
+ end
57
+
58
+ it "supports ! methods on an Array" do
59
+ Grandparent.last_name = %w(Merb Core)
60
+ Parent.last_name.reverse!
61
+ Grandparent.last_name.should == %w(Merb Core)
62
+ Parent.last_name.should == %w(Core Merb)
63
+ end
64
+
65
+ it "support modifying a parent Hash" do
66
+ Grandparent.last_name = {"Merb" => "name"}
67
+ Parent.last_name["Core"] = "name"
68
+ Parent.last_name.should == {"Merb" => "name", "Core" => "name"}
69
+ Grandparent.last_name.should == {"Merb" => "name"}
70
+ end
71
+
72
+ it "supports hard-merging a parent Hash" do
73
+ Grandparent.last_name = {"Merb" => "name"}
74
+ Parent.last_name.merge!("Core" => "name")
75
+ Parent.last_name.should == {"Merb" => "name", "Core" => "name"}
76
+ Grandparent.last_name.should == {"Merb" => "name"}
77
+ end
78
+
79
+ it "supports changes to the parent even if the child has already been read" do
80
+ Child.last_name
81
+ Grandparent.last_name = "Merb"
82
+ Child.last_name.should == "Merb"
83
+ end
84
+
85
+ it "handles nil being set midstream" do
86
+ Child.last_name
87
+ Parent.last_name = nil
88
+ Grandparent.last_name = "Merb"
89
+ Child.last_name.should == nil
90
+ end
91
+
92
+ it "handles false being used in Parent" do
93
+ Child.last_name
94
+ Parent.last_name = false
95
+ Grandparent.last_name = "Merb"
96
+ Child.last_name.should == false
97
+ end
98
+
99
+ it "handles the grandparent changing the value (as long as the child isn't read first)" do
100
+ Grandparent.last_name = "Merb"
101
+ Grandparent.last_name = "Core"
102
+ Child.last_name.should == "Core"
103
+ end
104
+
105
+ end
106
+
107
+ #
108
+ # The bug that prompted this estoric spec was found in
109
+ # the wild when using dm-is-versioned with c_i_w.
110
+ #
111
+
112
+ module Plugin
113
+ def self.included(base)
114
+ base.class_eval do
115
+ class_inheritable_writer :plugin_options
116
+ class_inheritable_reader :plugin_options
117
+ self.plugin_options = :foo
118
+ end
119
+ end
120
+ end
121
+
122
+ class Model
123
+ def self.new
124
+ model = Class.new
125
+ model.send(:include, Plugin)
126
+ model
127
+ end
128
+
129
+ include Plugin
130
+ self.const_set("Version", Model.new)
131
+ end
132
+
133
+ describe Class, "#inheritable_accessor" do
134
+ it "uses object_id for comparison" do
135
+ Model.methods.should include("plugin_options")
136
+ Model.plugin_options.should == :foo
137
+
138
+ Model::Version.methods.should include("plugin_options")
139
+ Model::Version.plugin_options.should == :foo
140
+ end
141
+ end