kiss 1.1 → 1.7
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.
- data/LICENSE +1 -1
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/bin/kiss +151 -34
- data/data/scaffold.tgz +0 -0
- data/lib/kiss.rb +389 -742
- data/lib/kiss/accessors/controller.rb +47 -0
- data/lib/kiss/accessors/request.rb +106 -0
- data/lib/kiss/accessors/template.rb +23 -0
- data/lib/kiss/action.rb +502 -132
- data/lib/kiss/bench.rb +14 -5
- data/lib/kiss/debug.rb +14 -6
- data/lib/kiss/exception_report.rb +22 -299
- data/lib/kiss/ext/core.rb +700 -0
- data/lib/kiss/ext/rack.rb +33 -0
- data/lib/kiss/ext/sequel_database.rb +47 -0
- data/lib/kiss/ext/sequel_mysql_dataset.rb +23 -0
- data/lib/kiss/form.rb +404 -179
- data/lib/kiss/form/field.rb +183 -307
- data/lib/kiss/form/field_types.rb +239 -0
- data/lib/kiss/format.rb +88 -70
- data/lib/kiss/html/exception_report.css +222 -0
- data/lib/kiss/html/exception_report.html +210 -0
- data/lib/kiss/iterator.rb +14 -12
- data/lib/kiss/login.rb +8 -8
- data/lib/kiss/mailer.rb +68 -66
- data/lib/kiss/model.rb +323 -36
- data/lib/kiss/rack/bench.rb +16 -8
- data/lib/kiss/rack/email_errors.rb +25 -15
- data/lib/kiss/rack/errors_ok.rb +2 -2
- data/lib/kiss/rack/facebook.rb +6 -6
- data/lib/kiss/rack/file_not_found.rb +10 -8
- data/lib/kiss/rack/log_exceptions.rb +3 -3
- data/lib/kiss/rack/recorder.rb +2 -2
- data/lib/kiss/rack/show_debug.rb +2 -2
- data/lib/kiss/rack/show_exceptions.rb +2 -2
- data/lib/kiss/request.rb +435 -0
- data/lib/kiss/sequel_session.rb +15 -14
- data/lib/kiss/static_file.rb +20 -13
- data/lib/kiss/template.rb +327 -0
- metadata +60 -25
- data/lib/kiss/controller_accessors.rb +0 -81
- data/lib/kiss/hacks.rb +0 -188
- data/lib/kiss/sequel_mysql.rb +0 -25
- data/lib/kiss/template_methods.rb +0 -167
@@ -0,0 +1,222 @@
|
|
1
|
+
body {
|
2
|
+
margin: 0;
|
3
|
+
}
|
4
|
+
#container {
|
5
|
+
font-size: 12px;
|
6
|
+
padding: 8px;
|
7
|
+
background-color: #611;
|
8
|
+
}
|
9
|
+
#container * {
|
10
|
+
padding: 12px;
|
11
|
+
}
|
12
|
+
#container * * {
|
13
|
+
padding: 0;
|
14
|
+
}
|
15
|
+
#container {
|
16
|
+
font: small sans-serif;
|
17
|
+
}
|
18
|
+
#container > div {
|
19
|
+
border-bottom: 1px solid #cba;
|
20
|
+
}
|
21
|
+
a {
|
22
|
+
color: #b00;
|
23
|
+
}
|
24
|
+
code {
|
25
|
+
white-space: pre-wrap;
|
26
|
+
}
|
27
|
+
h1 {
|
28
|
+
margin: 0;
|
29
|
+
}
|
30
|
+
h2 {
|
31
|
+
font-size: 16px;
|
32
|
+
margin: 0 0 .8em 0;
|
33
|
+
}
|
34
|
+
h2 span {
|
35
|
+
font-size: 80%;
|
36
|
+
color: #000;
|
37
|
+
font-weight: normal;
|
38
|
+
}
|
39
|
+
h3 {
|
40
|
+
margin: 1em 0 .5em 0;
|
41
|
+
}
|
42
|
+
h4 {
|
43
|
+
margin: 0 0 .5em 0;
|
44
|
+
font-weight: normal;
|
45
|
+
}
|
46
|
+
small {
|
47
|
+
color: #444;
|
48
|
+
}
|
49
|
+
table {
|
50
|
+
border: 1px solid #ccc;
|
51
|
+
border-collapse: collapse;
|
52
|
+
background: white;
|
53
|
+
}
|
54
|
+
tbody td, tbody th {
|
55
|
+
vertical-align: top;
|
56
|
+
padding: 2px 3px;
|
57
|
+
}
|
58
|
+
thead th {
|
59
|
+
padding: 1px 6px 1px 3px;
|
60
|
+
background: #fefefe;
|
61
|
+
text-align: left;
|
62
|
+
font-weight: normal;
|
63
|
+
font-size: 9px;
|
64
|
+
border: 1px solid #ddd;
|
65
|
+
}
|
66
|
+
tbody th {
|
67
|
+
text-align: right;
|
68
|
+
padding-right: .5em;
|
69
|
+
}
|
70
|
+
table.vars {
|
71
|
+
margin: 5px 0 2px 40px;
|
72
|
+
}
|
73
|
+
table.vars td, table.req td {
|
74
|
+
font-family: monospace;
|
75
|
+
}
|
76
|
+
table td.code {
|
77
|
+
width: 100%;
|
78
|
+
}
|
79
|
+
table td.code div {
|
80
|
+
overflow: hidden;
|
81
|
+
}
|
82
|
+
table.source th {
|
83
|
+
color: #666;
|
84
|
+
}
|
85
|
+
table.source td {
|
86
|
+
font-family: monospace;
|
87
|
+
white-space: pre;
|
88
|
+
border-bottom: 1px solid #eee;
|
89
|
+
}
|
90
|
+
ul.traceback {
|
91
|
+
list-style-type: none;
|
92
|
+
}
|
93
|
+
ul.traceback li.frame {
|
94
|
+
padding: 8px 4px;
|
95
|
+
border-top: 1px solid #ccc;
|
96
|
+
}
|
97
|
+
div.context {
|
98
|
+
margin: 6px 0 2px 40px;
|
99
|
+
background-color: #fff;
|
100
|
+
}
|
101
|
+
div.context ol {
|
102
|
+
padding: 1px;
|
103
|
+
margin-bottom: -1px;
|
104
|
+
}
|
105
|
+
div.context ol li {
|
106
|
+
font-family: monospace;
|
107
|
+
white-space: pre-wrap;
|
108
|
+
color: #666;
|
109
|
+
cursor: pointer;
|
110
|
+
padding: 0 2px;
|
111
|
+
}
|
112
|
+
div.context ol.context-line li {
|
113
|
+
color: black;
|
114
|
+
background-color: #eca;
|
115
|
+
}
|
116
|
+
div.context ol.context-line li span {
|
117
|
+
float: right;
|
118
|
+
}
|
119
|
+
div.commands {
|
120
|
+
margin-left: 40px;
|
121
|
+
}
|
122
|
+
div.commands a {
|
123
|
+
color: black;
|
124
|
+
text-decoration: none;
|
125
|
+
}
|
126
|
+
#masthead {
|
127
|
+
background-color: #af1111;
|
128
|
+
border-top: 1px solid #d77;
|
129
|
+
padding: 3px 12px 6px 12px;
|
130
|
+
|
131
|
+
font-family: georgia,'times new roman','times',serif;
|
132
|
+
font-weight: normal;
|
133
|
+
font-size: 18px;
|
134
|
+
letter-spacing: -1px;
|
135
|
+
color: #fdc;
|
136
|
+
}
|
137
|
+
#masthead .kiss {
|
138
|
+
color: #fff;
|
139
|
+
font-size: 24px;
|
140
|
+
padding-right: 3px;
|
141
|
+
}
|
142
|
+
#summary {
|
143
|
+
background-color: #fdfbee;
|
144
|
+
}
|
145
|
+
#summary h1 {
|
146
|
+
font-size: 18px;
|
147
|
+
font-weight: normal;
|
148
|
+
font-style: italic;
|
149
|
+
color: #c65;
|
150
|
+
}
|
151
|
+
#summary h2 {
|
152
|
+
font-size: 14px;
|
153
|
+
font-weight: bold;
|
154
|
+
color: #b21;
|
155
|
+
}
|
156
|
+
#summary ul#quicklinks {
|
157
|
+
list-style-type: none;
|
158
|
+
margin: 0 -8px 2em -8px;
|
159
|
+
font-size: 12px
|
160
|
+
}
|
161
|
+
#summary ul#quicklinks li {
|
162
|
+
float: left;
|
163
|
+
padding: 0 8px;
|
164
|
+
}
|
165
|
+
#summary ul#quicklinks>li+li {
|
166
|
+
border-left: 1px #999 solid;
|
167
|
+
}
|
168
|
+
#summary .info td {
|
169
|
+
padding-top: 4px;
|
170
|
+
}
|
171
|
+
#summary .info th {
|
172
|
+
padding: 5px 7px 0 0;
|
173
|
+
font-size: 11px;
|
174
|
+
color: #444;
|
175
|
+
}
|
176
|
+
#template, #template-not-exist {
|
177
|
+
background: #f6f6f6;
|
178
|
+
}
|
179
|
+
#template-not-exist ul {
|
180
|
+
margin: 0 0 0 20px;
|
181
|
+
}
|
182
|
+
#traceback {
|
183
|
+
background: #fff6e0;
|
184
|
+
}
|
185
|
+
#traceback .frame {
|
186
|
+
padding: 6px 0;
|
187
|
+
}
|
188
|
+
#requestinfo {
|
189
|
+
background: #f9ebd4;
|
190
|
+
padding-left: 120px;
|
191
|
+
border: none;
|
192
|
+
}
|
193
|
+
#requestinfo p {
|
194
|
+
margin: 0;
|
195
|
+
}
|
196
|
+
#summary table {
|
197
|
+
border: none;
|
198
|
+
background: transparent;
|
199
|
+
}
|
200
|
+
#requestinfo h2, #requestinfo h3 {
|
201
|
+
position: relative;
|
202
|
+
left: -100px;
|
203
|
+
}
|
204
|
+
#requestinfo h3 {
|
205
|
+
width: 100px;
|
206
|
+
margin-right: -100px;
|
207
|
+
margin-bottom: -1.1em;
|
208
|
+
}
|
209
|
+
#explanation {
|
210
|
+
background: #c11;
|
211
|
+
color: #fed;
|
212
|
+
border-top: 1px solid #e77;
|
213
|
+
border-bottom-color: #711;
|
214
|
+
padding: 6px 12px;
|
215
|
+
}
|
216
|
+
.error {
|
217
|
+
background: #ffc;
|
218
|
+
}
|
219
|
+
.specific {
|
220
|
+
color: #cc3300;
|
221
|
+
font-weight: bold;
|
222
|
+
}
|
@@ -0,0 +1,210 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
2
|
+
|
3
|
+
<!--
|
4
|
+
# adapted from Rack::ShowExceptions
|
5
|
+
# Used under the MIT license
|
6
|
+
#
|
7
|
+
# adapted from Django <djangoproject.com>
|
8
|
+
# Copyright (c) 2005, the Lawrence Journal-World
|
9
|
+
# Used under the modified BSD license:
|
10
|
+
# http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5
|
11
|
+
-->
|
12
|
+
|
13
|
+
<html lang="en">
|
14
|
+
<head>
|
15
|
+
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
16
|
+
<meta name="robots" content="NONE,NOARCHIVE" />
|
17
|
+
<title>Exception: <%=h exception.class %> - <%=h url %></title>
|
18
|
+
<meta http-equiv="exception-message" content="<%= (h exception.message).gsub(/\n/,' ') %>" />
|
19
|
+
<meta http-equiv="exception-where" content="<%= (h frames.first.filename) %>: in <%= h frames.first.function %>, line <%= h frames.first.lineno %>" />
|
20
|
+
<style type="text/css">
|
21
|
+
<%= File.read(template_dir + '/exception_report.css') %>
|
22
|
+
</style>
|
23
|
+
<script type="text/javascript">
|
24
|
+
//<!--
|
25
|
+
function toggle(object_id) {
|
26
|
+
var pre = document.getElementById('pre' + object_id);
|
27
|
+
document.getElementById('post' + object_id).style.display = pre.style.display =
|
28
|
+
pre.style.display == 'none' ? 'block' : 'none';
|
29
|
+
return false;
|
30
|
+
}
|
31
|
+
//-->
|
32
|
+
</script>
|
33
|
+
</head>
|
34
|
+
<body>
|
35
|
+
<div id="container">
|
36
|
+
<div id="masthead">
|
37
|
+
<span class="kiss">Kiss</span>
|
38
|
+
Exception Report
|
39
|
+
</div>
|
40
|
+
<div id="summary">
|
41
|
+
<a name="summary"></a>
|
42
|
+
<h1><%=h exception.class %></h1>
|
43
|
+
<h2><code><%=(h exception.message).gsub(/\n/,'<br>') %></code></h2>
|
44
|
+
<% if env %>
|
45
|
+
<table class="info"><tr>
|
46
|
+
<th>Where</th>
|
47
|
+
<td><code><%=h frames.first.filename %></code>: in <code><%=h frames.first.function %></code>, <a href="<%= textmate_href(frames.first) %>">line <%=h frames.first.lineno %></a></td>
|
48
|
+
</tr><tr>
|
49
|
+
<th><%=h req.request_method %> URL</th>
|
50
|
+
<td><code><%= h(url + (env['rack.request.query_string'] ? "?#{env['rack.request.query_string']}" : '')) %></code></td>
|
51
|
+
</tr><tr>
|
52
|
+
<th>Referer</th>
|
53
|
+
<td><code><%=h env['HTTP_REFERER'] || 'None' %></code></td>
|
54
|
+
</tr><tr>
|
55
|
+
<th>Context</th>
|
56
|
+
<td><ul id="quicklinks">
|
57
|
+
<li><a href="#get-info">GET</a></li>
|
58
|
+
<li><a href="#post-info">POST</a></li>
|
59
|
+
<li><a href="#cache">Cache</a></li>
|
60
|
+
<li><a href="#last-sql">Last SQL</a></li>
|
61
|
+
<li><a href="#cookie-info">Cookies</a></li>
|
62
|
+
<li><a href="#env-info">ENV</a></li>
|
63
|
+
</ul></td>
|
64
|
+
</tr></table>
|
65
|
+
<% end %>
|
66
|
+
</div>
|
67
|
+
|
68
|
+
<div id="traceback">
|
69
|
+
<h2>Traceback <span>(innermost first)</span></h2>
|
70
|
+
<ul class="traceback">
|
71
|
+
<% frames.each { |frame| %>
|
72
|
+
<li class="frame">
|
73
|
+
<a href="<%= textmate_href(frame) %>">line <%= h frame.lineno %></a> of <code><%=w h frame.filename %></code> (in <code><b><%=h frame.function %></b></code>)
|
74
|
+
|
75
|
+
<% if frame.context_line %>
|
76
|
+
<div class="context" id="c<%=h frame.object_id %>">
|
77
|
+
<% if frame.pre_context %>
|
78
|
+
<ol start="<%=h frame.pre_context_lineno+1 %>" class="pre-context" id="pre<%=h frame.object_id %>"<% unless frame == toggle_frame %> style="display: none"<% end %>>
|
79
|
+
<% frame.pre_context.each { |line| %>
|
80
|
+
<li onclick="toggle(<%=h frame.object_id %>)"><%=h line %></li>
|
81
|
+
<% } %>
|
82
|
+
</ol>
|
83
|
+
<% end %>
|
84
|
+
|
85
|
+
<ol start="<%=h frame.lineno %>" class="context-line">
|
86
|
+
<li onclick="toggle(<%=h frame.object_id %>)"><%=h frame.context_line %></li></ol>
|
87
|
+
|
88
|
+
<% if frame.post_context %>
|
89
|
+
<ol start='<%=h frame.lineno+1 %>' class="post-context" id="post<%=h frame.object_id %>"<% unless frame == toggle_frame %> style="display: none"<% end %>>
|
90
|
+
<% frame.post_context.each { |line| %>
|
91
|
+
<li onclick="toggle(<%=h frame.object_id %>)"><%=h line %></li>
|
92
|
+
<% } %>
|
93
|
+
</ol>
|
94
|
+
<% end %>
|
95
|
+
</div>
|
96
|
+
<% end %>
|
97
|
+
</li>
|
98
|
+
<% } %>
|
99
|
+
</ul>
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<% if env %>
|
103
|
+
<div id="requestinfo">
|
104
|
+
<h2>Additional information</h2>
|
105
|
+
|
106
|
+
<a name="get-info"></a>
|
107
|
+
<h3 id="get-info">GET</h3>
|
108
|
+
<% unless req.GET.empty? %>
|
109
|
+
<table class="req">
|
110
|
+
<thead>
|
111
|
+
<tr>
|
112
|
+
<th>Variable</th>
|
113
|
+
<th>Value</th>
|
114
|
+
</tr>
|
115
|
+
</thead>
|
116
|
+
<tbody>
|
117
|
+
<% req.GET.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
118
|
+
<tr>
|
119
|
+
<td><%=h key %></td>
|
120
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
121
|
+
</tr>
|
122
|
+
<% } %>
|
123
|
+
</tbody>
|
124
|
+
</table>
|
125
|
+
<% else %>
|
126
|
+
<p>No GET data.</p>
|
127
|
+
<% end %>
|
128
|
+
|
129
|
+
<a name="post-info"></a>
|
130
|
+
<h3 id="post-info">POST</h3>
|
131
|
+
<% unless req.POST.empty? %>
|
132
|
+
<table class="req">
|
133
|
+
<thead>
|
134
|
+
<tr>
|
135
|
+
<th>Variable</th>
|
136
|
+
<th>Value</th>
|
137
|
+
</tr>
|
138
|
+
</thead>
|
139
|
+
<tbody>
|
140
|
+
<% req.POST.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
141
|
+
<tr>
|
142
|
+
<td><%=h key %></td>
|
143
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
144
|
+
</tr>
|
145
|
+
<% } %>
|
146
|
+
</tbody>
|
147
|
+
</table>
|
148
|
+
<% else %>
|
149
|
+
<p>No POST data.</p>
|
150
|
+
<% end %>
|
151
|
+
|
152
|
+
<a name="cache"></a>
|
153
|
+
<h3 id="cache">Cache</h3>
|
154
|
+
<p><code><%=h cache.inspect %></code></p>
|
155
|
+
|
156
|
+
<a name="last-sql"></a>
|
157
|
+
<h3 id="last-sql">Last SQL</h3>
|
158
|
+
<p><% if sql %><code><%=(h sql).gsub(/\n/,'<br/>') %></code><% else %>n/a<% end %></p>
|
159
|
+
|
160
|
+
<a name="cookie-info"></a>
|
161
|
+
<h3 id="cookie-info">Cookies</h3>
|
162
|
+
<% unless req.cookies.empty? %>
|
163
|
+
<table class="req">
|
164
|
+
<thead>
|
165
|
+
<tr>
|
166
|
+
<th>Variable</th>
|
167
|
+
<th>Value</th>
|
168
|
+
</tr>
|
169
|
+
</thead>
|
170
|
+
<tbody>
|
171
|
+
<% req.cookies.each { |key, val| %>
|
172
|
+
<tr>
|
173
|
+
<td><%=h key %></td>
|
174
|
+
<td class="code"><div><%=h val.inspect %></div></td>
|
175
|
+
</tr>
|
176
|
+
<% } %>
|
177
|
+
</tbody>
|
178
|
+
</table>
|
179
|
+
<% else %>
|
180
|
+
<p>No cookie data.</p>
|
181
|
+
<% end %>
|
182
|
+
|
183
|
+
<a name="env-info"></a>
|
184
|
+
<h3 id="env-info">Rack ENV</h3>
|
185
|
+
<table class="req">
|
186
|
+
<thead>
|
187
|
+
<tr>
|
188
|
+
<th>Variable</th>
|
189
|
+
<th>Value</th>
|
190
|
+
</tr>
|
191
|
+
</thead>
|
192
|
+
<tbody>
|
193
|
+
<% env.sort_by { |k, v| k.to_s }.each { |key, val| %>
|
194
|
+
<tr>
|
195
|
+
<td><%=h key %></td>
|
196
|
+
<td class="code"><div><%=w h val %></div></td>
|
197
|
+
</tr>
|
198
|
+
<% } %>
|
199
|
+
</tbody>
|
200
|
+
</table>
|
201
|
+
|
202
|
+
</div>
|
203
|
+
<% end %>
|
204
|
+
|
205
|
+
<div id="explanation">
|
206
|
+
Generated at <%= Time.now.hm_mdy_full %> (<%= Time.now.zone %>).
|
207
|
+
</div>
|
208
|
+
</div>
|
209
|
+
</body>
|
210
|
+
</html>
|
data/lib/kiss/iterator.rb
CHANGED
@@ -2,55 +2,57 @@ class Kiss
|
|
2
2
|
# Enables `loop' features for certain template loops (while, for...in).
|
3
3
|
# Similar to features of Perl's Template::Iterator by Andy Wardley.
|
4
4
|
class Iterator
|
5
|
-
|
5
|
+
_attr_reader :index, :collection
|
6
6
|
|
7
7
|
# Creates a new loop iterator.
|
8
8
|
def initialize(collection = nil)
|
9
|
-
@
|
10
|
-
@
|
9
|
+
@_collection = collection
|
10
|
+
@_index = -1
|
11
11
|
end
|
12
12
|
|
13
13
|
# Return current iteration number, indexed from one instead of zero.
|
14
14
|
def count
|
15
|
-
@
|
15
|
+
@_index + 1
|
16
16
|
end
|
17
17
|
|
18
18
|
# Returns true if this is loop's first iteration.
|
19
|
-
def first
|
20
|
-
@
|
19
|
+
def first?
|
20
|
+
@_index == 0
|
21
21
|
end
|
22
|
+
alias_method :first, :first?
|
22
23
|
|
23
24
|
# Returns true if this is the last iteration of a
|
24
25
|
# loop over a collection.
|
25
|
-
def last
|
26
|
+
def last?
|
26
27
|
count == size
|
27
28
|
end
|
29
|
+
alias_method :last, :last?
|
28
30
|
|
29
31
|
# Return previous item in loop-iterated collection.
|
30
32
|
def prev
|
31
|
-
@
|
33
|
+
@_collection ? @_collection[index-1] : nil
|
32
34
|
end
|
33
35
|
|
34
36
|
# Return next item in loop-iterated collection.
|
35
37
|
def next
|
36
|
-
@
|
38
|
+
@_collection ? @_collection[index+1] : nil
|
37
39
|
end
|
38
40
|
|
39
41
|
# Returns index of loop's last iteration.
|
40
42
|
def max
|
41
|
-
@
|
43
|
+
@_collection ? @_collection.size-1 : nil
|
42
44
|
end
|
43
45
|
|
44
46
|
# Returns number of iterations in loop over a collection
|
45
47
|
# (size of the iterated collection).
|
46
48
|
def size
|
47
|
-
@
|
49
|
+
@_collection ? @_collection.size : nil
|
48
50
|
end
|
49
51
|
|
50
52
|
# Used by template erubis pre-processing voodoo to advance
|
51
53
|
# the iterator index. Not intended for any other use.
|
52
54
|
def increment
|
53
|
-
@
|
55
|
+
@_index = @_index + 1
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|