nitro 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 (102) hide show
  1. data/AUTHORS +14 -4
  2. data/ChangeLog +192 -1
  3. data/README +50 -6
  4. data/RELEASES +60 -0
  5. data/Rakefile +1 -1
  6. data/bin/cluster.rb +2 -2
  7. data/bin/new_form.rb +1 -1
  8. data/examples/blog/config.rb +5 -4
  9. data/examples/blog/lib/blog.rb +56 -36
  10. data/examples/blog/root/comments.xhtml +5 -2
  11. data/examples/blog/root/entry_form.xhtml +7 -2
  12. data/examples/blog/root/login.xhtml +1 -1
  13. data/examples/blog/root/style.xsl +7 -0
  14. data/examples/og/mock_example.rb +6 -9
  15. data/examples/og/mysql_to_psql.rb +100 -0
  16. data/examples/og/run.rb +8 -17
  17. data/lib/glue.rb +7 -8
  18. data/lib/glue/array.rb +1 -1
  19. data/lib/glue/attribute.rb +86 -0
  20. data/lib/glue/cache.rb +1 -1
  21. data/lib/glue/hash.rb +1 -1
  22. data/lib/glue/inflector.rb +1 -1
  23. data/lib/glue/logger.rb +118 -18
  24. data/lib/glue/mixins.rb +1 -1
  25. data/lib/glue/number.rb +1 -1
  26. data/lib/glue/pool.rb +1 -1
  27. data/lib/glue/property.rb +48 -31
  28. data/lib/glue/string.rb +1 -1
  29. data/lib/glue/time.rb +2 -2
  30. data/lib/glue/validation.rb +400 -0
  31. data/lib/nitro/application.rb +6 -6
  32. data/lib/nitro/builders/form.rb +5 -5
  33. data/lib/nitro/builders/rss.rb +1 -1
  34. data/lib/nitro/builders/xhtml.rb +119 -0
  35. data/lib/nitro/builders/xml.rb +111 -0
  36. data/lib/nitro/config.rb +6 -6
  37. data/lib/nitro/events.rb +1 -1
  38. data/lib/nitro/html.rb +1 -1
  39. data/lib/nitro/markup.rb +15 -20
  40. data/lib/nitro/scaffold.rb +2 -2
  41. data/lib/nitro/server/appserver.rb +3 -3
  42. data/lib/nitro/server/cluster.rb +2 -2
  43. data/lib/nitro/server/dispatcher.rb +2 -2
  44. data/lib/nitro/server/filters/autologin.rb +1 -1
  45. data/lib/nitro/server/fragment.rb +2 -2
  46. data/lib/nitro/server/handlers.rb +2 -2
  47. data/lib/nitro/server/render.rb +17 -15
  48. data/lib/nitro/server/request.rb +6 -6
  49. data/lib/nitro/server/script.rb +2 -2
  50. data/lib/nitro/server/server.rb +2 -2
  51. data/lib/nitro/server/session.rb +6 -6
  52. data/lib/nitro/server/shaders.rb +2 -2
  53. data/lib/nitro/server/webrick.rb +1 -1
  54. data/lib/nitro/sitemap.rb +2 -2
  55. data/lib/nitro/uri.rb +1 -1
  56. data/lib/nitro/version.rb +7 -5
  57. data/lib/og.rb +95 -129
  58. data/lib/og/backend.rb +47 -46
  59. data/lib/og/backends/mysql.rb +64 -63
  60. data/lib/og/backends/psql.rb +73 -72
  61. data/lib/og/connection.rb +7 -8
  62. data/lib/og/enchant.rb +80 -0
  63. data/lib/og/meta.rb +21 -21
  64. data/lib/og/mock.rb +31 -88
  65. data/lib/og/version.rb +6 -5
  66. data/lib/parts/README +9 -0
  67. data/lib/parts/content.rb +23 -9
  68. data/test/glue/tc_attribute.rb +22 -0
  69. data/test/glue/tc_cache.rb +4 -6
  70. data/test/glue/tc_hash.rb +2 -2
  71. data/test/glue/tc_logger.rb +36 -0
  72. data/test/glue/tc_numbers.rb +2 -2
  73. data/test/glue/tc_property_mixins.rb +35 -4
  74. data/test/glue/tc_strings.rb +32 -32
  75. data/test/glue/tc_validation.rb +186 -0
  76. data/test/nitro/builders/tc_xhtml.rb +38 -0
  77. data/test/nitro/builders/tc_xml.rb +47 -0
  78. data/test/nitro/server/tc_request.rb +2 -2
  79. data/test/nitro/server/tc_session.rb +1 -1
  80. data/test/nitro/tc_sitemap.rb +1 -1
  81. data/test/nitro/ui/tc_pager.rb +1 -10
  82. data/test/tc_og.rb +3 -3
  83. data/vendor/blankslate.rb +53 -0
  84. data/vendor/extensions/_base.rb +153 -0
  85. data/vendor/extensions/_template.rb +36 -0
  86. data/vendor/extensions/all.rb +21 -0
  87. data/vendor/extensions/array.rb +68 -0
  88. data/vendor/extensions/binding.rb +224 -0
  89. data/vendor/extensions/class.rb +50 -0
  90. data/vendor/extensions/continuation.rb +71 -0
  91. data/vendor/extensions/enumerable.rb +250 -0
  92. data/vendor/extensions/hash.rb +23 -0
  93. data/vendor/extensions/io.rb +58 -0
  94. data/vendor/extensions/kernel.rb +42 -0
  95. data/vendor/extensions/module.rb +114 -0
  96. data/vendor/extensions/numeric.rb +230 -0
  97. data/vendor/extensions/object.rb +164 -0
  98. data/vendor/extensions/ostruct.rb +41 -0
  99. data/vendor/extensions/string.rb +316 -0
  100. data/vendor/extensions/symbol.rb +28 -0
  101. metadata +35 -13
  102. data/lib/glue/property.rb.old +0 -307
@@ -1,5 +1,4 @@
1
- # code:
2
- # * George Moschovitis <gm@navel.gr>
1
+ # George Moschovitis <gm@navel.gr>
3
2
  #
4
3
  # (c) 2004 Navel, all rights reserved.
5
4
  # $Id: blog.rb 185 2004-12-10 13:29:09Z gmosx $
@@ -8,6 +7,8 @@ require 'nitro/service'
8
7
  require 'nitro/builders/rss'
9
8
  require 'nitro/ui/pager'
10
9
 
10
+ require 'parts/content'
11
+
11
12
  $blog_username = 'George Moschovitis'
12
13
  $blog_password = 'mypassword'
13
14
 
@@ -16,53 +17,48 @@ module N
16
17
  # = Common
17
18
  #
18
19
  # Common properties/methods for the other classes.
19
- #
20
- class Common
21
- prop :create_time, Time
22
- prop_accessor :author, String
23
- prop_accessor :body, String, :form => :textarea
20
+ # Since markup is required, automatically handles
21
+ # the markup expanding/compacting for the body.
24
22
 
25
- def initialize
26
- @create_time = Time.now
27
- end
28
-
23
+ module Common
24
+ include N::BaseContent
25
+ include N::CreateTime
26
+
27
+ prop_accessor :author, String
28
+ validate_value :body
29
29
  end
30
30
 
31
- class Comment < Common; end
31
+
32
+ # Forward reference to the Comment definition.
33
+
34
+ class Comment; end
32
35
 
33
36
  # = BlogEntry
34
- #
35
- class BlogEntry < Common
36
- prop_accessor :title, String
37
- has_many :comments, N::Comment, :linkback => 'entry_oid'
38
37
 
39
- # Play a bit with the text the user enters.
40
- #
41
- def body=(str)
42
- if str
43
- str.gsub!(/</, '&lt;')
44
- str.gsub!(/>/, '&gt;')
45
- str.gsub!(/"/, '&quot;')
46
- str.gsub!(/'/, '&#39;')
47
- str.gsub!(/\r\n/, ' <br />')
48
- @body = str
49
- end
50
- end
38
+ class BlogEntry
39
+ include N::Common
40
+ has_many :comments, N::Comment, :linkback => 'entry_oid'
41
+ validate_value :title, :msg => 'Please provide a title'
51
42
  end
52
43
 
53
44
  # = Comment
54
- #
55
- class Comment < Common
45
+
46
+ class Comment
47
+ include N::Common
56
48
  belongs_to :entry, N::BlogEntry
49
+ validate_value :author, :msg => 'Please enter your name'
57
50
  end
58
51
 
59
52
  # = BlogService
60
53
  #
54
+ # Implements the Blog service. This encapsulates
55
+ # the action controller.
56
+
61
57
  class BlogService < N::Service
62
58
  SOURCE_FILE = __FILE__
63
59
 
64
- before_filter :audit
65
- after_filter :cache
60
+ before_filter :get_errors
61
+ # after_filter :cache
66
62
 
67
63
  scaffold N::BlogEntry, :name => 'entry', :index => true
68
64
  scaffold N::Comment
@@ -71,11 +67,19 @@ class BlogService < N::Service
71
67
  @pager = N::UI::Pager.new('entries', @request, 3)
72
68
  @entries = N::BlogEntry.all("ORDER BY oid DESC #{@pager.sql_limit}")
73
69
  @pager.set(N::BlogEntry.count)
70
+
71
+ puts N::Common.__meta[:validations]
74
72
  end
75
73
 
76
74
  def new_entry
77
75
  entry = request.fill(N::BlogEntry.new)
78
76
  entry.author = session['username']
77
+
78
+ unless entry.valid?
79
+ session[:errors] = entry.errors
80
+ redirect_referer '#new_entry'
81
+ end
82
+
79
83
  entry.save!
80
84
  end
81
85
 
@@ -86,6 +90,12 @@ class BlogService < N::Service
86
90
 
87
91
  def new_comment
88
92
  comment = request.fill(N::Comment.new)
93
+
94
+ unless comment.valid?
95
+ session[:errors] = comment.errors
96
+ redirect_referer '#new_comment'
97
+ end
98
+
89
99
  comment.save!
90
100
  end
91
101
 
@@ -112,14 +122,24 @@ class BlogService < N::Service
112
122
 
113
123
  private
114
124
 
115
- def audit
116
- puts "audit (before filter example)"
125
+ # A helper prefilter, autocleans session errors.
126
+ # Used as an example.
127
+
128
+ def get_errors
129
+ # gmosx: should better implement top-level filters!
130
+ if errors = session.delete(:errors)
131
+ @errors = errors
132
+ end
117
133
  end
118
134
 
135
+ # Just an example
136
+
119
137
  def cache
120
- puts "cache (after filter example)"
138
+ # Call the automatically configured logger.
139
+
140
+ Logger.info "cache (after filter example)"
121
141
  end
122
142
 
123
143
  end
124
144
 
125
- end # module
145
+ end
@@ -1,6 +1,6 @@
1
1
  <?xml version="1.0"?>
2
2
 
3
- <root>
3
+ <root xmlns:x="http://www.navel.gr/xml/shader.xsd">
4
4
 
5
5
  <h2>#{@entry.comments_count} Comments:</h2>
6
6
  <?r
@@ -22,15 +22,18 @@ else
22
22
  ?>
23
23
  no comments.
24
24
  <?r end ?>
25
- <form action="new_comment" method="post">
25
+ <form id="new_comment" action="new_comment" method="post">
26
26
  <input type="hidden" name="entry_oid" value="#{@entry.oid}" />
27
27
  <p>
28
28
  <b>Your name:</b><br />
29
29
  <input type="text" name="author" value="#{session['username']}" />
30
+ <x:error attr="author" />
31
+ <x:error attr="title" />
30
32
  </p>
31
33
  <p>
32
34
  <b>Write your thoughts:</b><br />
33
35
  <textarea name="body" style="width: 90%; height: 100px">#{}</textarea>
36
+ <x:error attr="body"><br /></x:error>
34
37
  </p>
35
38
  <input type="submit" value="Add comment" />
36
39
  </form>
@@ -1,16 +1,21 @@
1
1
  <?xml version="1.0"?>
2
2
 
3
- <div id="comments">
3
+ <div id="comments" xmlns:x="http://www.navel.gr/xml/shader.xsd">
4
+
5
+ <?r errors = session[:errors] ?>
6
+
4
7
  <h2>Post new entry:</h2>
5
8
 
6
- <form action="new_entry" method="post">
9
+ <form id="new_entry" action="new_entry" method="post">
7
10
  <p>
8
11
  <b>Title:</b><br />
9
12
  <input type="text" name="title" />
13
+ <x:error attr="title" />
10
14
  </p>
11
15
  <p>
12
16
  <b>Body:</b><br />
13
17
  <textarea name="body" style="width: 90%; height: 100px">#{}</textarea>
18
+ <x:error attr="body"><br /></x:error>
14
19
  </p>
15
20
  <input type="submit" value="Post" />
16
21
  </form>
@@ -15,7 +15,7 @@
15
15
  <form action="login" method="post">
16
16
  <p>
17
17
  <b>Password:</b><br />
18
- <input type="password" name="password" />
18
+ <input type="password" name="password" value="#$blog_password" />
19
19
  </p>
20
20
  <input type="submit" value="Login" />
21
21
  </form>
@@ -60,6 +60,13 @@ $Id: style.xsl 194 2004-12-20 20:23:57Z gmosx $
60
60
  </div>
61
61
  </xsl:template>
62
62
 
63
+ <xsl:template name="x:error" match="x:error">
64
+ <ruby>if @errors and __err__ = @errors[:<xsl:value-of select="@attr" />]</ruby>
65
+ <xsl:apply-templates />
66
+ <span class="error">#{__err__}</span>
67
+ <ruby>end</ruby>
68
+ </xsl:template>
69
+
63
70
  <!--
64
71
  can only include x:blocks, all other templates are ignored
65
72
  -->
@@ -9,15 +9,12 @@
9
9
  # (c) 2004 Navel, all rights reserved.
10
10
  # $Id: run.rb 185 2004-12-10 13:29:09Z gmosx $
11
11
 
12
- $LOAD_PATH.unshift '../../lib'
12
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
13
13
 
14
14
  require 'rubygems'
15
15
  require 'flexmock'
16
16
  require 'og'
17
17
  require 'og/mock'
18
- require 'logger'
19
-
20
- $log = Logger.new($stderr)
21
18
 
22
19
  class Article
23
20
  prop_accessor :body, String
@@ -30,11 +27,11 @@ end
30
27
  class SimpleTest < Test::Unit::TestCase
31
28
 
32
29
  def setup
33
- $og = Og::MockDatabase.new
30
+ @og = Og::MockDatabase.new
34
31
  end
35
32
 
36
33
  def teardown
37
- $og = nil
34
+ @og = nil
38
35
  end
39
36
 
40
37
  def test_me
@@ -43,15 +40,15 @@ class SimpleTest < Test::Unit::TestCase
43
40
  Article.new('body2'),
44
41
  Article.new('body3')
45
42
  ]
46
- $og.mock_handle(:load_all) { |klass, extrasql| mocks }
43
+ @og.mock_handle(:load_all) { |klass, extrasql| mocks }
47
44
 
48
45
  # differnt ways to call the mocked method...
49
46
  puts 'Here are the articles:', Article.all
50
47
  puts 'Here are the articles:', Article.load_all
51
- puts 'Here are the articles:', $og.load_all(Article)
48
+ puts 'Here are the articles:', @og.load_all(Article)
52
49
 
53
50
  # 3 times called
54
- assert_equal(3, $og.mock_count(:load_all))
51
+ assert_equal(3, @og.mock_count(:load_all))
55
52
  end
56
53
 
57
54
  end
@@ -0,0 +1,100 @@
1
+ # = Og Mysql to PostgreSQL copy example
2
+ #
3
+ # A simple example to demonstrate the flexibility of
4
+ # Og. Two connections to different databases are
5
+ # created and data is copied from a MySQL database
6
+ # to a PostgreSQL database.
7
+ #
8
+ # Og makes it easier to switch to a REAL database :)
9
+ #
10
+ # code:
11
+ # * George Moschovitis <gm@navel.gr>
12
+ #
13
+ # (c) 2004 Navel, all rights reserved.
14
+ # $Id$
15
+
16
+ raise 'WARNING, this example does not work yet, for the moment ' +
17
+ 'just have a look at the source code.'
18
+
19
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
20
+
21
+ require 'og'
22
+
23
+ # An example managed object.
24
+ # Looks like an ordinary Ruby object.
25
+ #
26
+ class Article
27
+ prop_accessor :name, :body, String
28
+
29
+ def initialize(name = nil, body = nil)
30
+ @name, @body = name, body
31
+ end
32
+ end
33
+
34
+ # Configure databases.
35
+
36
+ psql_config = {
37
+ :address => 'localhost',
38
+ :database => 'test',
39
+ :backend => 'psql',
40
+ :user => 'postgres',
41
+ :password => 'navelrulez',
42
+ :connection_count => 1
43
+ }
44
+
45
+ mysql_config = {
46
+ :address => 'localhost',
47
+ :database => 'mysql',
48
+ :backend => 'psql',
49
+ :user => 'postgres',
50
+ :password => 'navelrulez',
51
+ :connection_count => 1
52
+ }
53
+ =begin
54
+ mysql_config = {
55
+ :address => 'localhost',
56
+ :database => 'test',
57
+ :backend => 'mysql',
58
+ :user => 'root',
59
+ :password => 'navelrulez',
60
+ :connection_count => 1
61
+ }
62
+ =end
63
+
64
+ # Cleanup the databases, remove data from
65
+ # earlier executions.
66
+
67
+ Og::Database.drop!(psql_config)
68
+ Og::Database.drop!(mysql_config)
69
+
70
+ # Initialize Og.
71
+
72
+ psql = Og::Database.new(psql_config)
73
+ mysql = Og::Database.new(mysql_config)
74
+
75
+ # First populate the mysql database.
76
+
77
+ Og.use(mysql)
78
+
79
+ a1 = Article.create('name1', 'body1')
80
+ a1 = Article.create('name1', 'body1')
81
+ a1 = Article.create('name1', 'body1')
82
+
83
+ # Read all articles from Mysql.
84
+
85
+ articles = Article.all
86
+
87
+ # Switch to PostgreSQL.
88
+
89
+ Og.use(psql)
90
+
91
+ # Store all articles.
92
+
93
+ for article in articles
94
+ article.save!
95
+ end
96
+
97
+ # Fetch an article from PostgreSQL
98
+ # as an example. Lookup by name.
99
+
100
+ article = Article['name1']
@@ -8,10 +8,9 @@
8
8
  # (c) 2004 Navel, all rights reserved.
9
9
  # $Id: run.rb 198 2004-12-22 11:26:59Z gmosx $
10
10
 
11
- $:.unshift "../../lib"
11
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
12
12
 
13
- require "glue/logger"
14
- require "og"
13
+ require 'og'
15
14
 
16
15
  # Full debug information.
17
16
  $DBG = true
@@ -138,9 +137,6 @@ class Part
138
137
  end
139
138
  end
140
139
 
141
- # Initialize a logger.
142
-
143
- $log = Logger.new(STDERR);
144
140
  # Og configuration.
145
141
  config = {
146
142
  :address => "localhost",
@@ -162,23 +158,19 @@ config = {
162
158
  =end
163
159
  # Cleanup the database for earlier executions
164
160
 
165
- Og::Database.drop_db!(config)
161
+ Og::Database.drop!(config)
166
162
 
167
163
  # Initialize Og
168
164
 
169
- $og = Og::Database.new(config)
170
-
171
- # Get an Og connection for this thread.
172
-
173
- $og.get_connection
165
+ db = Og::Database.new(config)
174
166
 
175
167
  # Create some articles
176
168
 
177
169
  a1 = Article.new("Title1", "Body1")
178
170
  a1.save!
179
171
 
180
- a2 = Article.new("Title2", "Body2")
181
- a2.save!
172
+ # shortcut
173
+ a2 = Article.create("Title2", "Body2")
182
174
 
183
175
  puts "\n\n"
184
176
  puts "* Get and print all articles:"
@@ -194,9 +186,8 @@ c1.save!
194
186
  c2 = ArticleComment.new("Comment 2")
195
187
  # alternative way to set the parent.
196
188
  c2.article_oid = a1.oid
197
- # an alternative way to save (add to the $og 'virtal collection' of
198
- # managed objects).
199
- $og << c2
189
+ # an alternative way to save
190
+ db << c2
200
191
 
201
192
  # an alternative (easier and cooler) way to add children in a
202
193
  # has_many relation:
@@ -5,13 +5,14 @@
5
5
  # code:
6
6
  # * George Moschovitis <gm@navel.gr>
7
7
  #
8
- # (c) 2004 Navel, all rights reserved.
8
+ # (c) 2004-2005 Navel, all rights reserved.
9
9
  # $Id: glue.rb 175 2004-11-26 16:11:27Z gmosx $
10
10
 
11
- require "English"
12
- require "pp"
11
+ require 'English'
12
+ require 'pp'
13
13
 
14
14
  require 'glue/property'
15
+ require 'glue/attribute'
15
16
 
16
17
  class NilClass
17
18
  # quite usefull for error tolerant apps.
@@ -26,12 +27,13 @@ class Class
26
27
  #--
27
28
  # gmosx: is this really needed?
28
29
  #++
29
- def to_i()
30
- return self.hash()
30
+ def to_i
31
+ return self.hash
31
32
  end
32
33
  end
33
34
 
34
35
  module Kernel
36
+
35
37
  # pretty prints an exception/error object
36
38
  # usefull for helpfull debug messages
37
39
  #
@@ -47,6 +49,3 @@ module Kernel
47
49
 
48
50
  end
49
51
 
50
- # predefine some comonly used objects
51
-
52
- EMPTY_STRING = ""