slippers 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/LICENSE +20 -0
  2. data/README +56 -0
  3. data/Rakefile +27 -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 +30 -0
  8. data/examples/blog/model/entry.rb +31 -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 +19 -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/forms/Rakefile +22 -0
  22. data/examples/forms/controller/init.rb +12 -0
  23. data/examples/forms/controller/main.rb +20 -0
  24. data/examples/forms/controller/registration.rb +24 -0
  25. data/examples/forms/forms.db +0 -0
  26. data/examples/forms/model/core_extensions/string_extensions.rb +5 -0
  27. data/examples/forms/model/field.rb +33 -0
  28. data/examples/forms/model/form.rb +33 -0
  29. data/examples/forms/model/init.rb +18 -0
  30. data/examples/forms/model/orm/registration.rb +12 -0
  31. data/examples/forms/model/registration_form_builder.rb +7 -0
  32. data/examples/forms/model/registration_repository.rb +39 -0
  33. data/examples/forms/model/registration_rules/incorrect_email_format.rb +11 -0
  34. data/examples/forms/model/registration_rules/number_field.rb +10 -0
  35. data/examples/forms/model/registration_rules/required_field.rb +9 -0
  36. data/examples/forms/model/registration_validator.rb +17 -0
  37. data/examples/forms/public/css/ramaze_error.css +90 -0
  38. data/examples/forms/public/dispatch.fcgi +11 -0
  39. data/examples/forms/public/favicon.ico +0 -0
  40. data/examples/forms/public/js/jquery.js +3549 -0
  41. data/examples/forms/public/ramaze.png +0 -0
  42. data/examples/forms/public/web-application.js +0 -0
  43. data/examples/forms/spec/form_spec.rb +16 -0
  44. data/examples/forms/spec/main.rb +25 -0
  45. data/examples/forms/spec/registration_controller_spec.rb +0 -0
  46. data/examples/forms/spec/registration_repository_spec.rb +38 -0
  47. data/examples/forms/spec/registration_validator_spec.rb +53 -0
  48. data/examples/forms/spec/spec_helper.rb +3 -0
  49. data/examples/forms/start.rb +12 -0
  50. data/examples/forms/start.ru +16 -0
  51. data/examples/forms/view/error.xhtml +64 -0
  52. data/examples/forms/view/index.xhtml +34 -0
  53. data/examples/forms/view/page.xhtml +27 -0
  54. data/examples/forms/view/registration/index.st +26 -0
  55. data/examples/main_controller.rb +40 -0
  56. data/examples/start.rb +7 -0
  57. data/examples/todolist/README +1 -0
  58. data/examples/todolist/controller/main.rb +71 -0
  59. data/examples/todolist/layout/page.rb +31 -0
  60. data/examples/todolist/model/tasks.rb +14 -0
  61. data/examples/todolist/public/favicon.ico +0 -0
  62. data/examples/todolist/public/js/jquery.js +1923 -0
  63. data/examples/todolist/public/ramaze.png +0 -0
  64. data/examples/todolist/start.rb +11 -0
  65. data/examples/todolist/todolist.db +11 -0
  66. data/examples/todolist/view/index.st +39 -0
  67. data/examples/todolist/view/index.xhtml +17 -0
  68. data/examples/todolist/view/new.st +41 -0
  69. data/examples/todolist/view/new.xhtml +7 -0
  70. data/examples/todolist/view/tasks.st +6 -0
  71. data/examples/todolist.db +5 -0
  72. data/examples/view/index.st +11 -0
  73. data/examples/view/person/age.st +1 -0
  74. data/examples/view/person/age_renderer.rb +6 -0
  75. data/examples/view/person/index.st +2 -0
  76. data/lib/engine/binding_wrapper.rb +10 -0
  77. data/lib/engine/engine.rb +28 -0
  78. data/lib/engine/file_template.rb +12 -0
  79. data/lib/engine/slippers.treetop +169 -0
  80. data/lib/engine/slippers_nodes.rb +119 -0
  81. data/lib/engine/template.rb +17 -0
  82. data/lib/engine/template_group.rb +40 -0
  83. data/lib/engine/template_group_directory.rb +57 -0
  84. data/lib/ramazeTemplates/0001-Adding-slippers-as-a-new-template.patch +138 -0
  85. data/lib/ramazeTemplates/0002-Fixing-problem-with-using-other-renderers.patch +27 -0
  86. data/lib/ramazeTemplates/slippers.rb +22 -0
  87. data/lib/slippers.rb +14 -0
  88. data/spec/binding_wrapper.rb +19 -0
  89. data/spec/engine.rb +89 -0
  90. data/spec/file_template.rb +9 -0
  91. data/spec/parse_attributes.rb +98 -0
  92. data/spec/parse_renderers.rb +35 -0
  93. data/spec/parse_templates.rb +73 -0
  94. data/spec/person_template.st +1 -0
  95. data/spec/spec_helper.rb +14 -0
  96. data/spec/template_group.rb +52 -0
  97. data/spec/template_group_directory.rb +43 -0
  98. data/spec/views/index.st +1 -0
  99. data/spec/views/money.rb +2 -0
  100. data/spec/views/person/age.st +1 -0
  101. data/spec/views/person/date_renderer.rb +5 -0
  102. data/spec/views/person/name.st +1 -0
  103. metadata +218 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 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,56 @@
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 statements 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 an 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 an 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'}) #=> "This is a template and then this is a subtemplate with a message of hello world!"
36
+
37
+ 6. Render a subtemplate using a different rendering technology
38
+ age_renderer = AgeRenderer.new
39
+ subtemplate = Slippers::Engine.new('$first$ $last$')
40
+ person = OpenStruct.new({:name => {:first => 'Fred', :last => 'Flinstone'}, :dob => Date.new(DateTime.now.year - 34, 2, 4)})
41
+ template_group = Slippers::TemplateGroup.new(:templates => {:name => subtemplate, :age => age_renderer})
42
+ engine = Slippers::Engine.new("Introducing $name:name()$ who is $dob:age()$.", :template_group => template_group)
43
+ engine.render(person) #=> "Introducing Fred Flinstone who is 34 years old."
44
+
45
+ 7. Select a renderer based on the type of the object to render
46
+ person = OpenStruct.new({:name => {:first => 'Fred', :last => 'Flinstone'}, :dob => Date.new(DateTime.now.year-34, 2, 4)})
47
+ template_group = Slippers::TemplateGroup.new(:templates => {:name => Slippers::Engine.new('$first$ $last$'), Date => AgeRenderer.new})
48
+ engine = Slippers::Engine.new("Introducing $name:name()$ who is $dob$.", :template_group => template_group)
49
+ engine.render(person) #=> "Introducing Fred Flinstone who is 34 years old."
50
+
51
+ 8. Use the specified expression options to render list items
52
+ template = 'This is a list of values $values; null="-1", seperator=", "$'
53
+ engine = Slippers::Engine.new(template)
54
+ engine.render(:values => [1,2,3,nil]) #=> "This is a list of values 1, 2, 3, -1"
55
+
56
+
data/Rakefile ADDED
@@ -0,0 +1,27 @@
1
+ load File.expand_path(File.dirname(__FILE__) + "/tasks/spec.rake")
2
+ #load File.expand_path(File.dirname(__FILE__) + "/tasks/git.rake")
3
+
4
+ require 'rake'
5
+ require 'spec/rake/spectask'
6
+
7
+ desc "Generate the gem using technicalpickles jeweler"
8
+ begin
9
+ require 'jeweler'
10
+ Jeweler::Tasks.new do |gem|
11
+ gem.name = "slippers"
12
+ gem.summary = "A strict templating library for Ruby"
13
+ gem.email = "me@sarahtaraporewalla.com"
14
+ gem.homepage = "http://github.com/starapor/slippers"
15
+ gem.description = "A strict templating library for ruby"
16
+ gem.authors = ["Sarah Taraporewalla"]
17
+ gem.files = FileList["[A-Z]*", "{bin,lib,spec,examples}/**/*"]
18
+ gem.add_dependency 'schacon-git'
19
+ gem.add_dependency 'treetop'
20
+ end
21
+ Jeweler::GemcutterTasks.new
22
+ rescue LoadError
23
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
24
+ end
25
+
26
+ task :default => "spec:run"
27
+
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :patch: 10
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,30 @@
1
+ class MainController < Ramaze::Controller
2
+ layout '/layout'
3
+ engine :Slippers
4
+
5
+ def index
6
+ @entries = Entry.order(:created.desc).all
7
+ end
8
+
9
+ def delete id
10
+ entry = Entry[id]
11
+ entry.delete
12
+ redirect :/
13
+ end
14
+
15
+ def edit id
16
+ @entry = Entry[id]
17
+ redirect_referrer unless @entry
18
+ end
19
+
20
+ def create
21
+ Entry.add(*request[:title, :content])
22
+ redirect :/
23
+ end
24
+
25
+ def save
26
+ redirect_referer unless entry = Entry[request[:id]]
27
+ entry.update(*request[:title, :content])
28
+ redirect :/
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ require 'sequel'
2
+ Sequel::Model.plugin(:schema)
3
+
4
+ DB = Sequel.connect("sqlite:///#{__DIR__}/../blog.db")
5
+
6
+ class Entry < Sequel::Model(:entry)
7
+ set_schema do
8
+ primary_key :id
9
+
10
+ time :created
11
+ time :updated
12
+ text :title
13
+ text :content
14
+ end
15
+
16
+ def self.add(title, content)
17
+ create :title => title, :content => content,
18
+ :created => Time.now, :updated => Time.now
19
+ end
20
+
21
+ def update(title = title, content = content)
22
+ self.title, self.content, self.updated = title, content, Time.now
23
+ save
24
+ end
25
+ end
26
+
27
+ Entry.create_table! unless Entry.table_exists?
28
+
29
+ if Entry.empty?
30
+ Entry.add 'Blog created', 'Exciting news today, this blog was created'
31
+ 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,19 @@
1
+ <h2>Editing entry</h2>
2
+ <div id="entries">
3
+ <div class="entry">
4
+ $entry:{
5
+ <form method="post" action="/save">
6
+ <input name="id" type="hidden" value="$id$"/>
7
+ <div class="header">
8
+ <div class="title">
9
+ <input name="title" type="text" value="$title$"/>
10
+ </div>
11
+ </div>
12
+ <div class="content">
13
+ <textarea name="content">$content$</textarea>
14
+ </div>
15
+ <input type="submit" value="Update Entry"/>
16
+ </form>
17
+ }$
18
+ </div>
19
+ </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</a></li>
7
+ <li><a href='/delete/$id$'>delete</a></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,22 @@
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['spec/**/*_spec.rb']
7
+ end
8
+
9
+ require 'spec/rake/spectask'
10
+ Spec::Rake::SpecTask.new(:spec) do |t|
11
+ t.libs << 'lib' << 'spec'
12
+ t.spec_files = FileList['spec/**/*.rb']
13
+ end
14
+
15
+ Spec::Rake::SpecTask.new(:rcov) do |t|
16
+ t.libs << 'lib' << 'spec'
17
+ t.spec_files = FileList['spec/**/*_spec.rb']
18
+ t.rcov = true
19
+ end
20
+
21
+
22
+ task :default => :examples
@@ -0,0 +1,12 @@
1
+ # Define a subclass of Ramaze::Controller holding your defaults for all
2
+ # controllers
3
+
4
+ class Controller < Ramaze::Controller
5
+ layout '/page'
6
+ helper :xhtml
7
+ engine :Slippers
8
+ end
9
+
10
+ # Here go your requires for subclasses of Controller:
11
+ require 'controller/main'
12
+ require 'controller/registration'
@@ -0,0 +1,20 @@
1
+ # Default url mappings are:
2
+ # a controller called Main is mapped on the root of the site: /
3
+ # a controller called Something is mapped on: /something
4
+ # If you want to override this, add a line like this inside the class
5
+ # map '/otherurl'
6
+ # this will force the controller to be mounted on: /otherurl
7
+
8
+ class MainController < Controller
9
+ # the index action is called automatically when no other action is specified
10
+ def index
11
+ @title = "Welcome to Ramaze!"
12
+ end
13
+
14
+ # the string returned at the end of the function is used as the html body
15
+ # if there is no template for the action. if there is a template, the string
16
+ # is silently ignored
17
+ def notemplate
18
+ "there is no 'notemplate.xhtml' associated with this action"
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ class RegistrationController < Controller
2
+
3
+ def initialize
4
+ @registrationRepository = RegistrationRepository.new
5
+ @registrationValidator = RegistrationValidator.new
6
+ end
7
+ def index
8
+ key = request[:key]
9
+ @form = @registrationRepository.find(key)
10
+ @message = flash[:message] if flash[:message]
11
+ end
12
+
13
+ def save
14
+ key=request[:key]
15
+ form = @registrationRepository.find(key)
16
+ form.update(:name => request[:name], :address => request[:address], :email => request[:email], :phone => request[:phone])
17
+
18
+ @registrationValidator.validate(form)
19
+
20
+ @registrationRepository.save(form)
21
+ flash[:message] = "Saved!"
22
+ redirect route('/registration', :index, :key=>form[:key])
23
+ end
24
+ end
Binary file
@@ -0,0 +1,5 @@
1
+ class String
2
+ def is_numeric?
3
+ true if Float(object) rescue false
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ class Field
2
+
3
+ def initialize(key, value)
4
+ @key = key
5
+ @value = value
6
+ @errors = []
7
+ end
8
+
9
+ def update(value)
10
+ @value = value
11
+ end
12
+
13
+ def value
14
+ @value
15
+ end
16
+
17
+ def is?(key)
18
+ @key == key
19
+ end
20
+
21
+ def is_valid?
22
+ @errors.empty?
23
+ end
24
+
25
+ def invalid(error)
26
+ @errors << error
27
+ end
28
+
29
+ def errors
30
+ @errors
31
+ end
32
+
33
+ end