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
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
class Object
|
3
|
+
|
4
|
+
##
|
5
|
+
# Return the metaclass of this object.
|
6
|
+
|
7
|
+
def metaclass
|
8
|
+
class << self; self end
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Evaluate a +string+ or +block+ in context to this
|
13
|
+
# object metaclass.
|
14
|
+
|
15
|
+
def meta_eval string = nil, &block
|
16
|
+
return metaclass.class_eval(string) if string
|
17
|
+
metaclass.class_eval &block
|
18
|
+
end
|
19
|
+
alias :metaeval :meta_eval
|
20
|
+
|
21
|
+
##
|
22
|
+
# Define a singleton method.
|
23
|
+
|
24
|
+
def meta_def name, &block
|
25
|
+
meta_eval { define_method name, &block }
|
26
|
+
end
|
27
|
+
alias :metadef :meta_def
|
28
|
+
|
29
|
+
end
|
data/lib/rext/proc.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
class Proc
|
3
|
+
|
4
|
+
##
|
5
|
+
# Yield or instance evaluate the +object+ passed
|
6
|
+
# based on this proc's arity.
|
7
|
+
#
|
8
|
+
# === Examples
|
9
|
+
#
|
10
|
+
# def foo &block
|
11
|
+
# block.yield_or_eval 'bar'
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# foo { |v| v.length } # => 3
|
15
|
+
# foo { length } # => 3
|
16
|
+
#
|
17
|
+
|
18
|
+
def yield_or_eval object
|
19
|
+
arity > 0 ? self.call(object) : object.instance_eval(&self)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
data/lib/rext/string.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
|
2
|
+
require 'rack'
|
3
|
+
require 'digest/sha2'
|
4
|
+
require 'digest/md5'
|
5
|
+
|
6
|
+
class String
|
7
|
+
|
8
|
+
##
|
9
|
+
# Return 32 character md5 string.
|
10
|
+
#
|
11
|
+
# === Examples
|
12
|
+
#
|
13
|
+
# 'test'.to_md5 # => 098f6bcd4621d373cade4e832627b4f6
|
14
|
+
#
|
15
|
+
|
16
|
+
def to_md5
|
17
|
+
::Digest::MD5.hexdigest self
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Return 128 character sha512 string.
|
22
|
+
#
|
23
|
+
# === Examples
|
24
|
+
#
|
25
|
+
# 'test'.to_sha512 # => ee26b0dd4af7e749aa1a8ee3c10ae9923f618980772e473f8819a5d4940e0db27ac185f8a0e1d5f84f88bc887fd67b143732c304cc5fa9ad8e6f57f50028a8ff
|
26
|
+
#
|
27
|
+
|
28
|
+
def to_sha512
|
29
|
+
::Digest::SHA512.hexdigest self
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Return Base 64 decoded string.
|
34
|
+
#
|
35
|
+
# === Examples
|
36
|
+
#
|
37
|
+
# 'Y29va2llcw=='.base64_decode # => cookies
|
38
|
+
#
|
39
|
+
|
40
|
+
def base64_decode
|
41
|
+
unpack('m').first
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Return Base 64 encoded string.
|
46
|
+
#
|
47
|
+
# === Examples
|
48
|
+
#
|
49
|
+
# 'cookies'.base64_encode # => Y29va2llcw==
|
50
|
+
#
|
51
|
+
|
52
|
+
def base64_encode
|
53
|
+
[self].pack('m').chop
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# URL encode. Shortcut for Rack::Utils.encode.
|
58
|
+
|
59
|
+
def url_encode
|
60
|
+
Rack::Utils.escape self
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# URL decode. Shortcut for Rack::Utils.unescape.
|
65
|
+
|
66
|
+
def url_decode
|
67
|
+
Rack::Utils.unescape self
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Escape html entities. Shortcut for Rack::Utils.escape_html.
|
72
|
+
#
|
73
|
+
# === Examples
|
74
|
+
#
|
75
|
+
# 'im <strong>strong</strong>.escape_html # => im <strong>strong</strong>
|
76
|
+
#
|
77
|
+
|
78
|
+
def escape_html
|
79
|
+
Rack::Utils.escape_html self
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
|
2
|
+
require 'extlib'
|
3
|
+
|
4
|
+
class String
|
5
|
+
|
6
|
+
##
|
7
|
+
# Returns a File instance.
|
8
|
+
#
|
9
|
+
# === Examples
|
10
|
+
#
|
11
|
+
# 'History.rdoc'.file.mtime
|
12
|
+
#
|
13
|
+
|
14
|
+
def file
|
15
|
+
File.new self
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Returns a Pathname instance.
|
20
|
+
#
|
21
|
+
# === Examples
|
22
|
+
#
|
23
|
+
# 'lib'.path.join('foo').expand_path
|
24
|
+
#
|
25
|
+
|
26
|
+
def path
|
27
|
+
require 'pathname'
|
28
|
+
Pathname.new self
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Returns an array of files matching self.
|
33
|
+
#
|
34
|
+
# === Examples
|
35
|
+
#
|
36
|
+
# 'lib/**/*.rb'.files
|
37
|
+
#
|
38
|
+
|
39
|
+
def files
|
40
|
+
Dir[self]
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Merge the +word+ passed into the string. This
|
45
|
+
# is useful for adding classes which may already
|
46
|
+
# exist in a string.
|
47
|
+
#
|
48
|
+
# === Examples
|
49
|
+
#
|
50
|
+
# 'product'.merge_word('sold') # => "product sold"
|
51
|
+
# 'product sold'.merge_word('sold') # => "product sold"
|
52
|
+
#
|
53
|
+
|
54
|
+
def merge_word word
|
55
|
+
self << " #{word}" unless split.include? word
|
56
|
+
self
|
57
|
+
end
|
58
|
+
alias :add_class :merge_word
|
59
|
+
|
60
|
+
##
|
61
|
+
# Digitize a string.
|
62
|
+
#
|
63
|
+
# === Examples:
|
64
|
+
#
|
65
|
+
# '$100,000'.digitize # => 100000
|
66
|
+
#
|
67
|
+
|
68
|
+
def digitize
|
69
|
+
gsub /[^\d]/, ''
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# Returns a constant when the string is a valid constant name.
|
74
|
+
|
75
|
+
def constantize
|
76
|
+
Extlib::Inflection.constantize self
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Convert a string to camel-case, and optionally +capitalize_first_letter+.
|
81
|
+
|
82
|
+
def camelize capitalize_first_letter = false
|
83
|
+
string = Extlib::Inflection.camelize(self)
|
84
|
+
return string if capitalize_first_letter
|
85
|
+
string[0,1] = string.first.downcase
|
86
|
+
string
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Wrap a string with a +prefix+ and optional
|
91
|
+
# +suffix+. When the +suffix+ is not present
|
92
|
+
# the +prefix+ will be used.
|
93
|
+
#
|
94
|
+
# === Examples
|
95
|
+
#
|
96
|
+
# 'foo'.wrap('|') # => |foo|
|
97
|
+
# 'foo'.wrap('(', ')') # => (foo)
|
98
|
+
#
|
99
|
+
|
100
|
+
def wrap prefix, suffix = nil
|
101
|
+
prefix + self + (suffix || prefix)
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Check if a string starts with another +string+.
|
106
|
+
#
|
107
|
+
# === Examples
|
108
|
+
#
|
109
|
+
# 'foo bar'.starts_with? 'foo' # => true
|
110
|
+
#
|
111
|
+
|
112
|
+
def starts_with? string
|
113
|
+
index(string) == 0
|
114
|
+
end
|
115
|
+
|
116
|
+
##
|
117
|
+
# Check if a string ends with another +string+.
|
118
|
+
#
|
119
|
+
# === Examples
|
120
|
+
#
|
121
|
+
# 'foo bar'.ends_with? 'bar' # => true
|
122
|
+
#
|
123
|
+
|
124
|
+
def ends_with? string
|
125
|
+
rindex(string) == length - string.length
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Determines if a string is plural.
|
130
|
+
#
|
131
|
+
# === Examples
|
132
|
+
#
|
133
|
+
# 'cookies'.plural? # => true
|
134
|
+
# 'cookie'.plural? # => false
|
135
|
+
#
|
136
|
+
|
137
|
+
def plural?
|
138
|
+
singular != self
|
139
|
+
end
|
140
|
+
|
141
|
+
##
|
142
|
+
# Determines if a string is singular.
|
143
|
+
#
|
144
|
+
# === Examples
|
145
|
+
#
|
146
|
+
# 'cookies'.singular? # => false
|
147
|
+
# 'cookie'.singular? # => true
|
148
|
+
#
|
149
|
+
|
150
|
+
def singular?
|
151
|
+
not plural?
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# First +n+ character(s).
|
156
|
+
#
|
157
|
+
# === Examples
|
158
|
+
#
|
159
|
+
# 'foo'.first # => f
|
160
|
+
# 'foo'.first(2) # => fo
|
161
|
+
#
|
162
|
+
|
163
|
+
def first n = 1
|
164
|
+
self[0, n]
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Last +n+ character(s).
|
169
|
+
#
|
170
|
+
# === Examples
|
171
|
+
#
|
172
|
+
# 'bar'.last # => r
|
173
|
+
# 'bar'.last(2) # => ar
|
174
|
+
#
|
175
|
+
|
176
|
+
def last n = 1
|
177
|
+
self[-n, n]
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# All characters after +n+.
|
182
|
+
#
|
183
|
+
# === Examples
|
184
|
+
#
|
185
|
+
# '.css'.from(1) #=> css
|
186
|
+
#
|
187
|
+
|
188
|
+
def from n
|
189
|
+
self[n, length]
|
190
|
+
end
|
191
|
+
|
192
|
+
##
|
193
|
+
# Replace all underscores with hyphens.
|
194
|
+
|
195
|
+
def dasherize
|
196
|
+
tr '_', '-'
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Return hash of word frequencies.
|
201
|
+
#
|
202
|
+
# === Examples
|
203
|
+
#
|
204
|
+
# 'foo foo bar'.word_frequency
|
205
|
+
# # => { 'foo' => 2, 'bar' => 1 }
|
206
|
+
#
|
207
|
+
|
208
|
+
def word_frequency
|
209
|
+
split.inject Hash.new(0) do |frequencies, word|
|
210
|
+
frequencies[word] += 1
|
211
|
+
frequencies
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
##
|
216
|
+
# Return frequency of _word_ or 0.
|
217
|
+
#
|
218
|
+
# === Examples
|
219
|
+
#
|
220
|
+
# 'foo foo bar'.frequency_of_word('foo') # => 2
|
221
|
+
# 'foo foo bar'.frequency_of_word('bar') # => 1
|
222
|
+
#
|
223
|
+
|
224
|
+
def frequency_of_word word
|
225
|
+
word_frequency[word]
|
226
|
+
end
|
227
|
+
|
228
|
+
class InvalidSwitchError < StandardError; end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Returns the switch equivilant of this string.
|
232
|
+
#
|
233
|
+
# === Examples
|
234
|
+
#
|
235
|
+
# 'foo_bar'.switchify # => --foo-bar
|
236
|
+
# 'lots_of_foobar'.switchify # => --lots-of-foobar
|
237
|
+
# 't'.switchify # => -t
|
238
|
+
# ''.switchify # => InvalidSwitchError
|
239
|
+
#
|
240
|
+
|
241
|
+
def switchify
|
242
|
+
raise InvalidSwitchError, 'switch must have a length > 0' if length.zero?
|
243
|
+
length > 1 ? "--#{dasherize}" : "-#{self}"
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
data/lib/rext/symbol.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
class Symbol
|
3
|
+
|
4
|
+
##
|
5
|
+
# Return a proc which sends itself as a message
|
6
|
+
# to the first proc argument.
|
7
|
+
#
|
8
|
+
# === Examples
|
9
|
+
#
|
10
|
+
# %w( some foo bar ).map(&:length) # => [4, 3, 3]
|
11
|
+
#
|
12
|
+
|
13
|
+
def to_proc
|
14
|
+
Proc.new { |object| object.send self }
|
15
|
+
end
|
16
|
+
end
|
data/lib/rext/time.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
|
2
|
+
class Time
|
3
|
+
|
4
|
+
def to_time #:nodoc:
|
5
|
+
self
|
6
|
+
end
|
7
|
+
|
8
|
+
##
|
9
|
+
# Time in words since +time+ or now.
|
10
|
+
#
|
11
|
+
# === Examples
|
12
|
+
#
|
13
|
+
# 5.seconds.ago.in_words_since_now # => less than one minute
|
14
|
+
# 5.days.ago.in_words_since_now # => 5 days
|
15
|
+
# 1.month.ago.in_words_since_now # => 1 month
|
16
|
+
# 101.years.ago.in_words_since_now # => hundreds of years
|
17
|
+
#
|
18
|
+
# "the article was published #{article.created_at.in_words_since_now} ago"
|
19
|
+
# # => the article was published 15 minutes ago
|
20
|
+
#
|
21
|
+
|
22
|
+
def in_words_since time = Time.now
|
23
|
+
return if self > time
|
24
|
+
seconds = (time - self).to_i
|
25
|
+
# TODO: abstract this out
|
26
|
+
pluralize = lambda do |type|
|
27
|
+
n = seconds.send(:"to_#{type}s")
|
28
|
+
n == 1 ? "one #{type}" : "#{n} #{type}s"
|
29
|
+
end
|
30
|
+
case seconds
|
31
|
+
when 0..59 ; 'less than one minute'
|
32
|
+
when 1.minute..59.minutes ; pluralize[:minute]
|
33
|
+
when 1.hour..23.hours ; pluralize[:hour]
|
34
|
+
when 1.day..6.days ; pluralize[:day]
|
35
|
+
when 1.week..3.weeks ; pluralize[:week]
|
36
|
+
when 1.month..11.months ; pluralize[:month]
|
37
|
+
when 1.year..99.years ; pluralize[:year]
|
38
|
+
else 'hundreds of years'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
alias :in_words_since_now :in_words_since
|
42
|
+
|
43
|
+
end
|