rext 0.3.4
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +97 -0
- data/Manifest +54 -0
- data/README.rdoc +136 -0
- data/Rakefile +16 -0
- data/benchmarks/enumerable.rb +14 -0
- data/benchmarks/proc.rb +24 -0
- data/lib/rext.rb +24 -0
- data/lib/rext/all.rb +18 -0
- data/lib/rext/array.rb +6 -0
- data/lib/rext/array/helpers.rb +64 -0
- data/lib/rext/date.rb +6 -0
- data/lib/rext/date/helpers.rb +11 -0
- data/lib/rext/enumerable.rb +6 -0
- data/lib/rext/enumerable/helpers.rb +88 -0
- data/lib/rext/hash.rb +6 -0
- data/lib/rext/hash/helpers.rb +42 -0
- data/lib/rext/integer.rb +6 -0
- data/lib/rext/integer/helpers.rb +29 -0
- data/lib/rext/module.rb +6 -0
- data/lib/rext/module/helpers.rb +85 -0
- data/lib/rext/numeric.rb +7 -0
- data/lib/rext/numeric/bytes.rb +16 -0
- data/lib/rext/numeric/time.rb +57 -0
- data/lib/rext/object.rb +7 -0
- data/lib/rext/object/helpers.rb +62 -0
- data/lib/rext/object/metaclass.rb +29 -0
- data/lib/rext/proc.rb +7 -0
- data/lib/rext/proc/helpers.rb +22 -0
- data/lib/rext/string.rb +7 -0
- data/lib/rext/string/encode.rb +82 -0
- data/lib/rext/string/helpers.rb +246 -0
- data/lib/rext/symbol.rb +6 -0
- data/lib/rext/symbol/helpers.rb +16 -0
- data/lib/rext/time.rb +6 -0
- data/lib/rext/time/helpers.rb +43 -0
- data/lib/rext/version.rb +4 -0
- data/rext.gemspec +30 -0
- data/spec/array_spec.rb +61 -0
- data/spec/date_spec.rb +14 -0
- data/spec/enumerable_spec.rb +55 -0
- data/spec/hash_spec.rb +36 -0
- data/spec/integer_spec.rb +19 -0
- data/spec/module_spec.rb +41 -0
- data/spec/numeric_spec.rb +31 -0
- data/spec/object_spec.rb +101 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/string_spec.rb +194 -0
- data/spec/symbol_spec.rb +14 -0
- data/spec/time_spec.rb +22 -0
- data/tasks/benchmark.rake +13 -0
- data/tasks/docs.rake +13 -0
- data/tasks/gemspec.rake +3 -0
- data/tasks/spec.rake +25 -0
- metadata +147 -0
data/lib/rext/date.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
|
2
|
+
require 'rext/module/helpers'
|
3
|
+
require 'rext/proc/helpers'
|
4
|
+
|
5
|
+
module Enumerable
|
6
|
+
|
7
|
+
##
|
8
|
+
# Proxy
|
9
|
+
#
|
10
|
+
# The enumerable proxy class is utilized to
|
11
|
+
# allow methods such as #group_by, #map, and others
|
12
|
+
# to provide a method call alternative to a block.
|
13
|
+
#
|
14
|
+
# For example words.group_by { |word| word.length } can
|
15
|
+
# be replaced by words.group_by_.length
|
16
|
+
#
|
17
|
+
# === See
|
18
|
+
#
|
19
|
+
# * Enumerable#proxy
|
20
|
+
#
|
21
|
+
|
22
|
+
class Proxy
|
23
|
+
instance_methods.each { |m| undef_method m unless m.match(/^__/) }
|
24
|
+
|
25
|
+
def initialize object, meth
|
26
|
+
@object, @method = object, meth
|
27
|
+
end
|
28
|
+
|
29
|
+
def method_missing meth, *args, &block
|
30
|
+
@object.__send__(@method) { |o| o.__send__(meth, *args, &block) }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Shortcut for Proxy.new self, +meth+.
|
36
|
+
|
37
|
+
def proxy meth
|
38
|
+
Proxy.new self, meth
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Return a hash grouped by +block+.
|
43
|
+
#
|
44
|
+
# === Examples
|
45
|
+
#
|
46
|
+
# words = %w( just some foo bar )
|
47
|
+
# words.group_by { |word| word.length } # => {3=>["foo", "bar"], 4=>["just", "some"]}
|
48
|
+
# words.group_by { length } # => {3=>["foo", "bar"], 4=>["just", "some"]}
|
49
|
+
# words.group_by.length # => {3=>["foo", "bar"], 4=>["just", "some"]}
|
50
|
+
#
|
51
|
+
|
52
|
+
def group_by &block
|
53
|
+
return proxy(:group_by) unless block
|
54
|
+
inject({}) do |hash, value|
|
55
|
+
(hash[block.yield_or_eval(value)] ||= []) << value
|
56
|
+
hash
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# Sexy Symbol#to_proc replacement for mapping enums.
|
62
|
+
#
|
63
|
+
# === Examples
|
64
|
+
#
|
65
|
+
# names = %w( tj scott joe bob )
|
66
|
+
# names.every.length.join # => 2533
|
67
|
+
# names.every.empty?.any? # => false
|
68
|
+
# names.every { length > 4 }.all? # => true
|
69
|
+
#
|
70
|
+
|
71
|
+
def every &block
|
72
|
+
block ? proxy(:map).instance_eval(&block) : proxy(:map)
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Check if all +args+ are included.
|
77
|
+
#
|
78
|
+
# === Examples
|
79
|
+
#
|
80
|
+
# permissions = 'save', 'edit', 'delete'
|
81
|
+
# permissions.includes_all? 'save', 'edit' # => true
|
82
|
+
#
|
83
|
+
|
84
|
+
def includes_all? *args
|
85
|
+
args.all? { |arg| include? arg }
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
data/lib/rext/hash.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
##
|
5
|
+
# Delete key-value pairs, returning the values found
|
6
|
+
# using the +keys+ passed. Aliased as extract!
|
7
|
+
#
|
8
|
+
# === Examples
|
9
|
+
#
|
10
|
+
# options = { :width => 25, :height => 100 }
|
11
|
+
# width, height = options.delete_at :width, :height
|
12
|
+
#
|
13
|
+
# width # => 25
|
14
|
+
# height # => 100
|
15
|
+
# options # => {}
|
16
|
+
#
|
17
|
+
|
18
|
+
def delete_at *keys
|
19
|
+
keys.map { |key| delete key }
|
20
|
+
end
|
21
|
+
alias :extract! :delete_at
|
22
|
+
|
23
|
+
##
|
24
|
+
# Return an array of switches and their arguments.
|
25
|
+
#
|
26
|
+
# === Examples
|
27
|
+
#
|
28
|
+
# { :use_foobar => true }.switchify # => ['--use-foobar']
|
29
|
+
# { :use_foobar => false }.switchify # => []
|
30
|
+
# { :interval => 15, :icon => :jpeg } # => ['--interval', '15', '--icon', 'jpeg']
|
31
|
+
#
|
32
|
+
|
33
|
+
def switchify
|
34
|
+
inject [] do |args, (key, value)|
|
35
|
+
next args unless value
|
36
|
+
args << key.to_s.switchify
|
37
|
+
args << (String === value ? value.inspect : value.to_s) unless value === true
|
38
|
+
args
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
data/lib/rext/integer.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
class Integer
|
3
|
+
|
4
|
+
##
|
5
|
+
# Ordinalize turns a number into an ordinal string used to denote the
|
6
|
+
# position in an ordered sequence such as 1st, 2nd, 3rd, 4th.
|
7
|
+
#
|
8
|
+
# === Examples
|
9
|
+
#
|
10
|
+
# 1.ordinalize # => "1st"
|
11
|
+
# 2.ordinalize # => "2nd"
|
12
|
+
# 1002.ordinalize # => "1002nd"
|
13
|
+
# 1003.ordinalize # => "1003rd"
|
14
|
+
#
|
15
|
+
|
16
|
+
def ordinalize
|
17
|
+
if (11..13).include? self % 100
|
18
|
+
"#{self}th"
|
19
|
+
else
|
20
|
+
case self % 10
|
21
|
+
when 1 ; "#{self}st"
|
22
|
+
when 2 ; "#{self}nd"
|
23
|
+
when 3 ; "#{self}rd"
|
24
|
+
else "#{self}th"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/rext/module.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
|
2
|
+
require 'rext/object/metaclass'
|
3
|
+
|
4
|
+
class Module
|
5
|
+
|
6
|
+
##
|
7
|
+
# Shortcut for including an anonymous module.
|
8
|
+
|
9
|
+
def chainable &block
|
10
|
+
include Module.new(&block)
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Shortcut for extending with an anonymous module.
|
15
|
+
|
16
|
+
def extendable &block
|
17
|
+
extend Module.new(&block)
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Call +method+ when conditions are met.
|
22
|
+
#
|
23
|
+
# This method provides a simple means of
|
24
|
+
# utilizing method_missing, and should
|
25
|
+
# be used in most cases.
|
26
|
+
#
|
27
|
+
# When using a regular expression with
|
28
|
+
# the :if option, all captures are passed
|
29
|
+
# to the handling method.
|
30
|
+
#
|
31
|
+
# === Examples
|
32
|
+
#
|
33
|
+
# class Foo
|
34
|
+
# call_method :find_by, :if => /^find_by_(\w+)/
|
35
|
+
# def find_by attr, *args
|
36
|
+
# "finding by #{attr} with #{args.join(', ')}"
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# foo = Foo.new
|
41
|
+
# foo.find_by_name('bar') # => "finding by name with bar"
|
42
|
+
#
|
43
|
+
# === Options
|
44
|
+
#
|
45
|
+
# :if regexp or proc
|
46
|
+
#
|
47
|
+
|
48
|
+
def call_method method, options = {}
|
49
|
+
chainable {
|
50
|
+
define_method :method_missing do |meth, *args|
|
51
|
+
if options[:if].is_a?(Regexp) && meth.to_s =~ options[:if]
|
52
|
+
send method, *($~.captures + args)
|
53
|
+
elsif options[:if].respond_to?(:call) && options[:if].call(meth, *args)
|
54
|
+
send method, *args
|
55
|
+
else
|
56
|
+
super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
##
|
63
|
+
# Equivalent to defining self.included and
|
64
|
+
# instance evaluating the module passed.
|
65
|
+
#
|
66
|
+
# === Examples
|
67
|
+
#
|
68
|
+
# def self.included mod
|
69
|
+
# mod.instance_eval do
|
70
|
+
# include InstanceMethods
|
71
|
+
# end
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# setup do
|
75
|
+
# include InstanceMethods
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
|
79
|
+
def setup &block
|
80
|
+
meta_def :included do |mod|
|
81
|
+
mod.instance_eval &block
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
data/lib/rext/numeric.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
class Numeric
|
3
|
+
|
4
|
+
def bytes; self end
|
5
|
+
def kilobytes; self << 10 end
|
6
|
+
def megabytes; self << 20 end
|
7
|
+
def gigabytes; self << 30 end
|
8
|
+
def terabytes; self << 40 end
|
9
|
+
|
10
|
+
alias :byte :bytes
|
11
|
+
alias :kilobyte :kilobytes
|
12
|
+
alias :megabyte :megabytes
|
13
|
+
alias :gigabyte :gigabytes
|
14
|
+
alias :terabyte :terabytes
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
class Numeric
|
3
|
+
|
4
|
+
def seconds; self end
|
5
|
+
def minutes; self * 60 end
|
6
|
+
def hours; self * 3600 end
|
7
|
+
def days; self * 86400 end
|
8
|
+
def weeks; self * 604800 end
|
9
|
+
def months; self * 2592000 end
|
10
|
+
def years; self * 31471200 end
|
11
|
+
|
12
|
+
alias :second :seconds
|
13
|
+
alias :minute :minutes
|
14
|
+
alias :hour :hours
|
15
|
+
alias :day :days
|
16
|
+
alias :week :weeks
|
17
|
+
alias :month :months
|
18
|
+
alias :year :years
|
19
|
+
|
20
|
+
def to_minutes; self / 1.minute end
|
21
|
+
def to_hours; self / 1.hour end
|
22
|
+
def to_days; self / 1.day end
|
23
|
+
def to_weeks; self / 1.week end
|
24
|
+
def to_months; self / 1.month end
|
25
|
+
def to_years; self / 1.year end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Time before specified +time+, which defaults to now.
|
29
|
+
#
|
30
|
+
# === Examples
|
31
|
+
#
|
32
|
+
# event = 10.days.ago
|
33
|
+
# 15.minutes.before event
|
34
|
+
#
|
35
|
+
|
36
|
+
def ago time = ::Time.now
|
37
|
+
time - self
|
38
|
+
end
|
39
|
+
alias :before :ago
|
40
|
+
|
41
|
+
##
|
42
|
+
# Time since specified +time+, which defaults to now.
|
43
|
+
#
|
44
|
+
# === Examples
|
45
|
+
#
|
46
|
+
# event = 1.year.ago
|
47
|
+
# 3.months.since event
|
48
|
+
#
|
49
|
+
# 4.days.from_now
|
50
|
+
#
|
51
|
+
|
52
|
+
def since time = ::Time.now
|
53
|
+
time + self
|
54
|
+
end
|
55
|
+
alias :from_now :since
|
56
|
+
|
57
|
+
end
|
data/lib/rext/object.rb
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
|
2
|
+
class Object
|
3
|
+
|
4
|
+
##
|
5
|
+
# Returns a hash indifferent to symbols or strings for
|
6
|
+
# accessor keys.
|
7
|
+
#
|
8
|
+
# === Examples
|
9
|
+
#
|
10
|
+
# hash = indifferent_hash
|
11
|
+
# hash['foo'] = 'bar'
|
12
|
+
#
|
13
|
+
# hash[:foo] #=> 'bar'
|
14
|
+
# hash['foo'] #=> 'bar'
|
15
|
+
#
|
16
|
+
|
17
|
+
def indifferent_hash
|
18
|
+
Hash.new { |hash, key| hash[key.to_s] if key.is_a? Symbol }
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Yield and return +value+.
|
23
|
+
#
|
24
|
+
# === Examples
|
25
|
+
#
|
26
|
+
# people = []
|
27
|
+
# people << 'tj'
|
28
|
+
# people << 'foo'
|
29
|
+
#
|
30
|
+
# returning [] do |people|
|
31
|
+
# people << 'tj'
|
32
|
+
# people << 'foo'
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
|
36
|
+
def returning value, &block
|
37
|
+
yield value
|
38
|
+
value
|
39
|
+
end
|
40
|
+
|
41
|
+
##
|
42
|
+
# Retry a _block_ of statements upto a number of _times_.
|
43
|
+
# When no error is raised the value returned by _block_ is
|
44
|
+
# simply returned.
|
45
|
+
#
|
46
|
+
# === Examples
|
47
|
+
#
|
48
|
+
# try 3 do
|
49
|
+
# open 'http://vision-media.ca'
|
50
|
+
# end
|
51
|
+
# # => allows 3 tries to fetch the response
|
52
|
+
#
|
53
|
+
|
54
|
+
def try times = 1, options = {}, &block
|
55
|
+
value = yield
|
56
|
+
rescue options[:on] || Exception
|
57
|
+
retry if (times -= 1) > 0
|
58
|
+
else
|
59
|
+
value
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|