starapor-slippers 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/LICENSE +20 -0
  2. data/README +35 -0
  3. data/Rakefile +61 -0
  4. data/VERSION.yml +4 -0
  5. data/examples/blog/README +3 -0
  6. data/examples/blog/blog.db +0 -0
  7. data/examples/blog/controller/main.rb +29 -0
  8. data/examples/blog/model/entry.rb +30 -0
  9. data/examples/blog/public/styles/blog.css +132 -0
  10. data/examples/blog/spec/blog.rb +87 -0
  11. data/examples/blog/start.rb +7 -0
  12. data/examples/blog/view/edit.st +17 -0
  13. data/examples/blog/view/edit.xhtml +17 -0
  14. data/examples/blog/view/entry.st +12 -0
  15. data/examples/blog/view/index.st +4 -0
  16. data/examples/blog/view/index.xhtml +17 -0
  17. data/examples/blog/view/layout.st +11 -0
  18. data/examples/blog/view/layout.xhtml +11 -0
  19. data/examples/blog/view/new.st +16 -0
  20. data/examples/blog/view/new.xhtml +16 -0
  21. data/examples/main_controller.rb +16 -0
  22. data/examples/start.rb +7 -0
  23. data/examples/todolist/README +1 -0
  24. data/examples/todolist/public/favicon.ico +0 -0
  25. data/examples/todolist/public/js/jquery.js +1923 -0
  26. data/examples/todolist/public/ramaze.png +0 -0
  27. data/examples/todolist/spec/todolist.rb +133 -0
  28. data/examples/todolist/src/controller/main.rb +71 -0
  29. data/examples/todolist/src/element/page.rb +31 -0
  30. data/examples/todolist/src/model.rb +14 -0
  31. data/examples/todolist/start.rb +11 -0
  32. data/examples/todolist/template/index.st +39 -0
  33. data/examples/todolist/template/index.xhtml +17 -0
  34. data/examples/todolist/template/new.st +41 -0
  35. data/examples/todolist/template/new.xhtml +7 -0
  36. data/examples/todolist/template/tasks.st +6 -0
  37. data/examples/todolist/todolist.db +7 -0
  38. data/examples/todolist.db +5 -0
  39. data/examples/view/index.st +8 -0
  40. data/examples/view/person/age.st +1 -0
  41. data/examples/view/person/index.st +2 -0
  42. data/examples/view/person/name.st +1 -0
  43. data/lib/engine/binding_wrapper.rb +10 -0
  44. data/lib/engine/engine.rb +26 -0
  45. data/lib/engine/file_template.rb +12 -0
  46. data/lib/engine/slippers.treetop +109 -0
  47. data/lib/engine/slippers_nodes.rb +90 -0
  48. data/lib/engine/template.rb +17 -0
  49. data/lib/engine/template_group.rb +20 -0
  50. data/lib/engine/template_group_directory.rb +39 -0
  51. data/lib/ramazeTemplates/0001-SarahTaraporewalla-adding-new-template-file-for-sli.patch +25 -0
  52. data/lib/ramazeTemplates/slippers.rb +25 -0
  53. data/lib/slippers.rb +14 -0
  54. data/spec/binding_wrapper.rb +14 -0
  55. data/spec/engine.rb +76 -0
  56. data/spec/file_template.rb +9 -0
  57. data/spec/parser.rb +111 -0
  58. data/spec/person_template.st +1 -0
  59. data/spec/slippers_spec.rb +5 -0
  60. data/spec/spec_helper.rb +14 -0
  61. data/spec/template_group.rb +24 -0
  62. data/spec/template_group_directory.rb +38 -0
  63. data/spec/views/index.st +1 -0
  64. data/spec/views/money.rb +2 -0
  65. data/spec/views/person/age.st +1 -0
  66. data/spec/views/person/date_renderer.rb +5 -0
  67. data/spec/views/person/name.st +1 -0
  68. metadata +151 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 starapor
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 ADDED
@@ -0,0 +1,35 @@
1
+ There are many template engines that you can choose for the generation of views in your mvc application. The problem with most of the them, however, is that they are too permissive. These turing-complete engines allow for many complex constructs within the template, which begin at simple if statement and for loops, and expand to complex object traversal. While these permissive languages are intended to offer great flexibility, in reality they promote bad practices. Allowing logic to permeate your view is bad for many reasons: firstly, the code in views is rarely tested; secondly, the separation between the models and the view blurs and business logic creeps into the view.
2
+
3
+ All we want our template engine to do is read a string which has holes in it, and replace those holes with the desired string, much like mail merge. String Template is a template engine originally for Java but now ported to C# and python, which enforces strict separation of model and view by only supporting these strings with holes. Unfortunately, it has not been ported to ruby...until now.
4
+
5
+ Introducing...Slippers, a strict template engine for ruby. Slippers supports the syntax from string template.
6
+
7
+ Examples
8
+ 1. Rendering template of a string without any holes
9
+ template = "This is a string without any holes in it"
10
+ engine = Slippers::Engine.new(template)
11
+ engine.render #=> "This is a string without any holes in it"
12
+
13
+ 2. Filling in a hole within a template
14
+ template = "This is a string with a message of $message$"
15
+ engine = Slippers::Engine.new(template)
16
+ engine.render(:message => "hello world") #=> "This is a string with a message of hello world"
17
+
18
+ 3. Rendering a subtemplate within a template
19
+ subtemplate = Slippers::Template.new("this is a subtemplate")
20
+ template_group = Slippers::TemplateGroup.new(:templates => {:message => subtemplate})
21
+ template = "This is a template and then $message()$"
22
+ engine = Slippers::Engine.new(template, :template_group => template_group)
23
+ engine.render #=> "This is a template and then this is a subtemplate"
24
+
25
+ 4. Applying a new object to a subtemplate
26
+ subtemplate = Slippers::Template.new("this is a subtemplate with a message of $saying$")
27
+ template_group = Slippers::TemplateGroup.new(:templates => {:message_subtemplate => subtemplate})
28
+ template = "This is a template and then $message:message_subtemplate()$!"
29
+ engine = Slippers::Engine.new(template, :template_group => template_group)
30
+ engine.render(:message => {:saying => 'hello world'}) #=> "This is a template and then this is a subtemplate with a message of hello world!"
31
+
32
+ 5. Applying a new object to an anonymous subtemplate
33
+ template = "This is a template and then $message:{this is a subtemplate with a message of $saying$}$!"
34
+ engine = Slippers::Engine.new(template)
35
+ engine.render(:message => {:saying => 'hello world'}).should eql("This is a template and then this is a subtemplate with a message of hello world!")
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ desc "Run all examples"
5
+ Spec::Rake::SpecTask.new('examples') do |t|
6
+ t.spec_files = FileList['engine/spec/**/*.rb']
7
+ end
8
+
9
+ desc "Generate HTML report for failing examples"
10
+ Spec::Rake::SpecTask.new('failing_examples_with_html') do |t|
11
+ t.spec_files = FileList['failing_examples/**/*.rb']
12
+ t.spec_opts = ["--format", "html:doc/reports/tools/failing_examples.html", "--diff"]
13
+ t.fail_on_error = false
14
+ end
15
+
16
+ desc "Generate the gem using technicalpickles jeweler"
17
+ begin
18
+ require 'jeweler'
19
+ Jeweler::Tasks.new do |gem|
20
+ gem.name = "slippers"
21
+ gem.summary = "A strict templating library for Ruby"
22
+ gem.email = "me@sarahtaraporewalla.com"
23
+ gem.homepage = "http://github.com/starapor/slippers"
24
+ gem.description = "A strict templating library for ruby"
25
+ gem.authors = ["Sarah Taraporewalla"]
26
+ gem.files = FileList["[A-Z]*", "{bin,lib,spec,examples}/**/*"]
27
+ gem.add_dependency 'schacon-git'
28
+ end
29
+ rescue LoadError
30
+ puts "Slippers, or one of its dependencies, is not available. Install it with: sudo gem install starapor-slippers -s http://gems.github.com"
31
+ end
32
+
33
+ require 'rake/rdoctask'
34
+ Rake::RDocTask.new do |rdoc|
35
+ rdoc.rdoc_dir = 'rdoc'
36
+ rdoc.title = 'slippers'
37
+ rdoc.options << '--line-numbers' << '--inline-source'
38
+ rdoc.rdoc_files.include('README*')
39
+ rdoc.rdoc_files.include('lib/**/*.rb')
40
+ end
41
+
42
+ require 'spec/rake/spectask'
43
+ Spec::Rake::SpecTask.new(:spec) do |t|
44
+ t.libs << 'lib' << 'spec'
45
+ t.spec_files = FileList['spec/**/*.rb']
46
+ end
47
+
48
+ Spec::Rake::SpecTask.new(:rcov) do |t|
49
+ t.libs << 'lib' << 'spec'
50
+ t.spec_files = FileList['spec/**/*_spec.rb']
51
+ t.rcov = true
52
+ end
53
+
54
+ begin
55
+ require 'cucumber/rake/task'
56
+ Cucumber::Rake::Task.new(:features)
57
+ rescue LoadError
58
+ puts "Cucumber is not available. In order to run features, you must: sudo gem install cucumber"
59
+ end
60
+
61
+ task :default => :spec
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 0
3
+ :major: 0
4
+ :minor: 0
@@ -0,0 +1,3 @@
1
+ A simple blog engine that uses Sequel as the persistence layer.
2
+ Sequel uses sqlite as the default DBMS engine and will create the database
3
+ automatically on startup.
Binary file
@@ -0,0 +1,29 @@
1
+ class MainController < Ramaze::Controller
2
+ layout '/layout'
3
+
4
+ def index
5
+ @entries = Entry.order(:created.desc).all
6
+ end
7
+
8
+ def delete id
9
+ entry = Entry[id]
10
+ entry.delete
11
+ redirect :/
12
+ end
13
+
14
+ def edit id
15
+ @entry = Entry[id]
16
+ redirect_referrer unless @entry
17
+ end
18
+
19
+ def create
20
+ Entry.add(*request[:title, :content])
21
+ redirect :/
22
+ end
23
+
24
+ def save
25
+ redirect_referer unless entry = Entry[request[:id]]
26
+ entry.update(*request[:title, :content])
27
+ redirect :/
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ require 'sequel'
2
+
3
+ DB = Sequel.connect("sqlite:///#{__DIR__}/../blog.db")
4
+
5
+ class Entry < Sequel::Model(:entry)
6
+ set_schema do
7
+ primary_key :id
8
+
9
+ time :created
10
+ time :updated
11
+ text :title
12
+ text :content
13
+ end
14
+
15
+ def self.add(title, content)
16
+ create :title => title, :content => content,
17
+ :created => Time.now, :updated => Time.now
18
+ end
19
+
20
+ def update(title = title, content = content)
21
+ self.title, self.content, self.updated = title, content, Time.now
22
+ save
23
+ end
24
+ end
25
+
26
+ Entry.create_table! unless Entry.table_exists?
27
+
28
+ if Entry.empty?
29
+ Entry.add 'Blog created', 'Exciting news today, this blog was created'
30
+ end
@@ -0,0 +1,132 @@
1
+ body {
2
+ margin: 0;
3
+ padding: 0;
4
+ }
5
+
6
+ h1 {
7
+ background: #FFC;
8
+ margin: 0;
9
+ padding: 0.25em 3em 0.25em 0.25em;
10
+ font-size: 32pt;
11
+ text-align: right;
12
+ color: #884;
13
+ border-bottom: 1px solid #004;
14
+ }
15
+
16
+ h2 {
17
+ margin: 8pt 0 0 0;
18
+ padding: 0 8pt 4pt 8pt;
19
+ font-size: 24pt;
20
+ color: #884;
21
+ }
22
+
23
+ div#actions {
24
+ margin: -1px 8pt 0 0;
25
+ padding: 2pt 8pt 4pt 8pt;
26
+ float: right;
27
+ background: #FFC;
28
+ border-style: solid;
29
+ border-width: 0 2px 2px 1px;
30
+ border-color: 0 #004 #004 #448;
31
+ font-size: 10pt;
32
+ color: #884;
33
+ }
34
+
35
+ div#actions a {
36
+ color: inherit;
37
+ text-decoration: none;
38
+ }
39
+
40
+ div#actions a:hover {
41
+ color: black;
42
+ }
43
+
44
+ div#entries {
45
+ margin: 0pt 20pt 10pt 12pt;
46
+ }
47
+
48
+ div.entry {
49
+ margin: 10pt 0 0 0;
50
+ padding: 0;
51
+ background-color: #FFD;
52
+ border-left: 8pt solid #CC8;
53
+ border-top: 1px solid #CC8;
54
+ }
55
+
56
+ div.entry div.header {
57
+ background-color: #EEA;
58
+ border-bottom: 1px solid #CC8;
59
+ }
60
+
61
+ div.entry div.header div.title {
62
+ font-size: 18pt;
63
+ color: black;
64
+ padding: 2pt 4pt 2pt 4pt;
65
+ }
66
+
67
+ div.entry div.header div.title input {
68
+ width: 100%;
69
+ border: none;
70
+ font-size: inherit;
71
+ }
72
+
73
+ div.entry div.header ul {
74
+ float: left;
75
+ margin: 0;
76
+ padding: 0;
77
+ }
78
+
79
+ div.entry div.header ul li {
80
+ background-color: #EEA;
81
+ margin: 0 0 0 4pt;
82
+ padding: 0 4pt 0 4pt;
83
+ display: inline;
84
+ border-style: none solid solid solid;
85
+ border-width: 1px;
86
+ border-color: #CC8;
87
+ font-size: 9pt;
88
+ color: #884;
89
+ }
90
+
91
+ div.entry div.header ul li:hover {
92
+ color: black;
93
+ }
94
+
95
+ div.entry div.header ul li a {
96
+ text-decoration: none;
97
+ color: inherit;
98
+ }
99
+
100
+ div.entry div.header div.created {
101
+ float: right;
102
+ font-size: 8pt;
103
+ color: #888;
104
+ margin: 0.25em 0.5em 0 0;
105
+ }
106
+
107
+ div.entry div.content {
108
+ padding: 24pt 16pt 16pt 16pt;
109
+ border-bottom: 1px solid #CC8;
110
+ }
111
+
112
+ div.entry div.content textarea {
113
+ width: 100%;
114
+ border: none;
115
+ font-size: inherit;
116
+ height: 12em;
117
+ margin: -16pt -8pt -8pt -8pt;
118
+ padding: 8pt;
119
+ }
120
+
121
+ div.entry input[type=submit] {
122
+ margin: 4pt 16pt 4pt 4pt;
123
+ border: 1px solid #CC8;
124
+ background-color: #EEC;
125
+ }
126
+
127
+ div.entry div.updated {
128
+ float: right;
129
+ font-size: 8pt;
130
+ color: #888;
131
+ margin: -1.25em 0.5em 0 0;
132
+ }
@@ -0,0 +1,87 @@
1
+ require 'ramaze'
2
+ require 'ramaze/spec/helper'
3
+
4
+ spec_require 'hpricot', 'sequel'
5
+
6
+ $LOAD_PATH.unshift base = __DIR__('..')
7
+ require 'start'
8
+
9
+ describe 'Blog' do
10
+ behaves_like 'http'
11
+ ramaze :public_root => base/:public,
12
+ :view_root => base/:view
13
+
14
+ after do
15
+ Entry.each{|e| e.delete unless e.id == 1 }
16
+ end
17
+
18
+ def check_page(name = '')
19
+ page = get("/#{name}")
20
+ page.status.should == 200
21
+ page.body.should.not == nil
22
+
23
+ doc = Hpricot(page.body)
24
+ doc.at('title').inner_html.should == 'Blog'
25
+ doc.at('h1').inner_html.should == 'Blog'
26
+
27
+ doc.search('div#entries').size.should == 1
28
+
29
+ doc
30
+ end
31
+
32
+ def create_page(title,content)
33
+ page = post('/create','title'=>title,'content'=>content)
34
+ page.status.should == 302
35
+ page.location.should == '/'
36
+ end
37
+
38
+ it 'should have main page' do
39
+ doc = check_page
40
+ doc.at('div#actions>a').inner_html.should == 'new entry'
41
+ doc.search('div.entry').size.should == 1
42
+ end
43
+
44
+ it 'should have new entry page' do
45
+ doc = check_page('new')
46
+ form = doc.at('div.entry>form')
47
+ form.at('input[@name=title]')['value'].should == ''
48
+ form.at('textarea').inner_html.should == ''
49
+ form.at('input[@type=submit]')['value'].should == 'Add Entry'
50
+ end
51
+
52
+ it 'should add new pages' do
53
+ create_page('new page', 'cool! a new page')
54
+ doc = check_page
55
+ entry = doc.search('div.entry')
56
+ entry.size.should == 2
57
+ entry = entry.last
58
+
59
+ entry.at('div.title').inner_html == 'new page'
60
+ entry.at('div.content').inner_html == 'cool! a new page'
61
+ end
62
+
63
+ it 'should edit existing pages' do
64
+ create_page('new page', 'cool! a new page')
65
+ post('/save','id'=>'2','title'=>'new title','content'=>'bla bla')
66
+ doc = check_page
67
+ entries = doc/'div.entry'
68
+ entries.size.should == 2
69
+ entry = entries.first
70
+
71
+ entry.at('div.title').inner_html == 'new title'
72
+ entry.at('div.content').inner_html == 'bla bla'
73
+ end
74
+
75
+ it 'should delete existing pages' do
76
+ create_page("page to delete", 'content')
77
+ entries = check_page/'div.entry'
78
+ entries.size.should == 2
79
+ delete_link = entries.last.at("a:contains('delete')")
80
+ page = get(delete_link[:href])
81
+ page.status.should == 302
82
+ page.location.should == '/'
83
+ (check_page/'div.entry').size.should == 1
84
+ end
85
+
86
+ FileUtils.rm_f(__DIR__('../blog.db'))
87
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'ramaze'
3
+
4
+ require 'model/entry'
5
+ require 'controller/main'
6
+
7
+ Ramaze.start :port => 3000
@@ -0,0 +1,17 @@
1
+ <h2>Editing entry</h2>
2
+ <div id="entries">
3
+ <div class="entry">
4
+ <form method="post" action="/save">
5
+ <input name="id" type="hidden" value="$id$"/>
6
+ <div class="header">
7
+ <div class="title">
8
+ <input name="title" type="text" value="$title$"/>
9
+ </div>
10
+ </div>
11
+ <div class="content">
12
+ <textarea name="content">$content$</textarea>
13
+ </div>
14
+ <input type="submit" value="Update Entry"/>
15
+ </form>
16
+ </div>
17
+ </div>
@@ -0,0 +1,17 @@
1
+ <h2>Editing entry</h2>
2
+ <div id="entries">
3
+ <div class="entry">
4
+ <form method="post" action="#{R self,:save}">
5
+ <input name="id" type="hidden" value="#{@entry.id}"/>
6
+ <div class="header">
7
+ <div class="title">
8
+ <input name="title" type="text" value="#{@entry.title}"/>
9
+ </div>
10
+ </div>
11
+ <div class="content">
12
+ <textarea name="content">#{@entry.content}</textarea>
13
+ </div>
14
+ <input type="submit" value="Update Entry"/>
15
+ </form>
16
+ </div>
17
+ </div>
@@ -0,0 +1,12 @@
1
+ <div class="entry">
2
+ <div class="header">
3
+ <div class="title">$title$</div>
4
+ <div class="created">Created: $created$</div>
5
+ <ul>
6
+ <li><a href='/edit/$id$'>edit</li>
7
+ <li><a href='/delete/$id$'>delete</li>
8
+ </ul>
9
+ </div>
10
+ <div class="content">$content$</div>
11
+ <div class="updated">Last updated: $updated$</div>
12
+ </div>
@@ -0,0 +1,4 @@
1
+ <div id="actions"><a href="/new">new entry</a></div>
2
+ <div id="entries">
3
+ $entries:entry()$
4
+ </div>
@@ -0,0 +1,17 @@
1
+ <div id="actions">#{A 'new entry', :href => Rs(:new)}</div>
2
+ <div id="entries">
3
+ <?r @entries.each do |entry| ?>
4
+ <div class="entry">
5
+ <div class="header">
6
+ <div class="title">#{entry.title}</div>
7
+ <div class="created">Created: #{entry.created}</div>
8
+ <ul>
9
+ <li>#{A 'edit', :href => Rs(:edit, entry.id)}</li>
10
+ <li>#{A 'delete', :href => Rs(:delete, entry.id)}</li>
11
+ </ul>
12
+ </div>
13
+ <div class="content">#{entry.content}</div>
14
+ <div class="updated">Last updated: #{entry.updated}</div>
15
+ </div>
16
+ <?r end ?>
17
+ </div>
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ <title>Blog</title>
4
+ <link rel="stylesheet" href="/styles/blog.css" type="text/css"/>
5
+ </head>
6
+ <body>
7
+ <h1>Blog</h1>
8
+ #@content
9
+ </body>
10
+ </html>
11
+
@@ -0,0 +1,11 @@
1
+ <html>
2
+ <head>
3
+ <title>Blog</title>
4
+ <link rel="stylesheet" href="/styles/blog.css" type="text/css"/>
5
+ </head>
6
+ <body>
7
+ <h1>Blog</h1>
8
+ #@content
9
+ </body>
10
+ </html>
11
+
@@ -0,0 +1,16 @@
1
+ <h2>New entry</h2>
2
+ <div id="entries">
3
+ <div class="entry">
4
+ <form method="post" action="/create">
5
+ <div class="header">
6
+ <div class="title">
7
+ <input name="title" type="text" value=""/>
8
+ </div>
9
+ </div>
10
+ <div class="content">
11
+ <textarea name="content"></textarea>
12
+ </div>
13
+ <input type="submit" value="Add Entry"/>
14
+ </form>
15
+ </div>
16
+ </div>
@@ -0,0 +1,16 @@
1
+ <h2>New entry</h2>
2
+ <div id="entries">
3
+ <div class="entry">
4
+ <form method="post" action="#{R self,:create}">
5
+ <div class="header">
6
+ <div class="title">
7
+ <input name="title" type="text" value=""/>
8
+ </div>
9
+ </div>
10
+ <div class="content">
11
+ <textarea name="content"></textarea>
12
+ </div>
13
+ <input type="submit" value="Add Entry"/>
14
+ </form>
15
+ </div>
16
+ </div>
@@ -0,0 +1,16 @@
1
+ class Person
2
+ def initialize(name, date_of_birth)
3
+ @name, @dob = name, date_of_birth
4
+ end
5
+ attr_reader :name, :dob
6
+ end
7
+
8
+
9
+ class MainController < Ramaze::Controller
10
+ engine :Slippers
11
+
12
+ def index
13
+ @person = Person.new('Sarah', DateTime.new(1983, 9, 2))
14
+ end
15
+ end
16
+
data/examples/start.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'ramaze'
3
+
4
+ require 'main_controller'
5
+
6
+
7
+ Ramaze.start :adapter => :webrick, :port => 7000
@@ -0,0 +1 @@
1
+ A simple ToDo list example that uses Ramaze::Store as the persistence layer.