kelredd-useful 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +44 -0
- data/Rakefile +40 -0
- data/lib/useful/ruby_extensions/array.rb +45 -0
- data/lib/useful/ruby_extensions/fixnum.rb +30 -0
- data/lib/useful/ruby_extensions/hash.rb +108 -0
- data/lib/useful/ruby_extensions/numeric.rb +255 -0
- data/lib/useful/ruby_extensions/object.rb +23 -0
- data/lib/useful/ruby_extensions/string.rb +51 -0
- data/lib/useful/ruby_extensions.rb +7 -0
- data/lib/useful/sinatra_helpers/environment_tests.rb +17 -0
- data/lib/useful/sinatra_helpers/erb/error_pages.rb +23 -0
- data/lib/useful/sinatra_helpers/erb/partials.rb +42 -0
- data/lib/useful/sinatra_helpers/erb.rb +3 -0
- data/lib/useful/sinatra_helpers/tags.rb +89 -0
- data/lib/useful/sinatra_helpers.rb +4 -0
- data/lib/useful/version.rb +13 -0
- data/lib/useful.rb +2 -0
- data/test/test_helper.rb +10 -0
- data/test/unit/useful_test.rb +13 -0
- metadata +77 -0
data/README.rdoc
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
= Useful
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
A collection of useful helpers for various ruby things. Includes
|
6
|
+
helpers for sinatra, ruby base classes, mysql, rails, erb, etc...
|
7
|
+
|
8
|
+
You probably never want them all, all the time, but just require in
|
9
|
+
the pieces you are interested in.
|
10
|
+
|
11
|
+
== Installation
|
12
|
+
|
13
|
+
sudo gem install kelredd-useful --source http://gems.github.com
|
14
|
+
|
15
|
+
== Usage
|
16
|
+
|
17
|
+
require 'rubygems'
|
18
|
+
require 'useful/sinatra_helpers'
|
19
|
+
require 'useful/mysql_helpers'
|
20
|
+
|
21
|
+
== License
|
22
|
+
|
23
|
+
Copyright (c) 2009 Kelly Redding
|
24
|
+
|
25
|
+
Permission is hereby granted, free of charge, to any person
|
26
|
+
obtaining a copy of this software and associated documentation
|
27
|
+
files (the "Software"), to deal in the Software without
|
28
|
+
restriction, including without limitation the rights to use,
|
29
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
30
|
+
copies of the Software, and to permit persons to whom the
|
31
|
+
Software is furnished to do so, subject to the following
|
32
|
+
conditions:
|
33
|
+
|
34
|
+
The above copyright notice and this permission notice shall be
|
35
|
+
included in all copies or substantial portions of the Software.
|
36
|
+
|
37
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
38
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
39
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
40
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
41
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
42
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
43
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
44
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/gempackagetask'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
require 'lib/useful/version'
|
6
|
+
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
spec = Gem::Specification.new do |s|
|
10
|
+
s.name = 'useful'
|
11
|
+
s.version = Useful::Version.to_s
|
12
|
+
s.has_rdoc = true
|
13
|
+
s.extra_rdoc_files = %w(README.rdoc)
|
14
|
+
s.rdoc_options = %w(--main README.rdoc)
|
15
|
+
s.summary = "A collection of useful helpers for various ruby things."
|
16
|
+
s.author = 'Kelredd'
|
17
|
+
s.email = ''
|
18
|
+
s.homepage = ''
|
19
|
+
s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
|
20
|
+
# s.executables = ['useful']
|
21
|
+
|
22
|
+
# s.add_dependency('gem_name', '~> 0.0.1')
|
23
|
+
end
|
24
|
+
|
25
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
26
|
+
pkg.gem_spec = spec
|
27
|
+
end
|
28
|
+
|
29
|
+
Rake::TestTask.new do |t|
|
30
|
+
t.libs << 'test'
|
31
|
+
t.test_files = FileList["test/**/*_test.rb"]
|
32
|
+
t.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'Generate the gemspec to serve this Gem from Github'
|
36
|
+
task :github do
|
37
|
+
file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
|
38
|
+
File.open(file, 'w') {|f| f << spec.to_ruby }
|
39
|
+
puts "Created gemspec: #{file}"
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensions
|
3
|
+
module Array
|
4
|
+
|
5
|
+
module ClassMethods; end
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# adds the contents of a2 to a1, removing duplicates
|
13
|
+
def merge(a1,a2)
|
14
|
+
a2.each{|item| a1 << item unless a1.include?(item)}
|
15
|
+
a1
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns a new array, containing the contents of an_a with the contents of this array, removing duplicates
|
21
|
+
def merge(an_a)
|
22
|
+
self.class.merge(self.clone, an_a)
|
23
|
+
end
|
24
|
+
# adds the contents of an_a to this array, removing duplicates (inline version of #merge)
|
25
|
+
def merge!(an_a)
|
26
|
+
self.class.merge(self, an_a)
|
27
|
+
end
|
28
|
+
|
29
|
+
# split into an array of sized-arrays
|
30
|
+
def groups(size=1)
|
31
|
+
return [] if size <= 0
|
32
|
+
n,r = self.size.divmod(size)
|
33
|
+
grps = (0..(n-1)).collect{|i| self[i*size,size]}
|
34
|
+
r > 0 ? grps << self[-r,r] : grps
|
35
|
+
end
|
36
|
+
alias / groups
|
37
|
+
alias chunks groups
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class Array
|
44
|
+
include Useful::RubyExtensions::Array
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensions
|
3
|
+
module Fixnum
|
4
|
+
|
5
|
+
# returns a string reprensentation of the number padded with pad_num to a specified length
|
6
|
+
def pad(length = 3, pad_num = 0)
|
7
|
+
self.to_s.rjust(length,pad_num.to_s) rescue self.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
# return the value in values that is nearest to the number
|
11
|
+
def to_nearest_value(values = [])
|
12
|
+
return self if values.length == 0
|
13
|
+
value = values.first.to_i rescue self
|
14
|
+
diff = (self-value).abs
|
15
|
+
values.each do |val|
|
16
|
+
if (self-val.to_i).abs < diff
|
17
|
+
diff = (self-val.to_i).abs
|
18
|
+
value = val.to_i
|
19
|
+
end
|
20
|
+
end
|
21
|
+
value
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class Fixnum
|
29
|
+
include Useful::RubyExtensions::Fixnum
|
30
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Useful
|
4
|
+
module RubyExtensions
|
5
|
+
module Hash
|
6
|
+
|
7
|
+
module ClassMethods; end
|
8
|
+
def self.included(klass)
|
9
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
|
14
|
+
# inspired by ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
15
|
+
def stringify_keys(hash)
|
16
|
+
hash.keys.each{ |key| hash[(key.to_s rescue key)] ||= hash.delete(key) }
|
17
|
+
hash
|
18
|
+
end
|
19
|
+
|
20
|
+
# inspired by from ActiveSupport::CoreExtensions::Hash::Keys (http://api.rubyonrails.org/)
|
21
|
+
def symbolize_keys(hash)
|
22
|
+
hash.keys.each{ |key| hash[(key.to_sym rescue key)] ||= hash.delete(key) }
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
|
26
|
+
def only(hash, *keys)
|
27
|
+
hash.delete_if{ |k,v| !keys.flatten.include?(k) }
|
28
|
+
hash
|
29
|
+
end
|
30
|
+
|
31
|
+
def except(hash, *keys)
|
32
|
+
hash.delete_if{ |k,v| keys.flatten.include?(k) }
|
33
|
+
hash
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return a new hash with all keys converted to strings.
|
39
|
+
def stringify_keys
|
40
|
+
self.class.stringify_keys(self.clone)
|
41
|
+
end
|
42
|
+
# Destructively convert all keys to strings.
|
43
|
+
def stringify_keys!
|
44
|
+
self.class.stringify_keys(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return a new hash with all keys converted to strings.
|
48
|
+
def symbolize_keys
|
49
|
+
self.class.symbolize_keys(self.clone)
|
50
|
+
end
|
51
|
+
# Destructively convert all keys to strings.
|
52
|
+
def symbolize_keys!
|
53
|
+
self.class.symbolize_keys(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Return a new hash with only keys in *keys
|
57
|
+
def only(*keys)
|
58
|
+
self.class.only(self.clone, keys)
|
59
|
+
end
|
60
|
+
# Destructively remove all keys not in *keys
|
61
|
+
def only!(*keys)
|
62
|
+
self.class.only(self, keys)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return a new hash with only keys not in *keys
|
66
|
+
def except(*keys)
|
67
|
+
self.class.except(self.clone, keys)
|
68
|
+
end
|
69
|
+
# Destructively remove all keys in *keys
|
70
|
+
def except!(*keys)
|
71
|
+
self.class.except(self, keys)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Determines if a value exists for the provided key(s). Allows searching in nested hashes
|
75
|
+
def check_value?(*keys)
|
76
|
+
val = self[keys.first] || self[keys.first.to_s]
|
77
|
+
val = self[keys.first.to_s.intern] unless val || keys.first.kind_of?(Symbol)
|
78
|
+
return val.check_value?(*keys[1..-1]) if val.kind_of?(Hash) && keys.length > 1
|
79
|
+
return true if val && !val.empty?
|
80
|
+
false
|
81
|
+
end
|
82
|
+
|
83
|
+
# takes any empty values and makes them nil inline
|
84
|
+
def nillify!
|
85
|
+
self.each { |key,value| self[key] = nil if !value.nil? && value.to_s.empty? }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns string formatted for HTTP URL encoded name-value pairs.
|
89
|
+
# For example,
|
90
|
+
# {:id => 'thomas_hardy'}.to_http_str
|
91
|
+
# # => "id=thomas_hardy"
|
92
|
+
# {:id => 23423, :since => Time.now}.to_http_str
|
93
|
+
# # => "since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423"
|
94
|
+
def to_http_str
|
95
|
+
self.empty? ? '' : self.collect{|key, val| "#{key.to_s}=#{CGI.escape(val.to_s)}"}.join('&')
|
96
|
+
end
|
97
|
+
|
98
|
+
def to_html_attrs
|
99
|
+
self.empty? ? '' : self.collect{|key, val| "#{key}=\"#{val}\""}.join(' ')
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class Hash
|
107
|
+
include Useful::RubyExtensions::Hash
|
108
|
+
end
|
@@ -0,0 +1,255 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'object')
|
2
|
+
require File.join(File.dirname(__FILE__), 'string')
|
3
|
+
require File.join(File.dirname(__FILE__), 'hash')
|
4
|
+
|
5
|
+
module Useful
|
6
|
+
module RubyExtensions
|
7
|
+
module Numeric #:nodoc:
|
8
|
+
|
9
|
+
LOCALES = {
|
10
|
+
:en => {
|
11
|
+
:currency => {:format => "%u%n", :unit=> '$'},
|
12
|
+
:storage => {:format => "%n %u", :delimiter => ''},
|
13
|
+
:format => {:delimiter => ',', :separator => '.'},
|
14
|
+
:defaults => {:precision => 2}
|
15
|
+
}
|
16
|
+
}.freeze
|
17
|
+
STORAGE_UNITS = [:bytes, :kb, :mb, :gb, :tb].freeze
|
18
|
+
|
19
|
+
module ClassMethods; end
|
20
|
+
def self.included(klass)
|
21
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
22
|
+
end
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
|
26
|
+
def pad_precision(num, opts = {})
|
27
|
+
opts[:precision] ||= 2
|
28
|
+
opts[:separator] ||= '.'
|
29
|
+
opts[:pad_number] ||= 0
|
30
|
+
num.to_s.ljust(num.to_s.split(opts[:separator])[0].length + num.to_s.count(opts[:separator]) + opts[:precision].to_i, opts[:pad_number].to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
# Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
|
36
|
+
# customize the format in the +options+ hash.
|
37
|
+
# => taken and inspired from ActionView::Helpers::NumberHelper (http://api.rubyonrails.org/)
|
38
|
+
#
|
39
|
+
# ==== Options
|
40
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
|
41
|
+
# * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
|
42
|
+
#
|
43
|
+
# ==== Examples
|
44
|
+
# 12345678.with_delimiter # => 12,345,678
|
45
|
+
# 12345678.05.with_delimiter # => 12,345,678.05
|
46
|
+
# 12345678.with_delimiter(:delimiter => ".") # => 12.345.678
|
47
|
+
# 12345678.with_delimiter(:seperator => ",") # => 12,345,678
|
48
|
+
# 98765432.98.with_delimiter(:delimiter => " ", :separator => ",")
|
49
|
+
# # => 98 765 432,98
|
50
|
+
def with_delimiter(opts = {})
|
51
|
+
number = self.to_s.strip
|
52
|
+
opts.symbolize_keys!
|
53
|
+
opts[:locale] ||= :en
|
54
|
+
locale = LOCALES[opts.delete(:locale)]
|
55
|
+
opts = locale[:format].merge(opts) unless locale.nil?
|
56
|
+
opts[:delimiter] ||= ','
|
57
|
+
opts[:separator] ||= '.'
|
58
|
+
|
59
|
+
begin
|
60
|
+
parts = number.to_s.split('.')
|
61
|
+
parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{opts[:delimiter]}")
|
62
|
+
parts.join(opts[:separator])
|
63
|
+
rescue
|
64
|
+
number
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Converts a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision of 2).
|
69
|
+
# => taken and inspired from ActionView::Helpers::NumberHelper (http://api.rubyonrails.org/)
|
70
|
+
def to_precision(precision = 2)
|
71
|
+
rounded_number = (Float(self) * (10 ** precision)).round
|
72
|
+
rounded_number = rounded_number.to_f if precision > 0
|
73
|
+
(rounded_number / 10 ** precision) rescue self
|
74
|
+
end
|
75
|
+
|
76
|
+
# Formats a +number+ with the specified level of <tt>:precision</tt> (e.g., 112.32 has a precision of 2).
|
77
|
+
# You can customize the format in the +options+ hash.
|
78
|
+
# => taken and inspired from ActionView::Helpers::NumberHelper (http://api.rubyonrails.org/)
|
79
|
+
#
|
80
|
+
# ==== Options
|
81
|
+
# * <tt>:precision</tt> - Sets the level of precision (defaults to 3).
|
82
|
+
# * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
|
83
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
84
|
+
#
|
85
|
+
# ==== Examples (:locale => :en)
|
86
|
+
# 111.2345.with_precision # => 111.235
|
87
|
+
# 111.2345.with_precision(:precision => 2) # => 111.23
|
88
|
+
# 13.with_precision(:precision => 5) # => 13.00000
|
89
|
+
# 389.32314.with_precision(:precision => 0) # => 389
|
90
|
+
# 1111.2345.with_precision(:precision => 2, :separator => ',', :delimiter => '.')
|
91
|
+
# # => 1,111.23
|
92
|
+
def with_precision(opts = {})
|
93
|
+
opts.symbolize_keys!
|
94
|
+
opts[:locale] ||= :en
|
95
|
+
locale = LOCALES[opts.delete(:locale)]
|
96
|
+
opts = locale[:defaults].merge(locale[:format]).merge(opts) unless locale.nil?
|
97
|
+
opts[:precision] ||= 2
|
98
|
+
|
99
|
+
self.class.pad_precision(self.to_precision(opts[:precision]).with_delimiter(opts.only(:separator, :delimiter)), opts) rescue self
|
100
|
+
end
|
101
|
+
|
102
|
+
# Formats a +number+ as a percentage string (e.g., 65%). You can customize the
|
103
|
+
# format in the +options+ hash.
|
104
|
+
#
|
105
|
+
# ==== Options
|
106
|
+
# * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
|
107
|
+
# * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
|
108
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
109
|
+
#
|
110
|
+
# ==== Examples
|
111
|
+
# 100.to_percentage # => 100.00%
|
112
|
+
# 100.to_percentage(:precision => 0) # => 100%
|
113
|
+
# 1000.to_percentage(:delimiter => '.', :separator => ',') # => 1.000,00%
|
114
|
+
# 302.24398923423.to_percentage(:precision => 5) # => 302.24399%
|
115
|
+
def to_percentage(opts = {})
|
116
|
+
opts.symbolize_keys!
|
117
|
+
opts[:locale] ||= :en
|
118
|
+
locale = LOCALES[opts.delete(:locale)]
|
119
|
+
opts = locale[:defaults].merge(locale[:format]).merge(opts) unless locale.nil?
|
120
|
+
|
121
|
+
"#{self.with_precision(opts.only(:precision, :separator, :delimiter))}%" rescue self
|
122
|
+
end
|
123
|
+
|
124
|
+
# Formats a +number+ into a currency string (e.g., $13.65). You can customize the format
|
125
|
+
# in the +options+ hash.
|
126
|
+
# => taken and inspired from ActionView::Helpers::NumberHelper (http://api.rubyonrails.org/)
|
127
|
+
#
|
128
|
+
# ==== Options
|
129
|
+
# * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
|
130
|
+
# * <tt>:unit</tt> - Sets the denomination of the currency (defaults to "$").
|
131
|
+
# * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
|
132
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to ",").
|
133
|
+
# * <tt>:format</tt> - Sets the format of the output string (defaults to "%u%n"). The field types are:
|
134
|
+
# %u The currency unit
|
135
|
+
# %n The number
|
136
|
+
#
|
137
|
+
# ==== Examples (:locale => :en)
|
138
|
+
# 1234567890.50.to_currency # => $1,234,567,890.50
|
139
|
+
# 1234567890.506.to_currency # => $1,234,567,890.51
|
140
|
+
# 1234567890.506.to_currency(:precision => 3) # => $1,234,567,890.506
|
141
|
+
#
|
142
|
+
# 1234567890.50.to_currency(:unit => "£", :separator => ",", :delimiter => "")
|
143
|
+
# # => £1234567890,50
|
144
|
+
# 1234567890.50.to_currency(:unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
|
145
|
+
# # => 1234567890,50 £
|
146
|
+
def to_currency(opts = {})
|
147
|
+
opts.symbolize_keys!
|
148
|
+
opts[:locale] ||= :en
|
149
|
+
locale = LOCALES[opts.delete(:locale)]
|
150
|
+
opts = locale[:defaults].merge(locale[:format]).merge(locale[:currency]).merge(opts) unless locale.nil?
|
151
|
+
|
152
|
+
opts[:format].gsub(/%n/, self.with_precision(opts.only(:precision, :delimiter, :separator))).gsub(/%u/, opts[:unit]) #rescue self
|
153
|
+
end
|
154
|
+
|
155
|
+
# Formats the bytes in +size+ into a more understandable representation
|
156
|
+
# (e.g., giving it 1500 yields 1.5 KB). This method is useful for
|
157
|
+
# reporting file sizes to users. This method returns nil if
|
158
|
+
# +size+ cannot be converted into a number. You can customize the
|
159
|
+
# format in the +options+ hash.
|
160
|
+
#
|
161
|
+
# ==== Options
|
162
|
+
# * <tt>:precision</tt> - Sets the level of precision (defaults to 2).
|
163
|
+
# * <tt>:separator</tt> - Sets the separator between the units (defaults to ".").
|
164
|
+
# * <tt>:delimiter</tt> - Sets the thousands delimiter (defaults to "").
|
165
|
+
#
|
166
|
+
# ==== Examples
|
167
|
+
# 123.to_storage_size # => 123 Bytes
|
168
|
+
# 1234.to_storage_size # => 1.2 KB
|
169
|
+
# 12345.to_storage_size # => 12.1 KB
|
170
|
+
# 1234567.to_storage_size # => 1.2 MB
|
171
|
+
# 1234567890.to_storage_size # => 1.1 GB
|
172
|
+
# 1234567890123.to_storage_size # => 1.1 TB
|
173
|
+
# 1234567.to_storage_size(:precision => 2) # => 1.18 MB
|
174
|
+
# 483989.to_storage_size(:precision => 0) # => 473 KB
|
175
|
+
# 1234567.to_storage_size(:precision => 2, :separator => ',') # => 1,18 MB
|
176
|
+
def to_storage_size(opts = {})
|
177
|
+
return nil if self.nil?
|
178
|
+
opts.symbolize_keys!
|
179
|
+
opts[:locale] ||= :en
|
180
|
+
locale = LOCALES[opts.delete(:locale)]
|
181
|
+
opts = locale[:defaults].merge(locale[:format]).merge(locale[:storage]).merge(opts) unless locale.nil?
|
182
|
+
opts[:format] ||= "%n %u"
|
183
|
+
|
184
|
+
value = self.to_f
|
185
|
+
unit = ''
|
186
|
+
STORAGE_UNITS.each do |storage_unit|
|
187
|
+
unit = storage_unit.to_s.capitalize
|
188
|
+
return opts[:format].gsub(/%n/, value.with_precision(opts.only(:precision, :delimiter, :separator))).gsub(/%u/, unit) if value < 1024 || storage_unit == STORAGE_UNITS.last
|
189
|
+
value /= 1024.0
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Returns the string representation of the number's +parity+.
|
194
|
+
#
|
195
|
+
# ==== Examples
|
196
|
+
# 1.to_parity # => "odd"
|
197
|
+
# 2.to_parity # => "even"
|
198
|
+
def to_parity
|
199
|
+
self.to_i.even? ? 'even' : 'odd'
|
200
|
+
end
|
201
|
+
|
202
|
+
# Provides methods for converting numbers into formatted strings.
|
203
|
+
# Methods are provided for phone numbers, currency, percentage,
|
204
|
+
# precision, positional notation, and file size.
|
205
|
+
# => taken and inspired from ActionView::Helpers::NumberHelper (http://api.rubyonrails.org/)
|
206
|
+
|
207
|
+
# Formats a +number+ into a US phone number (e.g., (555) 123-9876). You can customize the format
|
208
|
+
# in the +options+ hash.
|
209
|
+
#
|
210
|
+
# ==== Options
|
211
|
+
# * <tt>:area_code</tt> - Adds parentheses around the area code.
|
212
|
+
# * <tt>:delimiter</tt> - Specifies the delimiter to use (defaults to "-").
|
213
|
+
# * <tt>:extension</tt> - Specifies an extension to add to the end of the
|
214
|
+
# generated number.
|
215
|
+
# * <tt>:country_code</tt> - Sets the country code for the phone number.
|
216
|
+
#
|
217
|
+
# ==== Examples
|
218
|
+
# 5551234.to_phone # => 555-1234
|
219
|
+
# 1235551234.to_phone # => 123-555-1234
|
220
|
+
# 1235551234.to_phone(:area_code => true) # => (123) 555-1234
|
221
|
+
# 1235551234.to_phone(:delimiter => " ") # => 123 555 1234
|
222
|
+
# 1235551234.to_phone(:area_code => true, :extension => 555) # => (123) 555-1234 x 555
|
223
|
+
# 1235551234.to_phone(:country_code => 1) # => +1-123-555-1234
|
224
|
+
# 1235551234.to_phone({ :country_code => 1,
|
225
|
+
# :extension => 1343, :delimiter => "." }) # => +1.123.555.1234 x 1343
|
226
|
+
def to_phone(opts={})
|
227
|
+
number = self.to_s.strip
|
228
|
+
opts.symbolize_keys!
|
229
|
+
opts[:delimiter] ||= '-'
|
230
|
+
opts[:extension] = opts[:extension].to_s.strip unless opts[:extension].nil?
|
231
|
+
|
232
|
+
begin
|
233
|
+
str = ""
|
234
|
+
str << "+#{opts[:country_code]}#{opts[:delimiter]}" unless opts[:country_code].blank?
|
235
|
+
str << if opts[:area_code]
|
236
|
+
number.gsub!(/([0-9]{1,3})([0-9]{3})([0-9]{4}$)/,"(\\1) \\2#{opts[:delimiter]}\\3")
|
237
|
+
else
|
238
|
+
number.gsub!(/([0-9]{0,3})([0-9]{3})([0-9]{4})$/,"\\1#{opts[:delimiter]}\\2#{opts[:delimiter]}\\3")
|
239
|
+
number.starts_with?('-') ? number.slice!(1..-1) : number
|
240
|
+
end
|
241
|
+
str << " x #{opts[:extension]}" unless opts[:extension].blank?
|
242
|
+
str
|
243
|
+
rescue
|
244
|
+
number
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
class Numeric
|
253
|
+
include Useful::RubyExtensions::Numeric
|
254
|
+
end
|
255
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensions
|
3
|
+
module Object
|
4
|
+
|
5
|
+
def false?
|
6
|
+
self == false
|
7
|
+
end
|
8
|
+
|
9
|
+
def true?
|
10
|
+
self == true
|
11
|
+
end
|
12
|
+
|
13
|
+
def blank?
|
14
|
+
self.nil? || self.empty? rescue false
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Object
|
22
|
+
include Useful::RubyExtensions::Object
|
23
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Useful
|
2
|
+
module RubyExtensions
|
3
|
+
module String
|
4
|
+
|
5
|
+
module ClassMethods; end
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend(ClassMethods) if klass.kind_of?(Class)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# adds the contents of a2 to a1, removing duplicates
|
13
|
+
def hsub(string, hash)
|
14
|
+
hash.each {|k,v| string.gsub!(":#{k}",v.to_s)}
|
15
|
+
string
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
# returns a new string, with hash values sub'd in where hash keys exist in original string
|
21
|
+
def hsub(hash)
|
22
|
+
self.class.hsub(self.clone, hash)
|
23
|
+
end
|
24
|
+
# substitutes the keys in hash that exist in the string, with values of hash
|
25
|
+
def hsub!(hash)
|
26
|
+
self.class.hsub(self, hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
def match?(pattern)
|
30
|
+
!self.match(pattern).nil?
|
31
|
+
end
|
32
|
+
|
33
|
+
def starts_with?(string)
|
34
|
+
self.match?(Regexp.new("\\A#{string}"))
|
35
|
+
end
|
36
|
+
|
37
|
+
def show_regexp(re)
|
38
|
+
if self =~ re
|
39
|
+
"#{$`}<<#{$&}>>#{$'}"
|
40
|
+
else
|
41
|
+
"no match"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class String
|
50
|
+
include Useful::RubyExtensions::String
|
51
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module SinatraHelpers
|
5
|
+
module EnvironmentTests
|
6
|
+
def production?
|
7
|
+
Sinatra::Application.environment.to_s == 'production'
|
8
|
+
end
|
9
|
+
def development?
|
10
|
+
Sinatra::Application.environment.to_s == 'development'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Sinatra::Application.helpers Sinatra::SinatraHelpers::EnvironmentTests
|
16
|
+
Sinatra::Application.register Sinatra::SinatraHelpers::EnvironmentTests
|
17
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module SinatraHelpers
|
5
|
+
module Erb
|
6
|
+
module ErrorPages
|
7
|
+
def self.registered(app)
|
8
|
+
app.configure :production do
|
9
|
+
app.not_found do
|
10
|
+
erb :'404.html'
|
11
|
+
end
|
12
|
+
app.error do
|
13
|
+
@err = request.env['sinatra_error']
|
14
|
+
erb :'500.html'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Sinatra::Application.register Sinatra::SinatraHelpers::Erb::ErrorPages
|
23
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module SinatraHelpers
|
5
|
+
module Erb
|
6
|
+
module Partials
|
7
|
+
|
8
|
+
# helper to emulate rails 'render :partial' helper, using erb
|
9
|
+
# => taken from the sinatra book, http://sinatra-book.gittr.com/#implemention_of_rails_style_partials
|
10
|
+
# Render the page once:
|
11
|
+
# Usage: partial :foo
|
12
|
+
#
|
13
|
+
# foo will be rendered once for each element in the array, passing in a local variable named "foo"
|
14
|
+
# Usage: partial :foo, :collection => @my_foos
|
15
|
+
def partial(template, *args)
|
16
|
+
options = args.extract_options!
|
17
|
+
options.merge!(:layout => false)
|
18
|
+
path = template.to_s.split(File::SEPARATOR)
|
19
|
+
object = path[-1].to_sym
|
20
|
+
path[-1] = "_#{path[-1]}"
|
21
|
+
template = File.join(path).to_sym
|
22
|
+
raise 'partial collection specified but is nil' if options.has_key?(:collection) && options[:collection].nil?
|
23
|
+
if collection = options.delete(:collection)
|
24
|
+
counter = 0
|
25
|
+
collection.inject([]) do |buffer, member|
|
26
|
+
counter += 1
|
27
|
+
buffer << erb(template, options.merge(:locals => {object => member, "#{object}_counter".to_sym => counter}))
|
28
|
+
end.join("\n")
|
29
|
+
else
|
30
|
+
if member = options.delete(:object)
|
31
|
+
options.merge!(:locals => {object => member})
|
32
|
+
end
|
33
|
+
erb(template, options)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
Sinatra::Application.helpers Sinatra::SinatraHelpers::Erb::Partials
|
42
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
|
3
|
+
module Sinatra
|
4
|
+
module SinatraHelpers
|
5
|
+
module Tags
|
6
|
+
|
7
|
+
# helper to emulate action view's 'link_to'
|
8
|
+
# => inspired from vanntastic-sinatra-gen gem, http://github.com/vanntastic/sinatra-gen/tree/master
|
9
|
+
# EX : link_to "google", "http://google.com"
|
10
|
+
# => <a href="http://google.com">google</a>
|
11
|
+
def link_to(content,href,options={})
|
12
|
+
options.update :href => href
|
13
|
+
tag(:a, options) { content }
|
14
|
+
end
|
15
|
+
|
16
|
+
# helper to emulate 'image_tag'
|
17
|
+
# => inspired from vanntastic-sinatra-gen gem, http://github.com/vanntastic/sinatra-gen/tree/master
|
18
|
+
# helper for image_tags
|
19
|
+
# EX : image_tag 'logo.jpg'
|
20
|
+
# => <img src="images/logo.jpg" />
|
21
|
+
def image_tag(src,options={})
|
22
|
+
options[:src] = ['/'].include?(src.first) ? src : "/images/#{src}"
|
23
|
+
tag(:img, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def clear_tag(options={})
|
27
|
+
options[:tag] ||= :div
|
28
|
+
options[:style] ||= ''
|
29
|
+
options[:style] = "clear: both;#{options[:style]}"
|
30
|
+
tag(options.delete(:tag), options) { '' }
|
31
|
+
end
|
32
|
+
|
33
|
+
include Rack::Utils
|
34
|
+
alias_method :h, :escape_html
|
35
|
+
|
36
|
+
# helper to emulate 'stylesheet_link_tag'
|
37
|
+
# => inspired from vanntastic-sinatra-gen gem, http://github.com/vanntastic/sinatra-gen/tree/master
|
38
|
+
# EX : stylesheet_link_tag 'default'
|
39
|
+
# => <link rel="stylesheet" href="/stylesheets/default.css" type="text/css" media="all" title="no title" charset="utf-8">
|
40
|
+
def stylesheet_link_tag(srcs,options={})
|
41
|
+
options[:media] ||= "screen"
|
42
|
+
options[:type] ||= "text/css"
|
43
|
+
options[:rel] ||= "stylesheet"
|
44
|
+
srcs.to_a.collect do |src|
|
45
|
+
options[:href] = "/stylesheets/#{src}.css#{"?#{Time.now.to_i}" if Sinatra::Application.environment.to_s == 'development'}"
|
46
|
+
tag(:link, options)
|
47
|
+
end.join("\n")
|
48
|
+
end
|
49
|
+
|
50
|
+
# helper to emulate 'javascript_include_tag'
|
51
|
+
# => inspired from vanntastic-sinatra-gen gem, http://github.com/vanntastic/sinatra-gen/tree/master
|
52
|
+
# EX : javascript_include_tag 'app'
|
53
|
+
# => <script src="/js/app.js" type="text/javascript" />
|
54
|
+
# EX : javascript_include_tag ['app', 'jquery']
|
55
|
+
# => <script src="/js/app.js" type="text/javascript" />
|
56
|
+
# => <script src="/js/jquery.js" type="text/javascript" />
|
57
|
+
def javascript_include_tag(srcs,options={})
|
58
|
+
options[:type] ||= "text/javascript"
|
59
|
+
srcs.to_a.collect do |src|
|
60
|
+
options[:src] = "/javascripts/#{src}.js#{"?#{Time.now.to_i}" if Sinatra::Application.environment.to_s == 'development'}"
|
61
|
+
tag(:script, options) { '' }
|
62
|
+
end.join("\n")
|
63
|
+
end
|
64
|
+
|
65
|
+
# helper to emulate 'javascript_tag'
|
66
|
+
def javascript_tag(options={})
|
67
|
+
options[:type] ||= "text/javascript"
|
68
|
+
tag(:script, options) { yield }
|
69
|
+
end
|
70
|
+
|
71
|
+
# emulator for 'tag'
|
72
|
+
# => inspired from vanntastic-sinatra-gen gem, http://github.com/vanntastic/sinatra-gen/tree/master
|
73
|
+
# EX : tag :h1, "shizam", :title => "shizam"
|
74
|
+
# => <h1 title="shizam">shizam</h1>
|
75
|
+
def tag(name,options={})
|
76
|
+
"<#{name.to_s} #{hash_to_html_attrs(options)} #{block_given? ? ">#{yield}</#{name}" : "/"}>"
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def hash_to_html_attrs(a_hash)
|
82
|
+
a_hash.collect{|key, val| "#{key}=\"#{val}\""}.join(' ')
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
Sinatra::Application.helpers Sinatra::SinatraHelpers::Tags
|
89
|
+
end
|
data/lib/useful.rb
ADDED
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kelredd-useful
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kelredd
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-02 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: ""
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README.rdoc
|
24
|
+
files:
|
25
|
+
- README.rdoc
|
26
|
+
- Rakefile
|
27
|
+
- lib/useful
|
28
|
+
- lib/useful/ruby_extensions
|
29
|
+
- lib/useful/ruby_extensions/array.rb
|
30
|
+
- lib/useful/ruby_extensions/fixnum.rb
|
31
|
+
- lib/useful/ruby_extensions/hash.rb
|
32
|
+
- lib/useful/ruby_extensions/numeric.rb
|
33
|
+
- lib/useful/ruby_extensions/object.rb
|
34
|
+
- lib/useful/ruby_extensions/string.rb
|
35
|
+
- lib/useful/ruby_extensions.rb
|
36
|
+
- lib/useful/sinatra_helpers
|
37
|
+
- lib/useful/sinatra_helpers/environment_tests.rb
|
38
|
+
- lib/useful/sinatra_helpers/erb
|
39
|
+
- lib/useful/sinatra_helpers/erb/error_pages.rb
|
40
|
+
- lib/useful/sinatra_helpers/erb/partials.rb
|
41
|
+
- lib/useful/sinatra_helpers/erb.rb
|
42
|
+
- lib/useful/sinatra_helpers/tags.rb
|
43
|
+
- lib/useful/sinatra_helpers.rb
|
44
|
+
- lib/useful/version.rb
|
45
|
+
- lib/useful.rb
|
46
|
+
- test/test_helper.rb
|
47
|
+
- test/unit
|
48
|
+
- test/unit/useful_test.rb
|
49
|
+
has_rdoc: true
|
50
|
+
homepage: ""
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options:
|
53
|
+
- --main
|
54
|
+
- README.rdoc
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.2.0
|
73
|
+
signing_key:
|
74
|
+
specification_version: 2
|
75
|
+
summary: A collection of useful helpers for various ruby things.
|
76
|
+
test_files: []
|
77
|
+
|