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.
Files changed (51) hide show
  1. data/AUTHORS +14 -4
  2. data/ChangeLog +192 -1
  3. data/README.og +2 -1
  4. data/RELEASES.og +35 -0
  5. data/Rakefile +1 -1
  6. data/examples/og/mock_example.rb +6 -9
  7. data/examples/og/mysql_to_psql.rb +100 -0
  8. data/examples/og/run.rb +8 -17
  9. data/lib/glue/array.rb +1 -1
  10. data/lib/glue/attribute.rb +86 -0
  11. data/lib/glue/cache.rb +1 -1
  12. data/lib/glue/hash.rb +1 -1
  13. data/lib/glue/inflector.rb +1 -1
  14. data/lib/glue/logger.rb +118 -18
  15. data/lib/glue/mixins.rb +1 -1
  16. data/lib/glue/number.rb +1 -1
  17. data/lib/glue/pool.rb +1 -1
  18. data/lib/glue/property.rb +48 -31
  19. data/lib/glue/string.rb +1 -1
  20. data/lib/glue/time.rb +2 -2
  21. data/lib/glue/validation.rb +400 -0
  22. data/lib/glue.rb +7 -8
  23. data/lib/og/backend.rb +47 -46
  24. data/lib/og/backends/mysql.rb +64 -63
  25. data/lib/og/backends/psql.rb +73 -72
  26. data/lib/og/connection.rb +7 -8
  27. data/lib/og/enchant.rb +80 -0
  28. data/lib/og/meta.rb +21 -21
  29. data/lib/og/mock.rb +31 -88
  30. data/lib/og/version.rb +6 -5
  31. data/lib/og.rb +95 -129
  32. data/test/tc_og.rb +3 -3
  33. data/vendor/extensions/_base.rb +153 -0
  34. data/vendor/extensions/_template.rb +36 -0
  35. data/vendor/extensions/all.rb +21 -0
  36. data/vendor/extensions/array.rb +68 -0
  37. data/vendor/extensions/binding.rb +224 -0
  38. data/vendor/extensions/class.rb +50 -0
  39. data/vendor/extensions/continuation.rb +71 -0
  40. data/vendor/extensions/enumerable.rb +250 -0
  41. data/vendor/extensions/hash.rb +23 -0
  42. data/vendor/extensions/io.rb +58 -0
  43. data/vendor/extensions/kernel.rb +42 -0
  44. data/vendor/extensions/module.rb +114 -0
  45. data/vendor/extensions/numeric.rb +230 -0
  46. data/vendor/extensions/object.rb +164 -0
  47. data/vendor/extensions/ostruct.rb +41 -0
  48. data/vendor/extensions/string.rb +316 -0
  49. data/vendor/extensions/symbol.rb +28 -0
  50. metadata +24 -4
  51. 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