updateable_views_inheritance 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +3 -0
  2. data/Gemfile +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +110 -0
  5. data/Rakefile +35 -0
  6. data/doc/template/horo.rb +613 -0
  7. data/lib/generators/updateable_views_inheritance_migration/USAGE +8 -0
  8. data/lib/generators/updateable_views_inheritance_migration/templates/migration.rb +17 -0
  9. data/lib/generators/updateable_views_inheritance_migration/uvi_migration_generator.rb +12 -0
  10. data/lib/updateable_views_inheritance.rb +5 -0
  11. data/lib/updateable_views_inheritance/active_record.rb +16 -0
  12. data/lib/updateable_views_inheritance/postgresql_adapter.rb +450 -0
  13. data/lib/updateable_views_inheritance/version.rb +3 -0
  14. data/tasks/updateable_views_inheritance_tasks.rake +19 -0
  15. data/test/app/models/bicycle.rb +3 -0
  16. data/test/app/models/boat.rb +3 -0
  17. data/test/app/models/car.rb +3 -0
  18. data/test/app/models/electric_locomotive.rb +3 -0
  19. data/test/app/models/electric_train.rb +3 -0
  20. data/test/app/models/locomotive.rb +3 -0
  21. data/test/app/models/maglev_locomotive.rb +3 -0
  22. data/test/app/models/maglev_train.rb +3 -0
  23. data/test/app/models/rack_locomotive.rb +3 -0
  24. data/test/app/models/rack_train.rb +3 -0
  25. data/test/app/models/railed_vehicle.rb +3 -0
  26. data/test/app/models/steam_locomotive.rb +3 -0
  27. data/test/app/models/steam_train.rb +3 -0
  28. data/test/app/models/train.rb +3 -0
  29. data/test/app/models/vehicle.rb +3 -0
  30. data/test/app/models/wheeled_vehicle.rb +3 -0
  31. data/test/config/database.yml +19 -0
  32. data/test/config/environment.rb +14 -0
  33. data/test/config/routes.rb +3 -0
  34. data/test/config/schema.rb +3 -0
  35. data/test/content_test.rb +66 -0
  36. data/test/database.yml +7 -0
  37. data/test/deep_hierarchy_test.rb +64 -0
  38. data/test/fixtures/bicycles.yml +6 -0
  39. data/test/fixtures/boats.yml +6 -0
  40. data/test/fixtures/cars.yml +12 -0
  41. data/test/fixtures/electric_locomotives.yml +6 -0
  42. data/test/fixtures/electric_trains.yml +7 -0
  43. data/test/fixtures/maglev_locomotives.yml +7 -0
  44. data/test/fixtures/maglev_trains.yml +8 -0
  45. data/test/fixtures/migrations/1_add_class_table_inheritance.rb +15 -0
  46. data/test/fixtures/migrations/2_create_with_default_table.rb +19 -0
  47. data/test/fixtures/migrations/3_create_with_explicit_table.rb +11 -0
  48. data/test/fixtures/migrations/4_create_deeper_hierarchy.rb +11 -0
  49. data/test/fixtures/migrations/5_default_column_values.rb +13 -0
  50. data/test/fixtures/migrations/6_single_table_inheritance_view.rb +10 -0
  51. data/test/fixtures/migrations/7_second_deep_hierarchy.rb +70 -0
  52. data/test/fixtures/migrations/8_second_single_table_inheritance_view.rb +10 -0
  53. data/test/fixtures/rack_trains.yml +7 -0
  54. data/test/fixtures/steam_locomotives.yml +7 -0
  55. data/test/fixtures/steam_trains.yml +8 -0
  56. data/test/migration_test.rb +30 -0
  57. data/test/schema_test.rb +179 -0
  58. data/test/single_table_inheritance.rb +141 -0
  59. data/test/test_helper.rb +80 -0
  60. data/updateable_views_inheritance.gemspec +26 -0
  61. metadata +219 -0
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ test/*.log
2
+ pkg/*
3
+ html/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in updateable_views_inheritance.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007 Tutuf Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,110 @@
1
+ ==Class Table Inheritance
2
+
3
+ Class Table Inheritance for ActiveRecord using updateable views.
4
+
5
+ More about the pattern on http://www.martinfowler.com/eaaCatalog/classTableInheritance.html. This gem messes very little with Rails inheritance mechanism.
6
+ Instead it relies on updatable views in the database to represent classes in the inheritance chain. The approach was first {suggested by John
7
+ Wilger}[http://web.archive.org/web/20060408145717/johnwilger.com/articles/2005/09/29/class-table-inheritance-in-rails-with-postgresql].
8
+
9
+
10
+ ==Requirements
11
+
12
+ Rails: 3.2.x
13
+
14
+ Ruby: tested with 1.8.7 and 1.9.3
15
+
16
+ Database: PostgreSQL 8.1+ only. Patches for other DBMS are welcome. Note that you are not required to use updateable views, children relations can be tables (with some triggers involved) or materialized views.
17
+
18
+ ==Install
19
+
20
+ gem install updateable_views_inheritance
21
+
22
+ ==Usage
23
+
24
+ ===Setup
25
+
26
+ In Gemfile
27
+
28
+ gem 'updateable_views_inheritance'
29
+
30
+ Keep in mind that only PostgreSQL is currently supported.
31
+ 1. <tt>rake updateable_views_inheritance:setup</tt> to create a migration.
32
+ 1. <tt>rake db:migrate</tt>.
33
+ 1. In <tt>config/environment.rb</tt> set <tt>config.active_record.schema_format = :sql</tt>. Database views and rules are not supported in default schema.rb.
34
+
35
+ ===Example
36
+
37
+ class CtiExample < ActiveRecord::Migration
38
+ def self.up
39
+ create_table :locomotives do |t|
40
+ t.column :name, :string
41
+ t.column :max_speed, :integer
42
+ t.column :type, :string
43
+ end
44
+
45
+ create_child(:steam_locomotives, :parent => :locomotives) do |t|
46
+ t.decimal :water_consumption, :precision => 6, :scale => 2
47
+ t.decimal :coal_consumption, :precision => 6, :scale => 2
48
+ end
49
+
50
+ create_child(:electric_locomotives, :table => :raw_electric_locomotives, :parent => :locomotives) do |t|
51
+ t.decimal :electricity_consumption, :precision => 6, :scale => 2
52
+ end
53
+ end
54
+
55
+ def self.down
56
+ drop_child :steam_locomotives
57
+ drop_child :electric_locomotives
58
+ drop_table :locomotives
59
+ end
60
+ end
61
+
62
+ And the models:
63
+ class Locomotive
64
+ end
65
+
66
+ class SteamLocomotive < Locomotive
67
+ self.table_name = :steam_locomotives
68
+ end
69
+
70
+ class ElectricLocomotive < Locomotive
71
+ self.table_name = :electric_locomotives
72
+ end
73
+
74
+ Note that models of children classes must specify table name explicitly.
75
+
76
+ ===Changing Columns in Underlying Tables
77
+
78
+ class RemoveColumnInParentTable < ActiveRecord::Migration
79
+ def self.up
80
+ remove_parent_and_children_views(:locomotives)
81
+ remove_column(:locomotives, :max_speed)
82
+ rename_column(:name, :title)
83
+ rebuild_parent_and_children_views(:locomotives)
84
+ end
85
+ end
86
+
87
+ ===Renaming Underlying Tables
88
+
89
+ remove_parent_and_children_views(:old_name)
90
+ rename_table(:old_name,:new_name)
91
+ execute "UPDATE updateable_views_inheritance SET child_aggregate_view = 'new_name' WHERE child_aggregate_view = 'old_name'"
92
+ execute "UPDATE updateable_views_inheritance SET parent_relation = 'new_name' WHERE parent_relation = 'old_name'"
93
+ rebuild_parent_and_children_views(:new_name)
94
+
95
+ ===Removing Classes
96
+
97
+ Note that you should remove only leaf classes (i.e. those that do not have descendants). If you want to erase a whole chain or part of chain you have to remove first the leaves and then their ancestors. Use <tt>drop_child(child_view)</tt> in migrations.
98
+
99
+ ==Compatibility with Single Table Inheritance
100
+
101
+ The approach of this gem is completely independent from Rails single table inheritance. STI and CLTI can safely be mixed in one inheritance chain.
102
+
103
+ ==Testing Your App
104
+
105
+ Run <tt>rake updateable_views_inheritance:fixture</tt> to generate fixture for the updateable_views_inheritance table. <b>Without it primary key sequence for
106
+ inheritors' tables won't be bumped to the max and it might not be possible to save objects!</b>
107
+
108
+ This gem re-enables referential integrity on fixture loading, so if you are using foreign keys you will have to explicitly declare fixture load order in test_helper.rb like this:
109
+
110
+ fixtures(:roots, :trunks, :leafs, ...)
data/Rakefile ADDED
@@ -0,0 +1,35 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ desc 'Run unit tests'
6
+ Rake::TestTask.new(:test => 'test:rebuild_database') do |t|
7
+ t.libs << "#{File.dirname(__FILE__)}/lib"
8
+ t.pattern = "#{File.dirname(__FILE__)}/test/*_test.rb"
9
+ t.verbose = true
10
+ end
11
+
12
+ desc 'Generate documentation'
13
+ Rake::RDocTask.new(:rdoc) do |rdoc|
14
+ rdoc.rdoc_dir = 'html'
15
+ rdoc.title = 'Class Table Inheritance for Rails'
16
+ rdoc.options << '--line-numbers' << '--inline-source'
17
+ rdoc.template = ENV['template'] ? "#{ENV['template']}.rb" : './doc/template/horo'
18
+ rdoc.rdoc_files.include('README.rdoc')
19
+ rdoc.rdoc_files.include('./lib/**/*.rb')
20
+ end
21
+
22
+ namespace :test do
23
+ desc 'Build the test database'
24
+ task :create_database do
25
+ %x( createdb -U postgres updateable_views_inheritance_test )
26
+ end
27
+
28
+ desc 'Drop the test database'
29
+ task :drop_database do
30
+ %x( dropdb -U postgres updateable_views_inheritance_test )
31
+ end
32
+
33
+ desc 'Rebuild the test database'
34
+ task :rebuild_database => [:drop_database, :create_database]
35
+ end
@@ -0,0 +1,613 @@
1
+ # Horo RDoc template
2
+ # Author: Hongli Lai - http://izumi.plan99.net/blog/
3
+ #
4
+ # Based on the Jamis template:
5
+ # http://weblog.jamisbuck.org/2005/4/8/rdoc-template
6
+
7
+ if defined?(RDoc::Diagram)
8
+ RDoc::Diagram.class_eval do
9
+ remove_const(:FONT)
10
+ const_set(:FONT, "\"Bitstream Vera Sans\"")
11
+ end
12
+ end
13
+
14
+ module RDoc
15
+ module Page
16
+
17
+ FONTS = "\"Bitstream Vera Sans\", Verdana, Arial, Helvetica, sans-serif"
18
+
19
+ STYLE = <<CSS
20
+ a {
21
+ color: #00F;
22
+ text-decoration: none;
23
+ }
24
+
25
+ a:hover {
26
+ color: #77F;
27
+ text-decoration: underline;
28
+ }
29
+
30
+ body, td, p {
31
+ font-family: %fonts%;
32
+ background: #FFF;
33
+ color: #000;
34
+ margin: 0px;
35
+ font-size: small;
36
+ }
37
+
38
+ p {
39
+ margin-top: 0.5em;
40
+ margin-bottom: 0.5em;
41
+ }
42
+
43
+ #content {
44
+ margin: 2em;
45
+ margin-left: 3.5em;
46
+ margin-right: 3.5em;
47
+ }
48
+
49
+ #description p {
50
+ margin-bottom: 0.5em;
51
+ }
52
+
53
+ .sectiontitle {
54
+ margin-top: 1em;
55
+ margin-bottom: 1em;
56
+ padding: 0.5em;
57
+ padding-left: 2em;
58
+ background: #005;
59
+ color: #FFF;
60
+ font-weight: bold;
61
+ }
62
+
63
+ .attr-rw {
64
+ padding-left: 1em;
65
+ padding-right: 1em;
66
+ text-align: center;
67
+ color: #055;
68
+ }
69
+
70
+ .attr-name {
71
+ font-weight: bold;
72
+ }
73
+
74
+ .attr-desc {
75
+ }
76
+
77
+ .attr-value {
78
+ font-family: monospace;
79
+ }
80
+
81
+ .file-title-prefix {
82
+ font-size: large;
83
+ }
84
+
85
+ .file-title {
86
+ font-size: large;
87
+ font-weight: bold;
88
+ background: #005;
89
+ color: #FFF;
90
+ }
91
+
92
+ .banner {
93
+ background: #005;
94
+ color: #FFF;
95
+ border: 1px solid black;
96
+ padding: 1em;
97
+ }
98
+
99
+ .banner td {
100
+ background: transparent;
101
+ color: #FFF;
102
+ }
103
+
104
+ h1 a, h2 a, .sectiontitle a, .banner a {
105
+ color: #FF0;
106
+ }
107
+
108
+ h1 a:hover, h2 a:hover, .sectiontitle a:hover, .banner a:hover {
109
+ color: #FF7;
110
+ }
111
+
112
+ .dyn-source {
113
+ display: none;
114
+ background: #fffde8;
115
+ color: #000;
116
+ border: #ffe0bb dotted 1px;
117
+ margin: 0.5em 2em 0.5em 2em;
118
+ padding: 0.5em;
119
+ }
120
+
121
+ .dyn-source .cmt {
122
+ color: #00F;
123
+ font-style: italic;
124
+ }
125
+
126
+ .dyn-source .kw {
127
+ color: #070;
128
+ font-weight: bold;
129
+ }
130
+
131
+ .method {
132
+ margin-left: 1em;
133
+ margin-right: 1em;
134
+ margin-bottom: 1em;
135
+ }
136
+
137
+ .description pre {
138
+ padding: 0.5em;
139
+ border: #ffe0bb dotted 1px;
140
+ background: #fffde8;
141
+ }
142
+
143
+ .method .title {
144
+ font-family: monospace;
145
+ font-size: large;
146
+ border-bottom: 1px dashed black;
147
+ margin-bottom: 0.3em;
148
+ padding-bottom: 0.1em;
149
+ }
150
+
151
+ .method .description, .method .sourcecode {
152
+ margin-left: 1em;
153
+ }
154
+
155
+ .description p, .sourcecode p {
156
+ margin-bottom: 0.5em;
157
+ }
158
+
159
+ .method .sourcecode p.source-link {
160
+ text-indent: 0em;
161
+ margin-top: 0.5em;
162
+ }
163
+
164
+ .method .aka {
165
+ margin-top: 0.3em;
166
+ margin-left: 1em;
167
+ font-style: italic;
168
+ text-indent: 2em;
169
+ }
170
+
171
+ h1 {
172
+ padding: 1em;
173
+ margin-left: -1.5em;
174
+ font-size: x-large;
175
+ font-weight: bold;
176
+ color: #FFF;
177
+ background: #007;
178
+ }
179
+
180
+ h2 {
181
+ padding: 0.5em 1em 0.5em 1em;
182
+ margin-left: -1.5em;
183
+ font-size: large;
184
+ font-weight: bold;
185
+ color: #FFF;
186
+ background: #009;
187
+ }
188
+
189
+ h3, h4, h5, h6 {
190
+ color: #220088;
191
+ border-bottom: #5522bb solid 1px;
192
+ }
193
+
194
+ .sourcecode > pre {
195
+ padding: 0.5em;
196
+ border: 1px dotted black;
197
+ background: #FFE;
198
+ }
199
+
200
+ dt {
201
+ font-weight: bold
202
+ }
203
+
204
+ dd {
205
+ margin-bottom: 0.7em;
206
+ }
207
+ CSS
208
+
209
+ XHTML_PREAMBLE = %{<?xml version="1.0" encoding="%charset%"?>
210
+ <!DOCTYPE html
211
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
212
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
213
+ }
214
+
215
+ XHTML_FRAMESET_PREAMBLE = %{
216
+ <!DOCTYPE html
217
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
218
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
219
+ }
220
+
221
+ HEADER = XHTML_PREAMBLE + <<ENDHEADER
222
+ <html>
223
+ <head>
224
+ <title>%title%</title>
225
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
226
+ <link rel="stylesheet" href="%style_url%" type="text/css" media="screen" />
227
+
228
+ <script language="JavaScript" type="text/javascript">
229
+ // <![CDATA[
230
+
231
+ function toggleSource( id )
232
+ {
233
+ var elem
234
+ var link
235
+
236
+ if( document.getElementById )
237
+ {
238
+ elem = document.getElementById( id )
239
+ link = document.getElementById( "l_" + id )
240
+ }
241
+ else if ( document.all )
242
+ {
243
+ elem = eval( "document.all." + id )
244
+ link = eval( "document.all.l_" + id )
245
+ }
246
+ else
247
+ return false;
248
+
249
+ if( elem.style.display == "block" )
250
+ {
251
+ elem.style.display = "none"
252
+ link.innerHTML = "show source"
253
+ }
254
+ else
255
+ {
256
+ elem.style.display = "block"
257
+ link.innerHTML = "hide source"
258
+ }
259
+ }
260
+
261
+ function openCode( url )
262
+ {
263
+ window.open( url, "SOURCE_CODE", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=480,width=750" ).focus();
264
+ }
265
+ // ]]>
266
+ </script>
267
+ </head>
268
+
269
+ <body>
270
+ ENDHEADER
271
+
272
+ FILE_PAGE = <<HTML
273
+ <table border='0' cellpadding='0' cellspacing='0' width="100%" class='banner'>
274
+ <tr><td>
275
+ <table width="100%" border='0' cellpadding='0' cellspacing='0'><tr>
276
+ <td class="file-title" colspan="2"><span class="file-title-prefix">File</span><br />%short_name%</td>
277
+ <td align="right">
278
+ <table border='0' cellspacing="0" cellpadding="2">
279
+ <tr>
280
+ <td>Path:</td>
281
+ <td>%full_path%
282
+ IF:cvsurl
283
+ &nbsp;(<a href="%cvsurl%">CVS</a>)
284
+ ENDIF:cvsurl
285
+ </td>
286
+ </tr>
287
+ <tr>
288
+ <td>Modified:</td>
289
+ <td>%dtm_modified%</td>
290
+ </tr>
291
+ </table>
292
+ </td></tr>
293
+ </table>
294
+ </td></tr>
295
+ </table><br />
296
+ HTML
297
+
298
+ ###################################################################
299
+
300
+ CLASS_PAGE = <<HTML
301
+ <table width="100%" border='0' cellpadding='0' cellspacing='0' class='banner'><tr>
302
+ <td class="file-title"><span class="file-title-prefix">%classmod%</span><br />%full_name%</td>
303
+ <td align="right">
304
+ <table cellspacing="0" cellpadding="2">
305
+ <tr valign="top">
306
+ <td>In:</td>
307
+ <td>
308
+ START:infiles
309
+ HREF:full_path_url:full_path:
310
+ IF:cvsurl
311
+ &nbsp;(<a href="%cvsurl%">CVS</a>)
312
+ ENDIF:cvsurl
313
+ END:infiles
314
+ </td>
315
+ </tr>
316
+ IF:parent
317
+ <tr>
318
+ <td>Parent:</td>
319
+ <td>
320
+ IF:par_url
321
+ <a href="%par_url%">
322
+ ENDIF:par_url
323
+ %parent%
324
+ IF:par_url
325
+ </a>
326
+ ENDIF:par_url
327
+ </td>
328
+ </tr>
329
+ ENDIF:parent
330
+ </table>
331
+ </td>
332
+ </tr>
333
+ </table>
334
+ HTML
335
+
336
+ ###################################################################
337
+
338
+ METHOD_LIST = <<HTML
339
+ <div id="content">
340
+ IF:diagram
341
+ <table cellpadding='0' cellspacing='0' border='0' width="100%"><tr><td align="center">
342
+ %diagram%
343
+ </td></tr></table>
344
+ ENDIF:diagram
345
+
346
+ IF:description
347
+ <div class="description">%description%</div>
348
+ ENDIF:description
349
+
350
+ IF:requires
351
+ <div class="sectiontitle">Required Files</div>
352
+ <ul>
353
+ START:requires
354
+ <li>HREF:aref:name:</li>
355
+ END:requires
356
+ </ul>
357
+ ENDIF:requires
358
+
359
+ IF:toc
360
+ <div class="sectiontitle">Contents</div>
361
+ <ul>
362
+ START:toc
363
+ <li><a href="#%href%">%secname%</a></li>
364
+ END:toc
365
+ </ul>
366
+ ENDIF:toc
367
+
368
+ IF:methods
369
+ <div class="sectiontitle">Methods</div>
370
+ <ul>
371
+ START:methods
372
+ <li>HREF:aref:name:</li>
373
+ END:methods
374
+ </ul>
375
+ ENDIF:methods
376
+
377
+ IF:includes
378
+ <div class="sectiontitle">Included Modules</div>
379
+ <ul>
380
+ START:includes
381
+ <li>HREF:aref:name:</li>
382
+ END:includes
383
+ </ul>
384
+ ENDIF:includes
385
+
386
+ START:sections
387
+ IF:sectitle
388
+ <div class="sectiontitle"><a name="%secsequence%">%sectitle%</a></div>
389
+ IF:seccomment
390
+ <div class="description">
391
+ %seccomment%
392
+ </div>
393
+ ENDIF:seccomment
394
+ ENDIF:sectitle
395
+
396
+ IF:classlist
397
+ <div class="sectiontitle">Classes and Modules</div>
398
+ %classlist%
399
+ ENDIF:classlist
400
+
401
+ IF:constants
402
+ <div class="sectiontitle">Constants</div>
403
+ <table border='0' cellpadding='5'>
404
+ START:constants
405
+ <tr valign='top'>
406
+ <td class="attr-name">%name%</td>
407
+ <td>=</td>
408
+ <td class="attr-value">%value%</td>
409
+ </tr>
410
+ IF:desc
411
+ <tr valign='top'>
412
+ <td>&nbsp;</td>
413
+ <td colspan="2" class="attr-desc">%desc%</td>
414
+ </tr>
415
+ ENDIF:desc
416
+ END:constants
417
+ </table>
418
+ ENDIF:constants
419
+
420
+ IF:attributes
421
+ <div class="sectiontitle">Attributes</div>
422
+ <table border='0' cellpadding='5'>
423
+ START:attributes
424
+ <tr valign='top'>
425
+ <td class='attr-rw'>
426
+ IF:rw
427
+ [%rw%]
428
+ ENDIF:rw
429
+ </td>
430
+ <td class='attr-name'>%name%</td>
431
+ <td class='attr-desc'>%a_desc%</td>
432
+ </tr>
433
+ END:attributes
434
+ </table>
435
+ ENDIF:attributes
436
+
437
+ IF:method_list
438
+ START:method_list
439
+ IF:methods
440
+ <div class="sectiontitle">%type% %category% methods</div>
441
+ START:methods
442
+ <div class="method">
443
+ <div class="title">
444
+ IF:callseq
445
+ <a name="%aref%"></a><b>%callseq%</b>
446
+ ENDIF:callseq
447
+ IFNOT:callseq
448
+ <a name="%aref%"></a><b>%name%</b>%params%
449
+ ENDIF:callseq
450
+ IF:codeurl
451
+ [&nbsp;<a href="%codeurl%" target="SOURCE_CODE" onclick="javascript:openCode('%codeurl%'); return false;">source</a>&nbsp;]
452
+ ENDIF:codeurl
453
+ </div>
454
+ IF:m_desc
455
+ <div class="description">
456
+ %m_desc%
457
+ </div>
458
+ ENDIF:m_desc
459
+ IF:aka
460
+ <div class="aka">
461
+ This method is also aliased as
462
+ START:aka
463
+ <a href="%aref%">%name%</a>
464
+ END:aka
465
+ </div>
466
+ ENDIF:aka
467
+ IF:sourcecode
468
+ <div class="sourcecode">
469
+ <p class="source-link">[ <a href="javascript:toggleSource('%aref%_source')" id="l_%aref%_source">show source</a> ]</p>
470
+ <div id="%aref%_source" class="dyn-source">
471
+ <pre>
472
+ %sourcecode%
473
+ </pre>
474
+ </div>
475
+ </div>
476
+ ENDIF:sourcecode
477
+ </div>
478
+ END:methods
479
+ ENDIF:methods
480
+ END:method_list
481
+ ENDIF:method_list
482
+ END:sections
483
+ </div>
484
+ HTML
485
+
486
+ FOOTER = <<ENDFOOTER
487
+ </body>
488
+ </html>
489
+ ENDFOOTER
490
+
491
+ BODY = HEADER + <<ENDBODY
492
+ !INCLUDE! <!-- banner header -->
493
+
494
+ <div id="bodyContent">
495
+ #{METHOD_LIST}
496
+ </div>
497
+
498
+ #{FOOTER}
499
+ ENDBODY
500
+
501
+ ########################## Source code ##########################
502
+
503
+ SRC_PAGE = XHTML_PREAMBLE + <<HTML
504
+ <html>
505
+ <head><title>%title%</title>
506
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
507
+ <style type="text/css">
508
+ .ruby-comment { color: green; font-style: italic }
509
+ .ruby-constant { color: #4433aa; font-weight: bold; }
510
+ .ruby-identifier { color: #222222; }
511
+ .ruby-ivar { color: #2233dd; }
512
+ .ruby-keyword { color: #3333FF; font-weight: bold }
513
+ .ruby-node { color: #777777; }
514
+ .ruby-operator { color: #111111; }
515
+ .ruby-regexp { color: #662222; }
516
+ .ruby-value { color: #662222; font-style: italic }
517
+ .kw { color: #3333FF; font-weight: bold }
518
+ .cmt { color: green; font-style: italic }
519
+ .str { color: #662222; font-style: italic }
520
+ .re { color: #662222; }
521
+ </style>
522
+ </head>
523
+ <body bgcolor="white">
524
+ <pre>%code%</pre>
525
+ </body>
526
+ </html>
527
+ HTML
528
+
529
+ ########################## Index ################################
530
+
531
+ FR_INDEX_BODY = <<HTML
532
+ !INCLUDE!
533
+ HTML
534
+
535
+ FILE_INDEX = XHTML_PREAMBLE + <<HTML
536
+ <html>
537
+ <head>
538
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
539
+ <title>Index</title>
540
+ <style type="text/css">
541
+ <!--
542
+ body {
543
+ background-color: #EEE;
544
+ font-family: #{FONTS};
545
+ color: #000;
546
+ margin: 0px;
547
+ }
548
+ .banner {
549
+ background: #005;
550
+ color: #FFF;
551
+ padding: 0.2em;
552
+ font-size: small;
553
+ font-weight: bold;
554
+ text-align: center;
555
+ }
556
+ .entries {
557
+ margin: 0.25em 1em 0 1em;
558
+ font-size: x-small;
559
+ }
560
+ a {
561
+ color: #00F;
562
+ text-decoration: none;
563
+ white-space: nowrap;
564
+ }
565
+ a:hover {
566
+ color: #77F;
567
+ text-decoration: underline;
568
+ }
569
+ -->
570
+ </style>
571
+ <base target="docwin" />
572
+ </head>
573
+ <body>
574
+ <div class="banner">%list_title%</div>
575
+ <div class="entries">
576
+ START:entries
577
+ <a href="%href%">%name%</a><br />
578
+ END:entries
579
+ </div>
580
+ </body></html>
581
+ HTML
582
+
583
+ CLASS_INDEX = FILE_INDEX
584
+ METHOD_INDEX = FILE_INDEX
585
+
586
+ INDEX = XHTML_FRAMESET_PREAMBLE + <<HTML
587
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
588
+ <head>
589
+ <title>%title%</title>
590
+ <meta http-equiv="Content-Type" content="text/html; charset=%charset%" />
591
+ </head>
592
+
593
+ <frameset cols="20%,*">
594
+ <frameset rows="15%,55%,30%">
595
+ <frame src="fr_file_index.html" title="Files" name="Files" />
596
+ <frame src="fr_class_index.html" name="Classes" />
597
+ <frame src="fr_method_index.html" name="Methods" />
598
+ </frameset>
599
+ <frame src="%initial_page%" name="docwin" />
600
+ <noframes>
601
+ <body bgcolor="white">
602
+ Click <a href="html/index.html">here</a> for a non-frames
603
+ version of this page.
604
+ </body>
605
+ </noframes>
606
+ </frameset>
607
+
608
+ </html>
609
+ HTML
610
+
611
+ end
612
+ end
613
+