nitro 0.8.0 → 0.9.3

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 (198) hide show
  1. data/AUTHORS +3 -4
  2. data/ChangeLog +418 -0
  3. data/LICENSE +1 -1
  4. data/README +157 -89
  5. data/RELEASES +50 -0
  6. data/Rakefile +5 -7
  7. data/benchmark/nitro/bench.rb +5 -0
  8. data/benchmark/nitro/simple-webrick-n-200.txt +44 -0
  9. data/benchmark/nitro/static-webrick-n-200.txt +43 -0
  10. data/benchmark/nitro/tiny-lhttpd-n-200-c-5.txt +43 -0
  11. data/benchmark/nitro/tiny-webrick-n-200-c-5.txt +44 -0
  12. data/benchmark/nitro/tiny-webrick-n-200.txt +44 -0
  13. data/benchmark/nitro/tiny2-webrick-n-200.txt +44 -0
  14. data/{lib/nitro/server/cluster.rb → bin/cluster} +26 -30
  15. data/bin/proto/README +2 -2
  16. data/bin/proto/{apache.conf → conf/apache.conf} +0 -0
  17. data/bin/proto/conf/app.conf.rb +22 -0
  18. data/bin/proto/conf/lhttpd.conf +236 -0
  19. data/bin/proto/ctl +4 -0
  20. data/bin/proto/lib/README +5 -0
  21. data/bin/proto/log/README +3 -0
  22. data/bin/proto/root/fcgi.rb +6 -0
  23. data/bin/proto/root/index.xhtml +65 -7
  24. data/bin/proto/root/m/nitro.png +0 -0
  25. data/examples/blog/README +7 -5
  26. data/examples/blog/{apache.conf → conf/apache.conf} +0 -0
  27. data/examples/blog/conf/app.conf.rb +56 -0
  28. data/examples/blog/conf/lhttpd.conf +236 -0
  29. data/examples/blog/ctl +4 -0
  30. data/examples/blog/lib/blog.rb +11 -136
  31. data/examples/blog/lib/blog/controller.rb +99 -0
  32. data/examples/blog/lib/blog/model.rb +39 -0
  33. data/examples/blog/log/README +3 -0
  34. data/examples/blog/root/comments.xhtml +2 -2
  35. data/examples/blog/root/fcgi.rb +6 -0
  36. data/examples/blog/root/index.xhtml +4 -5
  37. data/examples/blog/root/login.xhtml +2 -2
  38. data/examples/blog/root/style.xsl +9 -9
  39. data/examples/blog/root/view_entry.xhtml +2 -2
  40. data/examples/flash/conf/app.conf.rb +23 -0
  41. data/examples/flash/ctl +4 -0
  42. data/examples/flash/log/README +3 -0
  43. data/examples/flash/root/index.xhtml +0 -9
  44. data/examples/flash/root/show_inline_text.xhtml +10 -5
  45. data/examples/no_xsl_blog/README +12 -0
  46. data/examples/no_xsl_blog/conf/apache.conf +0 -0
  47. data/examples/no_xsl_blog/conf/app.conf.rb +57 -0
  48. data/examples/no_xsl_blog/conf/lhttpd.conf +236 -0
  49. data/examples/no_xsl_blog/ctl +4 -0
  50. data/examples/no_xsl_blog/lib/blog.rb +20 -0
  51. data/examples/no_xsl_blog/lib/blog/controller.rb +102 -0
  52. data/examples/no_xsl_blog/lib/blog/model.rb +39 -0
  53. data/examples/no_xsl_blog/lib/blog/template.rb +134 -0
  54. data/examples/no_xsl_blog/log/README +3 -0
  55. data/examples/no_xsl_blog/root/comments.xhtml +41 -0
  56. data/examples/no_xsl_blog/root/entry_form.xhtml +22 -0
  57. data/examples/no_xsl_blog/root/fcgi.rb +6 -0
  58. data/examples/no_xsl_blog/root/index.xhtml +39 -0
  59. data/examples/no_xsl_blog/root/login.xhtml +21 -0
  60. data/examples/no_xsl_blog/root/m/bubbles.gif +0 -0
  61. data/examples/no_xsl_blog/root/m/comments_curve.gif +0 -0
  62. data/examples/no_xsl_blog/root/m/down.gif +0 -0
  63. data/examples/no_xsl_blog/root/m/footer_bg.gif +0 -0
  64. data/examples/no_xsl_blog/root/m/garrow.gif +0 -0
  65. data/examples/no_xsl_blog/root/m/gbull.gif +0 -0
  66. data/examples/no_xsl_blog/root/m/grbull.gif +0 -0
  67. data/examples/no_xsl_blog/root/m/h1_bg.gif +0 -0
  68. data/examples/no_xsl_blog/root/m/header_bg.gif +0 -0
  69. data/examples/no_xsl_blog/root/m/nitro.gif +0 -0
  70. data/examples/no_xsl_blog/root/m/obull.gif +0 -0
  71. data/examples/no_xsl_blog/root/m/page_bg.gif +0 -0
  72. data/examples/no_xsl_blog/root/m/rss.gif +0 -0
  73. data/examples/no_xsl_blog/root/m/side_title_bg.gif +0 -0
  74. data/examples/no_xsl_blog/root/m/sidebar_bg.gif +0 -0
  75. data/examples/no_xsl_blog/root/recent_posts.xhtml +14 -0
  76. data/examples/no_xsl_blog/root/style.css +301 -0
  77. data/examples/no_xsl_blog/root/view_entry.xhtml +25 -0
  78. data/examples/no_xsl_blog/root/view_entry.xml +12 -0
  79. data/examples/og/run.rb +2 -2
  80. data/examples/tiny/README +2 -2
  81. data/examples/tiny/conf/apache.conf +5 -0
  82. data/examples/tiny/conf/app.conf.rb +21 -0
  83. data/examples/tiny/conf/lhttpd.conf +236 -0
  84. data/examples/tiny/ctl +4 -0
  85. data/examples/tiny/log/README +3 -0
  86. data/examples/tiny/root/fcgi.rb +6 -0
  87. data/examples/tiny/root/index.xhtml +7 -4
  88. data/examples/tiny/root/nitro.png +0 -0
  89. data/lib/glue.rb +13 -9
  90. data/lib/glue/array.rb +1 -1
  91. data/lib/glue/cache.rb +1 -1
  92. data/lib/glue/flexob.rb +12 -0
  93. data/lib/glue/hash.rb +1 -1
  94. data/lib/glue/inflector.rb +2 -2
  95. data/lib/glue/logger.rb +4 -8
  96. data/lib/glue/misc.rb +14 -0
  97. data/lib/glue/number.rb +1 -1
  98. data/lib/glue/object.rb +26 -0
  99. data/lib/glue/pool.rb +1 -1
  100. data/lib/glue/property.rb +84 -91
  101. data/lib/glue/string.rb +1 -1
  102. data/lib/glue/time.rb +1 -1
  103. data/lib/glue/validation.rb +1 -1
  104. data/lib/nitro.rb +18 -6
  105. data/lib/nitro/adaptors/cgi.rb +291 -0
  106. data/lib/nitro/adaptors/fastcgi.rb +42 -0
  107. data/lib/nitro/adaptors/runner.rb +123 -0
  108. data/lib/nitro/adaptors/webrick.rb +110 -0
  109. data/lib/nitro/buffering.rb +43 -0
  110. data/lib/nitro/builders/form.rb +1 -1
  111. data/lib/nitro/builders/rss.rb +1 -1
  112. data/{bin → lib/nitro}/cluster.rb +26 -30
  113. data/lib/nitro/context.rb +82 -0
  114. data/lib/nitro/controller.rb +50 -0
  115. data/lib/nitro/cookie.rb +46 -0
  116. data/lib/nitro/dispatcher.rb +105 -0
  117. data/lib/nitro/filters.rb +9 -10
  118. data/lib/nitro/localization.rb +42 -0
  119. data/lib/nitro/mail.rb +11 -14
  120. data/lib/nitro/render.rb +275 -0
  121. data/lib/nitro/request.rb +128 -0
  122. data/lib/nitro/response.rb +38 -0
  123. data/lib/nitro/scaffold.rb +11 -11
  124. data/lib/nitro/session.rb +84 -0
  125. data/lib/nitro/{server/shaders.rb → shaders.rb} +56 -36
  126. data/lib/nitro/ui/pager.rb +23 -26
  127. data/lib/nitro/{sitemap.rb → ui/sitemap.rb} +4 -12
  128. data/lib/nitro/uri.rb +1 -1
  129. data/lib/nitro/version.rb +10 -8
  130. data/lib/og.rb +66 -65
  131. data/lib/og/backend.rb +1 -1
  132. data/lib/og/backends/mysql.rb +48 -52
  133. data/lib/og/backends/psql.rb +34 -37
  134. data/lib/og/connection.rb +15 -15
  135. data/lib/og/enchant.rb +16 -9
  136. data/lib/og/meta.rb +127 -54
  137. data/lib/og/mock.rb +18 -18
  138. data/lib/og/version.rb +6 -4
  139. data/lib/parts/content.rb +4 -8
  140. data/test/glue/tc_logger.rb +3 -0
  141. data/test/glue/tc_property.rb +19 -3
  142. data/test/nitro/adaptors/tc_cgi.rb +63 -0
  143. data/test/nitro/adaptors/tc_webrick.rb +15 -0
  144. data/test/nitro/builders/tc_xml.rb +2 -2
  145. data/test/nitro/tc_context.rb +13 -0
  146. data/test/nitro/tc_controller.rb +47 -0
  147. data/test/nitro/tc_dispatcher.rb +64 -0
  148. data/test/nitro/tc_session.rb +20 -0
  149. data/test/nitro/{tc_sitemap.rb → ui/tc_sitemap.rb} +1 -1
  150. data/test/root/blog/list.xhtml +6 -0
  151. data/test/tc_og.rb +41 -4
  152. metadata +115 -59
  153. data/bin/proto/app.rb +0 -20
  154. data/bin/proto/config.rb +0 -77
  155. data/examples/blog/app.rb +0 -21
  156. data/examples/blog/config.rb +0 -95
  157. data/examples/blog/env.rb +0 -22
  158. data/examples/flash/README +0 -34
  159. data/examples/flash/app.rb +0 -20
  160. data/examples/flash/config.rb +0 -38
  161. data/examples/flash/lib/flash.rb +0 -40
  162. data/examples/flash/tmp.swf +0 -0
  163. data/examples/tiny/app.rb +0 -19
  164. data/examples/tiny/config.rb +0 -29
  165. data/examples/tiny/root/nitro-small.png +0 -0
  166. data/lib/nitro/application.rb +0 -217
  167. data/lib/nitro/config.rb +0 -128
  168. data/lib/nitro/events.rb +0 -122
  169. data/lib/nitro/html.rb +0 -151
  170. data/lib/nitro/http.rb +0 -102
  171. data/lib/nitro/l10n.rb +0 -30
  172. data/lib/nitro/server.rb +0 -59
  173. data/lib/nitro/server/appserver.rb +0 -67
  174. data/lib/nitro/server/cookie.rb +0 -87
  175. data/lib/nitro/server/dispatcher.rb +0 -62
  176. data/lib/nitro/server/filters.rb +0 -75
  177. data/lib/nitro/server/filters/autologin.rb +0 -51
  178. data/lib/nitro/server/fragment.rb +0 -70
  179. data/lib/nitro/server/handlers.rb +0 -127
  180. data/lib/nitro/server/render.rb +0 -426
  181. data/lib/nitro/server/request.rb +0 -658
  182. data/lib/nitro/server/requestpart.rb +0 -54
  183. data/lib/nitro/server/script.rb +0 -387
  184. data/lib/nitro/server/server.rb +0 -57
  185. data/lib/nitro/server/session.rb +0 -220
  186. data/lib/nitro/server/user.rb +0 -46
  187. data/lib/nitro/server/webrick.rb +0 -180
  188. data/lib/nitro/service.rb +0 -26
  189. data/lib/xsl/ui.xsl +0 -51
  190. data/lib/xsl/xforms.xsl +0 -28
  191. data/test/nitro/server/tc_cookie.rb +0 -34
  192. data/test/nitro/server/tc_filters.rb +0 -38
  193. data/test/nitro/server/tc_request.rb +0 -70
  194. data/test/nitro/server/tc_requestpart.rb +0 -28
  195. data/test/nitro/server/tc_session.rb +0 -34
  196. data/test/nitro/tc_events.rb +0 -44
  197. data/test/nitro/tc_html.rb +0 -79
  198. data/test/nitro/tc_http.rb +0 -18
@@ -1,17 +1,15 @@
1
- # code:
2
- # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
5
- # $Id: connection.rb 167 2004-11-23 14:03:10Z gmosx $
1
+ #--
2
+ # George Moschovitis <gm@navel.gr>
3
+ # (c) 2004-2005 Navel, all rights reserved.
4
+ # $Id: connection.rb 248 2005-01-31 13:38:34Z gmosx $
5
+ #++
6
6
 
7
7
  class Og;
8
8
 
9
- require "glue/property"
10
- require "glue/array"
11
- require "glue/time"
9
+ require 'glue/property'
10
+ require 'glue/array'
11
+ require 'glue/time'
12
12
 
13
- # = Connection
14
- #
15
13
  # A Connection to the Database. This file defines the skeleton
16
14
  # functionality. A backend specific implementation file (driver)
17
15
  # implements all methods.
@@ -20,20 +18,23 @@ require "glue/time"
20
18
  #
21
19
  # - support caching.
22
20
  # - support prepared statements.
23
- #
21
+
24
22
  class Connection
25
23
  # The frontend (Og) contains useful strucutres.
24
+
26
25
  attr_reader :og
27
26
 
28
27
  # The backend
28
+
29
29
  attr_reader :db
30
30
 
31
31
  # If set to true, the select methods deserialize the
32
32
  # resultset to create entities.
33
+
33
34
  attr_accessor :deserialize
34
35
 
35
36
  # Initialize a connection to the database
36
- #
37
+
37
38
  def initialize(og)
38
39
  @og = og
39
40
  @db = @og.config[:backend].new(@og.config)
@@ -189,9 +190,8 @@ class Connection
189
190
  # TODO: implement this as stored procedure? naaah.
190
191
  transaction do |tx|
191
192
  tx.exec "DELETE FROM #{klass::DBTABLE} WHERE oid=#{oid}"
192
-
193
- if cascade and klass.respond_to?(:og_descendants)
194
- klass.og_descendants.each do |dclass, linkback|
193
+ if cascade and klass.__meta.include?(:has)
194
+ klass.__meta[:has].each do |dclass, linkback|
195
195
  tx.exec "DELETE FROM #{dclass::DBTABLE} WHERE #{linkback}=#{oid}"
196
196
  end
197
197
  end
@@ -1,20 +1,18 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
2
+ # (c) 2004-2005 Navel, all rights reserved.
5
3
  # $Id: meta.rb 198 2004-12-22 11:26:59Z gmosx $
6
4
 
7
5
  class Og
8
6
 
9
7
  module Enchant
10
8
 
11
- # Enchant a managed class. Add useful DB related methods to the
12
- # class and its instances.
13
- #
9
+ # Enchant a managed class. Add useful DB related methods
10
+ # to the class and its instances.
11
+
14
12
  def enchant(klass)
15
13
  klass.module_eval <<-"end_eval", __FILE__, __LINE__
16
- def self.create(*params)
17
- obj = #{klass}.new(*params)
14
+ def self.create(*params, &block)
15
+ obj = #{klass}.new(*params, &block)
18
16
  obj.save!
19
17
  end
20
18
 
@@ -26,6 +24,10 @@ module Enchant
26
24
  Og.db.load(oid_or_name, #{klass})
27
25
  end
28
26
 
27
+ def self.get(oid_or_name)
28
+ Og.db.load(oid_or_name, #{klass})
29
+ end
30
+
29
31
  def self.[](oid_or_name)
30
32
  Og.db.load(oid_or_name, #{klass})
31
33
  end
@@ -57,6 +59,11 @@ module Enchant
57
59
  def self.delete(obj_or_oid)
58
60
  Og.db.delete(obj_or_oid, #{klass})
59
61
  end
62
+
63
+ def each(&block)
64
+ all.each(&block)
65
+ end
66
+ include Enumerable
60
67
 
61
68
  def save
62
69
  Og.db << self
@@ -77,4 +84,4 @@ module Enchant
77
84
 
78
85
  end
79
86
 
80
- end # namespace
87
+ end
@@ -1,8 +1,6 @@
1
- # code:
2
1
  # * George Moschovitis <gm@navel.gr>
3
- #
4
- # (c) 2004 Navel, all rights reserved.
5
- # $Id: meta.rb 198 2004-12-22 11:26:59Z gmosx $
2
+ # (c) 2004-2005 Navel, all rights reserved.
3
+ # $Id: meta.rb 248 2005-01-31 13:38:34Z gmosx $
6
4
 
7
5
  require 'og/backend'
8
6
  require 'glue/inflector'
@@ -12,18 +10,42 @@ class Og
12
10
  # = MetaUtils
13
11
  #
14
12
  # Some useful meta-language utilities.
15
- #
13
+
16
14
  module MetaUtils # :nodoc: all
17
15
 
18
- # Conver the klass to a string representation
16
+ # Convert the klass to a string representation
19
17
  # The leading module if available is removed.
20
18
  #--
21
19
  # gmosx, FIXME: unify with the ogutils.encode method?
22
20
  #++
21
+
23
22
  def self.expand(klass)
24
23
  return klass.name.gsub(/^.*::/, '').gsub(/::/, '_').downcase
25
24
  end
26
25
 
26
+ # Infer the target klass for a relation. When defining
27
+ # relations, tha target class is typically given. Some times
28
+ # in order to avoid forward declarations a symbol is given instead
29
+ # of a class. Other times on class is given at all, and
30
+ # the inflection mechanism is used to infer the class name.
31
+
32
+ def self.resolve_class(name, klass)
33
+ klass ||= N::Inflector.camelize(name)
34
+
35
+ return klass if klass.is_a?(Class)
36
+
37
+ unless klass.is_a?(String) or klass.is_a?(Symbol)
38
+ raise 'Invalid class definition'
39
+ end
40
+
41
+ unless Object.const_get(klass.intern)
42
+ # Forward declaration.
43
+ Object.class_eval("class #{klass}; end")
44
+ end
45
+
46
+ return Object.const_get(klass)
47
+ end
48
+
27
49
  end
28
50
 
29
51
  # = MetaLanguage
@@ -33,11 +55,12 @@ end
33
55
  # from the excellent ActiveRecord library.
34
56
  #
35
57
  # Many more useful relations will be available soon.
36
- #
58
+
37
59
  module MetaLanguage
38
60
 
39
- # Defines an SQL index.
40
- #
61
+ # Defines an SQL index. Useful for defining indiced
62
+ # over multiple columns.
63
+
41
64
  def sql_index(index, options = {})
42
65
  meta :sql_index, [index, options]
43
66
  end
@@ -56,12 +79,14 @@ module MetaLanguage
56
79
  # prop_accessor Fixnum, :parent_oid
57
80
  # def parent; ... end
58
81
  # def parent=(obj_or_oid); ... end
59
- #
82
+
60
83
  def belongs_to(name, klass, options = {})
61
84
  prop_eval = "prop_accessor Fixnum, :#{name}_oid"
62
85
  prop_eval << ", :sql => '#{options[:sql]}'" if options[:sql]
63
86
  prop_eval << ", :extra_sql => '#{options[:extra_sql]}'" if options[:extra_sql]
64
87
 
88
+ meta :belongs_to, klass
89
+
65
90
  module_eval %{
66
91
  #{prop_eval}
67
92
 
@@ -81,31 +106,31 @@ module MetaLanguage
81
106
  # Example:
82
107
  #
83
108
  # class MyObject
84
- # has_one AnotherObject
109
+ # has_one :child, TheClass
110
+ # has_one :article
85
111
  # end
86
112
  #
87
113
  # creates the code:
88
114
  #
89
115
  # ...
90
- #
91
- def has_one(name, klass, options = {})
116
+
117
+ def has_one(name, klass = nil, options = {})
118
+
92
119
  # linkback is the property of the child object that 'links back'
93
120
  # to this object.
121
+
94
122
  linkback = options[:linkback] || "#{MetaUtils.expand(self)}_oid"
95
123
 
124
+ meta :has, [klass, linkback]
125
+
96
126
  module_eval %{
97
- @@og_descendants ||= {}
98
- @@og_descendants[#{klass}] = :#{linkback}
99
-
100
- unless defined?(og_descendants)
101
- def self.og_descendants
102
- @@og_descendants
103
- end
104
- end
105
-
106
127
  def #{name}(extrasql = nil)
107
- Og.db.select_one("SELECT * FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
128
+ Og.db.select_one("SELECT * FROM #{Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
108
129
  end
130
+
131
+ def delete_#{name}(extrasql = nil)
132
+ Og.db.exec("DELETE FROM #{Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}")
133
+ end
109
134
  }
110
135
  end
111
136
 
@@ -121,36 +146,37 @@ module MetaLanguage
121
146
  # creates the code:
122
147
  #
123
148
  # def children; ... end
124
- #
149
+
125
150
  def has_many(name, klass, options = {})
126
151
  name_s = N::Inflector.singularize(name.to_s)
127
152
 
128
153
  # linkback is the property of the child object that 'links back'
129
154
  # to this object.
155
+
130
156
  linkback = options[:linkback] || "#{MetaUtils.expand(self)}_oid"
131
157
 
158
+ # keep belongs to metadata, useful for
159
+ # reflection/scaffolding.
160
+
161
+ meta :has, [klass, linkback]
162
+
132
163
  module_eval %{
133
- @@og_descendants ||= {}
134
- @@og_descendants[#{klass}] = :#{linkback}
135
-
136
- unless defined?(og_descendants)
137
- def self.og_descendants
138
- @@og_descendants
139
- end
140
- end
141
-
142
164
  def #{name}(extrasql = nil)
143
- Og.db.select("SELECT * FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
165
+ Og.db.select("SELECT * FROM #{Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}", #{klass})
144
166
  end
145
167
 
146
168
  def #{name}_count(extrasql = nil)
147
- Og.db.count("SELECT COUNT(*) FROM #{Og::Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}")
169
+ Og.db.count("SELECT COUNT(*) FROM #{Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}")
148
170
  end
149
171
 
150
172
  def add_#{name_s}(obj, extra = nil)
151
173
  obj.#{linkback} = @oid
152
174
  obj.save!
153
175
  end
176
+
177
+ def delete_all_#{name}(extrasql = nil)
178
+ Og.db.exec("DELETE FROM #{Backend.table(klass)} WHERE #{linkback}=\#\@oid \#\{extrasql\}")
179
+ end
154
180
  }
155
181
  end
156
182
 
@@ -173,10 +199,10 @@ module MetaLanguage
173
199
  #
174
200
  # category.articles
175
201
  # ...
176
- #
177
202
  #--
178
203
  # FIXME: make more compatible with other enchant methods.
179
204
  #++
205
+
180
206
  def many_to_many(name, klass, options = {})
181
207
  list_o = name.to_s
182
208
  prop_o = N::Inflector.singularize(list_o)
@@ -185,36 +211,38 @@ module MetaLanguage
185
211
 
186
212
  # exit if the class is allready indirectly 'enchanted' from the
187
213
  # other class of the many_to_many relation.
214
+
188
215
  return if self.respond_to?(prop_m)
189
216
 
190
217
  # Add some metadata to the class to allow for automatic join table
191
218
  # calculation.
219
+
192
220
  meta :sql_join, [klass, options]
193
221
 
194
- # gmosx, FIXME: should I update descendants here ?
222
+ meta :many_to_many, klass
223
+ klass.meta :many_to_many, self
195
224
 
196
225
  # enchant this class
197
226
 
198
227
  module_eval %{
199
228
  def #{list_o}(extrasql = nil)
200
- Og.db.select("SELECT d.* FROM #{Og::Backend.table(klass)} AS d, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
229
+ Og.db.select("SELECT d.* FROM #{Backend.table(klass)} AS d, #{Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
201
230
  end
202
231
 
203
232
  def #{list_o}_count(extrasql = nil)
204
- Og.db.select("SELECT COUNT(*) FROM #{Og::Backend.table(klass)} AS d, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
233
+ Og.db.select("SELECT COUNT(*) FROM #{Backend.table(klass)} AS d, #{Backend.join_table(self, klass)} AS j WHERE j.key1=\#\@oid AND j.key2=d.oid \#\{extrasql\}", #{klass})
205
234
  end
206
235
 
207
236
  def add_#{prop_o}(obj, extra = nil)
208
- Og.db.exec("INSERT INTO #{Og::Backend.join_table(self, klass)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})")
237
+ Og.db.exec("INSERT INTO #{Backend.join_table(self, klass)} (key1, key2) VALUES (\#\@oid, \#\{obj.oid\})")
209
238
  end
210
239
 
211
- def del_#{prop_o}(obj_or_oid, extra = nil)
212
- Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key2=\#\{obj_or_oid.to_i\}")
240
+ def delete_#{prop_o}(obj_or_oid, extra = nil)
241
+ Og.db.exec("DELETE FROM #{Backend.join_table(self, klass)} WHERE key2=\#\{obj_or_oid.to_i\}")
213
242
  end
214
- alias_method :delete_#{prop_o}, :del_#{prop_o}
215
243
 
216
244
  def clear_#{list_o}
217
- Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key1=\#\@oid")
245
+ Og.db.exec("DELETE FROM #{Backend.join_table(self, klass)} WHERE key1=\#\@oid")
218
246
  end
219
247
  }
220
248
 
@@ -222,40 +250,85 @@ module MetaLanguage
222
250
 
223
251
  klass.module_eval %{
224
252
  def #{list_m}(extrasql = nil)
225
- Og.db.select("SELECT s.* FROM #{Og::Backend.table(self)} AS s, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
253
+ Og.db.select("SELECT s.* FROM #{Backend.table(self)} AS s, #{Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
226
254
  end
227
255
 
228
256
  def #{list_m}_count(extrasql = nil)
229
- Og.db.select("SELECT COUNT(*) FROM #{Og::Backend.table(self)} AS s, #{Og::Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
257
+ Og.db.select("SELECT COUNT(*) FROM #{Backend.table(self)} AS s, #{Backend.join_table(self, klass)} AS j WHERE j.key2=\#\@oid AND j.key1=s.oid \#\{extrasql\}", #{self})
230
258
  end
231
259
 
232
260
  def add_#{prop_m}(obj, extra = nil)
233
- Og.db.exec("INSERT INTO #{Og::Backend.join_table(self, klass)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)")
261
+ Og.db.exec("INSERT INTO #{Backend.join_table(self, klass)} (key1, key2) VALUES (\#\{obj.oid\}, \#\@oid)")
234
262
  end
235
263
 
236
- def del_#{prop_m}(obj_or_oid, extra = nil)
237
- Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key1=\#\{obj_or_oid.to_i\}")
264
+ def delete_#{prop_m}(obj_or_oid, extra = nil)
265
+ Og.db.exec("DELETE FROM #{Backend.join_table(self, klass)} WHERE key1=\#\{obj_or_oid.to_i\}")
238
266
  end
239
- alias_method :delete_#{prop_m}, :del_#{prop_m}
240
267
 
241
268
  def clear_#{list_m}
242
- Og.db.exec("DELETE FROM #{Og::Backend.join_table(self, klass)} WHERE key2=\#\@oid")
269
+ Og.db.exec("DELETE FROM #{Backend.join_table(self, klass)} WHERE key2=\#\@oid")
243
270
  end
244
271
  }
245
272
  end
246
273
  alias :has_and_belongs_to_many :many_to_many
247
274
 
275
+ # Implements a 'refers_to' relation.
276
+ # This is a one-way version of the 'has_one'/'belongs_to'
277
+ # relations. The target object cannot link back to the source
278
+ # object.
279
+ # This is in fact EXACTLY the same as belongs_to with a
280
+ # different name (!!!!)
281
+ #
282
+ # Automatically enchants the calling class with helper methods.
283
+ #
284
+ #
285
+ # Example:
286
+ #
287
+ # class MyObject
288
+ # refers_to article, Article
289
+ # end
290
+ #
291
+ # creates the code:
292
+ #
293
+ # prop_accessor Fixnum, :article_oid
294
+ # def article; ... end
295
+ # def article=(obj_or_oid); ... end
296
+
297
+ def refers_to(name, klass, options = {})
298
+ prop_eval = "prop_accessor Fixnum, :#{name}_oid"
299
+ prop_eval << ", :sql => '#{options[:sql]}'" if options[:sql]
300
+ prop_eval << ", :extra_sql => '#{options[:extra_sql]}'" if options[:extra_sql]
301
+
302
+ meta :refers_to, klass
303
+ klass.meta :has, [self, "#{name}_oid"]
304
+
305
+ module_eval %{
306
+ #{prop_eval}
307
+
308
+ def #{name}
309
+ Og.db.load_by_oid(@#{name}_oid, #{klass})
310
+ end
311
+
312
+ def #{name}=(obj_or_oid)
313
+ @#{name}_oid = obj_or_oid.to_i
314
+ end
315
+ }
316
+ end
317
+
248
318
  end
249
319
 
250
- end # namespace
320
+ end
251
321
 
252
322
  # Include the meta-language extensions into Module. If the flag is
253
323
  # false the developer is responsible for including the MetaLanguage
254
324
  # module where needed.
255
- #
325
+ #
326
+ # By default this is FALSE, to avoid polution of the Module object.
327
+ # However if you include a prop_accessor or a managed Mixin in your
328
+ # object MetaLanguage gets automatically extended in the class.
329
+
256
330
  if Og.include_meta_language
257
331
  class Module # :nodoc: all
258
332
  include Og::MetaLanguage
259
333
  end
260
334
  end
261
-