og 0.7.0 → 0.8.0
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/AUTHORS +14 -4
- data/ChangeLog +192 -1
- data/README.og +2 -1
- data/RELEASES.og +35 -0
- data/Rakefile +1 -1
- data/examples/og/mock_example.rb +6 -9
- data/examples/og/mysql_to_psql.rb +100 -0
- data/examples/og/run.rb +8 -17
- data/lib/glue/array.rb +1 -1
- data/lib/glue/attribute.rb +86 -0
- data/lib/glue/cache.rb +1 -1
- data/lib/glue/hash.rb +1 -1
- data/lib/glue/inflector.rb +1 -1
- data/lib/glue/logger.rb +118 -18
- data/lib/glue/mixins.rb +1 -1
- data/lib/glue/number.rb +1 -1
- data/lib/glue/pool.rb +1 -1
- data/lib/glue/property.rb +48 -31
- data/lib/glue/string.rb +1 -1
- data/lib/glue/time.rb +2 -2
- data/lib/glue/validation.rb +400 -0
- data/lib/glue.rb +7 -8
- data/lib/og/backend.rb +47 -46
- data/lib/og/backends/mysql.rb +64 -63
- data/lib/og/backends/psql.rb +73 -72
- data/lib/og/connection.rb +7 -8
- data/lib/og/enchant.rb +80 -0
- data/lib/og/meta.rb +21 -21
- data/lib/og/mock.rb +31 -88
- data/lib/og/version.rb +6 -5
- data/lib/og.rb +95 -129
- data/test/tc_og.rb +3 -3
- data/vendor/extensions/_base.rb +153 -0
- data/vendor/extensions/_template.rb +36 -0
- data/vendor/extensions/all.rb +21 -0
- data/vendor/extensions/array.rb +68 -0
- data/vendor/extensions/binding.rb +224 -0
- data/vendor/extensions/class.rb +50 -0
- data/vendor/extensions/continuation.rb +71 -0
- data/vendor/extensions/enumerable.rb +250 -0
- data/vendor/extensions/hash.rb +23 -0
- data/vendor/extensions/io.rb +58 -0
- data/vendor/extensions/kernel.rb +42 -0
- data/vendor/extensions/module.rb +114 -0
- data/vendor/extensions/numeric.rb +230 -0
- data/vendor/extensions/object.rb +164 -0
- data/vendor/extensions/ostruct.rb +41 -0
- data/vendor/extensions/string.rb +316 -0
- data/vendor/extensions/symbol.rb +28 -0
- metadata +24 -4
- data/lib/glue/property.rb.old +0 -307
@@ -0,0 +1,250 @@
|
|
1
|
+
#
|
2
|
+
# == extensions/enumerable.rb
|
3
|
+
#
|
4
|
+
# Adds methods to the builtin Enumerable module.
|
5
|
+
#
|
6
|
+
|
7
|
+
require "extensions/_base"
|
8
|
+
|
9
|
+
#
|
10
|
+
# * Enumerable#build_hash
|
11
|
+
#
|
12
|
+
ExtensionsProject.implement(Enumerable, :build_hash) do
|
13
|
+
module Enumerable
|
14
|
+
#
|
15
|
+
# Like <tt>#map</tt>/<tt>#collect</tt>, but it generates a Hash. The block
|
16
|
+
# is expected to return two values: the key and the value for the new hash.
|
17
|
+
# numbers = (1..3)
|
18
|
+
# squares = numbers.build_hash { |n| [n, n*n] } # 1=>1, 2=>4, 3=>9
|
19
|
+
# sq_roots = numbers.build_hash { |n| [n*n, n] } # 1=>1, 4=>2, 9=>3
|
20
|
+
#
|
21
|
+
def build_hash
|
22
|
+
result = {}
|
23
|
+
self.each do |elt|
|
24
|
+
key, value = yield elt
|
25
|
+
result[key] = value
|
26
|
+
end
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# There was a bug in Hash which causes the above code to issue a warning when
|
32
|
+
# used with a Hash. That was fixed on 2003-10-24.
|
33
|
+
if RUBY_RELEASE_DATE < "2003-10-25"
|
34
|
+
class Hash #:nodoc:
|
35
|
+
def build_hash
|
36
|
+
result = {}
|
37
|
+
self.each_pair do |k, v|
|
38
|
+
key, value = yield(k, v)
|
39
|
+
result[key] = value
|
40
|
+
end
|
41
|
+
result
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
#
|
49
|
+
# Enumerable#mapf
|
50
|
+
#
|
51
|
+
ExtensionsProject.implement(Enumerable, :mapf) do
|
52
|
+
module Enumerable
|
53
|
+
#
|
54
|
+
# "map function"
|
55
|
+
# enum.mapf(:x)
|
56
|
+
# is short for
|
57
|
+
# enum.map { |elt| elt.x }
|
58
|
+
#
|
59
|
+
def mapf(message)
|
60
|
+
self.map { |elt| elt.send(message) }
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
#
|
67
|
+
# Enumerable#collectf
|
68
|
+
#
|
69
|
+
ExtensionsProject.implement(Enumerable, :collectf) do
|
70
|
+
module Enumerable
|
71
|
+
alias collectf mapf
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
#
|
77
|
+
# * Enumerable#includes?
|
78
|
+
#
|
79
|
+
ExtensionsProject.implement(Enumerable, :includes?) do
|
80
|
+
module Enumerable
|
81
|
+
alias includes? include?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
#
|
87
|
+
# * Enumerable#contains?
|
88
|
+
#
|
89
|
+
ExtensionsProject.implement(Enumerable, :contains?) do
|
90
|
+
module Enumerable
|
91
|
+
alias contains? include?
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
#
|
97
|
+
# * Enumerable#has?
|
98
|
+
#
|
99
|
+
ExtensionsProject.implement(Enumerable, :has?) do
|
100
|
+
module Enumerable
|
101
|
+
alias has? include?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
#
|
107
|
+
# * Enumerable#map_with_index
|
108
|
+
#
|
109
|
+
ExtensionsProject.implement(Enumerable, :map_with_index) do
|
110
|
+
module Enumerable
|
111
|
+
#
|
112
|
+
# Same as Enumerable#map, but the index is yielded as well. See
|
113
|
+
# Enumerable#each_with_index.
|
114
|
+
# puts files.map_with_index { |fn, idx| "#{idx}. #{fn}" }
|
115
|
+
# print "Please select a file (0-#{files.size}): "
|
116
|
+
#
|
117
|
+
def map_with_index
|
118
|
+
result = []
|
119
|
+
self.each_with_index do |elt, idx|
|
120
|
+
result << yield(elt, idx)
|
121
|
+
end
|
122
|
+
result
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
#
|
129
|
+
# * Enumerable#collect_with_index
|
130
|
+
#
|
131
|
+
ExtensionsProject.implement(Enumerable, :collect_with_index) do
|
132
|
+
module Enumerable
|
133
|
+
alias collect_with_index map_with_index
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
#
|
139
|
+
# * Enumerable#partition_by
|
140
|
+
#
|
141
|
+
ExtensionsProject.implement(Enumerable, :partition_by) do
|
142
|
+
module Enumerable
|
143
|
+
#
|
144
|
+
# See Enumerable#partition for the background. #partition_by is best
|
145
|
+
# explained by example.
|
146
|
+
#
|
147
|
+
# (1..5).partition_by { |n| n % 3 }
|
148
|
+
# # -> { 0 => [3], 1 => [1, 4], 2 => [2,5] }
|
149
|
+
#
|
150
|
+
# ["I had", 1, "dollar and", 50, "cents"].partition_by { |e| e.class }
|
151
|
+
# # -> { String => ["I had","dollar and","cents"], Fixnum => [1,50] }
|
152
|
+
#
|
153
|
+
# #partition_by is used to group items in a collection by something they
|
154
|
+
# have in common. The common factor is the key in the resulting hash, the
|
155
|
+
# array of like elements is the value.
|
156
|
+
#
|
157
|
+
def partition_by
|
158
|
+
result = {}
|
159
|
+
self.each do |e|
|
160
|
+
value = yield e
|
161
|
+
(result[value] ||= []) << e
|
162
|
+
end
|
163
|
+
result
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
#
|
170
|
+
# * Enumerable#none?
|
171
|
+
#
|
172
|
+
ExtensionsProject.implement(Enumerable, :none?) do
|
173
|
+
module Enumerable
|
174
|
+
#
|
175
|
+
# Enumerable#none? is the logical opposite of the builtin method Enumerable#any?. It
|
176
|
+
# returns +true+ if and only if _none_ of the elements in the collection satisfy the
|
177
|
+
# predicate.
|
178
|
+
#
|
179
|
+
# If no predicate is provided, Enumerable#none? returns +true+ if and only if _none_ of the
|
180
|
+
# elements have a true value (i.e. not +nil+ or +false+).
|
181
|
+
#
|
182
|
+
# [].none? # true
|
183
|
+
# [nil].none? # true
|
184
|
+
# [5,8,9].none? # false
|
185
|
+
# (1...10).none? { |n| n < 0 } # true
|
186
|
+
# (1...10).none? { |n| n > 0 } # false
|
187
|
+
#
|
188
|
+
def none? # :yield: e
|
189
|
+
if block_given?
|
190
|
+
not self.any? { |e| yield e }
|
191
|
+
else
|
192
|
+
not self.any?
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
#
|
200
|
+
# * Enumerable#one?
|
201
|
+
#
|
202
|
+
ExtensionsProject.implement(Enumerable, :one?) do
|
203
|
+
module Enumerable
|
204
|
+
#
|
205
|
+
# Enumerable#one? returns +true+ if and only if <em>exactly one</em> element in the
|
206
|
+
# collection satisfies the given predicate.
|
207
|
+
#
|
208
|
+
# If no predicate is provided, Enumerable#one? returns +true+ if and only if <em>exactly
|
209
|
+
# one</em> element has a true value (i.e. not +nil+ or +false+).
|
210
|
+
#
|
211
|
+
# [].one? # false
|
212
|
+
# [nil].one? # false
|
213
|
+
# [5].one? # true
|
214
|
+
# [5,8,9].one? # false
|
215
|
+
# (1...10).one? { |n| n == 5 } # true
|
216
|
+
# (1...10).one? { |n| n < 5 } # false
|
217
|
+
#
|
218
|
+
def one? # :yield: e
|
219
|
+
matches = 0
|
220
|
+
if block_given?
|
221
|
+
self.each do |e|
|
222
|
+
if yield(e)
|
223
|
+
matches += 1
|
224
|
+
return false if matches > 1
|
225
|
+
end
|
226
|
+
end
|
227
|
+
return (matches == 1)
|
228
|
+
else
|
229
|
+
one? { |e| e }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
#
|
237
|
+
# * Object.in?
|
238
|
+
# This has special treatment: it's included here and in object.rb, so we don't
|
239
|
+
# want a warning if it's alredy defined.
|
240
|
+
#
|
241
|
+
unless Object.method_defined?(:in?)
|
242
|
+
ExtensionsProject.implement(Object, :in?) do
|
243
|
+
class Object
|
244
|
+
def in?(enumerable) # :nodoc: It's documented in object.rb.
|
245
|
+
enumerable.include?(self)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/hash.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Hash class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
#
|
11
|
+
# * Hash#select!
|
12
|
+
#
|
13
|
+
ExtensionsProject.implement(Hash, :select!) do
|
14
|
+
class Hash
|
15
|
+
#
|
16
|
+
# In-place version of Hash#select. (Counterpart to, and opposite of, the
|
17
|
+
# built-in #reject!)
|
18
|
+
#
|
19
|
+
def select!
|
20
|
+
reject! { |k,v| not yield(k,v) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
#
|
4
|
+
# == extensions/io.rb
|
5
|
+
#
|
6
|
+
# Adds methods to the builtin IO class.
|
7
|
+
#
|
8
|
+
|
9
|
+
require "extensions/_base"
|
10
|
+
|
11
|
+
# This is Ruby's built-in IO class.
|
12
|
+
class IO
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# * IO.write
|
17
|
+
#
|
18
|
+
ExtensionsProject.implement(IO, :write, :class) do
|
19
|
+
class << IO
|
20
|
+
#
|
21
|
+
# Writes the given data to the given path and closes the file. This is
|
22
|
+
# done in binary mode, complementing <tt>IO.read</tt> in standard Ruby.
|
23
|
+
#
|
24
|
+
# Returns the number of bytes written.
|
25
|
+
#
|
26
|
+
def write(path, data)
|
27
|
+
File.open(path, "wb") do |file|
|
28
|
+
return file.write(data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# * IO.writelines
|
36
|
+
#
|
37
|
+
ExtensionsProject.implement(IO, :writelines, :class) do
|
38
|
+
class << IO
|
39
|
+
#
|
40
|
+
# Writes the given array of data to the given path and closes the file.
|
41
|
+
# This is done in binary mode, complementing <tt>IO.readlines</tt> in
|
42
|
+
# standard Ruby.
|
43
|
+
#
|
44
|
+
# Note that +readlines+ (the standard Ruby method) returns an array of lines
|
45
|
+
# <em>with newlines intact</em>, whereas +writelines+ uses +puts+, and so
|
46
|
+
# appends newlines if necessary. In this small way, +readlines+ and
|
47
|
+
# +writelines+ are not exact opposites.
|
48
|
+
#
|
49
|
+
# Returns +nil+.
|
50
|
+
#
|
51
|
+
def writelines(path, data)
|
52
|
+
File.open(path, "wb") do |file|
|
53
|
+
file.puts(data)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/module.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Kernel module.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
ExtensionsProject.implement(Kernel, :require_relative) do
|
11
|
+
module Kernel
|
12
|
+
#
|
13
|
+
# <tt>require_relative</tt> complements the builtin method <tt>require</tt> by allowing
|
14
|
+
# you to load a file that is <em>relative to the file containing the require_relative
|
15
|
+
# statement</em>.
|
16
|
+
#
|
17
|
+
# When you use <tt>require</tt> to load a file, you are usually accessing functionality
|
18
|
+
# that has been properly installed, and made accessible, in your system. <tt>require</tt>
|
19
|
+
# does not offer a good solution for loading files within the project's code. This may
|
20
|
+
# be useful during a development phase, for accessing test data, or even for accessing
|
21
|
+
# files that are "locked" away inside a project, not intended for outside use.
|
22
|
+
#
|
23
|
+
# For example, if you have unit test classes in the "test" directory, and data for them
|
24
|
+
# under the test "test/data" directory, then you might use a line like this in a test
|
25
|
+
# case:
|
26
|
+
#
|
27
|
+
# require_relative "data/customer_data_1"
|
28
|
+
#
|
29
|
+
# Since neither "test" nor "test/data" are likely to be in Ruby's library path (and for
|
30
|
+
# good reason), a normal <tt>require</tt> won't find them. <tt>require_relative</tt> is
|
31
|
+
# a good solution for this particular problem.
|
32
|
+
#
|
33
|
+
# You may include or omit the extension (<tt>.rb</tt> or <tt>.so</tt>) of the file you
|
34
|
+
# are loading.
|
35
|
+
#
|
36
|
+
# _path_ must respond to <tt>to_str</tt>.
|
37
|
+
#
|
38
|
+
def require_relative(path)
|
39
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/module.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Module class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
ExtensionsProject.implement(Module, :deep_const_get) do
|
11
|
+
class Module
|
12
|
+
#
|
13
|
+
# Recursively dereferences constants separated by "<tt>::</tt>".
|
14
|
+
#
|
15
|
+
# _const_ is a Symbol or responds to #to_str, for compatibility with the builtin method
|
16
|
+
# <tt>Module#const_get</tt>.
|
17
|
+
#
|
18
|
+
# Object.const_get("String") # -> String
|
19
|
+
# Object.const_get(:String) # -> String
|
20
|
+
#
|
21
|
+
# Object.deep_const_get("String") # -> String
|
22
|
+
# Object.deep_const_get(:String) # -> String
|
23
|
+
#
|
24
|
+
# Object.deep_const_get("Process::Sys") # -> Process::Sys
|
25
|
+
# Object.deep_const_get("Regexp::IGNORECASE") # -> 1
|
26
|
+
# Object.deep_const_get("Regexp::MULTILINE") # -> 4
|
27
|
+
#
|
28
|
+
# require 'test/unit'
|
29
|
+
# Test.deep_const_get("Unit::Assertions") # -> Test::Unit::Assertions
|
30
|
+
# Test.deep_const_get("::Test::Unit") # -> Test::Unit
|
31
|
+
#
|
32
|
+
# For resolving classes or modules based on their name, see Module.by_name, which uses this
|
33
|
+
# method.
|
34
|
+
#
|
35
|
+
def deep_const_get(const)
|
36
|
+
if Symbol === const
|
37
|
+
const = const.to_s
|
38
|
+
else
|
39
|
+
const = const.to_str.dup
|
40
|
+
end
|
41
|
+
if const.sub!(/^::/, '')
|
42
|
+
base = Object
|
43
|
+
else
|
44
|
+
base = self
|
45
|
+
end
|
46
|
+
const.split(/::/).inject(base) { |mod, name| mod.const_get(name) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
ExtensionsProject.implement(Module, :by_name, :class) do
|
53
|
+
class Module
|
54
|
+
#
|
55
|
+
# <em>Note: the following documentation uses "class" because it's more common, but it
|
56
|
+
# applies to modules as well.</em>
|
57
|
+
#
|
58
|
+
# Given the _name_ of a class, returns the class itself (i.e. instance of Class). The
|
59
|
+
# dereferencing starts at Object. That is,
|
60
|
+
#
|
61
|
+
# Class.by_name("String")
|
62
|
+
#
|
63
|
+
# is equivalent to
|
64
|
+
#
|
65
|
+
# Object.get_const("String")
|
66
|
+
#
|
67
|
+
# The parameter _name_ is expected to be a Symbol or String, or at least to respond to
|
68
|
+
# <tt>to_str</tt>.
|
69
|
+
#
|
70
|
+
# An ArgumentError is raised if _name_ does not correspond to an existing class. If _name_
|
71
|
+
# is not even a valid class name, the error you'll get is not defined.
|
72
|
+
#
|
73
|
+
# Examples:
|
74
|
+
#
|
75
|
+
# Class.by_name("String") # -> String
|
76
|
+
# Class.by_name("::String") # -> String
|
77
|
+
# Class.by_name("Process::Sys") # -> Process::Sys
|
78
|
+
# Class.by_name("GorillaZ") # -> (ArgumentError)
|
79
|
+
#
|
80
|
+
# Class.by_name("Enumerable") # -> Enumerable
|
81
|
+
# Module.by_name("Enumerable") # -> Enumerable
|
82
|
+
#
|
83
|
+
def Module.by_name(name)
|
84
|
+
if Symbol === name
|
85
|
+
name = name.to_s
|
86
|
+
else
|
87
|
+
name = name.to_str
|
88
|
+
end
|
89
|
+
result = Object.deep_const_get(name)
|
90
|
+
if result.is_a? Module
|
91
|
+
return result
|
92
|
+
else
|
93
|
+
raise ArgumentError, "#{name} is not a class or module"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
ExtensionsProject.implement(Module, :basename) do
|
101
|
+
class Module
|
102
|
+
#
|
103
|
+
# Returns the immediate name of the class/module, stripped of any containing classes or
|
104
|
+
# modules. Compare Ruby's builtin methods <tt>Module#name</tt> and <tt>File.basename</tt>.
|
105
|
+
#
|
106
|
+
# Process::Sys.name # -> "Process::Sys"
|
107
|
+
# Process::Sys.basename # -> "Sys"
|
108
|
+
# String.basename # -> "String"
|
109
|
+
#
|
110
|
+
def basename
|
111
|
+
self.name.sub(/^.*::/, '')
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|