qualitysmith_extensions 0.0.60 → 0.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/qualitysmith_extensions/find/select.rb +68 -0
- data/lib/qualitysmith_extensions/kernel/autoreload.rb +128 -0
- data/lib/qualitysmith_extensions/kernel/example_printer.rb +8 -2
- data/lib/qualitysmith_extensions/object/if_else.rb +157 -0
- data/lib/qualitysmith_extensions/object/send_if.rb +7 -1
- metadata +5 -2
@@ -0,0 +1,68 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?::
|
6
|
+
# Developer notes::
|
7
|
+
# Changes::
|
8
|
+
#++
|
9
|
+
|
10
|
+
|
11
|
+
require 'find'
|
12
|
+
require 'enumerator'
|
13
|
+
|
14
|
+
module Find
|
15
|
+
# Identical to +find+ except +select+ returns the matching files as an _array_. (+find+ returns nil, which is not very useful if you actually wanted an array.)
|
16
|
+
#
|
17
|
+
# Calls the associated block with the name of every file and directory listed as arguments, then recursively on their subdirectories, and so on.
|
18
|
+
#
|
19
|
+
# Return a true (non-false) value from the block for every path that you want to be returned in the resulting array.
|
20
|
+
#
|
21
|
+
# You can still use <tt>Find.prune</tt>.
|
22
|
+
#
|
23
|
+
def self.select(*paths, &block)
|
24
|
+
Enumerable::Enumerator.new(self, :find, *paths).select{|value| yield value}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
# _____ _
|
34
|
+
# |_ _|__ ___| |_
|
35
|
+
# | |/ _ \/ __| __|
|
36
|
+
# | | __/\__ \ |_
|
37
|
+
# |_|\___||___/\__|
|
38
|
+
#
|
39
|
+
=begin test
|
40
|
+
require 'test/unit'
|
41
|
+
|
42
|
+
class TheTest < Test::Unit::TestCase
|
43
|
+
# to do: would probably be safer if we *created* our own files/directories during setup, rather than expecting there to be some for us to use in cwd
|
44
|
+
|
45
|
+
def test_true
|
46
|
+
dir = '.'
|
47
|
+
files_expected = []
|
48
|
+
Find.find(dir) { |path| files_expected << path }
|
49
|
+
|
50
|
+
files = Find.select(dir) { |path| true }
|
51
|
+
assert_equal files_expected, files
|
52
|
+
|
53
|
+
# Doesn't have to be true necessarily -- can be a string
|
54
|
+
files = Find.select(dir) { |path| path }
|
55
|
+
assert_equal files_expected, files
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_false
|
59
|
+
dir = '.'
|
60
|
+
files = Find.select(dir) { |path| false }
|
61
|
+
|
62
|
+
assert_equal [], files
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
=end
|
67
|
+
|
68
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# CREDIT Michael Neumann
|
2
|
+
# CREDIT George Moschovitis
|
3
|
+
|
4
|
+
module Kernel
|
5
|
+
|
6
|
+
# Autoreload feature files.
|
7
|
+
#
|
8
|
+
# Automatically reload, at regular intervals, any previously loaded features,
|
9
|
+
# and/or other files not already loaded, if they have been modified since the last
|
10
|
+
# interval check. A numeric parameter sets the reload interval in seconds
|
11
|
+
# and the file parameter can either be a glob string or an array
|
12
|
+
# of file paths. If a glob string, it is expanded only once on the initial
|
13
|
+
# method call. Supplying a boolean parameter of 'false' will force autreload to
|
14
|
+
# skip previously loaded features and only reload the specified files.
|
15
|
+
# Also keeps a "dirty" flag.
|
16
|
+
|
17
|
+
def autoreload( *args )
|
18
|
+
|
19
|
+
check_interval=10
|
20
|
+
include_features = true
|
21
|
+
files = nil
|
22
|
+
|
23
|
+
args.each do |arg|
|
24
|
+
case arg
|
25
|
+
when Numeric
|
26
|
+
check_interval = arg
|
27
|
+
when String
|
28
|
+
files = Dir.glob( arg )
|
29
|
+
when Array
|
30
|
+
files = arg
|
31
|
+
when TrueClass, FalseClass
|
32
|
+
include_features = arg
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
file_mtime = {}
|
37
|
+
|
38
|
+
Thread.new(Time.now) do |start_time|
|
39
|
+
loop do
|
40
|
+
sleep check_interval
|
41
|
+
|
42
|
+
if include_features
|
43
|
+
feature_files = $LOADED_FEATURES.collect { |feature|
|
44
|
+
$LOAD_PATH.each { |lp| file = File.join(lp, feature) }
|
45
|
+
}.flatten
|
46
|
+
p feature_files
|
47
|
+
|
48
|
+
feature_files.each { |file|
|
49
|
+
if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
|
50
|
+
$autoreload_dirty = true
|
51
|
+
file_mtime[file] = mtime
|
52
|
+
STDERR.puts "File '#{ file }' reloaded"
|
53
|
+
begin
|
54
|
+
load(file)
|
55
|
+
rescue Exception => e
|
56
|
+
STDERR.puts e.inspect
|
57
|
+
end
|
58
|
+
end
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
if files
|
63
|
+
files.each do |file|
|
64
|
+
if File.exists?(file) and (mtime = File.stat(file).mtime) > (file_mtime[file] || start_time)
|
65
|
+
$autoreload_dirty = true
|
66
|
+
file_mtime[file] = mtime
|
67
|
+
STDERR.puts "File '#{ file }' changed"
|
68
|
+
begin
|
69
|
+
load(file)
|
70
|
+
rescue Exception => e
|
71
|
+
STDERR.puts e.inspect
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Same as #autoreload, but does not include previously loaded features.
|
84
|
+
# This is equivalent to as adding a 'false' parameter to #autoreload.
|
85
|
+
|
86
|
+
def autoreload_files( *args )
|
87
|
+
autoreload( false, *args )
|
88
|
+
end
|
89
|
+
|
90
|
+
# deprecate
|
91
|
+
alias_method :autoreload_glob, :autoreload_files
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
#--
|
96
|
+
# # OLD VERSION
|
97
|
+
# def autoreload(check_interval=10)
|
98
|
+
# Thread.new(Time.now) { |start_time|
|
99
|
+
# file_mtime = {}
|
100
|
+
# loop {
|
101
|
+
# sleep check_interval
|
102
|
+
# $LOADED_FEATURES.each { |feature|
|
103
|
+
# $LOAD_PATH.each { |lp|
|
104
|
+
# file = File.join(lp, feature)
|
105
|
+
# if (File.exists?(file) and
|
106
|
+
# File.stat(file).mtime > (file_mtime[file] || start_time))
|
107
|
+
# file_mtime[file] = File.stat(file).mtime
|
108
|
+
# STDERR.puts "reload #{ file }"
|
109
|
+
# begin
|
110
|
+
# load(file)
|
111
|
+
# rescue Exception => e
|
112
|
+
# STDERR.puts e.inspect
|
113
|
+
# end
|
114
|
+
# end
|
115
|
+
# }
|
116
|
+
# }
|
117
|
+
# }
|
118
|
+
# }
|
119
|
+
# end
|
120
|
+
#++
|
121
|
+
|
122
|
+
# _____ _
|
123
|
+
# |_ _|__ ___| |_
|
124
|
+
# | |/ _ \/ __| __|
|
125
|
+
# | | __/\__ \ |_
|
126
|
+
# |_|\___||___/\__|
|
127
|
+
#
|
128
|
+
# TODO
|
@@ -19,10 +19,15 @@ require 'rubygems'
|
|
19
19
|
# alternative is dirt simple, and it still works.
|
20
20
|
module ExamplePrinter
|
21
21
|
# Prints the given statement (+code+ -- a string) before evaluating it.
|
22
|
+
# Same as xmp only it doesn't print the return value.
|
23
|
+
#
|
24
|
+
# o = nil
|
25
|
+
# xmp 'o = C.new', binding
|
26
|
+
# # => o = C.new
|
22
27
|
def put_statement(code, binding = nil, file = __FILE__, line = __LINE__)
|
23
|
-
# This didn't work. Still got this error: undefined local variable or method `x' for #<TheTest:0xb7dbc358> (NameError)
|
28
|
+
# # This didn't work. Still got this error: undefined local variable or method `x' for #<TheTest:0xb7dbc358> (NameError)
|
24
29
|
# Binding.of_caller do |caller_binding|
|
25
|
-
# puts caller_binding
|
30
|
+
# #puts caller_binding
|
26
31
|
# puts code
|
27
32
|
# eval code, caller_binding
|
28
33
|
# end
|
@@ -31,6 +36,7 @@ module ExamplePrinter
|
|
31
36
|
end
|
32
37
|
alias_method :stp, :put_statement
|
33
38
|
|
39
|
+
# Prints the given statement (+code+ -- a string) before evaluating it. Then prints its return value.
|
34
40
|
# Pretty much compatible with irb/xmp. But you have currently have to pass
|
35
41
|
# in the binding manually if you have any local variables/methods that xmp
|
36
42
|
# should have access to.
|
@@ -0,0 +1,157 @@
|
|
1
|
+
#--
|
2
|
+
# Author:: Tyler Rick
|
3
|
+
# Copyright:: Copyright (c) 2007 QualitySmith, Inc.
|
4
|
+
# License:: Ruby License
|
5
|
+
# Submit to Facets?::
|
6
|
+
# Developer notes::
|
7
|
+
# Changes::
|
8
|
+
#++
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
class Object
|
13
|
+
# Returns +self+ if +condition+; otherwise, returns +else_value+.
|
14
|
+
#
|
15
|
+
# Example:
|
16
|
+
# "Average: #{array.average}". if_else array.size >= 3, ''
|
17
|
+
# That is another way to say this:
|
18
|
+
# array.size >= 3 ? "Average: #{array.average}" : '' )
|
19
|
+
#
|
20
|
+
# Sometimes you want to do 'something unless condition' and you want that whole expression to return '' (or some other value)
|
21
|
+
# if the condition is false, rather than nil, which is what it currently returns.
|
22
|
+
#
|
23
|
+
# *Important*: "+self+" will always be "evaluated". So if the receiver of this message is some _dangerous_ call (has side
|
24
|
+
# effects), then you would be advised to use the normal if/then/else or ?/: constructs instead.
|
25
|
+
#
|
26
|
+
# For example, +method_with_adverse_side_effects+ will be called unconditionally in this case (whether or not +ready?+ returns +false+):
|
27
|
+
# obj.method_with_adverse_side_effects. if_else ready?, NotReady
|
28
|
+
# But it will not be called in this case if +ready?+ returns +false+:
|
29
|
+
# ready? ? obj.method_with_adverse_side_effects : NotReady)
|
30
|
+
#
|
31
|
+
# "Isn't this method useless?" ... Yes, basically. Its main advantage is that it lets you put the condition _after_ the normal
|
32
|
+
# value, which may make it easier to follow the normal execution flow when reading the source.
|
33
|
+
#
|
34
|
+
# This is similar to something I saw in another language (Python?) where a similar syntax is built right into the language. Something like this:
|
35
|
+
# normal_value if condition else else_value
|
36
|
+
#
|
37
|
+
# I thought that was a neat idea so I implemented it as best I could in Ruby.
|
38
|
+
#
|
39
|
+
# This might also be interesting for folks coming from Smalltalk, where +if+ really _is_ just a message that you pass to an
|
40
|
+
# object along with a block (?) to be executed if +condition+ is +true+ and a block to be executed if +condition+ is +false+.
|
41
|
+
#
|
42
|
+
def if(condition, else_value = nil)
|
43
|
+
condition ?
|
44
|
+
self :
|
45
|
+
else_value
|
46
|
+
end
|
47
|
+
alias_method :if_else, :if
|
48
|
+
|
49
|
+
def unless(condition, else_value)
|
50
|
+
!condition ?
|
51
|
+
self :
|
52
|
+
else_value
|
53
|
+
end
|
54
|
+
alias_method :unless_else, :unless
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
|
60
|
+
|
61
|
+
|
62
|
+
# _____ _
|
63
|
+
# |_ _|__ ___| |_
|
64
|
+
# | |/ _ \/ __| __|
|
65
|
+
# | | __/\__ \ |_
|
66
|
+
# |_|\___||___/\__|
|
67
|
+
#
|
68
|
+
=begin test
|
69
|
+
require 'test/unit'
|
70
|
+
|
71
|
+
require 'rubygems'
|
72
|
+
require 'qualitysmith_extensions/array/average'
|
73
|
+
|
74
|
+
class TheTest < Test::Unit::TestCase
|
75
|
+
def test_1
|
76
|
+
array = [1, 2]
|
77
|
+
assert_equal 'not enough values', average(array)
|
78
|
+
assert_equal 'not enough values', average_the_normal_way(array)
|
79
|
+
|
80
|
+
array = [1, 2, 3]
|
81
|
+
assert_equal 'average = 2.0', average(array)
|
82
|
+
assert_equal 'average = 2.0', average_the_normal_way(array)
|
83
|
+
end
|
84
|
+
|
85
|
+
# This way is actually easier to read, so you'd be pretty silly to use if_else in this case!
|
86
|
+
def average_the_normal_way(array)
|
87
|
+
array.size >= 3 ?
|
88
|
+
"average = #{array.average}" :
|
89
|
+
'not enough values'
|
90
|
+
end
|
91
|
+
|
92
|
+
def average(array)
|
93
|
+
"average = #{array.average}".if_else( array.size >= 3, 'not enough values' )
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
def test_2
|
101
|
+
# Sometimes you want to do 'something unless condition' and you want that whole expression to return '' (or some other value)
|
102
|
+
# if the condition is false, rather than nil, which is what it currently returns.
|
103
|
+
assert_equal nil, render_list_the_naive_way([])
|
104
|
+
assert_equal '', render_list_the_long_way([])
|
105
|
+
assert_equal '', render_list([])
|
106
|
+
|
107
|
+
list = ['Alice', 'Malory']
|
108
|
+
|
109
|
+
[
|
110
|
+
render_list_the_naive_way(list),
|
111
|
+
render_list_the_long_way(list),
|
112
|
+
render_list(list),
|
113
|
+
].each {|a|
|
114
|
+
assert_equal '<ul><li>Alice</li><li>Malory</li></ul>', a
|
115
|
+
}
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
def render_list_the_naive_way(list)
|
120
|
+
content_tag(:ul,
|
121
|
+
list.map { |item|
|
122
|
+
content_tag(:li,
|
123
|
+
item
|
124
|
+
)
|
125
|
+
}
|
126
|
+
) unless list.empty?
|
127
|
+
end
|
128
|
+
def render_list_the_long_way(list)
|
129
|
+
unless list.empty?
|
130
|
+
content_tag(:ul,
|
131
|
+
list.map { |item|
|
132
|
+
content_tag(:li,
|
133
|
+
item
|
134
|
+
)
|
135
|
+
}
|
136
|
+
)
|
137
|
+
else
|
138
|
+
''
|
139
|
+
end
|
140
|
+
end
|
141
|
+
def render_list(list)
|
142
|
+
content_tag(:ul,
|
143
|
+
list.map { |item|
|
144
|
+
content_tag(:li,
|
145
|
+
item
|
146
|
+
)
|
147
|
+
}
|
148
|
+
). unless_else list.empty?, ''
|
149
|
+
end
|
150
|
+
|
151
|
+
def content_tag(tag, contents)
|
152
|
+
"<#{tag}>#{contents}</#{tag}>"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
=end
|
156
|
+
|
157
|
+
|
@@ -18,7 +18,13 @@ gem 'facets'
|
|
18
18
|
require 'facets/core/kernel/with' # returning
|
19
19
|
|
20
20
|
class Object
|
21
|
-
#
|
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+
|
22
28
|
#
|
23
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
|
24
30
|
# simply called without sending the message).
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: qualitysmith_extensions
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.0.63
|
7
|
+
date: 2007-07-17 00:00:00 -07:00
|
8
8
|
summary: A collection of reusable Ruby methods developed by QualitySmith.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- lib/qualitysmith_extensions/exception/inspect_with_backtrace.rb
|
45
45
|
- lib/qualitysmith_extensions/colored/toggleability.rb
|
46
46
|
- lib/qualitysmith_extensions/file_test/binary_file.rb
|
47
|
+
- lib/qualitysmith_extensions/kernel/autoreload.rb
|
47
48
|
- lib/qualitysmith_extensions/kernel/require_all.rb
|
48
49
|
- lib/qualitysmith_extensions/kernel/simulate_input.rb
|
49
50
|
- lib/qualitysmith_extensions/kernel/die.rb
|
@@ -66,6 +67,7 @@ files:
|
|
66
67
|
- lib/qualitysmith_extensions/object/methods.rb
|
67
68
|
- lib/qualitysmith_extensions/object/default.rb
|
68
69
|
- lib/qualitysmith_extensions/object/send_if.rb
|
70
|
+
- lib/qualitysmith_extensions/object/if_else.rb
|
69
71
|
- lib/qualitysmith_extensions/file/exact_match_regexp.rb
|
70
72
|
- lib/qualitysmith_extensions/date/iso8601.rb
|
71
73
|
- lib/qualitysmith_extensions/date/deprecated.rb
|
@@ -74,6 +76,7 @@ files:
|
|
74
76
|
- lib/qualitysmith_extensions/time/deprecated.rb
|
75
77
|
- lib/qualitysmith_extensions/time/all.rb
|
76
78
|
- lib/qualitysmith_extensions/regexp/join.rb
|
79
|
+
- lib/qualitysmith_extensions/find/select.rb
|
77
80
|
- lib/qualitysmith_extensions/mutex/if_available.rb
|
78
81
|
- lib/qualitysmith_extensions/console/command.rb
|
79
82
|
- lib/qualitysmith_extensions/console/command.facets.1.8.54.rb
|