mack-facets 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +3 -0
- data/lib/english_extensions/inflect.rb +50 -0
- data/lib/english_extensions/numerals.rb +12 -0
- data/lib/extensions/array.rb +90 -0
- data/lib/extensions/class.rb +38 -0
- data/lib/extensions/hash.rb +49 -0
- data/lib/extensions/kernel.rb +34 -0
- data/lib/extensions/math.rb +15 -0
- data/lib/extensions/module.rb +29 -0
- data/lib/extensions/object.rb +164 -0
- data/lib/extensions/string.rb +218 -0
- data/lib/extensions/symbol.rb +7 -0
- data/lib/mack-facets.rb +31 -0
- data/lib/utils/inflections.rb +63 -0
- data/lib/utils/inflector.rb +99 -0
- data/lib/utils/options_merger.rb +27 -0
- metadata +86 -0
data/README
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
module English # :nodoc:
|
2
|
+
|
3
|
+
# = English Nouns Number Inflection.
|
4
|
+
#
|
5
|
+
# This module provides english singular <-> plural noun inflections.
|
6
|
+
module Inflect # :nodoc:
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Convert an English word from plurel to singular.
|
11
|
+
#
|
12
|
+
# "boys".singular #=> boy
|
13
|
+
# "tomatoes".singular #=> tomato
|
14
|
+
#
|
15
|
+
def singular(word)
|
16
|
+
if result = singular_of[word]
|
17
|
+
return result.dup
|
18
|
+
end
|
19
|
+
result = word.dup
|
20
|
+
singularization_rules.each do |(match, replacement)|
|
21
|
+
break if result.gsub!(match, replacement)
|
22
|
+
end
|
23
|
+
# Mack: cache the result of the translation:
|
24
|
+
singular_of[word] = result unless word == result
|
25
|
+
return result
|
26
|
+
end
|
27
|
+
|
28
|
+
# Convert an English word from singular to plurel.
|
29
|
+
#
|
30
|
+
# "boy".plural #=> boys
|
31
|
+
# "tomato".plural #=> tomatoes
|
32
|
+
#
|
33
|
+
def plural(word)
|
34
|
+
if result = plural_of[word]
|
35
|
+
return result.dup
|
36
|
+
end
|
37
|
+
#return self.dup if /s$/ =~ self # ???
|
38
|
+
result = word.dup
|
39
|
+
pluralization_rules.each do |(match, replacement)|
|
40
|
+
break if result.gsub!(match, replacement)
|
41
|
+
end
|
42
|
+
# Mack: cache the result of the translation:
|
43
|
+
plural_of[word] = result unless word == result
|
44
|
+
return result
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Array
|
2
|
+
|
3
|
+
# This method is useful when you have a method that looks like this:
|
4
|
+
# def foo(*args)
|
5
|
+
# do something
|
6
|
+
# end
|
7
|
+
# The problem is when you use the * like that everything that comes in is
|
8
|
+
# an array. Here are a few problems with this:
|
9
|
+
# foo([1,2,3])
|
10
|
+
# When you pass an array into this type of method you get the following nested array:
|
11
|
+
# [[1,2,3]]
|
12
|
+
# The parse_splat_args method, if called, would do this:
|
13
|
+
# args.parse_splat_args # => [1,2,3]
|
14
|
+
# Now say you called this method like such:
|
15
|
+
# foo(1)
|
16
|
+
# args would be [1]
|
17
|
+
# args.parse_splat_args # => 1
|
18
|
+
# Finally
|
19
|
+
# foo
|
20
|
+
# args.parse_splat_args # => nil
|
21
|
+
def parse_splat_args
|
22
|
+
unless self.empty?
|
23
|
+
args = self#.flatten
|
24
|
+
case args.size
|
25
|
+
when 1
|
26
|
+
return args.first # if there was only one arg passed, return just that, without the array
|
27
|
+
when 0
|
28
|
+
return nil # if no args were passed return nil
|
29
|
+
else
|
30
|
+
return args # else return the array back, cause chances are that's what they passed you!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# This will return a new instance of the array sorted randomly.
|
36
|
+
def randomize(&block)
|
37
|
+
if block_given?
|
38
|
+
self.sort {|x,y| yield x, y}
|
39
|
+
else
|
40
|
+
self.sort_by { rand }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# This calls the randomize method, but will permantly replace the existing array.
|
45
|
+
def randomize!(&block)
|
46
|
+
if block_given?
|
47
|
+
self.replace(self.randomize(&block))
|
48
|
+
else
|
49
|
+
self.replace(self.randomize)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# This will pick a random value from the array
|
54
|
+
def pick_random
|
55
|
+
self[rand(self.length)]
|
56
|
+
end
|
57
|
+
|
58
|
+
# This allows you to easily recurse of the array randomly.
|
59
|
+
def random_each
|
60
|
+
self.randomize.each {|x| yield x}
|
61
|
+
end
|
62
|
+
|
63
|
+
def subset?(other)
|
64
|
+
self.each do |x|
|
65
|
+
return false if !(other.include? x)
|
66
|
+
end
|
67
|
+
true
|
68
|
+
end
|
69
|
+
|
70
|
+
def superset?(other)
|
71
|
+
other.subset?(self)
|
72
|
+
end
|
73
|
+
|
74
|
+
# This will give you a count, as a Hash, of all the values in the Array.
|
75
|
+
# %w{spam spam eggs ham eggs spam}.count # => {"eggs" => 2, "ham" => 1, "spam" => 3}
|
76
|
+
def count
|
77
|
+
k = Hash.new(0)
|
78
|
+
self.each{|x| k[x] += 1}
|
79
|
+
k
|
80
|
+
end
|
81
|
+
|
82
|
+
# This will invert the index and the values and return a Hash of the results.
|
83
|
+
# %w{red yellow orange}.invert # => {"red" => 0, "orange" => 2, "yellow" => 1}
|
84
|
+
def invert
|
85
|
+
h = {}
|
86
|
+
self.each_with_index{|x,i| h[x] = i}
|
87
|
+
h
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class Class
|
2
|
+
|
3
|
+
# Returns a new Object instance of the class name specified.
|
4
|
+
#
|
5
|
+
# Examples:
|
6
|
+
# Class.new_instance_of("Orange") => #<Orange:0x376c0c>
|
7
|
+
# Class.new_instance_of("Animals::Dog") => #<Animals::Dog:0x376a2c>
|
8
|
+
def self.new_instance_of(klass_name)
|
9
|
+
klass_name.constantize.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# This will through the ancestor tree of object and tell you if
|
13
|
+
# that object is of the specified type.
|
14
|
+
def class_is_a?(klass_name)
|
15
|
+
self.ancestors.each do |an|
|
16
|
+
if an == klass_name
|
17
|
+
return true
|
18
|
+
end
|
19
|
+
end
|
20
|
+
return false
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns an array of the classes parent classes.
|
24
|
+
#
|
25
|
+
# Examples:
|
26
|
+
# Orange.parents # => [Citrus, Fruit, Object]
|
27
|
+
# Citrus.parents # => [Fruit, Object]
|
28
|
+
# Fruit.parents # => [Object]
|
29
|
+
def parents
|
30
|
+
ans = [self.superclass]
|
31
|
+
until ans.last.superclass.nil?
|
32
|
+
ans << ans.last.superclass
|
33
|
+
end
|
34
|
+
ans
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'uri'
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def join(pair_string, join_string)
|
5
|
+
output = []
|
6
|
+
sorted = self.sort {|a,b| a[0].to_s <=> b[0].to_s}
|
7
|
+
sorted.each do |ar|
|
8
|
+
output << sprintf(pair_string, ar[0], ar[1])
|
9
|
+
end
|
10
|
+
output.join(join_string)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Deletes the key(s) passed in from the hash.
|
14
|
+
def -(ars)
|
15
|
+
[ars].flatten.each {|a| self.delete(a)}
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Converts a hash to query string parameters.
|
20
|
+
# An optional boolean escapes the values if true, which is the default.
|
21
|
+
def to_params(escape = true)
|
22
|
+
params = ''
|
23
|
+
stack = []
|
24
|
+
|
25
|
+
each do |k, v|
|
26
|
+
if v.is_a?(Hash)
|
27
|
+
stack << [k,v]
|
28
|
+
else
|
29
|
+
v = v.to_s.uri_escape if escape
|
30
|
+
params << "#{k}=#{v}&"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
stack.each do |parent, hash|
|
35
|
+
hash.each do |k, v|
|
36
|
+
if v.is_a?(Hash)
|
37
|
+
stack << ["#{parent}[#{k}]", v]
|
38
|
+
else
|
39
|
+
v = v.to_s.uri_escape if escape
|
40
|
+
params << "#{parent}[#{k}]=#{v}&"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
params.chop! # trailing &
|
46
|
+
params.split("&").sort.join("&")
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
|
6
|
+
def pp_to_s(object)
|
7
|
+
pp_out = StringIO.new
|
8
|
+
PP.pp(object,pp_out)
|
9
|
+
return pp_out.string
|
10
|
+
end
|
11
|
+
|
12
|
+
def retryable(options = {}, &block)
|
13
|
+
opts = { :tries => 1, :on => Exception }.merge(options)
|
14
|
+
|
15
|
+
retries = opts[:tries]
|
16
|
+
retry_exceptions = [opts[:on]].flatten
|
17
|
+
|
18
|
+
x = %{
|
19
|
+
begin
|
20
|
+
return yield
|
21
|
+
rescue #{retry_exceptions.join(", ")} => e
|
22
|
+
retries -= 1
|
23
|
+
if retries > 0
|
24
|
+
retry
|
25
|
+
else
|
26
|
+
raise e
|
27
|
+
end
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
eval(x, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Module
|
2
|
+
|
3
|
+
# Bulk converts the security level of methods in this Module from one level to another.
|
4
|
+
def convert_security_of_methods(old_level = :public, new_level = :protected)
|
5
|
+
eval("#{old_level}_instance_methods").each{ |meth| self.send(new_level, meth) }
|
6
|
+
self
|
7
|
+
end
|
8
|
+
|
9
|
+
# Includes this module into a Class, and changes all public methods to protected.
|
10
|
+
#
|
11
|
+
# Examples:
|
12
|
+
# module MyCoolUtils
|
13
|
+
# def some_meth
|
14
|
+
# "hi"
|
15
|
+
# end
|
16
|
+
# self.include_safely_into(FooController)
|
17
|
+
# end
|
18
|
+
# or:
|
19
|
+
# MyCoolUtils.include_safely_into(FooController, SomeOtherClass)
|
20
|
+
def include_safely_into(*args)
|
21
|
+
[args].flatten.each do |a|
|
22
|
+
if a.is_a?(String) || a.is_a?(Symbol)
|
23
|
+
a = a.to_s.constantize
|
24
|
+
end
|
25
|
+
a.send(:include, self.convert_security_of_methods)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
class Object
|
2
|
+
|
3
|
+
# Includes a module into the current Class, and changes all the module's public methods to protected.
|
4
|
+
#
|
5
|
+
# Example:
|
6
|
+
# class FooController
|
7
|
+
# safely_include_module(MyCoolUtils, MyOtherModule)
|
8
|
+
# end
|
9
|
+
def safely_include_module(*modules)
|
10
|
+
[modules].flatten.each do |mod|
|
11
|
+
mod.include_safely_into(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Prints out the methods associated with this object in alphabetical order.
|
16
|
+
def print_methods
|
17
|
+
m = "----- #{self} (methods) -----\n"
|
18
|
+
m << methods.sort.join("\n")
|
19
|
+
puts m
|
20
|
+
m
|
21
|
+
end
|
22
|
+
|
23
|
+
# An elegant way to refactor out common options
|
24
|
+
#
|
25
|
+
# with_options :order => 'created_at', :class_name => 'Comment' do |post|
|
26
|
+
# post.has_many :comments, :conditions => ['approved = ?', true], :dependent => :delete_all
|
27
|
+
# post.has_many :unapproved_comments, :conditions => ['approved = ?', false]
|
28
|
+
# post.has_many :all_comments
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Can also be used with an explicit receiver:
|
32
|
+
#
|
33
|
+
# map.with_options :controller => "people" do |people|
|
34
|
+
# people.connect "/people", :action => "index"
|
35
|
+
# people.connect "/people/:id", :action => "show"
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
def with_options(options)
|
39
|
+
yield Mack::Utils::OptionMerger.new(self, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
# See Class parents for more information.
|
43
|
+
def class_parents
|
44
|
+
self.class.parents
|
45
|
+
end
|
46
|
+
|
47
|
+
# This method gets called when a parameter is passed into a named route.
|
48
|
+
# This can be overridden in an Object to provlde custom handling of parameters.
|
49
|
+
def to_param
|
50
|
+
self.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
# Uses <code>define_method</code> to create an empty for the method parameter defined.
|
54
|
+
# That method will then raise MethodNotImplemented. This is useful for creating interfaces
|
55
|
+
# and you want to stub out methods that others need to implement.
|
56
|
+
def self.needs_method(meth)
|
57
|
+
define_method(meth) do
|
58
|
+
raise NoMethodError.new("The interface you are using requires you define the following method '#{meth}'")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# This prints out running time for the block provided. This is great for things
|
63
|
+
# like Rake tasks, etc... where you would like to know how long it, or a section of
|
64
|
+
# it took to run.
|
65
|
+
def running_time(message = "", logger = nil)
|
66
|
+
s_time = Time.now
|
67
|
+
s = "---Starting at #{s_time}---"
|
68
|
+
puts s
|
69
|
+
logger.info s unless logger.nil?
|
70
|
+
yield if block_given?
|
71
|
+
e_time = Time.now
|
72
|
+
e = "---Ending at #{e_time}---"
|
73
|
+
puts e
|
74
|
+
logger.info e unless logger.nil?
|
75
|
+
secs = e_time - s_time
|
76
|
+
if secs < 60
|
77
|
+
x = "Running time #{secs} seconds."
|
78
|
+
else
|
79
|
+
x = "Running time roughly #{secs/60} minutes [#{secs} seconds]"
|
80
|
+
end
|
81
|
+
x += " [MESSAGE]: #{message}" unless message.blank?
|
82
|
+
puts x
|
83
|
+
logger.info x unless logger.nil?
|
84
|
+
end
|
85
|
+
|
86
|
+
# This method will call send to all the methods defined on the previous method.
|
87
|
+
#
|
88
|
+
# Example:
|
89
|
+
# Fruit.send_with_chain([:new, :get_citrus, :get_orange, :class]) # => Orange
|
90
|
+
#
|
91
|
+
# This would be the equivalent:
|
92
|
+
# Fruit.new.get_citrus.get_orange.class
|
93
|
+
def send_with_chain(methods, *args)
|
94
|
+
obj = self
|
95
|
+
[methods].flatten.each {|m| obj = obj.send(m, *args)}
|
96
|
+
obj
|
97
|
+
end
|
98
|
+
|
99
|
+
# ivar_cache allows you to cache the results of the block into an instance variable in a class,
|
100
|
+
# and then will serve up that instance variable the next time you call that method again.
|
101
|
+
#
|
102
|
+
# old way:
|
103
|
+
# def show_page_link
|
104
|
+
# unless @show_page_link # check if instance variable exists
|
105
|
+
# # if the instance variable doesn't exist let's do some work and assign it to the instance variable.
|
106
|
+
# @show_page_link = link_to("show", some_url(:id => self.id, :foo => bar, etc... => etc))
|
107
|
+
# end
|
108
|
+
# @show_page_link # now return the instance variable
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# new way:
|
112
|
+
# def show_page_link
|
113
|
+
# ivar_cache do
|
114
|
+
# link_to("show", some_url(:id => self.id, :foo => bar, etc... => etc))
|
115
|
+
# end
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
# this does everything the old way did, but it is much cleaner, and a lot less code!
|
119
|
+
# in case you're wondering it caches the result, by default, to an instance variable named after the method,
|
120
|
+
# so in our above example the instance variable would be name, <code>@show_page_link</code>. this can be overridden like such:
|
121
|
+
#
|
122
|
+
# def show_page_link
|
123
|
+
# ivar_cache("foo_var") do
|
124
|
+
# link_to("show", some_url(:id => self.id, :foo => bar, etc... => etc))
|
125
|
+
# end
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
# now it will cache it to <code>@foo_var</code>
|
129
|
+
def ivar_cache(var_name = nil, &block)
|
130
|
+
if var_name.nil?
|
131
|
+
call = caller[0]
|
132
|
+
var_name = call[(call.index('`')+1)...call.index("'")]
|
133
|
+
end
|
134
|
+
var = instance_variable_get("@#{var_name}")
|
135
|
+
unless var
|
136
|
+
return instance_variable_set("@#{var_name}", yield) if block_given?
|
137
|
+
end
|
138
|
+
instance_variable_get("@#{var_name}")
|
139
|
+
end
|
140
|
+
|
141
|
+
def ivar_cache_clear(var_name = nil, &block)
|
142
|
+
if var_name.nil?
|
143
|
+
call = caller[0]
|
144
|
+
var_name = call[(call.index('`')+1)...call.index("'")]
|
145
|
+
end
|
146
|
+
remove_instance_variable("@#{var_name}") #rescue
|
147
|
+
yield if block_given?
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the namespaces for a particular object.
|
151
|
+
#
|
152
|
+
# Examples:
|
153
|
+
# Animals::Dog::Poodle.new.namespaces # => ["Animals", "Dog"]
|
154
|
+
def namespaces
|
155
|
+
ivar_cache("object_namespaces") do
|
156
|
+
nss = []
|
157
|
+
full_name = self.class.name.to_s
|
158
|
+
nss = full_name.split("::")
|
159
|
+
nss.pop
|
160
|
+
nss
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
class String
|
2
|
+
include Style
|
3
|
+
|
4
|
+
def methodize
|
5
|
+
x = self
|
6
|
+
|
7
|
+
# if we get down to a nil or an empty string raise an exception!
|
8
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
9
|
+
|
10
|
+
# get rid of the big stuff in the front/back
|
11
|
+
x.strip!
|
12
|
+
|
13
|
+
# if we get down to a nil or an empty string raise an exception!
|
14
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
15
|
+
|
16
|
+
x = x.underscore
|
17
|
+
|
18
|
+
# get rid of spaces and make the _
|
19
|
+
x.gsub!(' ', '_')
|
20
|
+
# get rid of everything that isn't 'safe' a-z, 0-9, ?, !, =, _
|
21
|
+
x.gsub!(/([^ a-zA-Z0-9\_\?\!\=]+)/n, '_')
|
22
|
+
|
23
|
+
# if we get down to a nil or an empty string raise an exception!
|
24
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
25
|
+
|
26
|
+
# condense multiple 'safe' non a-z chars to just one.
|
27
|
+
# ie. ___ becomes _ !!!! becomes ! etc...
|
28
|
+
[' ', '_', '?', '!', "="].each do |c|
|
29
|
+
x.squeeze!(c)
|
30
|
+
end
|
31
|
+
|
32
|
+
# if we get down to a nil or an empty string raise an exception!
|
33
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
34
|
+
|
35
|
+
#down case the whole thing
|
36
|
+
x.downcase!
|
37
|
+
|
38
|
+
# get rid of any characters at the beginning that aren't a-z
|
39
|
+
while !x.match(/^[a-z]/)
|
40
|
+
x.slice!(0)
|
41
|
+
|
42
|
+
# if we get down to a nil or an empty string raise an exception!
|
43
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
44
|
+
end
|
45
|
+
|
46
|
+
# let's trim this bad boy down a bit now that we've cleaned it up, somewhat.
|
47
|
+
# we should do this before cleaning up the end character, because it's possible to end up with a
|
48
|
+
# bad char at the end if you trim too late.
|
49
|
+
x = x[0..100] if x.length > 100
|
50
|
+
|
51
|
+
# get rid of any characters at the end that aren't safe
|
52
|
+
while !x.match(/[a-z0-9\?\!\=]$/)
|
53
|
+
x.slice!(x.length - 1)
|
54
|
+
# if we get down to a nil or an empty string raise an exception!
|
55
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
56
|
+
end
|
57
|
+
|
58
|
+
# if we get down to a nil or an empty string raise an exception!
|
59
|
+
raise NameError.new("#{self} cannot be converted to a valid method name!") if x.nil? || x == ''
|
60
|
+
|
61
|
+
# let's get rid of characters that don't belong in the 'middle' of the method.
|
62
|
+
orig_middle = x[1..(x.length - 2)]
|
63
|
+
n_middle = orig_middle.dup
|
64
|
+
|
65
|
+
['?', '!', "="].each do |c|
|
66
|
+
n_middle.gsub!(c, "_")
|
67
|
+
end
|
68
|
+
|
69
|
+
# the previous gsub can leave us with multiple underscores that need cleaning up.
|
70
|
+
n_middle.squeeze!("_")
|
71
|
+
|
72
|
+
x.gsub!(orig_middle, n_middle)
|
73
|
+
x.gsub!("_=", "=")
|
74
|
+
x
|
75
|
+
end
|
76
|
+
|
77
|
+
# Returns a constant of the string.
|
78
|
+
#
|
79
|
+
# Examples:
|
80
|
+
# "User".constantize # => User
|
81
|
+
# "HomeController".constantize # => HomeController
|
82
|
+
# "Mack::Configuration" # => Mack::Configuration
|
83
|
+
def constantize
|
84
|
+
Module.instance_eval("::#{self}")
|
85
|
+
end
|
86
|
+
|
87
|
+
def hexdigest
|
88
|
+
Digest::SHA1.hexdigest(self)
|
89
|
+
end
|
90
|
+
|
91
|
+
def hexdigest!
|
92
|
+
self.replace(self.hexdigest)
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.randomize(length = 10)
|
96
|
+
chars = ("A".."H").to_a + ("J".."N").to_a + ("P".."T").to_a + ("W".."Z").to_a + ("3".."9").to_a
|
97
|
+
newpass = ""
|
98
|
+
1.upto(length) { |i| newpass << chars[rand(chars.size-1)] }
|
99
|
+
return newpass.upcase
|
100
|
+
end
|
101
|
+
|
102
|
+
# Performs URI escaping so that you can construct proper
|
103
|
+
# query strings faster. Use this rather than the cgi.rb
|
104
|
+
# version since it's faster. (Stolen from Camping).
|
105
|
+
def uri_escape
|
106
|
+
self.gsub(/([^ a-zA-Z0-9_.-]+)/n) {
|
107
|
+
'%'+$1.unpack('H2'*$1.size).join('%').upcase
|
108
|
+
}.tr(' ', '+')
|
109
|
+
end
|
110
|
+
|
111
|
+
# Unescapes a URI escaped string. (Stolen from Camping).
|
112
|
+
def uri_unescape
|
113
|
+
self.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
|
114
|
+
[$1.delete('%')].pack('H*')
|
115
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def truncate(length = 30, truncate_string = "...")
|
119
|
+
if self.nil? then return end
|
120
|
+
l = length - truncate_string.length
|
121
|
+
if $KCODE == "NONE"
|
122
|
+
self.length > length ? self[0...l] + truncate_string : self
|
123
|
+
else
|
124
|
+
chars = self.split(//)
|
125
|
+
chars.length > length ? chars[0...l].join + truncate_string : self
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def truncate!(length = 30, truncate_string = "...")
|
130
|
+
self.replace(self.truncate(length, truncate_string))
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
# require 'digest'
|
135
|
+
# class String
|
136
|
+
#
|
137
|
+
# # Maps to Mack::Utils::Inflector.instance.pluralize
|
138
|
+
# def plural
|
139
|
+
# Mack::Utils::Inflector.instance.pluralize(self)
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# # Maps to Mack::Utils::Inflector.instance.singularize
|
143
|
+
# def singular
|
144
|
+
# Mack::Utils::Inflector.instance.singularize(self)
|
145
|
+
# end
|
146
|
+
#
|
147
|
+
|
148
|
+
#
|
149
|
+
#
|
150
|
+
# def underscore
|
151
|
+
# camel_cased_word = self.dup
|
152
|
+
# camel_cased_word.to_s.gsub(/::/, '/').
|
153
|
+
# gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
154
|
+
# gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
155
|
+
# tr("-", "_").
|
156
|
+
# downcase
|
157
|
+
# end
|
158
|
+
#
|
159
|
+
# def starts_with?(x)
|
160
|
+
# self.match(/^#{x}/) ? true : false
|
161
|
+
# end
|
162
|
+
#
|
163
|
+
# def ends_with?(x)
|
164
|
+
# self.match(/#{x}$/) ? true : false
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# # Returns "is" or "are" based on the number, i.e. "i=6; There #{isare(i)} #{i} topics here."
|
168
|
+
# def self.pluralize_word(num, vals = ["is", "are"])
|
169
|
+
# return vals[0] if num.to_i==1
|
170
|
+
# return vals[1]
|
171
|
+
# end
|
172
|
+
#
|
173
|
+
# def remove(val)
|
174
|
+
# gsub(val, '')
|
175
|
+
# end
|
176
|
+
#
|
177
|
+
# def remove!(val)
|
178
|
+
# gsub!(val, '')
|
179
|
+
# end
|
180
|
+
#
|
181
|
+
|
182
|
+
#
|
183
|
+
# def truncate(length = 30, truncate_string = "...")
|
184
|
+
# if self.nil? then return end
|
185
|
+
# l = length - truncate_string.length
|
186
|
+
# if $KCODE == "NONE"
|
187
|
+
# self.length > length ? self[0...l] + truncate_string : self
|
188
|
+
# else
|
189
|
+
# chars = self.split(//)
|
190
|
+
# chars.length > length ? chars[0...l].join + truncate_string : self
|
191
|
+
# end
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
# def truncate!(length = 30, truncate_string = "...")
|
195
|
+
# self.replace(self.truncate(length, truncate_string))
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# def capitalize_all_words
|
199
|
+
# self.gsub(/\b\w/) {|s| s.upcase}
|
200
|
+
# end
|
201
|
+
#
|
202
|
+
# def capitalize_all_words!
|
203
|
+
# self.replace(self.capitalize_all_words)
|
204
|
+
# end
|
205
|
+
#
|
206
|
+
# # keep adding on to this whenever it becomes apparent that unsafe strings
|
207
|
+
# # could get passed through into the database
|
208
|
+
# def sql_safe_str
|
209
|
+
# if !self.nil?
|
210
|
+
# self.gsub(/[\']/, "\'\'")
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
# def sql_safe_str!
|
215
|
+
# self.replace(self.sql_safe_str)
|
216
|
+
# end
|
217
|
+
#
|
218
|
+
# end
|
data/lib/mack-facets.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'digest'
|
3
|
+
require 'facets'
|
4
|
+
require 'facets/ruby'
|
5
|
+
require 'facets/style'
|
6
|
+
require 'facets/blank'
|
7
|
+
require 'facets/hash'
|
8
|
+
require 'facets/hash/symbolize_keys'
|
9
|
+
require 'facets/hash/stringify_keys'
|
10
|
+
require 'facets/module'
|
11
|
+
require 'facets/infinity'
|
12
|
+
require 'english/inflect'
|
13
|
+
require 'english/numerals'
|
14
|
+
[:inflector, :inflections, :options_merger].each do |k|
|
15
|
+
path = File.join File.dirname(__FILE__), "utils", "#{k}"
|
16
|
+
#puts "requiring #{path}"
|
17
|
+
require path
|
18
|
+
end
|
19
|
+
|
20
|
+
[:array, :class, :hash, :kernel, :math, :module, :object, :string, :symbol].each do |k|
|
21
|
+
path = File.join File.dirname(__FILE__), "extensions", "#{k}"
|
22
|
+
#puts "requiring #{path}"
|
23
|
+
require path
|
24
|
+
end
|
25
|
+
|
26
|
+
[:numerals, :inflect].each do |k|
|
27
|
+
path = File.join File.dirname(__FILE__), "english_extensions", "#{k}"
|
28
|
+
#puts "requiring #{path}"
|
29
|
+
require path
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "inflector")
|
2
|
+
# Default inflections. This is taken from Jeremy McAnally's great Rails plugin, acts_as_good_speeler. Thanks Jeremy! http://www.jeremymcanally.com/
|
3
|
+
Mack::Utils::Inflector.inflections do |inflect|
|
4
|
+
# inflect.plural(/$/, 's')
|
5
|
+
inflect.plural(/s$/i, 's')
|
6
|
+
inflect.plural(/(bu)s$/i, '\1ses')
|
7
|
+
inflect.plural(/(stimul|hippopotam|octop|vir|syllab|foc|alumn|fung|radi)us$/i, '\1i')
|
8
|
+
inflect.plural(/(ax|test)is$/i, '\1es')
|
9
|
+
inflect.plural(/(alias|status)$/i, '\1es')
|
10
|
+
inflect.plural(/(buffal|tomat|torped)o$/i, '\1oes')
|
11
|
+
inflect.plural(/([dti])um$/i, '\1a')
|
12
|
+
inflect.plural(/sis$/i, 'ses')
|
13
|
+
inflect.plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
14
|
+
inflect.plural(/(hive)$/i, '\1s')
|
15
|
+
inflect.plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
16
|
+
inflect.plural(/(x|ch|ss|sh)$/i, '\1es')
|
17
|
+
inflect.plural(/(matr|append|vert|ind)ix|ex$/i, '\1ices')
|
18
|
+
inflect.plural(/([m|l])ouse$/i, '\1ice')
|
19
|
+
inflect.plural(/^(ox)$/i, '\1en')
|
20
|
+
inflect.plural(/(quiz)$/i, '\1zes')
|
21
|
+
inflect.plural(/(phenomen|criteri)on$/i, '\1a')
|
22
|
+
inflect.plural(/^(?!(.*hu|.*ger|.*sha))(.*)(wom|m)an$/i, '\2\3en')
|
23
|
+
inflect.plural(/(curricul|bacteri|medi)um$/i, '\1a')
|
24
|
+
inflect.plural(/(nebul|formul|vit|vertebr|alg|alumn)a$/i, '\1ae')
|
25
|
+
|
26
|
+
# inflect.singular(/s$/i, '')
|
27
|
+
inflect.singular(/(n)ews$/i, '\1ews')
|
28
|
+
inflect.singular(/([dti])a$/i, '\1um')
|
29
|
+
inflect.singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
30
|
+
inflect.singular(/(^analy|cri|empha)ses$/i, '\1sis')
|
31
|
+
inflect.singular(/([^f])ves$/i, '\1fe')
|
32
|
+
inflect.singular(/(hive)s$/i, '\1')
|
33
|
+
inflect.singular(/(tive)s$/i, '\1')
|
34
|
+
inflect.singular(/(bus)es$/i, '\1')
|
35
|
+
inflect.singular(/(o)es$/i, '\1')
|
36
|
+
inflect.singular(/(shoe)s$/i, '\1')
|
37
|
+
inflect.singular(/(test|ax)es$/i, '\1is')
|
38
|
+
inflect.singular(/(stimul|hippopotam|octop|vir|syllab|foc|alumn|fung|radi)i$/i, '\1us')
|
39
|
+
inflect.singular(/(alias|status)es$/i, '\1')
|
40
|
+
inflect.singular(/^(ox)en$/i, '\1')
|
41
|
+
inflect.singular(/(vert|ind)ices$/i, '\1ex')
|
42
|
+
inflect.singular(/(matr|append)ices$/i, '\1ix')
|
43
|
+
inflect.singular(/(quiz)zes$/i, '\1')
|
44
|
+
inflect.singular(/(phenomen|criteri)a$/i, '\1on')
|
45
|
+
inflect.singular(/(.*)(wo|m)en$/i, '\1\2an')
|
46
|
+
inflect.singular(/(medi|curricul|bacteri)a$/i, '\1um')
|
47
|
+
inflect.singular(/(nebula|formula|vita|vertebra|alga|alumna)e$/i, '\1')
|
48
|
+
inflect.singular(/^(.*)ookies$/, '\1ookie')
|
49
|
+
inflect.singular(/(.*)ss$/, '\1ss')
|
50
|
+
inflect.singular(/(.*)ies$/, '\1y')
|
51
|
+
|
52
|
+
inflect.irregular('person', 'people')
|
53
|
+
inflect.irregular('child', 'children')
|
54
|
+
inflect.irregular('sex', 'sexes')
|
55
|
+
inflect.irregular('move', 'moves')
|
56
|
+
inflect.irregular('tooth', 'teeth')
|
57
|
+
inflect.irregular('die', 'dice')
|
58
|
+
inflect.irregular('talisman', 'talismans')
|
59
|
+
inflect.irregular('penis', 'penises')
|
60
|
+
inflect.irregular('christmas', 'christmases')
|
61
|
+
inflect.irregular('knowledge', 'knowledge')
|
62
|
+
inflect.irregular('quiz', 'quizzes')
|
63
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require File.join(File.dirname(__FILE__), "..", "english_extensions", 'inflect')
|
3
|
+
module Mack # :nodoc:
|
4
|
+
module Utils # :nodoc:
|
5
|
+
# This class is used to deal with inflection strings. This means taken a string and make it plural, or singular, etc...
|
6
|
+
# Inflection rules can be added very easy, and are checked from the bottom up. This means that the last rule is the first
|
7
|
+
# rule to be matched. The exception to this, kind of, is 'irregular' and 'uncountable' rules. The 'uncountable' rules are
|
8
|
+
# always checked first, then the 'irregular' rules, and finally either the 'singular' or 'plural' rules, depending on what
|
9
|
+
# you're trying to do. Within each of these sets of rules, the last rule in is the first rule matched.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
# Mack::Utils::Inflector.inflections do |inflect|
|
13
|
+
# inflect.plural(/$/, 's')
|
14
|
+
# inflect.plural(/^(ox)$/i, '\1en')
|
15
|
+
# inflect.plural(/(phenomen|criteri)on$/i, '\1a')
|
16
|
+
#
|
17
|
+
# inflect.singular(/s$/i, '')
|
18
|
+
# inflect.singular(/(n)ews$/i, '\1ews')
|
19
|
+
# inflect.singular(/^(.*)ookies$/, '\1ookie')
|
20
|
+
#
|
21
|
+
# inflect.irregular('person', 'people')
|
22
|
+
# inflect.irregular('child', 'children')
|
23
|
+
# end
|
24
|
+
class Inflector
|
25
|
+
include Singleton
|
26
|
+
|
27
|
+
# Adds a plural rule to the system.
|
28
|
+
#
|
29
|
+
# Example:
|
30
|
+
# Mack::Utils::Inflector.inflections do |inflect|
|
31
|
+
# inflect.plural(/$/, 's')
|
32
|
+
# inflect.plural(/^(ox)$/i, '\1en')
|
33
|
+
# inflect.plural(/(phenomen|criteri)on$/i, '\1a')
|
34
|
+
# end
|
35
|
+
def plural(rule, replacement)
|
36
|
+
English::Inflect.plural_rule(rule, replacement)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Adds a singular rule to the system.
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
# Mack::Utils::Inflector.inflections do |inflect|
|
43
|
+
# inflect.singular(/s$/i, '')
|
44
|
+
# inflect.singular(/(n)ews$/i, '\1ews')
|
45
|
+
# inflect.singular(/^(.*)ookies$/, '\1ookie')
|
46
|
+
# end
|
47
|
+
def singular(rule, replacement)
|
48
|
+
English::Inflect.singular_rule(rule, replacement)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Adds a irregular rule to the system.
|
52
|
+
#
|
53
|
+
# Example:
|
54
|
+
# Mack::Utils::Inflector.inflections do |inflect|
|
55
|
+
# inflect.irregular('person', 'people')
|
56
|
+
# inflect.irregular('child', 'children')
|
57
|
+
# end
|
58
|
+
def irregular(rule, replacement)
|
59
|
+
English::Inflect.rule(rule, replacement)
|
60
|
+
English::Inflect.word(rule, replacement)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the singular version of the word, if possible.
|
64
|
+
#
|
65
|
+
# Examples:
|
66
|
+
# Mack::Utils::Inflector.instance.singularize("armies") # => "army"
|
67
|
+
# Mack::Utils::Inflector.instance.singularize("people") # => "person"
|
68
|
+
# Mack::Utils::Inflector.instance.singularize("boats") # => "boat"
|
69
|
+
def singularize(word)
|
70
|
+
English::Inflect.singular(word)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the singular version of the word, if possible.
|
74
|
+
#
|
75
|
+
# Examples:
|
76
|
+
# Mack::Utils::Inflector.instance.pluralize("army") # => "armies"
|
77
|
+
# Mack::Utils::Inflector.instance.pluralize("person") # => "people"
|
78
|
+
# Mack::Utils::Inflector.instance.pluralize("boat") # => "boats"
|
79
|
+
def pluralize(word)
|
80
|
+
English::Inflect.plural(word)
|
81
|
+
end
|
82
|
+
|
83
|
+
public
|
84
|
+
class << self
|
85
|
+
|
86
|
+
# Yields up Mack::Utils::Inflector.instance
|
87
|
+
def inflections
|
88
|
+
if block_given?
|
89
|
+
yield Mack::Utils::Inflector.instance
|
90
|
+
else
|
91
|
+
Mack::Utils::Inflector.instance
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
end # Inflection
|
98
|
+
end # Utils
|
99
|
+
end # Mack
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mack
|
2
|
+
module Utils
|
3
|
+
class OptionMerger #:nodoc:
|
4
|
+
instance_methods.each do |method|
|
5
|
+
undef_method(method) if method !~ /^(__|instance_eval|class|object_id)/
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(context, options)
|
9
|
+
@context, @options = context, options
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
def method_missing(method, *arguments, &block)
|
14
|
+
merge_argument_options! arguments
|
15
|
+
@context.send(method, *arguments, &block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def merge_argument_options!(arguments)
|
19
|
+
arguments << if arguments.last.respond_to? :to_hash
|
20
|
+
@options.merge(arguments.pop)
|
21
|
+
else
|
22
|
+
@options.dup
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end # OptionMerger
|
26
|
+
end # Utils
|
27
|
+
end # Mack
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mack-facets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.6.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- markbates
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-07-16 00:00:00 -04:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: facets
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - "="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.4.1
|
23
|
+
version:
|
24
|
+
- !ruby/object:Gem::Dependency
|
25
|
+
name: english
|
26
|
+
version_requirement:
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - "="
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 0.2.0
|
32
|
+
version:
|
33
|
+
description: "mack-facets was developed by: markbates"
|
34
|
+
email: mark@mackframework.com
|
35
|
+
executables: []
|
36
|
+
|
37
|
+
extensions: []
|
38
|
+
|
39
|
+
extra_rdoc_files:
|
40
|
+
- README
|
41
|
+
files:
|
42
|
+
- lib/english_extensions/inflect.rb
|
43
|
+
- lib/english_extensions/numerals.rb
|
44
|
+
- lib/extensions/array.rb
|
45
|
+
- lib/extensions/class.rb
|
46
|
+
- lib/extensions/hash.rb
|
47
|
+
- lib/extensions/kernel.rb
|
48
|
+
- lib/extensions/math.rb
|
49
|
+
- lib/extensions/module.rb
|
50
|
+
- lib/extensions/object.rb
|
51
|
+
- lib/extensions/string.rb
|
52
|
+
- lib/extensions/symbol.rb
|
53
|
+
- lib/mack-facets.rb
|
54
|
+
- lib/utils/inflections.rb
|
55
|
+
- lib/utils/inflector.rb
|
56
|
+
- lib/utils/options_merger.rb
|
57
|
+
- README
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://www.mackframework.com
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: 1.8.6
|
71
|
+
version:
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project: magrathea
|
81
|
+
rubygems_version: 1.1.1
|
82
|
+
signing_key:
|
83
|
+
specification_version: 2
|
84
|
+
summary: Ruby language extensions for Mack
|
85
|
+
test_files: []
|
86
|
+
|