og 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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