marcandre-backports 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,11 +1,88 @@
1
1
  = Packable --- History
2
2
 
3
+ == Version 1.6 - April 29, 2009
4
+
5
+ Completed backport to 1.8.7.
6
+
7
+ * Array
8
+ * <tt>extract_options!</tt>
9
+
10
+ * Binding
11
+ * +eval+
12
+
13
+ * Dir
14
+ * +each+, +foreach+
15
+
16
+ * Enumerator
17
+ * +new+
18
+ * +with_object+
19
+ * +next+, +rewind+
20
+
21
+ * Hash
22
+ * Optional block for <tt>delete_if, each, each_key, each_pair, each_value, reject!, select</tt> (and ENV)
23
+
24
+ * Integer
25
+ * moved stuff out of Fixnum
26
+ * Optional block for +downto+, +times+, +upto+
27
+
28
+ * IO
29
+ * Optional block for +each+, +each_line+, +each_byte+, +foreach+ (and ARGF)
30
+
31
+ * Kernel
32
+ * +loop+, +StopIteration+
33
+ * +__method__+, +__callee__+
34
+
35
+ * Method
36
+ * +name+, +owner+, +receiver+
37
+
38
+ * Module
39
+ * +class_exec+, +module_exec+
40
+
41
+ * Numeric
42
+ * +step+
43
+
44
+ * Object
45
+ * +define_singleton_method+
46
+ * +instance_exec+
47
+
48
+ * ObjectSpace
49
+ * +each_object+
50
+
51
+ * Range
52
+ * Optional block for +each+, +step+
53
+
54
+ * Regexp
55
+ * +union+
56
+
57
+ * String
58
+ * +try_convert+
59
+ * <tt>ascii_only?</tt>
60
+ * +bytesize+
61
+ * +chr+
62
+ * +clear+
63
+ * +codepoints+, +each_codepoint+
64
+ * +stringify_keys+, +stringify_keys!+
65
+ * +each+, +each_line+, +each_byte+
66
+ * +gsub+
67
+ * +upto+
68
+
69
+ * Struct
70
+ * +each+, +each_pair+
71
+
72
+ * Symbol
73
+ * <tt><=></tt>, +casecmp+
74
+ * +capitalize+, +downcase+, +next+, +succ+, +swapcase+, +upcase+
75
+ * <tt>=~, [], empty?, length, match, size</tt>
76
+
77
+ * UnboundMethod
78
+ * +name+, +owner+
79
+
3
80
  == Version 1.5 - April 24, 2009
4
81
 
5
82
  * Array (completed)
6
83
  * +combination+
7
84
  * +try_convert+
8
- * Optional block for collect!, :map!, :each, :each_index, :reject, :reject!, :delete_if
85
+ * Optional block for <tt>collect!, :map!, :each, :each_index, :reject, :reject!, :delete_if</tt>
9
86
  * +pop+, +shift+
10
87
  * +product+
11
88
 
data/README.rdoc CHANGED
@@ -30,45 +30,95 @@ Compatible with Ruby 1.8 & 1.9.
30
30
 
31
31
  = List of backports
32
32
 
33
+ == Ruby 1.8.7
34
+
35
+ Complete Ruby 1.8.7 backporting. Refer to the official list of changes[http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS]. All builtin classes are compatible with Ruby 1.8.7:
36
+ * Array
37
+ * Binding
38
+ * Dir
39
+ * Enumerable
40
+ * Enumerator
41
+ * Fixnum
42
+ * Hash
43
+ * Integer
44
+ * IO (& ARGF)
45
+ * Method
46
+ * Numeric
47
+ * Object
48
+ * ObjectSpace
49
+ * Range
50
+ * Regexp
33
51
  * Symbol
34
- * +to_proc+ (e.g. <tt>foo.map(&:bar)</tt> )
52
+ * UnboundMethod
53
+
54
+ Only exceptions:
55
+ * GC.stress=
56
+ * Process.exec
57
+ * recursive data handling (Array and Hash)
58
+
59
+ As in Ruby 1.8.7+, there is no need to <tt>require 'enumerator'</tt> in older Ruby, and +Enumerator+ can be accessed directly (instead of <tt>Enumerable::Enumerator</tt>)
60
+
61
+ == Ruby 1.9
62
+
63
+ Additionally, the following Ruby 1.9 have been backported:
64
+
65
+ * Array
66
+ * +sample+
67
+
68
+ * Enumerable
69
+ * +each_with_object+
70
+ * +reverse_each+
71
+
72
+ * Enumerator
73
+ * +new+ (with block)
74
+
75
+ * Hash
76
+ * <tt>Hash[[[:foo, :bar],[:hello, "world"]]] ==> {:foo => :bar, :hello => "world"}</tt> (see _note_)
77
+ * <tt>default_proc=</tt>
78
+
35
79
  * Kernel
36
80
  * +require_relative+
81
+
82
+ * Object
83
+ * +define_singleton_method+
84
+
85
+ * Proc
86
+ * +yield+
87
+
88
+ * String
89
+ * +try_convert+
90
+ * <tt>ascii_only?</tt>
91
+ * +chr+
92
+ * +clear+
93
+ * +codepoints+, +each_codepoint+
94
+
95
+ _note_: This usage of <tt>Hash::[]</tt> is not yet documented[http://redmine.ruby-lang.org/issues/show/1385].
96
+
97
+ == Rails
98
+
99
+ Some generic methods from Rails methods have been copied:
100
+
101
+ * Enumerable
102
+ * +sum+
103
+
104
+ * Hash
105
+ * +symbolize_keys+, <tt>symbolize_keys!</tt>
106
+ * +reverse_merge+, <tt>reverse_merge!</tt>
107
+
37
108
  * Module
38
109
  * +alias_method_chain+
110
+
39
111
  * Object
40
- * +tap+, +returning+
41
112
  * +try+
113
+ * +returning+
114
+
42
115
  * String
43
- * +each_char+, +chars+
44
- * <tt>start_with?</tt>, <tt>end_with?</tt>
45
116
  * +camelize+, +underscore+
46
117
  * +dasherize+, +demodulize+
47
118
  * +constantize+
48
- * +partition+, +rpartition+
49
- * Hash
50
- * +symbolize_keys+, <tt>symbolize_keys!</tt>
51
- * +reverse_merge+, <tt>reverse_merge!</tt>
52
- * <tt>Hash[[[:foo, :bar],[:hello, "world"]]] ==> {:foo => :bar, :hello => "world"}</tt> (see _note_)
53
- * +key+
54
- * <tt>default_proc=</tt>
55
- * Enumerable
56
- * +sum+
57
- * complete Ruby 1.8.7 backport
58
- * Array
59
- * complete Ruby 1.8.7 backport
60
- * Fixnum
61
- * complete Ruby 1.8.7 backport
62
- * Proc
63
- * +yield+
64
-
65
- Finally, there is no need to <tt>require 'enumerator'</tt> in older Ruby, and +Enumerator+ can be accessed directly (instead of <tt>Enumerable::Enumerator</tt>)
66
-
67
- _note_: This usage of <tt>Hash::[]</tt> is not yet documented[http://redmine.ruby-lang.org/issues/show/1385].
68
119
 
69
120
  = License
70
121
 
71
122
  +backports+ is released under the terms of the MIT License, see the included LICENSE file.
72
- The code for backports was copied from rails when available.
73
123
 
74
124
  Author:: Marc-André Lafortune
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 1
3
- :minor: 5
3
+ :minor: 6
4
4
  :patch: 0
@@ -7,19 +7,7 @@ class Array
7
7
  end
8
8
 
9
9
  # Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
10
- unless ([42].map! rescue false)
11
- # Make block optional for...
12
- [:collect!, :map!, :each, :each_index, :reverse_each, :reject, :reject!, :delete_if].each do |selector|
13
- alias_method_chain(selector, :optional_block) do |aliased_target, punctuation|
14
- module_eval <<-end_eval
15
- def #{aliased_target}_with_optional_block#{punctuation}(*args, &block)
16
- return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, *args) unless block_given?
17
- #{aliased_target}_without_optional_block#{punctuation}(*args, &block)
18
- end
19
- end_eval
20
- end
21
- end
22
- end
10
+ make_block_optional :collect!, :map!, :each, :each_index, :reverse_each, :reject, :reject!, :delete_if, :test_on => [42]
23
11
 
24
12
  # Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
25
13
  def combination(num)
@@ -47,6 +35,8 @@ class Array
47
35
  nb.to_i.times{each(&block)}
48
36
  end unless method_defined? :cycle
49
37
 
38
+ # extract_options! in backports.rb
39
+
50
40
  # flatten & flatten!, standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Array.html]
51
41
  unless ([[]].flatten(1) rescue false)
52
42
 
@@ -72,8 +62,7 @@ class Array
72
62
  alias_method_chain :flatten, :optional_argument
73
63
  alias_method_chain :flatten!, :optional_argument
74
64
 
75
- # Helper to recurse through flattening since the method
76
- # is not allowed to recurse itself. Detects recursive structures.
65
+ # Helper to recurse through flattening
77
66
  # Adapted from rubinius'; recursion guards are not needed because level is finite
78
67
  def recursively_flatten_finite(array, out, level)
79
68
  ret = nil
@@ -116,19 +105,19 @@ class Array
116
105
  end
117
106
 
118
107
  def product(*arg)
119
- arg.unshift(self)
120
- arg._partial_cartesian_product(arg.size-1, Array.new(arg.size), [])
108
+ arrays = [self, *arg].reverse
109
+ first_enum = Enumerator.new{|yielder| yielder.yield [] }
110
+ arrays.inject(first_enum) do |enum, array|
111
+ Enumerator.new do |yielder|
112
+ array.each do |obj|
113
+ enum.each do |partial_product|
114
+ yielder.yield [obj] + partial_product
115
+ end
116
+ end
117
+ end
118
+ end.to_a
121
119
  end unless method_defined? :product
122
-
123
- def _partial_cartesian_product(combi, iterate_index, result)
124
- action = iterate_index.zero? ? Proc.new(result << combi.dup) : Proc.new(_sub(combi, iterate_index-1, &block))
125
- self[iterate_index].each do |obj|
126
- combi[iterate_index] = obj
127
- action.call
128
- end
129
- end
130
- private :_partial_cartesian_product
131
-
120
+
132
121
  # rindex
133
122
  unless ([1].rindex{true} rescue false)
134
123
  def rindex_with_block(*arg)
@@ -0,0 +1,6 @@
1
+ class Binding
2
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Symbol.html]
3
+ def eval(expr, *arg)
4
+ Kernel.eval(expr, self, *arg)
5
+ end unless method_defined? :eval
6
+ end
@@ -0,0 +1,7 @@
1
+ class Dir
2
+ make_block_optional :each, :test_on => Dir.new(".")
3
+ class << self
4
+ make_block_optional :foreach, :test_on => Dir, :arg => "."
5
+ end
6
+ end
7
+
@@ -29,15 +29,7 @@ module Enumerable
29
29
  to_a.cycle(*arg, &block)
30
30
  end unless method_defined? :cycle
31
31
 
32
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
33
- unless ([].detect rescue false)
34
- def detect_with_optional_block(ifnone = nil, &block)
35
- return to_enum(:detect, ifnone) unless block_given?
36
- detect_without_optional_block(ifnone, &block)
37
- end
38
- alias_method_chain :detect, :optional_block
39
- alias_method :find, :detect
40
- end
32
+ make_block_optional :detect, :find, :test_on => [42]
41
33
 
42
34
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
43
35
  def drop(n)
@@ -56,24 +48,7 @@ module Enumerable
56
48
  end unless method_defined? :drop_while
57
49
 
58
50
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
59
- unless ((1..2).each_cons(1) rescue false)
60
- def each_cons_with_optional_block(len, &block)
61
- raise ArgumentError, "invalid size" if len <= 0
62
- return to_enum(:each_cons, len) unless block_given?
63
- each_cons_without_optional_block(len, &block)
64
- end
65
- alias_method_chain :each_cons, :optional_block
66
- end
67
-
68
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
69
- unless ((1..2).each_slice(1) rescue false)
70
- def each_slice_with_optional_block(len, &block)
71
- raise ArgumentError, "invalid slice size" if len <= 0
72
- return to_enum(:each_slice, len) unless block_given?
73
- each_slice_without_optional_block(len, &block)
74
- end
75
- alias_method_chain :each_slice, :optional_block
76
- end
51
+ make_block_optional :each_cons, :each_slice, :test_on => 1..2, :arg => 1
77
52
 
78
53
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
79
54
  if instance_method(:each_with_index).arity.zero?
@@ -93,6 +68,7 @@ module Enumerable
93
68
 
94
69
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Enumerable.html]
95
70
  def find_index(*args)
71
+ raise ArgumentError, "Wrong number of arguments (#{args.size} for 1)" if args.size > 1
96
72
  if args.size == 1
97
73
  obj = args.first
98
74
  each_with_index do |element, i|
@@ -104,7 +80,7 @@ module Enumerable
104
80
  end
105
81
  each_with_index{|o,i| return i if yield o}
106
82
  else
107
- raise ArgumentError, "Wrong number of arguments (#{args.size} for 1)"
83
+ return to_enum(:find_index)
108
84
  end
109
85
  nil
110
86
  end unless method_defined? :find_index
@@ -239,7 +215,3 @@ module Enumerable
239
215
  end
240
216
 
241
217
  end
242
-
243
- class Enumerator
244
- alias_method :with_object, :each_with_object unless method_defined? :with_object
245
- end
@@ -0,0 +1,41 @@
1
+ class Enumerator
2
+ alias_method :with_object, :each_with_object unless method_defined? :with_object
3
+
4
+ def next
5
+ require 'generator'
6
+ @generator ||= Generator.new(self)
7
+ raise StopIteration unless @generator.next?
8
+ @generator.next
9
+ end unless method_defined? :next
10
+
11
+ def rewind
12
+ require 'generator'
13
+ @generator ||= Generator.new(self)
14
+ @generator.rewind
15
+ self
16
+ end unless method_defined? :rewind
17
+
18
+ # new with block, standard in Ruby 1.9
19
+ unless (self.new{} rescue false)
20
+ class Yielder
21
+ def initialize(&block)
22
+ @main_block = block
23
+ end
24
+
25
+ def each(&block)
26
+ @final_block = block
27
+ @main_block.call(self)
28
+ end
29
+
30
+ def yield(*arg)
31
+ @final_block.yield(*arg)
32
+ end
33
+ end
34
+
35
+ def initialize_with_optional_block(*arg, &block)
36
+ return initialize_without_optional_block(*arg, &nil) unless arg.empty? # Ruby 1.9 apparently ignores the block if any argument is present
37
+ initialize_without_optional_block(Yielder.new(&block))
38
+ end
39
+ alias_method_chain :initialize, :optional_block
40
+ end
41
+ end
@@ -4,30 +4,8 @@ class Fixnum
4
4
  (self / n).round
5
5
  end unless method_defined? :div
6
6
 
7
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
8
- def even?
9
- self & 1 == 0
10
- end unless method_defined? :even?
11
-
12
7
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
13
8
  def fdiv(n)
14
9
  to_f / n
15
10
  end unless method_defined? :fdiv
16
-
17
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
18
- def odd?
19
- self & 1 == 1
20
- end unless method_defined? :odd?
21
-
22
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
23
- def succ
24
- self + 1
25
- end unless method_defined? :succ
26
-
27
- alias_method :magnitude, :abs unless method_defined? :magnitude
28
-
29
-
30
-
31
-
32
-
33
11
  end
@@ -16,16 +16,13 @@ class Hash
16
16
  end unless method_defined? :to_hash
17
17
  end
18
18
 
19
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
20
- def symbolize_keys
21
- Hash[map{|key,value| [(key.to_sym rescue key) || key, value] }]
22
- end unless method_defined? :symbolize_keys
23
-
24
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
25
- def symbolize_keys!
26
- self.replace(self.symbolize_keys)
27
- end unless method_defined? :symbolize_keys!
19
+ make_block_optional :delete_if, :each, :each_key, :each_pair, :each_value, :reject!, :select, :test_on => {:hello => "world!"}
28
20
 
21
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Hash.html]
22
+ def default_proc=(proc)
23
+ replace(Hash.new(&proc).merge!(self))
24
+ end unless method_defined? :default_proc=
25
+
29
26
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Hash.html]
30
27
  alias_method :key, :index unless method_defined? :key
31
28
 
@@ -39,8 +36,27 @@ class Hash
39
36
  replace(reverse_merge(other_hash))
40
37
  end
41
38
 
42
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Hash.html]
43
- def default_proc=(proc)
44
- replace(Hash.new(&proc).merge!(self))
45
- end unless method_defined? :default_proc=
39
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
40
+ def symbolize_keys
41
+ Hash[map{|key,value| [(key.to_sym rescue key) || key, value] }]
42
+ end unless method_defined? :symbolize_keys
43
+
44
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
45
+ def symbolize_keys!
46
+ self.replace(self.symbolize_keys)
47
+ end unless method_defined? :symbolize_keys!
48
+
49
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
50
+ def stringify_keys
51
+ Hash[map{|key,value| [key.to_s, value] }]
52
+ end unless method_defined? :stringify_keys
53
+
54
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/Hash/Keys.html]
55
+ def stringify_keys!
56
+ self.replace(self.stringify_keys)
57
+ end unless method_defined? :stringify_keys!
58
+ end
59
+
60
+ class << ENV
61
+ make_block_optional :delete_if, :each, :each_key, :each_pair, :each_value, :reject!, :select, :test_on => ENV
46
62
  end
@@ -0,0 +1,34 @@
1
+ class Integer
2
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
3
+ def even?
4
+ self[0].zero?
5
+ end unless method_defined? :even?
6
+
7
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
8
+ def odd?
9
+ !even?
10
+ end unless method_defined? :odd?
11
+
12
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
13
+ def ord
14
+ self
15
+ end
16
+
17
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
18
+ def succ
19
+ self + 1
20
+ end unless method_defined? :succ
21
+
22
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Fixnum.html]
23
+ def pred
24
+ self - 1
25
+ end unless method_defined? :succ
26
+
27
+ alias_method :magnitude, :abs unless method_defined? :magnitude
28
+
29
+ make_block_optional :downto, :times, :upto, :test_on => 42, :arg => 42
30
+ end
31
+
32
+ class Numeric
33
+ make_block_optional :step, :test_on => 42, :arg => [100, 6]
34
+ end
@@ -0,0 +1,12 @@
1
+ if RUBY_VERSION < '1.8.7'
2
+ class IO
3
+ make_block_optional :each, :each_line, :each_byte
4
+ class << self
5
+ make_block_optional :foreach
6
+ end
7
+ end
8
+
9
+ class << ARGF
10
+ make_block_optional :each, :each_line, :each_byte
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ module Kernel
2
+ unless const_defined? :StopIteration
3
+
4
+ class StopIteration < IndexError; end
5
+
6
+ def loop_with_stop_iteration(&block)
7
+ loop_without_stop_iteration(&block)
8
+ rescue StopIteration
9
+ # ignore silently
10
+ end
11
+ alias_method_chain :loop, :stop_iteration
12
+
13
+ end
14
+
15
+ def __callee__
16
+ caller(1).first[/`(.*)'/,1].try(:to_sym)
17
+ end unless (__callee__ || true rescue false)
18
+
19
+ alias_method :__method__, :__callee__ unless (__method__ || true rescue false)
20
+ end
@@ -0,0 +1,47 @@
1
+ unless Method.method_defined? :name
2
+ class Method
3
+ attr_accessor :name, :receiver, :owner
4
+
5
+ def unbind_with_additional_info
6
+ returning unbind_without_additional_info do |unbound|
7
+ unbound.name = name
8
+ unbound.owner = owner
9
+ end
10
+ end
11
+ alias_method_chain :unbind, :additional_info
12
+ end
13
+
14
+ class UnboundMethod
15
+ attr_accessor :name, :owner
16
+
17
+ def bind_with_additional_info(to)
18
+ returning bind_without_additional_info(to) do |bound|
19
+ bound.name = name
20
+ bound.owner = owner
21
+ bound.receiver = to
22
+ end
23
+ end
24
+ alias_method_chain :bind, :additional_info
25
+ end
26
+
27
+ class Object
28
+ def method_with_additional_info(name)
29
+ returning method_without_additional_info(name) do |bound|
30
+ bound.name = name.to_sym
31
+ bound.receiver = self
32
+ bound.owner = self.class.ancestors.find{|mod| mod.instance_methods(false).include? name.to_s}
33
+ end
34
+ end
35
+ alias_method_chain :method, :additional_info
36
+ end
37
+
38
+ class Module
39
+ def instance_method_with_additional_info(name)
40
+ returning instance_method_without_additional_info(name) do |unbound|
41
+ unbound.name = name.to_sym
42
+ unbound.owner = ancestors.find{|mod| mod.instance_methods(false).include? name.to_s}
43
+ end
44
+ end
45
+ alias_method_chain :instance_method, :additional_info
46
+ end
47
+ end
@@ -20,4 +20,28 @@ class Module
20
20
  private target
21
21
  end
22
22
  end unless method_defined? :alias_method_chain
23
+
24
+ alias_method :module_exec, :instance_exec unless method_defined? :module_exec
25
+ alias_method :class_exec, :module_exec unless method_defined? :class_exec
26
+
27
+ # Metaprogramming utility to make block optional.
28
+ # Tests first if block is already optional when given options
29
+ def make_block_optional(*methods)
30
+ options = methods.extract_options!
31
+ methods.each do |selector|
32
+ next unless method_defined? selector
33
+ unless options.empty?
34
+ test_on = options[:test_on] || self.new
35
+ next if (test_on.send(selector, *options.fetch(:arg, [])) rescue false)
36
+ end
37
+ alias_method_chain(selector, :optional_block) do |aliased_target, punctuation|
38
+ module_eval <<-end_eval
39
+ def #{aliased_target}_with_optional_block#{punctuation}(*args, &block)
40
+ return to_enum(:#{aliased_target}_without_optional_block#{punctuation}, *args) unless block_given?
41
+ #{aliased_target}_without_optional_block#{punctuation}(*args, &block)
42
+ end
43
+ end_eval
44
+ end
45
+ end
46
+ end
23
47
  end
@@ -1,6 +1,7 @@
1
1
  require 'enumerator'
2
2
 
3
- class Object
3
+ module Kernel # Did you know that object instance methods are defined in Kernel?
4
+
4
5
  # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/Object.html]
5
6
  def try(method_id, *args, &block)
6
7
  send(method_id, *args, &block) unless self.nil? #todo: check new def
@@ -19,4 +20,15 @@ class Object
19
20
  end unless method_defined? :returning
20
21
 
21
22
  Enumerator = Enumerable::Enumerator unless const_defined? :Enumerator # Standard in ruby 1.9
22
- end
23
+
24
+ def define_singleton_method(symbol, &block)
25
+ class << self
26
+ self
27
+ end.send(:define_method, symbol, block)
28
+ end unless method_defined? :define_singleton_method
29
+
30
+ def instance_exec(*arg, &block)
31
+ define_singleton_method(:"temporary method for instance_exec", &block)
32
+ send(:"temporary method for instance_exec", *arg)
33
+ end unless method_defined? :instance_exec
34
+ end
@@ -0,0 +1,6 @@
1
+
2
+ module ObjectSpace
3
+ module_eval do
4
+ make_block_optional :each_object, :test_on => ObjectSpace
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ class Range
2
+ make_block_optional :each, :test_on => 69..666
3
+ make_block_optional :step, :test_on => 69..666, :arg => 42
4
+ end
@@ -0,0 +1,11 @@
1
+ class Regexp
2
+ class << self
3
+ unless (union(%w(a b)) rescue false)
4
+ def union_with_array_argument(*arg)
5
+ return union_without_array_argument(*arg) unless arg.size == 1
6
+ union_without_array_argument(*arg.first)
7
+ end
8
+ alias_method_chain :union, :array_argument
9
+ end
10
+ end
11
+ end
@@ -1,13 +1,93 @@
1
1
  class String
2
+ class << self
3
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
4
+ def try_convert(x)
5
+ return nil unless x.respond_do(:to_str)
6
+ x.to_str
7
+ end unless method_defined? :try_convert
8
+ end
9
+
10
+ def ascii_only?
11
+ !(self =~ /[^\x00-\x7f]/)
12
+ end unless method_defined? :ascii_only?
13
+
14
+ alias_method :bytesize, :length unless method_defined? :bytesize
15
+
16
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
17
+ def camelize(first_letter = :upper)
18
+ if first_letter == :upper
19
+ gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
20
+ else
21
+ first.downcase + camelize[1..-1]
22
+ end
23
+ end unless method_defined? :camelize
24
+
2
25
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
3
- def start_with?(*prefixes)
4
- prefixes.each do |prefix|
5
- prefix = prefix.to_s
6
- return true if self[0, prefix.length] == prefix
26
+ def chr
27
+ chars.first
28
+ end unless method_defined? :chr?
29
+
30
+
31
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
32
+ def clear
33
+ self[0,length] = ""
34
+ self
35
+ end unless method_defined? :clear?
36
+
37
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
38
+ def codepoints
39
+ return to_enum(:codepoints) unless block_given?
40
+ each_char.each do |s|
41
+ utf8 = s.each_byte.to_a
42
+ utf8[0] &= 0xff >> utf8.size # clear high bits (1 to 4, depending of number of bytes used)
43
+ yield utf8.inject{|result, b| (result << 6) + (b & 0x3f) }
7
44
  end
8
- false
9
- end unless method_defined? :start_with?
45
+ end unless method_defined? :codepoints
46
+
47
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
48
+ def constantize(camel_cased_word)
49
+ names = camel_cased_word.split('::')
50
+ names.shift if names.empty? || names.first.empty?
51
+
52
+ constant = Object
53
+ names.each do |name|
54
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
55
+ end
56
+ constant
57
+ end unless method_defined? :constantize
58
+
59
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
60
+ def dasherize(underscored_word)
61
+ underscored_word.gsub(/_/, '-')
62
+ end unless method_defined? :dasherize
63
+
64
+ # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
65
+ def demodulize(class_name_in_module)
66
+ class_name_in_module.to_s.gsub(/^.*::/, '')
67
+ end unless method_defined? :demodulize
68
+
69
+ make_block_optional :each_byte, :each, :each_line, :test_on => "abc"
70
+
71
+ unless ("abc".gsub(/./) rescue false)
72
+ def gsub_with_optional_block(*arg, &block)
73
+ return to_enum(:gsub_with_optional_block, *arg) unless block_given? || arg.size > 1
74
+ gsub_without_optional_block(*arg, &block)
75
+ end
76
+ alias_method_chain :gsub, :optional_block
77
+ end
78
+
79
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
80
+ unless method_defined? :each_char
81
+ def each_char(&block)
82
+ return to_enum(:each_char) unless block_given?
83
+ scan(/./, &block)
84
+ end
85
+
86
+ alias_method :chars, :each_char unless method_defined? :chars
87
+ end
10
88
 
89
+ alias_method :each_codepoint, :codepoints unless method_defined? :each_codepoint
90
+
11
91
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
12
92
  def end_with?(*suffixes)
13
93
  suffixes.each do |suffix|
@@ -22,17 +102,6 @@ class String
22
102
  self[i]
23
103
  end unless method_defined? :getbyte
24
104
 
25
- # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
26
- unless method_defined? :each_char
27
- def each_char(&block)
28
- return to_enum(:each_char) unless block_given?
29
- scan(/./, &block)
30
- end
31
- end
32
-
33
- alias_method :chars, :each_char unless method_defined? :chars
34
-
35
-
36
105
  # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
37
106
  unless ("check partition".partition(" ") rescue false)
38
107
  def partition_with_new_meaning(*args, &block)
@@ -68,14 +137,14 @@ class String
68
137
  end unless method_defined? :rpartition
69
138
 
70
139
 
71
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
72
- def camelize(first_letter = :upper)
73
- if first_letter == :upper
74
- gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
75
- else
76
- first.downcase + camelize[1..-1]
140
+ # Standard in ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/String.html]
141
+ def start_with?(*prefixes)
142
+ prefixes.each do |prefix|
143
+ prefix = prefix.to_s
144
+ return true if self[0, prefix.length] == prefix
77
145
  end
78
- end unless method_defined? :camelize
146
+ false
147
+ end unless method_defined? :start_with?
79
148
 
80
149
  # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
81
150
  def underscore(camel_cased_word)
@@ -86,26 +155,13 @@ class String
86
155
  downcase
87
156
  end unless method_defined? :underscore
88
157
 
89
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
90
- def constantize(camel_cased_word)
91
- names = camel_cased_word.split('::')
92
- names.shift if names.empty? || names.first.empty?
93
-
94
- constant = Object
95
- names.each do |name|
96
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
158
+ unless ("abc".upto("def", true) rescue false)
159
+ def upto_with_exclusive(to, excl=false, &block)
160
+ enum = Range.new(self, to, excl).to_enum
161
+ return enum unless block_given?
162
+ enum.each(&block)
163
+ self
97
164
  end
98
- constant
99
- end unless method_defined? :constantize
100
-
101
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
102
- def dasherize(underscored_word)
103
- underscored_word.gsub(/_/, '-')
104
- end unless method_defined? :dasherize
105
-
106
- # Standard in rails. See official documentation[http://api.rubyonrails.org/classes/ActiveSupport/CoreExtensions/String/Inflections.html]
107
- def demodulize(class_name_in_module)
108
- class_name_in_module.to_s.gsub(/^.*::/, '')
109
- end unless method_defined? :demodulize
110
-
165
+ alias_method_chain :upto, :exclusive
166
+ end
111
167
  end
@@ -0,0 +1,3 @@
1
+ class Struct
2
+ make_block_optional :each, :each_pair, :test_on => Struct.new(:foo, :bar)
3
+ end
@@ -3,4 +3,18 @@ class Symbol
3
3
  def to_proc
4
4
  Proc.new { |*args| args.shift.__send__(self, *args) }
5
5
  end unless :to_proc.respond_to?(:to_proc)
6
+
7
+ include Enumerable
8
+
9
+ [ [%w(<=> casecmp), {:before => "return nil unless args.first.is_a? Symbol" }],
10
+ [%w(capitalize downcase next succ swapcase upcase), {:after => ".to_s"}],
11
+ [%w(=~ [] empty? length match size), {}]
12
+ ].each { |methods, options| methods.each do |method|
13
+ module_eval <<-end_eval
14
+ def #{method}(*args)
15
+ #{options[:before]}
16
+ to_s.#{method}(*args)#{options[:after]}
17
+ end unless method_defined? :#{method}
18
+ end_eval
19
+ end }
6
20
  end
data/lib/backports.rb CHANGED
@@ -10,6 +10,13 @@ module Kernel
10
10
  end unless method_defined? :require_relative
11
11
  end
12
12
 
13
- %w(object module array enumerable string symbol fixnum hash proc).each do |lib|
13
+ class Array
14
+ # Standard in rails, and we use it in module.
15
+ def extract_options!
16
+ last.is_a?(::Hash) ? pop : {}
17
+ end unless method_defined? :extract_options!
18
+ end
19
+
20
+ %w(object module kernel object_space array enumerable enumerator string symbol integer fixnum hash proc binding dir io method regexp struct).each do |lib|
14
21
  require_relative "backports/#{lib}"
15
22
  end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class BindingTest < Test::Unit::TestCase
4
+ class Demo
5
+ def initialize(n)
6
+ @secret = n
7
+ end
8
+ def get_binding
9
+ return binding()
10
+ end
11
+ end
12
+
13
+ context "Binding" do
14
+ context "#eval" do
15
+ should "conform to doc" do
16
+ assert_equal 99, Demo.new(99).get_binding.eval("@secret")
17
+ end
18
+ end
19
+ end
20
+ end
@@ -83,6 +83,16 @@ class EnumerableTest < Test::Unit::TestCase
83
83
  end
84
84
  end
85
85
 
86
+ context "#find" do
87
+ should "not require a block" do
88
+ assert_equal 3, (1..10).find.each {|item| item > 2 }
89
+ end
90
+
91
+ should "work as expected" do
92
+ assert_equal 3, (1..10).find {|item| item > 2 }
93
+ end
94
+ end
95
+
86
96
  context "#find_index" do
87
97
  should "conform to doc" do
88
98
  assert_equal 3, %w{ant bat cat dog}.find_index {|item| item =~ /g/ }
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+
4
+ class EnumeratorTest < Test::Unit::TestCase
5
+ context "Enumerator" do
6
+ context "#with_object" do
7
+ should "conform to doc" do
8
+ animals = %w(cat dog wombat).to_enum
9
+ hash = animals.with_object({}).each do |item, memo|
10
+ memo[item] = item.upcase.reverse
11
+ end
12
+ assert_equal({"cat"=>"TAC", "dog"=>"GOD", "wombat"=>"TABMOW"}, hash)
13
+ end
14
+ end
15
+
16
+ context "#new" do
17
+ should "should accept block" do
18
+ enum = Enumerator.new do |yielder|
19
+ yielder.yield "This cool new syntax is sponsored by"
20
+ yielder.yield yielder.class
21
+ end
22
+ assert enum.is_a?(Enumerator)
23
+ 2.times do
24
+ assert_equal ["This cool new syntax is sponsored by", Enumerator::Yielder], enum.to_a
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require 'test_helper'
2
+
3
+ $outside = __callee__
4
+ def fred
5
+ "I'm in #{__callee__.inspect}"
6
+ end
7
+
8
+ class KernelTest < Test::Unit::TestCase
9
+ context "Kernel" do
10
+ context ".loop" do
11
+ should "conform to doc" do
12
+ enum1 = [1, 2, 3].to_enum
13
+ enum2 = [10, 20].to_enum
14
+ r = []
15
+ loop do
16
+ r << enum1.next + enum2.next
17
+ end
18
+ assert_equal [11,22], r
19
+ end
20
+ end
21
+
22
+
23
+ context ".__callee__" do
24
+ should "conform to doc" do
25
+ assert_equal "I'm in :fred", fred
26
+ assert_equal nil, $outside
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ require 'test_helper'
2
+
3
+ class ArrayTest < Test::Unit::TestCase
4
+
5
+ context "Method" do
6
+ setup do
7
+ @cat = "cat"
8
+ @bound = @cat.method(:upcase)
9
+ end
10
+
11
+ context "#name" do
12
+ should "conform to doc" do
13
+ assert_equal :upcase, @bound.name
14
+ end
15
+ end
16
+
17
+ context "#owner" do
18
+ should "conform to doc" do
19
+ assert_equal String, @bound.owner
20
+ end
21
+ end
22
+
23
+ context "#receiver" do
24
+ should "conform to doc" do
25
+ assert @cat === @bound.receiver
26
+ end
27
+ end
28
+
29
+ context "Unbound" do
30
+ setup do
31
+ @unbound = @bound.unbind
32
+ end
33
+
34
+ context "#name" do
35
+ should "conform to doc" do
36
+ assert_equal :upcase, @unbound.name
37
+ end
38
+ end
39
+
40
+ context "#owner" do
41
+ should "conform to doc" do
42
+ assert_equal String, @unbound.owner
43
+ end
44
+ end
45
+
46
+ context "bound again" do
47
+ setup do
48
+ @dog = "dog"
49
+ @bound_again = @unbound.bind(@dog)
50
+ end
51
+
52
+ context "#name" do
53
+ should "conform to doc" do
54
+ assert_equal :upcase, @bound_again.name
55
+ end
56
+ end
57
+
58
+ context "#owner" do
59
+ should "conform to doc" do
60
+ assert_equal String, @bound_again.owner
61
+ end
62
+ end
63
+
64
+ context "#receiver" do
65
+ should "conform to doc" do
66
+ assert @dog === @bound_again.receiver
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ class Thing
4
+ end
5
+
6
+ class ModuleTest < Test::Unit::TestCase
7
+ context "Module" do
8
+ context "#module_exec" do
9
+ should "conform to doc" do
10
+ name = :new_instance_variable
11
+ Thing.module_exec(name) do |iv_name|
12
+ attr_accessor iv_name
13
+ end
14
+ t = Thing.new
15
+ t.new_instance_variable = "wibble"
16
+ assert_equal "wibble", t.new_instance_variable
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class ObjectTest < Test::Unit::TestCase
4
+ class KlassWithSecret
5
+ def initialize
6
+ @secret = 99
7
+ end
8
+ end
9
+ context "Object" do
10
+ context "#instance_exec" do
11
+ should "conform to doc" do
12
+ k = KlassWithSecret.new
13
+ assert_equal 104, k.instance_exec(5) {|x| @secret+x }
14
+ end
15
+ end
16
+
17
+ context "#define_singleton_method" do
18
+ should "conform to doc" do
19
+ a = "cat"
20
+ a.define_singleton_method(:speak) do
21
+ "miaow"
22
+ end
23
+ assert_equal "miaow", a.speak
24
+
25
+ KlassWithSecret.class_eval do
26
+ define_method(:one) { "instance method" }
27
+ define_singleton_method(:two) { "class method" }
28
+ end
29
+ t = KlassWithSecret.new
30
+ assert_equal "instance method", t.one
31
+ assert_equal "class method", KlassWithSecret.two
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ class RegexpTest < Test::Unit::TestCase
4
+ context "Regexp" do
5
+ context ".union" do
6
+ should "conform to doc" do
7
+ assert_equal /cat/ , Regexp.union("cat")
8
+ assert_equal /cat|dog/ , Regexp.union("cat", "dog")
9
+ assert_equal /cat|dog/ , Regexp.union(%w{ cat dog })
10
+ assert_equal /cat|(?i-mx:dog)/, Regexp.union("cat", /dog/i)
11
+ end
12
+ end
13
+ end
14
+ end
data/test/string_test.rb CHANGED
@@ -4,6 +4,14 @@ require 'test_helper'
4
4
 
5
5
  class StringTest < Test::Unit::TestCase
6
6
  context "String" do
7
+ context "#ascii_only?" do
8
+ should "conform to doc" do
9
+ assert_equal true, "dog".ascii_only?
10
+ assert_equal false, "δog".ascii_only?
11
+ assert_equal true, "\x00 to \x7f".ascii_only?
12
+ end
13
+ end
14
+
7
15
  context "#chars" do
8
16
  should "conform to doc" do
9
17
  assert_equal ["d", "o", "g"], "dog".chars.to_a
@@ -13,6 +21,23 @@ class StringTest < Test::Unit::TestCase
13
21
  assert_equal ["δ", "o", "g"], result
14
22
  end
15
23
  end
24
+
25
+ context "#chr" do
26
+ should "conform to doc" do
27
+ assert_equal "d", "dog".chr
28
+ assert_equal "δ", "δog".chr
29
+ end
30
+ end
31
+
32
+ context "#codepoints" do
33
+ should "conform to doc" do
34
+ assert_equal [100, 111, 103], "dog".codepoints.to_a
35
+ assert_equal [948, 111, 103], "δog".codepoints.to_a # Note, there is an error in Pragmatics' book
36
+ result = []
37
+ assert_equal "δog", "δog".codepoints.each {|b| result << b }
38
+ assert_equal [948, 111, 103], result
39
+ end
40
+ end
16
41
 
17
42
  context "#start_with" do
18
43
  should "conform to doc" do
data/test/test_helper.rb CHANGED
@@ -6,5 +6,5 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
6
  $LOAD_PATH.unshift(File.dirname(__FILE__))
7
7
  require 'backports'
8
8
 
9
- class Test::Unit::TestCase
10
- end
9
+ # class Test::Unit::TestCase
10
+ # end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marcandre-backports
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Marc-Andr\xC3\xA9 Lafortune"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-24 00:00:00 -07:00
12
+ date: 2009-04-29 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -30,17 +30,35 @@ files:
30
30
  - VERSION.yml
31
31
  - lib/backports.rb
32
32
  - lib/backports/array.rb
33
+ - lib/backports/binding.rb
34
+ - lib/backports/dir.rb
33
35
  - lib/backports/enumerable.rb
36
+ - lib/backports/enumerator.rb
34
37
  - lib/backports/fixnum.rb
35
38
  - lib/backports/hash.rb
39
+ - lib/backports/integer.rb
40
+ - lib/backports/io.rb
41
+ - lib/backports/kernel.rb
42
+ - lib/backports/method.rb
36
43
  - lib/backports/module.rb
37
44
  - lib/backports/object.rb
45
+ - lib/backports/object_space.rb
38
46
  - lib/backports/proc.rb
47
+ - lib/backports/range.rb
48
+ - lib/backports/regexp.rb
39
49
  - lib/backports/string.rb
50
+ - lib/backports/struct.rb
40
51
  - lib/backports/symbol.rb
41
52
  - test/array_test.rb
53
+ - test/binding_test.rb
42
54
  - test/enumerable_test.rb
55
+ - test/enumerator_test.rb
43
56
  - test/hash_test.rb
57
+ - test/kernel_test.rb
58
+ - test/method_test.rb
59
+ - test/module_test.rb
60
+ - test/object_test.rb
61
+ - test/regexp_test.rb
44
62
  - test/string_test.rb
45
63
  - test/test_helper.rb
46
64
  has_rdoc: true
@@ -77,7 +95,14 @@ specification_version: 2
77
95
  summary: Backports or ruby 1.8.7+ & rails for older ruby.
78
96
  test_files:
79
97
  - test/array_test.rb
98
+ - test/binding_test.rb
80
99
  - test/enumerable_test.rb
100
+ - test/enumerator_test.rb
81
101
  - test/hash_test.rb
102
+ - test/kernel_test.rb
103
+ - test/method_test.rb
104
+ - test/module_test.rb
105
+ - test/object_test.rb
106
+ - test/regexp_test.rb
82
107
  - test/string_test.rb
83
108
  - test/test_helper.rb