quality_extensions 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme +54 -0
- data/lib/qualitysmith_extensions/all.rb +4 -0
- data/lib/qualitysmith_extensions/array/all.rb +2 -0
- data/lib/qualitysmith_extensions/array/average.rb +44 -0
- data/lib/qualitysmith_extensions/array/classify.rb +97 -0
- data/lib/qualitysmith_extensions/array/expand_ranges.rb +52 -0
- data/lib/qualitysmith_extensions/array/group_by.rb +134 -0
- data/lib/qualitysmith_extensions/array/sequence.rb +66 -0
- data/lib/qualitysmith_extensions/array/shell_escape.rb +36 -0
- data/lib/qualitysmith_extensions/array/to_a_recursive.rb +41 -0
- data/lib/qualitysmith_extensions/array/to_query_string.rb +96 -0
- data/lib/qualitysmith_extensions/collection_extensions_for_cgi.rb +2 -0
- data/lib/qualitysmith_extensions/colored/toggleability.rb +62 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.51.rb +749 -0
- data/lib/qualitysmith_extensions/console/command.facets.1.8.54.rb +748 -0
- data/lib/qualitysmith_extensions/console/command.rb +944 -0
- data/lib/qualitysmith_extensions/date/all.rb +2 -0
- data/lib/qualitysmith_extensions/date/deprecated.rb +40 -0
- data/lib/qualitysmith_extensions/date/iso8601.rb +31 -0
- data/lib/qualitysmith_extensions/date/month_ranges.rb +122 -0
- data/lib/qualitysmith_extensions/dir/each_child.rb +58 -0
- data/lib/qualitysmith_extensions/enumerable/enum.rb +69 -0
- data/lib/qualitysmith_extensions/enumerable/select_until.rb +4 -0
- data/lib/qualitysmith_extensions/enumerable/select_while.rb +109 -0
- data/lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb +65 -0
- data/lib/qualitysmith_extensions/file/exact_match_regexp.rb +34 -0
- data/lib/qualitysmith_extensions/file_test/binary_file.rb +110 -0
- data/lib/qualitysmith_extensions/find/select.rb +68 -0
- data/lib/qualitysmith_extensions/global_variable_set.rb +153 -0
- data/lib/qualitysmith_extensions/hash/all.rb +2 -0
- data/lib/qualitysmith_extensions/hash/to_date.rb +34 -0
- data/lib/qualitysmith_extensions/hash/to_query_string.rb +121 -0
- data/lib/qualitysmith_extensions/kernel/all.rb +2 -0
- data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
- data/lib/qualitysmith_extensions/kernel/backtrace.rb +71 -0
- data/lib/qualitysmith_extensions/kernel/capture_output.rb +115 -0
- data/lib/qualitysmith_extensions/kernel/die.rb +49 -0
- data/lib/qualitysmith_extensions/kernel/example_printer.rb +81 -0
- data/lib/qualitysmith_extensions/kernel/filter_output.rb +108 -0
- data/lib/qualitysmith_extensions/kernel/remove_const.rb +178 -0
- data/lib/qualitysmith_extensions/kernel/remove_module.rb +127 -0
- data/lib/qualitysmith_extensions/kernel/require_all.rb +186 -0
- data/lib/qualitysmith_extensions/kernel/require_local_all.rb +4 -0
- data/lib/qualitysmith_extensions/kernel/require_once.rb +18 -0
- data/lib/qualitysmith_extensions/kernel/simulate_input.rb +52 -0
- data/lib/qualitysmith_extensions/kernel/trap_chain.rb +61 -0
- data/lib/qualitysmith_extensions/kernel/windows_platform.rb +46 -0
- data/lib/qualitysmith_extensions/module/alias_method.rb +6 -0
- data/lib/qualitysmith_extensions/module/alias_method_chain.rb +165 -0
- data/lib/qualitysmith_extensions/module/ancestry_of_instance_method.rb +43 -0
- data/lib/qualitysmith_extensions/module/attribute_accessors.rb +49 -0
- data/lib/qualitysmith_extensions/module/basename.rb +76 -0
- data/lib/qualitysmith_extensions/module/bool_attr_accessor.rb +497 -0
- data/lib/qualitysmith_extensions/module/class_methods.rb +87 -0
- data/lib/qualitysmith_extensions/module/create.rb +315 -0
- data/lib/qualitysmith_extensions/module/create_setter.rb +9 -0
- data/lib/qualitysmith_extensions/module/dirname.rb +4 -0
- data/lib/qualitysmith_extensions/module/guard_method.rb +312 -0
- data/lib/qualitysmith_extensions/module/includable_once.rb +10 -0
- data/lib/qualitysmith_extensions/module/join.rb +66 -0
- data/lib/qualitysmith_extensions/module/malias_method_chain.rb +92 -0
- data/lib/qualitysmith_extensions/module/module_methods.rb +4 -0
- data/lib/qualitysmith_extensions/module/namespace.rb +112 -0
- data/lib/qualitysmith_extensions/module/parents.rb +61 -0
- data/lib/qualitysmith_extensions/module/remove_const.rb +117 -0
- data/lib/qualitysmith_extensions/module/split.rb +55 -0
- data/lib/qualitysmith_extensions/month.rb +66 -0
- data/lib/qualitysmith_extensions/mutex/if_available.rb +75 -0
- data/lib/qualitysmith_extensions/object/ancestry_of_method.rb +257 -0
- data/lib/qualitysmith_extensions/object/default.rb +69 -0
- data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
- data/lib/qualitysmith_extensions/object/ignore_access.rb +84 -0
- data/lib/qualitysmith_extensions/object/mcall.rb +92 -0
- data/lib/qualitysmith_extensions/object/methods.rb +63 -0
- data/lib/qualitysmith_extensions/object/send_if.rb +151 -0
- data/lib/qualitysmith_extensions/object/send_if_not_nil.rb +35 -0
- data/lib/qualitysmith_extensions/object/singleton_send.rb +129 -0
- data/lib/qualitysmith_extensions/regexp/join.rb +111 -0
- data/lib/qualitysmith_extensions/string/all.rb +2 -0
- data/lib/qualitysmith_extensions/string/constantize.rb +4 -0
- data/lib/qualitysmith_extensions/string/digits_only.rb +27 -0
- data/lib/qualitysmith_extensions/string/each_char_with_index.rb +41 -0
- data/lib/qualitysmith_extensions/string/md5.rb +29 -0
- data/lib/qualitysmith_extensions/string/shell_escape.rb +43 -0
- data/lib/qualitysmith_extensions/string/to_underscored_label.rb +37 -0
- data/lib/qualitysmith_extensions/string/with_knowledge_of_color.rb +64 -0
- data/lib/qualitysmith_extensions/symbol/constantize.rb +69 -0
- data/lib/qualitysmith_extensions/symbol/match.rb +157 -0
- data/lib/qualitysmith_extensions/template.rb +33 -0
- data/lib/qualitysmith_extensions/test/all.rb +2 -0
- data/lib/qualitysmith_extensions/test/assert_anything.rb +93 -0
- data/lib/qualitysmith_extensions/test/assert_changed.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_exception.rb +66 -0
- data/lib/qualitysmith_extensions/test/assert_includes.rb +36 -0
- data/lib/qualitysmith_extensions/test/assert_user_error.rb +37 -0
- data/lib/qualitysmith_extensions/test/difference_highlighting.rb +323 -0
- data/lib/qualitysmith_extensions/time/all.rb +2 -0
- data/lib/qualitysmith_extensions/time/deprecated.rb +31 -0
- data/test/all.rb +16 -0
- metadata +148 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# * The name of this method maybe ought to be a little more specific. What does anyone else think?
|
8
|
+
# * It should say something about the fact that it the message sending is conditional but the block execution is unconditional.
|
9
|
+
# * always_execute_block_but_only_send_message_if ? Hmm... a bit too verbose, perhaps.
|
10
|
+
# * conditional_passthrough ?
|
11
|
+
# * passthrough_unless ?
|
12
|
+
# * use_wrapper_method_if ?
|
13
|
+
# * Or just leave it how it is because all the alternatives are too long...
|
14
|
+
#++
|
15
|
+
|
16
|
+
require 'rubygems'
|
17
|
+
gem 'facets'
|
18
|
+
require 'facets/core/kernel/with' # returning
|
19
|
+
|
20
|
+
class Object
|
21
|
+
# Sends +message+ to +self+ (including +block_to_always_execute+ if supplied) if +condition+ is met. If +condition+ is _not_ met,
|
22
|
+
# +block_to_always_execute+ will still be called (if supplied), but we will _not_ pass the message. (If +condition+ is not met
|
23
|
+
# and +block_to_always_execute+ is not supplied, it will simply return +self+.)
|
24
|
+
#
|
25
|
+
# In summary:
|
26
|
+
# * +block+: _always_ executed
|
27
|
+
# * +message+: only sent if +condition+
|
28
|
+
#
|
29
|
+
# If a block (+block_to_always_execute+) is supplied, it is passed on to the message if the condition is met; (otherwise it is
|
30
|
+
# simply called without sending the message).
|
31
|
+
#
|
32
|
+
# This is useful if you want to wrap a block with some method but you only want the method itself to be used some of the time.
|
33
|
+
# For example, if it's for benchmarking, you may only want to enable it during development but disable during production to save on some overhead.
|
34
|
+
#
|
35
|
+
# Note: this cannot be used to call methods that expect blocks (Ruby 1.9 maybe?)
|
36
|
+
#
|
37
|
+
def send_if(condition, message, *args, &block_to_always_execute)
|
38
|
+
if condition
|
39
|
+
self.__send__(message, *args, &block_to_always_execute)
|
40
|
+
else
|
41
|
+
if block_given?
|
42
|
+
block_to_always_execute.call
|
43
|
+
else
|
44
|
+
self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Opposite of send_if
|
50
|
+
def send_unless(condition, *args, &block)
|
51
|
+
self.send_if(!condition, *args, &block)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Lets you reduce duplication a little bit. Can do this:
|
55
|
+
# @foo.send_if_true(color)
|
56
|
+
# instead of this:
|
57
|
+
# @foo.send_if(color, color)
|
58
|
+
#
|
59
|
+
def send_if_true(condition, *args, &block)
|
60
|
+
self.send_if(condition, condition, *args, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
|
70
|
+
# _____ _
|
71
|
+
# |_ _|__ ___| |_
|
72
|
+
# | |/ _ \/ __| __|
|
73
|
+
# | | __/\__ \ |_
|
74
|
+
# |_|\___||___/\__|
|
75
|
+
#
|
76
|
+
=begin test
|
77
|
+
require 'test/unit'
|
78
|
+
|
79
|
+
class Foo
|
80
|
+
attr_reader :called_benchmark
|
81
|
+
def benchmark(&block)
|
82
|
+
@called_benchmark = true
|
83
|
+
yield
|
84
|
+
sleep 0.1 # Simulate lots of overhead, which we may want to avoid if we can help it
|
85
|
+
end
|
86
|
+
end
|
87
|
+
class String
|
88
|
+
def pink
|
89
|
+
"#{self} (in pink)"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class TheTest < Test::Unit::TestCase
|
94
|
+
def setup
|
95
|
+
@foo = Foo.new
|
96
|
+
@string = 'food'
|
97
|
+
end
|
98
|
+
|
99
|
+
def test_send_if_with_true_condition
|
100
|
+
executed_block = false
|
101
|
+
@foo.send_if(true, :benchmark) do
|
102
|
+
executed_block = true
|
103
|
+
end
|
104
|
+
assert executed_block
|
105
|
+
assert @foo.called_benchmark
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_send_if_with_false_condition
|
109
|
+
executed_block = false
|
110
|
+
@foo.send_if(false, :benchmark) do
|
111
|
+
executed_block = true
|
112
|
+
end
|
113
|
+
assert executed_block
|
114
|
+
assert !@foo.called_benchmark
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_send_if_with_no_block
|
118
|
+
color = nil
|
119
|
+
returned = @string.send_if(color, color)
|
120
|
+
assert_equal 'food', @string
|
121
|
+
assert_equal @string, returned
|
122
|
+
|
123
|
+
color = :pink
|
124
|
+
returned = @string.send_if(color, color)
|
125
|
+
assert_equal 'food', @string # @string itself should be unchanged, but the return value should be be a modified form of @string
|
126
|
+
assert_equal "#{@string} (in pink)", returned
|
127
|
+
end
|
128
|
+
def test_send_if_true_with_no_block
|
129
|
+
color = nil
|
130
|
+
returned = @string.send_if_true(color)
|
131
|
+
assert_equal 'food', @string
|
132
|
+
assert_equal @string, returned
|
133
|
+
|
134
|
+
color = :pink
|
135
|
+
returned = @string.send_if_true(color)
|
136
|
+
assert_equal 'food', @string
|
137
|
+
assert_equal "#{@string} (in pink)", returned
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_send_unless
|
141
|
+
executed_block = false
|
142
|
+
@foo.send_unless(false, :benchmark) do
|
143
|
+
executed_block = true
|
144
|
+
end
|
145
|
+
assert executed_block
|
146
|
+
assert @foo.called_benchmark
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
=end
|
151
|
+
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Maybe.
|
6
|
+
# Developer notes::
|
7
|
+
#++
|
8
|
+
|
9
|
+
class Object
|
10
|
+
def send_if_not_nil(message, *args)
|
11
|
+
if message
|
12
|
+
send(message, *args)
|
13
|
+
else
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
# _____ _
|
21
|
+
# |_ _|__ ___| |_
|
22
|
+
# | |/ _ \/ __| __|
|
23
|
+
# | | __/\__ \ |_
|
24
|
+
# |_|\___||___/\__|
|
25
|
+
#
|
26
|
+
=begin test
|
27
|
+
require 'test/unit'
|
28
|
+
|
29
|
+
class TheTest < Test::Unit::TestCase
|
30
|
+
def test_1
|
31
|
+
assert_equal 'a', 'a'.send_if_not_nil(nil)
|
32
|
+
assert_equal 'A', 'a'.send_if_not_nil(:upcase)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
=end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Maybe.
|
6
|
+
# Developer notes::
|
7
|
+
# * Method name too long? Imagine if we wanted to string multiple calls together.
|
8
|
+
# * Ideas:
|
9
|
+
# * single_send
|
10
|
+
# * singleton_send
|
11
|
+
# * singleton_call
|
12
|
+
# * singleton
|
13
|
+
# * singsend
|
14
|
+
# * extend_send
|
15
|
+
# * extend_call
|
16
|
+
# * create_and_send
|
17
|
+
# * create_and_call
|
18
|
+
#++
|
19
|
+
|
20
|
+
class Object
|
21
|
+
|
22
|
+
# Creates a singleton method and then calls it.
|
23
|
+
#
|
24
|
+
# More specificaly, it <tt>extend</tt>s +self+ with the methods from +moduule+ and then sends the supplied +message+ and +args+ (if any).
|
25
|
+
#
|
26
|
+
# Examples:
|
27
|
+
# "whatever".ss(MyColorizer, :colorize, :blue)
|
28
|
+
#
|
29
|
+
# Advantages:
|
30
|
+
# * Keeps things object-oriented. Better than having global/class methods.
|
31
|
+
# * (<tt>"whatever".ss(MyColorizer, :colorize).ss(SomeOtherClass, :another_class_method)</tt> instead of
|
32
|
+
# * <tt>SomeOtherClass::another_class_method(MyColorizer::colorize("whatever"))</tt>)
|
33
|
+
# * Method calls are _listed_ in the order in which they are _called_.
|
34
|
+
# * Still lets you keep your methods in a namespace.
|
35
|
+
# * Doesn't clutter up the base classes with methods that are only useful within a very small context. The methods are only added to the objects you specify. So you can "use" the base class <b>without cluttering up _all_ instances of the class with your methods</b>.
|
36
|
+
# * Useful for cases where creating a subclass wouldn't help because the methods you are calling would still return instances of the base class.
|
37
|
+
#
|
38
|
+
# Disadvantages:
|
39
|
+
# * You have to have/create a *module* for the functions you want to use.
|
40
|
+
# * Can't just call .sigleton_send(self, :some_method) if you want to use +some_method+ that's defined in +self+.
|
41
|
+
# * So what do we call the module containing the "singleton method"? String::MyColorizer? MyColorizer::String? MyStringColorizer?
|
42
|
+
#
|
43
|
+
# Adding methods to the base class using Facets' own *namespacing* facilities (Module#namespace and Module#include_as)
|
44
|
+
# might actually be a more sensible alternative a lot of the time than bothering to create singleton methods for single objects!
|
45
|
+
# That would look somethig like:
|
46
|
+
#
|
47
|
+
# class String
|
48
|
+
# namespace :my_colorizer do
|
49
|
+
# def colorize(...); ...; end
|
50
|
+
# end
|
51
|
+
# end
|
52
|
+
# "whatever".my_colorizer.colorize(:blue)
|
53
|
+
#
|
54
|
+
# or
|
55
|
+
#
|
56
|
+
# class String
|
57
|
+
# include_as :my_colorizer => MyColorizer
|
58
|
+
# end
|
59
|
+
# "whatever".my_colorizer.colorize(:blue)
|
60
|
+
#
|
61
|
+
def singleton_send(moduule, message, *args, &block)
|
62
|
+
self.extend(moduule)
|
63
|
+
self.send(message, *args, &block)
|
64
|
+
end
|
65
|
+
alias_method :ss, :singleton_send
|
66
|
+
|
67
|
+
# Couldn't get this idea to work:
|
68
|
+
# def singleton_that_accepts_object(object, method_name, *args)
|
69
|
+
## #class << self
|
70
|
+
## #self.instance_eval do
|
71
|
+
## self.class.module_eval do
|
72
|
+
## define_method(:colorize2, object.class.instance_method(:colorize2))
|
73
|
+
## end
|
74
|
+
## # raises "TypeError: bind argument must be an instance of TheTest"
|
75
|
+
#
|
76
|
+
## object.class.instance_method(method_name).
|
77
|
+
## bind(self)
|
78
|
+
## # raises "TypeError: bind argument must be an instance of TheTest"
|
79
|
+
#
|
80
|
+
## self.class.extend(object.class)
|
81
|
+
## self.class.send(:include, object.class)
|
82
|
+
## # raises "TypeError: wrong argument type Class (expected Module)"
|
83
|
+
# self.send(method_name, *args)
|
84
|
+
# end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
# _____ _
|
89
|
+
# |_ _|__ ___| |_
|
90
|
+
# | |/ _ \/ __| __|
|
91
|
+
# | | __/\__ \ |_
|
92
|
+
# |_|\___||___/\__|
|
93
|
+
#
|
94
|
+
=begin test
|
95
|
+
require 'test/unit'
|
96
|
+
require 'rubygems'
|
97
|
+
require 'qualitysmith_extensions/test/assert_exception'
|
98
|
+
require 'qualitysmith_extensions/test/assert_includes'
|
99
|
+
|
100
|
+
|
101
|
+
module MyColorizer
|
102
|
+
def colorize(color = nil)
|
103
|
+
self + " (colorized in #{color})"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
#module PresentationLayer
|
108
|
+
# create_module_method :to_currency do
|
109
|
+
# #...
|
110
|
+
# end
|
111
|
+
#end
|
112
|
+
|
113
|
+
|
114
|
+
class TheTest1_UsingSingletonSend < Test::Unit::TestCase
|
115
|
+
def test_using_singleton_send
|
116
|
+
assert_equal "whatever (colorized in )", "whatever".ss(MyColorizer, :colorize)
|
117
|
+
assert_equal "whatever (colorized in blue)", "whatever".ss(MyColorizer, :colorize, :blue)
|
118
|
+
end
|
119
|
+
|
120
|
+
# def test_singleton_that_accepts_object
|
121
|
+
# assert_equal "whatever (colorized in )", "whatever".singleton_that_accepts_object(self, :colorize2)
|
122
|
+
# assert_equal "whatever (colorized in blue)", "whatever".singleton_that_accepts_object(self, :colorize2, :blue)
|
123
|
+
# end
|
124
|
+
# def colorize2(color = nil)
|
125
|
+
# self + " (colorized2 in #{color})"
|
126
|
+
# end
|
127
|
+
end
|
128
|
+
=end
|
129
|
+
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes.
|
6
|
+
# Developer notes::
|
7
|
+
# * Names considered:
|
8
|
+
# * intersection (since there's already a Regexp#union), but unlike Regexp#union, it really doesn't seem like this method lends itself to a name from set theory. Mostly because unlike when dealing with sets (or unioned Regexps), *order matters* here.
|
9
|
+
# * merge, concat, sum, add, combines
|
10
|
+
# * join -- Settled on this because it's a lot like File.join: it combines the given pieces, *in order*, to make a whole.
|
11
|
+
#++
|
12
|
+
|
13
|
+
|
14
|
+
class Regexp
|
15
|
+
# Returns a Regexp that results from interpolating each of the given +elements+ into an empty regular expression.
|
16
|
+
# /ab/ == Regexp.join(/a/, /b/) # except spelled differently
|
17
|
+
# Accepts both strings and Regexp's as +elements+ to join together. Strings that are passed in will be escaped (so characters like '*' will lose all of the Regexp powers that they would otherwise have and are treated as literals).
|
18
|
+
#
|
19
|
+
# Serving suggestion: Use it to check if the +actual+ string in an <tt>assert_match</tt> contains certain literal strings, which may be separated by any number of characters or lines that we don't care about. In other words, use it to see if a string contains the necessary "keywords" or "key phrases"...
|
20
|
+
# assert_match Regexp.join(
|
21
|
+
# 'keyword1',
|
22
|
+
# /.*/m,
|
23
|
+
# 'keyword2'
|
24
|
+
# ), some_method()
|
25
|
+
# # where some_method() returns "keyword1 blah blah blah keyword2"
|
26
|
+
#
|
27
|
+
def self.join(*elements)
|
28
|
+
elements.inject(//) do |accumulator, element|
|
29
|
+
accumulator + element
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Pads the +elements+ (which may be strings or Regexp's) with /.*/ (match any number of characters) patterns.
|
34
|
+
# Pass :multi_line => true if you want /.*/m as the padding pattern instead.
|
35
|
+
def self.loose_join(*elements)
|
36
|
+
options = (if elements.last.is_a?(Hash) then elements.pop else {} end)
|
37
|
+
multi_line = options[:multi_line] || options[:m]
|
38
|
+
padding = (multi_line ? /.*/m : /.*/)
|
39
|
+
elements.inject(//) do |accumulator, element|
|
40
|
+
accumulator + padding + element
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# /a/ + /b/ == /ab/
|
45
|
+
# Actually, the way it's currently implemented, it is
|
46
|
+
# /a/ + /b/ == /(?-mix:a)(?-mix:b)/
|
47
|
+
# But they seem to be functionally equivalent despite the different spellings.
|
48
|
+
def +(other)
|
49
|
+
other = Regexp.escape(other) if other.is_a?(String)
|
50
|
+
/#{self}#{other}/
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
# _____ _
|
58
|
+
# |_ _|__ ___| |_
|
59
|
+
# | |/ _ \/ __| __|
|
60
|
+
# | | __/\__ \ |_
|
61
|
+
# |_|\___||___/\__|
|
62
|
+
#
|
63
|
+
=begin test
|
64
|
+
require 'test/unit'
|
65
|
+
|
66
|
+
class TheTest < Test::Unit::TestCase
|
67
|
+
def test_1_simple_letters
|
68
|
+
assert_equal /(?-mix:)(?-mix:b)/, // + /b/
|
69
|
+
assert_equal /(?-mix:)b/, // + 'b'
|
70
|
+
assert_equal /(?-mix:a)(?-mix:b)/, /a/ + /b/
|
71
|
+
assert_equal /(?-mix:a)b/, /a/ + 'b'
|
72
|
+
assert_equal /(?-mix:(?-mix:(?-mix:)a)b)c/, Regexp.join('a', 'b', 'c')
|
73
|
+
#assert_equal /(?-mix:(?-mix:(?-mix:)a)b)c/, Regexp.join(/a/, /b/, /c/)
|
74
|
+
assert_equal 2, '__abc__' =~ Regexp.join('a', 'b', 'c')
|
75
|
+
assert_equal 2, '__abc__' =~ Regexp.join(/a/, /b/, /c/)
|
76
|
+
assert_equal nil, '__a.c__' =~ Regexp.join('a', 'b', 'c')
|
77
|
+
assert_equal nil, '__a.c__' =~ Regexp.join(/a/, /b/, /c/)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_2_escaping
|
81
|
+
assert_equal /(?-mix:)\./, // + '.' # Escaped
|
82
|
+
assert_equal /(?-mix:)(?-mix:.)/, // + /./ # Not escaped
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_3
|
86
|
+
assert_match Regexp.join(
|
87
|
+
'keyword1',
|
88
|
+
/.*/m,
|
89
|
+
'keyword2'
|
90
|
+
),
|
91
|
+
'keyword1
|
92
|
+
asuethausnthauesth
|
93
|
+
blah blah blah
|
94
|
+
keyword2'
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_loose_join
|
98
|
+
regexp = Regexp.loose_join('keyword1', 'keyword2')
|
99
|
+
assert_match regexp, 'keyword1 blah blah blah keyword2'
|
100
|
+
assert_equal nil, "keyword1 blah\nblah\nblah keyword2" =~ regexp
|
101
|
+
end
|
102
|
+
def test_loose_join_multiline
|
103
|
+
regexp = Regexp.loose_join('keyword1', 'keyword2', :m => true)
|
104
|
+
assert_match regexp, 'keyword1 blah blah blah keyword2'
|
105
|
+
assert_match regexp, "keyword1 blah\nblah\nblah keyword2"
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
=end
|
110
|
+
|
111
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?:: Yes
|
6
|
+
#++
|
7
|
+
|
8
|
+
class String
|
9
|
+
# Strips out everything except digits.
|
10
|
+
def digits_only
|
11
|
+
self.gsub(/[^0-9]/, "")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# _____ _
|
16
|
+
# |_ _|__ ___| |_
|
17
|
+
# | |/ _ \/ __| __|
|
18
|
+
# | | __/\__ \ |_
|
19
|
+
# |_|\___||___/\__|
|
20
|
+
#
|
21
|
+
=begin test
|
22
|
+
class TheTest < Test::Unit::TestCase
|
23
|
+
def test_digits_only
|
24
|
+
assert_equal "123", "$!@)(*&abc123[]{}".digits_only
|
25
|
+
end
|
26
|
+
end
|
27
|
+
=end
|