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.
- 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
|