og 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +183 -0
- data/ChangeLog.1 +2344 -0
- data/README.og +4 -3
- data/RELEASES.og +15 -0
- data/Rakefile +135 -0
- data/examples/og/README +7 -0
- data/examples/og/mock_example.rb +58 -0
- data/examples/og/run.rb +9 -5
- data/lib/glue/property.rb +166 -107
- data/lib/glue/property.rb.old +307 -0
- data/lib/og.rb +17 -6
- data/lib/og/backend.rb +34 -4
- data/lib/og/backends/mysql.rb +3 -17
- data/lib/og/backends/psql.rb +5 -17
- data/lib/og/meta.rb +41 -26
- data/lib/og/mock.rb +223 -0
- data/lib/og/version.rb +2 -2
- data/test/og/tc_lifecycle.rb +107 -0
- data/test/tc_og.rb +31 -4
- metadata +22 -14
data/README.og
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
= Og 0.6.0
|
2
2
|
|
3
|
-
Og (ObjectGraph)
|
3
|
+
Nitro integrates the Og (ObjectGraph) object-relational mapping
|
4
4
|
library. Og provides transparent serialization of object graphs to a RDBMS
|
5
5
|
backend. Unlike other similar libraries Og maps standard Ruby
|
6
6
|
objects to SQL tables and not vice versa. Og provides a meta language
|
7
7
|
to describe the relations between objects, a flexible and intuitive api
|
8
8
|
for querieng the database, raw access to the SQL language if needed
|
9
9
|
(for example to fine tune the automatically generated SQL tables, or
|
10
|
-
for custom queries), suports deserialization to Ruby objects or tuples
|
10
|
+
for custom queries), suports deserialization to Ruby objects or tuples,
|
11
|
+
automatically generates join tables for many_to_many relations
|
11
12
|
and provides a collection of usefull Mixins to synthesize common
|
12
|
-
|
13
|
+
Entities.
|
13
14
|
|
14
15
|
Og is a combination of the best features of Active Record and the
|
15
16
|
former O-R mapping library included in Nitro (NDB). Adapters for
|
data/RELEASES.og
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== Version 0.7 was released on 27/12/2004.
|
2
|
+
|
3
|
+
A snapshot of the latest code. Many fixes and new features result
|
4
|
+
in a more mature product. Many thanks to the ruby hackers that sent
|
5
|
+
suggestions and patches used in this release!
|
6
|
+
|
7
|
+
Most notable additions:
|
8
|
+
|
9
|
+
* Totaly recoded prop_accessor mechanism, avoids polution of the Module
|
10
|
+
class.
|
11
|
+
* prop_accessors for Modules, allows synthesizing of managed objects
|
12
|
+
from Mixins.
|
13
|
+
* new automatically generated methods in Og.
|
14
|
+
* MockDatabase leverages the FlexMock object for easier unit testing.
|
15
|
+
|
1
16
|
== Version 0.6 was released on 13/12/2004.
|
2
17
|
|
3
18
|
This is a preview release, the api for the new features is not
|
data/Rakefile
ADDED
@@ -0,0 +1,135 @@
|
|
1
|
+
# code:
|
2
|
+
# * George Moschovitis <gm@navel.gr>
|
3
|
+
#
|
4
|
+
# (c) 2004 Navel, all rights reserved.
|
5
|
+
# $Id: connection.rb 71 2004-10-18 10:50:22Z gmosx $
|
6
|
+
|
7
|
+
require "rake"
|
8
|
+
require "rake/rdoctask"
|
9
|
+
require "rake/gempackagetask"
|
10
|
+
require "rake/testtask"
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
#project = 'nitro'
|
14
|
+
project = 'og'
|
15
|
+
|
16
|
+
# ----------------------------------------------------------------------
|
17
|
+
|
18
|
+
desc "Default Task"
|
19
|
+
task :default => :package
|
20
|
+
|
21
|
+
# ----------------------------------------------------------------------
|
22
|
+
|
23
|
+
# Run the tests
|
24
|
+
|
25
|
+
Rake::TestTask.new do |t|
|
26
|
+
t.libs << "test"
|
27
|
+
t.test_files = FileList["test/**/tc*.rb"].exclude("**/tc*og*.rb")
|
28
|
+
t.verbose = true
|
29
|
+
end
|
30
|
+
|
31
|
+
# Run all tests
|
32
|
+
|
33
|
+
Rake::TestTask.new(:test_all) do |t|
|
34
|
+
t.libs << "test"
|
35
|
+
t.test_files = FileList["test/**/tc*.rb"]
|
36
|
+
t.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
# ----------------------------------------------------------------------
|
40
|
+
|
41
|
+
Rake::RDocTask.new do |rd|
|
42
|
+
rd.main = "README"
|
43
|
+
rd.rdoc_dir = "rdoc"
|
44
|
+
rd.rdoc_files.include("README", "lib/**/*.rb")
|
45
|
+
end
|
46
|
+
|
47
|
+
# ----------------------------------------------------------------------
|
48
|
+
|
49
|
+
if 'nitro' == project
|
50
|
+
|
51
|
+
# Nitro GemSpec
|
52
|
+
#
|
53
|
+
require "lib/nitro/version"
|
54
|
+
|
55
|
+
PKG_VERSION = $srv_version
|
56
|
+
PKG_FILES = FileList[
|
57
|
+
"[A-Z]*", "{bin,benchmark,etc,ext,examples,doc,lib,test,vendor}/**/*"
|
58
|
+
# "examples/*.rb"
|
59
|
+
].exclude(".svn/**/*").exclude("*.og").exclude("**/*.log")
|
60
|
+
|
61
|
+
spec = Gem::Specification.new do |s|
|
62
|
+
s.name = "nitro"
|
63
|
+
s.version = PKG_VERSION
|
64
|
+
s.summary = "Web Engine"
|
65
|
+
s.description = "An efficient, yet simple engine for Web Applications"
|
66
|
+
# s.add_dependency("postgres-pr", ">= 0.3.0")
|
67
|
+
# s.add_dependency("postgres", ">= 0.7.1")
|
68
|
+
# s.add_dependency("extensions", ">= 0.5")
|
69
|
+
s.required_ruby_version = ">= 1.8.1"
|
70
|
+
s.files = PKG_FILES.to_a
|
71
|
+
s.require_path = "lib"
|
72
|
+
s.autorequire = "nitro"
|
73
|
+
s.has_rdoc = true
|
74
|
+
s.extra_rdoc_files = FileList["[A-Z]*"].exclude("*.og").to_a
|
75
|
+
s.rdoc_options << "--main" << "README" << "--title" << "Nitro Documentation"
|
76
|
+
s.test_files = []
|
77
|
+
s.bindir = "bin"
|
78
|
+
s.author = "George Moschovitis"
|
79
|
+
s.email = "gm@navel.gr"
|
80
|
+
s.homepage = "http://www.navel.gr/nitro"
|
81
|
+
s.rubyforge_project = "nitro"
|
82
|
+
end
|
83
|
+
|
84
|
+
else
|
85
|
+
|
86
|
+
# Og stand-alone GemSpec
|
87
|
+
#
|
88
|
+
require "lib/og/version"
|
89
|
+
|
90
|
+
PKG_VERSION = $og_version
|
91
|
+
PKG_FILES = FileList[
|
92
|
+
"README.og", "RELEASES.og", "LICENSE", "AUTHORS", "Rakefile", "ChangeLog*",
|
93
|
+
"examples/og/*", "lib/glue.rb", "lib/glue/**/*", "lib/og/**/*", "lib/og.rb",
|
94
|
+
"test/*og*.rb", "test/og/*"
|
95
|
+
].exclude(".svn/**/*").exclude("**/*.log")
|
96
|
+
|
97
|
+
spec = Gem::Specification.new do |s|
|
98
|
+
s.name = 'og'
|
99
|
+
s.version = PKG_VERSION
|
100
|
+
s.summary = 'Og (ObjectGraph)'
|
101
|
+
s.description = 'An efficient and transparent Object-Relational mapping library'
|
102
|
+
# s.add_dependency("postgres", ">= 0.7.1")
|
103
|
+
# s.add_dependency("extensions", ">= 0.5")
|
104
|
+
# s.add_dependency("builder")
|
105
|
+
s.required_ruby_version = ">= 1.8.1"
|
106
|
+
s.files = PKG_FILES.to_a
|
107
|
+
s.require_path = "lib"
|
108
|
+
s.autorequire = "og"
|
109
|
+
s.has_rdoc = true
|
110
|
+
s.extra_rdoc_files = FileList["README.og", "RELEASES.og", "LICENSE", "AUTHORS"].to_a
|
111
|
+
s.rdoc_options << "--main" << "README.og" << "--title" << "Og Documentation"
|
112
|
+
s.test_files = []
|
113
|
+
s.bindir = "bin"
|
114
|
+
s.author = "George Moschovitis"
|
115
|
+
s.email = "gm@navel.gr"
|
116
|
+
s.homepage = "http://www.navel.gr/og"
|
117
|
+
s.rubyforge_project = "og-rml"
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
123
|
+
pkg.package_dir = "dist"
|
124
|
+
pkg.need_zip = true
|
125
|
+
pkg.need_tar = true
|
126
|
+
end
|
127
|
+
|
128
|
+
# ----------------------------------------------------------------------
|
129
|
+
|
130
|
+
desc "Install the gem"
|
131
|
+
task :install => :repackage do
|
132
|
+
sh "gem install --local --no-rdoc dist/nitro-#{PKG_VERSION}.gem"
|
133
|
+
end
|
134
|
+
|
135
|
+
# vim: ft=ruby
|
data/examples/og/README
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
# = Og Mocking Example
|
2
|
+
#
|
3
|
+
# A simple example to demonstrate how to mock Og.
|
4
|
+
# Very useful in test units.
|
5
|
+
#
|
6
|
+
# code:
|
7
|
+
# * George Moschovitis <gm@navel.gr>
|
8
|
+
#
|
9
|
+
# (c) 2004 Navel, all rights reserved.
|
10
|
+
# $Id: run.rb 185 2004-12-10 13:29:09Z gmosx $
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift '../../lib'
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'flexmock'
|
16
|
+
require 'og'
|
17
|
+
require 'og/mock'
|
18
|
+
require 'logger'
|
19
|
+
|
20
|
+
$log = Logger.new($stderr)
|
21
|
+
|
22
|
+
class Article
|
23
|
+
prop_accessor :body, String
|
24
|
+
|
25
|
+
def initialize(body = nil)
|
26
|
+
@body = body
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class SimpleTest < Test::Unit::TestCase
|
31
|
+
|
32
|
+
def setup
|
33
|
+
$og = Og::MockDatabase.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def teardown
|
37
|
+
$og = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_me
|
41
|
+
mocks = [
|
42
|
+
Article.new('body1'),
|
43
|
+
Article.new('body2'),
|
44
|
+
Article.new('body3')
|
45
|
+
]
|
46
|
+
$og.mock_handle(:load_all) { |klass, extrasql| mocks }
|
47
|
+
|
48
|
+
# differnt ways to call the mocked method...
|
49
|
+
puts 'Here are the articles:', Article.all
|
50
|
+
puts 'Here are the articles:', Article.load_all
|
51
|
+
puts 'Here are the articles:', $og.load_all(Article)
|
52
|
+
|
53
|
+
# 3 times called
|
54
|
+
assert_equal(3, $og.mock_count(:load_all))
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
data/examples/og/run.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# * George Moschovitis <gm@navel.gr>
|
7
7
|
#
|
8
8
|
# (c) 2004 Navel, all rights reserved.
|
9
|
-
# $Id: run.rb
|
9
|
+
# $Id: run.rb 198 2004-12-22 11:26:59Z gmosx $
|
10
10
|
|
11
11
|
$:.unshift "../../lib"
|
12
12
|
|
@@ -103,7 +103,7 @@ class Category
|
|
103
103
|
prop_accessor :body, String
|
104
104
|
|
105
105
|
# define a 'many to many' relation.
|
106
|
-
many_to_many Article
|
106
|
+
many_to_many :articles, Article
|
107
107
|
|
108
108
|
def initialize(title = nil)
|
109
109
|
@title = title
|
@@ -141,7 +141,6 @@ end
|
|
141
141
|
# Initialize a logger.
|
142
142
|
|
143
143
|
$log = Logger.new(STDERR);
|
144
|
-
|
145
144
|
# Og configuration.
|
146
145
|
config = {
|
147
146
|
:address => "localhost",
|
@@ -199,9 +198,11 @@ c2.article_oid = a1.oid
|
|
199
198
|
# managed objects).
|
200
199
|
$og << c2
|
201
200
|
|
201
|
+
# an alternative (easier and cooler) way to add children in a
|
202
|
+
# has_many relation:
|
202
203
|
c3 = ArticleComment.new("Comment 3")
|
203
|
-
|
204
|
-
c3
|
204
|
+
# add_comment is automatically added by Og.
|
205
|
+
a1.add_comment(c3)
|
205
206
|
|
206
207
|
puts "\n\n"
|
207
208
|
puts "* Print all all comments for article 1:"
|
@@ -287,4 +288,7 @@ puts '---'
|
|
287
288
|
|
288
289
|
article.categories.each { |c| puts c.title }
|
289
290
|
|
291
|
+
# create and save the article in one step.
|
292
|
+
article = Article.create("title", "body")
|
290
293
|
|
294
|
+
puts '--', article.oid
|
data/lib/glue/property.rb
CHANGED
@@ -2,10 +2,9 @@
|
|
2
2
|
# * George Moschovitis <gm@navel.gr>
|
3
3
|
# design:
|
4
4
|
# * Anastastios Koutoumanos <ak@navel.gr>
|
5
|
-
# * Elias Karakoulakis <ekarak@ktismata.com>
|
6
5
|
#
|
7
6
|
# (c) 2004 Navel, all rights reserved.
|
8
|
-
# $Id: property.rb
|
7
|
+
# $Id: property.rb 200 2004-12-27 11:24:41Z gmosx $
|
9
8
|
|
10
9
|
require "glue/array"
|
11
10
|
require "glue/hash"
|
@@ -25,10 +24,8 @@ module G
|
|
25
24
|
#
|
26
25
|
#--
|
27
26
|
# TODO:
|
28
|
-
# Inject only the really needd methods into Module.
|
29
27
|
# Perhaps a sync is needed in evals (!!!!)
|
30
28
|
#++
|
31
|
-
#
|
32
29
|
class Property
|
33
30
|
# the symbol of the property
|
34
31
|
attr_accessor :symbol
|
@@ -36,7 +33,7 @@ class Property
|
|
36
33
|
attr_accessor :name
|
37
34
|
# the class of the property
|
38
35
|
attr_accessor :klass
|
39
|
-
# additional metadata (like sql
|
36
|
+
# additional metadata (like sql declaration, sql index, etc)
|
40
37
|
attr_accessor :meta
|
41
38
|
|
42
39
|
def initialize(symbol, klass, meta = {})
|
@@ -52,6 +49,119 @@ class Property
|
|
52
49
|
def to_s
|
53
50
|
return name
|
54
51
|
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
# = PropertyUtils
|
56
|
+
#
|
57
|
+
# A collection of Property related utility methods.
|
58
|
+
#
|
59
|
+
module PropertyUtils
|
60
|
+
|
61
|
+
# Add accessors to the properties to the given target
|
62
|
+
# (Module or Class). For simplicity also create the
|
63
|
+
# meta accessors.
|
64
|
+
#--
|
65
|
+
# gmosx: Perhaps we 'll optimize this in the future.
|
66
|
+
#++
|
67
|
+
def self.enchant(target)
|
68
|
+
unless target.singleton_methods.include?('__props')
|
69
|
+
target.module_eval <<-"end_eval", __FILE__, __LINE__
|
70
|
+
@@__meta = G::SafeHash.new
|
71
|
+
@@__props = G::SafeArray.new
|
72
|
+
|
73
|
+
def self.__props
|
74
|
+
@@__props
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.__props=(props)
|
78
|
+
@@__props = props
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.__meta
|
82
|
+
@@__meta
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.__meta=(meta)
|
86
|
+
@@__meta = meta
|
87
|
+
end
|
88
|
+
end_eval
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Copy properties from src (Module or Class) to dest.
|
93
|
+
#
|
94
|
+
def self.copy_props(src, dest)
|
95
|
+
src.__props.each do |p|
|
96
|
+
add_prop(dest, p)
|
97
|
+
end
|
98
|
+
|
99
|
+
# copy the metadata.
|
100
|
+
src.__meta.each do |k, val|
|
101
|
+
val.each { |v| dest.meta(k, v) } if val
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Add the property to the target (Class or Module)
|
106
|
+
#
|
107
|
+
def self.add_prop(target, prop)
|
108
|
+
if idx = target.__props.index(prop)
|
109
|
+
# override in case of duplicates. Keep the order of the props.
|
110
|
+
target.__props[idx] = prop
|
111
|
+
else
|
112
|
+
target.__props << prop
|
113
|
+
end
|
114
|
+
|
115
|
+
# Precompile the property read/write methods
|
116
|
+
|
117
|
+
s, klass = prop.symbol, prop.klass
|
118
|
+
|
119
|
+
if prop.meta[:reader]
|
120
|
+
target.module_eval %{
|
121
|
+
def #{s}
|
122
|
+
return @#{s}
|
123
|
+
end
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
# gmosx: __force_xxx reuses xxx= to allow for easier
|
128
|
+
# overrides.
|
129
|
+
if prop.meta[:writer]
|
130
|
+
target.module_eval %{
|
131
|
+
#{prop_setter(prop)}
|
132
|
+
|
133
|
+
def __force_#{s}(val)
|
134
|
+
self.#{s}=(} + case klass.name
|
135
|
+
when Fixnum.name
|
136
|
+
"val.to_i()"
|
137
|
+
when String.name
|
138
|
+
"val.to_s()"
|
139
|
+
when Float.name
|
140
|
+
"val.to_f()"
|
141
|
+
when Time.name
|
142
|
+
"Time.parse(val.to_s())"
|
143
|
+
when TrueClass.name, FalseClass.name
|
144
|
+
"val.to_i() > 0"
|
145
|
+
else
|
146
|
+
"val"
|
147
|
+
end + %{)
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Generates the property setter code. Can be overriden
|
154
|
+
# to support extra functionality (example: markup)
|
155
|
+
#
|
156
|
+
def self.prop_setter(prop)
|
157
|
+
s = prop.symbol
|
158
|
+
%{
|
159
|
+
def #{s}=(val)
|
160
|
+
@#{s} = val
|
161
|
+
end
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
55
165
|
end
|
56
166
|
|
57
167
|
end # module
|
@@ -90,36 +200,55 @@ class Module
|
|
90
200
|
end
|
91
201
|
end
|
92
202
|
|
93
|
-
|
94
|
-
eval %{
|
95
|
-
# Properties
|
96
|
-
# An array is used to enforce order.
|
97
|
-
def __props
|
98
|
-
@__props
|
99
|
-
end
|
203
|
+
G::PropertyUtils.enchant(self)
|
100
204
|
|
101
|
-
|
102
|
-
|
205
|
+
if self.is_a?(Class)
|
206
|
+
|
207
|
+
# Add some extra code to append features to
|
208
|
+
# subclasses.
|
209
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
210
|
+
|
211
|
+
def self.inherited(sub)
|
212
|
+
G::PropertyUtils.enchant(sub)
|
213
|
+
G::PropertyUtils.copy_props(self, sub)
|
214
|
+
# gmosx: We have to define @@__props first to avoid reusing
|
215
|
+
# the hash from the module. super must stay at the end.
|
216
|
+
super
|
103
217
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
218
|
+
|
219
|
+
end_eval
|
220
|
+
|
221
|
+
else
|
222
|
+
|
223
|
+
# Add some extra code for modules to append
|
224
|
+
# their features to classes that include it.
|
225
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
226
|
+
|
227
|
+
def self.append_features(base)
|
228
|
+
G::PropertyUtils.enchant(base)
|
229
|
+
G::PropertyUtils.copy_props(self, base)
|
230
|
+
# gmosx: We have to define @@__props first to avoid reusing
|
231
|
+
# the hash from the module. super must stay at the end.
|
232
|
+
super
|
107
233
|
end
|
108
234
|
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
}
|
235
|
+
end_eval
|
236
|
+
|
113
237
|
end
|
114
|
-
|
115
|
-
@__props = G::SafeArray.new() unless @__props
|
116
|
-
|
238
|
+
|
117
239
|
property = G::Property.new(symbol, klass, meta)
|
118
240
|
|
119
241
|
reader = meta[:reader] || true
|
120
242
|
writer = writer || meta[:writer] || false
|
121
|
-
|
122
|
-
|
243
|
+
|
244
|
+
meta[:reader] = true if meta[:reader].nil?
|
245
|
+
if defined?(writer)
|
246
|
+
meta[:writer] = writer
|
247
|
+
else
|
248
|
+
meta[:writer] = true if meta[:writer].nil?
|
249
|
+
end
|
250
|
+
|
251
|
+
G::PropertyUtils.add_prop(self, property)
|
123
252
|
end
|
124
253
|
|
125
254
|
# Helper method. Accepts a collection of symbols and generates
|
@@ -218,90 +347,20 @@ class Module
|
|
218
347
|
end
|
219
348
|
end
|
220
349
|
|
221
|
-
# Add the property
|
222
|
-
#
|
223
|
-
def __add_prop(prop, reader = true, writer = true)
|
224
|
-
if idx = @__props.index(prop)
|
225
|
-
# override in case of duplicates. Keep the order of the props.
|
226
|
-
@__props[idx] = prop
|
227
|
-
else
|
228
|
-
@__props << prop
|
229
|
-
end
|
230
|
-
|
231
|
-
# Precompile the property read/write methods
|
232
|
-
|
233
|
-
s, klass = prop.symbol, prop.klass
|
234
|
-
|
235
|
-
if reader
|
236
|
-
module_eval %{
|
237
|
-
def #{s}
|
238
|
-
return @#{s}
|
239
|
-
end
|
240
|
-
}
|
241
|
-
end
|
242
|
-
|
243
|
-
# gmosx: __force_xxx reuses xxx= to allow for easier
|
244
|
-
# overrides.
|
245
|
-
if writer
|
246
|
-
module_eval %{
|
247
|
-
def #{s}=(val)
|
248
|
-
@#{s} = val
|
249
|
-
end
|
250
|
-
|
251
|
-
def __force_#{s}(val)
|
252
|
-
self.#{s}=(} + case klass.name
|
253
|
-
when Fixnum.name
|
254
|
-
"val.to_i()"
|
255
|
-
when String.name
|
256
|
-
"val.to_s()"
|
257
|
-
when Float.name
|
258
|
-
"val.to_f()"
|
259
|
-
when Time.name
|
260
|
-
"Time.parse(val.to_s())"
|
261
|
-
when TrueClass.name, FalseClass.name
|
262
|
-
"val.to_i() > 0"
|
263
|
-
else
|
264
|
-
"val"
|
265
|
-
end + %{)
|
266
|
-
end
|
267
|
-
}
|
268
|
-
end
|
269
|
-
end
|
270
350
|
|
271
|
-
# Attach metadata
|
272
|
-
#
|
351
|
+
# Attach metadata.
|
352
|
+
# Guard against duplicates, no need to keep order.
|
353
|
+
# This method uses closures :)
|
354
|
+
#--
|
355
|
+
# gmosx: crappy implementation, recode.
|
356
|
+
#++
|
273
357
|
def meta(key, val)
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
@__meta[key].delete_if { |v| val == v }
|
280
|
-
@__meta[key] << val
|
358
|
+
self.module_eval <<-"end_eval", __FILE__, __LINE__
|
359
|
+
@@__meta[key] ||= []
|
360
|
+
@@__meta[key].delete_if { |v| val == v }
|
361
|
+
@@__meta[key] << val
|
362
|
+
end_eval
|
281
363
|
end
|
282
|
-
|
283
|
-
# This method is typically called before including other
|
284
|
-
# modules to preserve properties order.
|
285
|
-
#
|
286
|
-
def inherit_meta(mod = superclass)
|
287
|
-
# concat props.
|
288
|
-
if mod.__props
|
289
|
-
@__props = G::SafeArray.new unless @__props
|
290
|
-
|
291
|
-
mod.__props.each { |p|
|
292
|
-
__add_prop(p)
|
293
|
-
}
|
294
|
-
end
|
295
364
|
|
296
|
-
# concat metadata
|
297
|
-
if mod.__meta
|
298
|
-
mod.__meta.each { |k, val|
|
299
|
-
val.each { |v|
|
300
|
-
meta(k, v)
|
301
|
-
} if val
|
302
|
-
}
|
303
|
-
end
|
304
|
-
end
|
305
|
-
|
306
365
|
end
|
307
366
|
|