og 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,230 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/integer.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the builtin Numeric and Integer classes.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
|
10
|
+
#
|
11
|
+
# * Integer#even?
|
12
|
+
#
|
13
|
+
ExtensionsProject.implement(Integer, :even?) do
|
14
|
+
class Integer
|
15
|
+
#
|
16
|
+
# Returns true if this integer is even, false otherwise.
|
17
|
+
# 14.even? # -> true
|
18
|
+
# 15.even? # -> false
|
19
|
+
#
|
20
|
+
def even?
|
21
|
+
self % 2 == 0
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
#
|
28
|
+
# * Integer#odd?
|
29
|
+
#
|
30
|
+
ExtensionsProject.implement(Integer, :odd?) do
|
31
|
+
class Integer
|
32
|
+
#
|
33
|
+
# Returns true if this integer is odd, false otherwise.
|
34
|
+
# -99.odd? # -> true
|
35
|
+
# -98.odd? # -> false
|
36
|
+
#
|
37
|
+
def odd?
|
38
|
+
self % 2 == 1
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
# This code arose from discussions with Francis Hwang. Leaving it here for future work.
|
45
|
+
#
|
46
|
+
# class Numeric
|
47
|
+
# def precision_format(nplaces, flag = :pad)
|
48
|
+
# format = "%.#{nplaces}f"
|
49
|
+
# result = sprintf(format, self)
|
50
|
+
# case flag
|
51
|
+
# when :pad
|
52
|
+
# when :nopad
|
53
|
+
# result.sub!(/\.?0*$/, '')
|
54
|
+
# else
|
55
|
+
# raise ArgumentError, "Invalid value for flag: #{flag.inspect}"
|
56
|
+
# end
|
57
|
+
# result
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# 100.precision_format(2) # -> "100.00"
|
62
|
+
# 100.precision_format(2, :nopad) # -> "100"
|
63
|
+
# 100.1.precision_format(2) # -> "100.10"
|
64
|
+
# 100.1.precision_format(2, :nopad) # -> "100.1"
|
65
|
+
# 100.1.precision_format(2, false)
|
66
|
+
# # -> "ArgumentError: Invalid value for flag: false"
|
67
|
+
#
|
68
|
+
|
69
|
+
|
70
|
+
ExtensionsProject.implement(Numeric, :format_s) do
|
71
|
+
#--
|
72
|
+
# Copyright � 2003 Austin Ziegler
|
73
|
+
#
|
74
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
75
|
+
# of this software and associated documentation files (the "Software"), to
|
76
|
+
# deal in the Software without restriction, including without limitation the
|
77
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
78
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
79
|
+
# furnished to do so, subject to the following conditions:
|
80
|
+
#
|
81
|
+
# The above copyright notice and this permission notice shall be included in
|
82
|
+
# all copies or substantial portions of the Software.
|
83
|
+
#
|
84
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
85
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
86
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
87
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
88
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
89
|
+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
90
|
+
# IN THE SOFTWARE.
|
91
|
+
#++
|
92
|
+
class Numeric
|
93
|
+
#
|
94
|
+
# Provides the base formatting styles for #format_s. See #format_s for
|
95
|
+
# more details. Two keys provided that are not supported in the
|
96
|
+
# #format_s arguments are:
|
97
|
+
#
|
98
|
+
# <tt>:style</tt>:: Allows a style to inherit from other styles. Styles
|
99
|
+
# will be applied in oldest-first order in the event
|
100
|
+
# of multiple inheritance layers.
|
101
|
+
# <tt>:id</tt>:: This must be provided on any default style created
|
102
|
+
# or provided so as to provide a stop marker so that
|
103
|
+
# recursive styles do not result in an infinite loop.
|
104
|
+
#
|
105
|
+
# This is an implementation detail, not important for users of the class.
|
106
|
+
#
|
107
|
+
FORMAT_STYLES = {
|
108
|
+
:us => { :sep => ',', :dec => '.', :id => :us },
|
109
|
+
:usd => { :style => :us, :currency => { :id => "$", :pos => :before }, :id => :usd },
|
110
|
+
:eu => { :sep => ' ', :dec => ',', :id => :us },
|
111
|
+
:euro => { :style => :eu, :currency => { :id => "�", :pos => :before }, :id => :euro },
|
112
|
+
:percent => { :style => :us, :currency => { :id => "%%", :pos => :after }, :id => :percent }
|
113
|
+
}
|
114
|
+
|
115
|
+
#
|
116
|
+
# Format a number as a string, using US or European conventions, and
|
117
|
+
# allowing for the accounting format of representing negative numbers.
|
118
|
+
# Optionally, currency formatting options can be provided.
|
119
|
+
#
|
120
|
+
# For example:
|
121
|
+
# x = -10259.8937
|
122
|
+
# x.format_s # => "-10,259.8937"
|
123
|
+
# x.format_s(:us) # => "-10,259.8937"
|
124
|
+
# x.format_s(:usd) # => "$-10,259.8937"
|
125
|
+
# x.format_s(:eu) # => "-10 259,8937"
|
126
|
+
# x.format_s(:euro) # => "�-10 259,8937"
|
127
|
+
# x.format_s(:us, :acct => true) # => "(10,259.8937)"
|
128
|
+
# x.format_s(:eu, :acct => true) # => "(10 259,8937)"
|
129
|
+
# x.format_s(:usd, :acct => true) # => "$(10,259.8937)"
|
130
|
+
# x.format_s(:euro, :acct => true) # => "�(10 259,8937)"
|
131
|
+
# x.format_s(:percent) # => "-10,259.8937%"
|
132
|
+
#
|
133
|
+
# You may configure several aspects of the formatting by providing keyword
|
134
|
+
# arguments after the country and accounting arguments. One example of that
|
135
|
+
# is the :acct keyword. A more insane example is:
|
136
|
+
#
|
137
|
+
# x = -10259.8937
|
138
|
+
# x.format_s(:us,
|
139
|
+
# :sep => ' ', :dec => ',',
|
140
|
+
# :neg => '<%s>', :size => 2,
|
141
|
+
# :fd => true) # -> "<1 02 59,89 37>"
|
142
|
+
#
|
143
|
+
# The keyword parameters are as follows:
|
144
|
+
#
|
145
|
+
# <tt>:acct</tt>:: If +true+, then use accounting style for negative
|
146
|
+
# numbers. This overrides any value for
|
147
|
+
# <tt>:neg</tt>.
|
148
|
+
# <tt>:sep</tt>:: Default "," for US, " " for Euro. Separate the
|
149
|
+
# number groups from each other with this string.
|
150
|
+
# <tt>:dec</tt>:: Default "." for US, "," for Euro. Separate the
|
151
|
+
# number's integer part from the fractional part
|
152
|
+
# with this string.
|
153
|
+
# <tt>:neg</tt>:: Default <tt>"-%s"</tt>. The format string used to
|
154
|
+
# represent negative numbers. If <tt>:acct</tt> is
|
155
|
+
# +true+, this is set to <tt>"(%s)"</tt>.
|
156
|
+
# <tt>:size</tt>:: The number of digits per group. Defaults to
|
157
|
+
# thousands (3).
|
158
|
+
# <tt>:fd</tt>:: Indicates whether the decimal portion of the
|
159
|
+
# number should be formatted the same way as the
|
160
|
+
# integer portion of the number. ("fd" == "format
|
161
|
+
# decimal".) Defaults to +false+.
|
162
|
+
# <tt>:currency</tt>:: This is an optional hash with two keys,
|
163
|
+
# <tt>:id</tt> and <tt>:pos</tt>. <tt>:id</tt> is
|
164
|
+
# the string value of the currency (e.g.,
|
165
|
+
# <tt>"$"</tt>, <tt>"�"</tt>, <tt>"USD "</tt>);
|
166
|
+
# <tt>:pos</tt> is either <tt>:before</tt> or
|
167
|
+
# <tt>:after</tt>, referring to the position of the
|
168
|
+
# currency indicator. The default <tt>:pos</tt> is
|
169
|
+
# <tt>:before</tt>.
|
170
|
+
#
|
171
|
+
def format_s(style = :us, configs={})
|
172
|
+
style = FORMAT_STYLES[style].dup # Adopt US style by default.
|
173
|
+
|
174
|
+
# Deal with recursive styles.
|
175
|
+
if style[:style]
|
176
|
+
styles = []
|
177
|
+
s = style
|
178
|
+
while s[:style]
|
179
|
+
s = FORMAT_STYLES[s[:style]].dup
|
180
|
+
styles << s
|
181
|
+
break if s[:style] = s[:id]
|
182
|
+
end
|
183
|
+
styles.reverse_each { |s| style.merge!(s) }
|
184
|
+
end
|
185
|
+
# Merge the configured style.
|
186
|
+
style.merge!(configs)
|
187
|
+
|
188
|
+
sm = style[:sep] || ','
|
189
|
+
dp = style[:dec] || '.'
|
190
|
+
if style[:acct]
|
191
|
+
fmt = '(%s)'
|
192
|
+
else
|
193
|
+
fmt = style[:neg] || '-%s'
|
194
|
+
end
|
195
|
+
sz = style[:size] || 3
|
196
|
+
format_decimal = style[:fd]
|
197
|
+
ng = (self < 0)
|
198
|
+
fmt = "%s" if not ng
|
199
|
+
|
200
|
+
dec, frac = self.abs.to_s.split(/\./)
|
201
|
+
|
202
|
+
dec.reverse!
|
203
|
+
dec.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
|
204
|
+
dec.gsub!(/#{sm}$/, '')
|
205
|
+
dec.reverse!
|
206
|
+
|
207
|
+
if format_decimal and not frac.nil?
|
208
|
+
frac.gsub!(/\d{#{sz}}/) { |m| "#{m}#{sm}" }
|
209
|
+
frac.gsub!(/#{sm}$/, '')
|
210
|
+
end
|
211
|
+
|
212
|
+
if frac.nil?
|
213
|
+
val = dec
|
214
|
+
else
|
215
|
+
val = "#{dec}#{dp}#{frac}"
|
216
|
+
end
|
217
|
+
|
218
|
+
if style[:currency]
|
219
|
+
if style[:currency][:pos].nil? or style[:currency][:pos] == :before
|
220
|
+
fmt = "#{style[:currency][:id]}#{fmt}"
|
221
|
+
elsif style[:currency][:pos] == :after
|
222
|
+
fmt = "#{fmt}#{style[:currency][:id]}"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
fmt % val
|
227
|
+
end
|
228
|
+
end # class Numeric
|
229
|
+
end # ExtensionsProject.implement
|
230
|
+
|
@@ -0,0 +1,164 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
#
|
4
|
+
# == extensions/object.rb
|
5
|
+
#
|
6
|
+
# Adds methods to the builtin Object class.
|
7
|
+
#
|
8
|
+
|
9
|
+
require 'extensions/_base'
|
10
|
+
|
11
|
+
|
12
|
+
#
|
13
|
+
# Object#singleton_class
|
14
|
+
#
|
15
|
+
ExtensionsProject.implement(Object, :singleton_class) do
|
16
|
+
class Object
|
17
|
+
#
|
18
|
+
# Returns the singleton class associated with this object. How useful this
|
19
|
+
# is I don't know, but it's an idiom that has appeared on ruby-talk several
|
20
|
+
# times.
|
21
|
+
#
|
22
|
+
def singleton_class
|
23
|
+
class << self
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
#
|
32
|
+
# * Object.in?
|
33
|
+
# This has special treatment: it's included here and in enumerable.rb, so we don't
|
34
|
+
# want a warning if it's already defined.
|
35
|
+
#
|
36
|
+
unless Object.method_defined?(:in?)
|
37
|
+
ExtensionsProject.implement(Object, :in?) do
|
38
|
+
class Object
|
39
|
+
#
|
40
|
+
# Test this object for inclusion in a given collection.
|
41
|
+
#
|
42
|
+
# 45.in? (1...100) => true
|
43
|
+
#
|
44
|
+
# This method is contained in <tt>object.rb</tt> and
|
45
|
+
# <tt>enumerable.rb</tt>, because it logically belongs in both.
|
46
|
+
#
|
47
|
+
def in?(enumerable)
|
48
|
+
enumerable.include?(self)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
#
|
56
|
+
# * Object.not_nil?
|
57
|
+
#
|
58
|
+
ExtensionsProject.implement(Object, :not_nil?) do
|
59
|
+
class Object
|
60
|
+
#
|
61
|
+
# The opposite of <tt>#nil?</tt>.
|
62
|
+
#
|
63
|
+
# "hello".not_nil? # -> true
|
64
|
+
# nil.not_nil? # -> false
|
65
|
+
#
|
66
|
+
def not_nil?
|
67
|
+
not self.nil?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
#
|
74
|
+
# * Object.non_nil?
|
75
|
+
#
|
76
|
+
ExtensionsProject.implement(Object, :non_nil?) do
|
77
|
+
class Object
|
78
|
+
#
|
79
|
+
# The opposite of <tt>#nil?</tt>.
|
80
|
+
#
|
81
|
+
# "hello".non_nil? # -> true
|
82
|
+
# nil.non_nil? # -> false
|
83
|
+
#
|
84
|
+
def non_nil?
|
85
|
+
not self.nil?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
#
|
92
|
+
# Object#pp_s
|
93
|
+
#
|
94
|
+
ExtensionsProject.implement(Object, :pp_s) do
|
95
|
+
require 'pp'
|
96
|
+
require 'stringio'
|
97
|
+
class Object
|
98
|
+
#
|
99
|
+
# Returns a pretty-printed string of the object. Requires libraries +pp+ and
|
100
|
+
# +stringio+ from the Ruby standard library.
|
101
|
+
#
|
102
|
+
# The following code pretty-prints an object (much like +p+ plain-prints an
|
103
|
+
# object):
|
104
|
+
#
|
105
|
+
# pp object
|
106
|
+
#
|
107
|
+
# The following code captures the pretty-printing in +str+ instead of
|
108
|
+
# sending it to +STDOUT+.
|
109
|
+
#
|
110
|
+
# str = object.pp_s
|
111
|
+
#
|
112
|
+
def pp_s
|
113
|
+
pps = StringIO.new
|
114
|
+
PP.pp(self, pps)
|
115
|
+
pps.string
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# Object#pp_s
|
122
|
+
#
|
123
|
+
ExtensionsProject.implement(Object, :define_method) do
|
124
|
+
class Object
|
125
|
+
#
|
126
|
+
# Defines a singleton method on the object. For example, the following are
|
127
|
+
# equivalent (assume <tt>o = Object.new</tt>):
|
128
|
+
#
|
129
|
+
# def o.add(x, y)
|
130
|
+
# x + y
|
131
|
+
# end
|
132
|
+
#
|
133
|
+
# o.define_method(:add) do |x, y|
|
134
|
+
# x + y
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# The difference is that with <tt>define_method</tt>, you can use variables
|
138
|
+
# local to the _current_ scope.
|
139
|
+
#
|
140
|
+
# x = 5
|
141
|
+
# o.define_method(:add_x) do |n|
|
142
|
+
# x + n
|
143
|
+
# end
|
144
|
+
# o.add_x(11) # -> 16
|
145
|
+
#
|
146
|
+
# You can't define such a method as <tt>add_x</tt> above with <tt>def
|
147
|
+
# o.add_x; x + n; end</tt>, as +def+ introduces a new scope.
|
148
|
+
#
|
149
|
+
# There are three ways to provide the body of the method: with a block (as
|
150
|
+
# in both examples above), or with a +Proc+ or +Method+ object. See the
|
151
|
+
# built-in method <tt>Module#define_method</tt> for details.
|
152
|
+
#
|
153
|
+
# (This method is exactly equivalent to calling <tt>Module#define_method</tt>
|
154
|
+
# in the scope of the singleton class of the object.)
|
155
|
+
#
|
156
|
+
def define_method(*args, &block)
|
157
|
+
singleton_class = class << self; self; end
|
158
|
+
singleton_class.module_eval do
|
159
|
+
define_method(*args, &block)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
#
|
3
|
+
# == extensions/ostruct.rb
|
4
|
+
#
|
5
|
+
# Adds methods to the standard library's OpenStruct class.
|
6
|
+
#
|
7
|
+
|
8
|
+
require "extensions/_base"
|
9
|
+
require 'ostruct'
|
10
|
+
|
11
|
+
#
|
12
|
+
# * OpenStruct#initialize
|
13
|
+
#
|
14
|
+
ExtensionsProject.implement(OpenStruct, :initialize) do
|
15
|
+
class OpenStruct
|
16
|
+
alias old_initialize initialize
|
17
|
+
private :old_initialize
|
18
|
+
|
19
|
+
#
|
20
|
+
# Allows the initialization of an OpenStruct with a block:
|
21
|
+
#
|
22
|
+
# person = OpenStruct.new do |p|
|
23
|
+
# p.name = 'John Smith'
|
24
|
+
# p.gender = :M
|
25
|
+
# p.age = 71
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# You can still provide a hash for initialization purposes, and even combine
|
29
|
+
# the two approaches if you wish.
|
30
|
+
#
|
31
|
+
# person = OpenStruct.new(:name => 'John Smith', :age => 31) do |p|
|
32
|
+
# p.gender = :M
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
def initialize(*args) # :yield: self
|
36
|
+
old_initialize(*args)
|
37
|
+
yield self if block_given?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|