ramaze 0.1.1 → 0.1.2

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 (89) hide show
  1. data/Rakefile +14 -29
  2. data/bin/ramaze +2 -3
  3. data/doc/AUTHORS +5 -2
  4. data/doc/CHANGELOG +262 -9
  5. data/doc/FAQ +6 -6
  6. data/doc/meta/announcement.txt +5 -19
  7. data/doc/tutorial/todolist.html +47 -57
  8. data/doc/tutorial/todolist.mkd +47 -55
  9. data/examples/memleak_detector.rb +31 -0
  10. data/examples/todolist/src/controller/main.rb +14 -13
  11. data/examples/todolist/src/element/page.rb +2 -2
  12. data/examples/todolist/src/model.rb +2 -2
  13. data/examples/todolist/todolist.db +0 -4
  14. data/examples/whywiki/main.rb +2 -2
  15. data/examples/whywiki/template/edit.xhtml +1 -1
  16. data/examples/whywiki/template/show.xhtml +3 -3
  17. data/lib/proto/src/controller/main.rb +18 -1
  18. data/lib/proto/template/index.xhtml +11 -2
  19. data/lib/ramaze.rb +1 -1
  20. data/lib/ramaze/action.rb +104 -5
  21. data/lib/ramaze/action/render.rb +54 -0
  22. data/lib/ramaze/adapter.rb +2 -1
  23. data/lib/ramaze/adapter/mongrel.rb +13 -4
  24. data/lib/ramaze/cache.rb +17 -8
  25. data/lib/ramaze/cache/memcached.rb +1 -5
  26. data/lib/ramaze/controller.rb +51 -18
  27. data/lib/ramaze/controller/resolve.rb +19 -14
  28. data/lib/ramaze/dispatcher.rb +13 -16
  29. data/lib/ramaze/dispatcher/action.rb +2 -3
  30. data/lib/ramaze/dispatcher/error.rb +8 -3
  31. data/lib/ramaze/dispatcher/file.rb +1 -4
  32. data/lib/ramaze/error.rb +5 -5
  33. data/lib/ramaze/global.rb +7 -1
  34. data/lib/ramaze/global/globalstruct.rb +1 -3
  35. data/lib/ramaze/helper/aspect.rb +8 -10
  36. data/lib/ramaze/helper/cgi.rb +21 -3
  37. data/lib/ramaze/helper/identity.rb +4 -6
  38. data/lib/ramaze/helper/link.rb +4 -4
  39. data/lib/ramaze/helper/pager.rb +316 -0
  40. data/lib/ramaze/helper/partial.rb +37 -0
  41. data/lib/ramaze/helper/stack.rb +1 -1
  42. data/lib/ramaze/inform.rb +9 -0
  43. data/lib/ramaze/inform/hub.rb +5 -0
  44. data/lib/ramaze/inform/informer.rb +12 -6
  45. data/lib/ramaze/inform/informing.rb +32 -7
  46. data/lib/ramaze/inform/knotify.rb +21 -0
  47. data/lib/ramaze/inform/xosd.rb +58 -24
  48. data/lib/ramaze/sourcereload.rb +30 -1
  49. data/lib/ramaze/template.rb +33 -12
  50. data/lib/ramaze/template/amrita2.rb +21 -20
  51. data/lib/ramaze/template/erubis.rb +18 -14
  52. data/lib/ramaze/template/ezamar.rb +15 -26
  53. data/lib/ramaze/template/ezamar/element.rb +1 -1
  54. data/lib/ramaze/template/ezamar/engine.rb +45 -36
  55. data/lib/ramaze/template/ezamar/morpher.rb +3 -3
  56. data/lib/ramaze/template/ezamar/render_partial.rb +26 -0
  57. data/lib/ramaze/template/haml.rb +23 -18
  58. data/lib/ramaze/template/liquid.rb +5 -3
  59. data/lib/ramaze/template/markaby.rb +14 -11
  60. data/lib/ramaze/template/remarkably.rb +11 -5
  61. data/lib/ramaze/tool/localize.rb +12 -4
  62. data/lib/ramaze/tool/tidy.rb +26 -23
  63. data/lib/ramaze/trinity/request.rb +11 -7
  64. data/lib/ramaze/trinity/session.rb +24 -8
  65. data/lib/ramaze/version.rb +1 -1
  66. data/rake_tasks/maintaince.rake +136 -11
  67. data/spec/examples/templates/template_liquid.rb +6 -3
  68. data/spec/examples/todolist.rb +1 -2
  69. data/spec/helper/minimal.rb +7 -7
  70. data/spec/ramaze/action/basics.rb +19 -0
  71. data/spec/ramaze/action/render.rb +18 -0
  72. data/spec/ramaze/controller.rb +1 -1
  73. data/spec/ramaze/controller/template_resolving.rb +1 -1
  74. data/spec/ramaze/dispatcher/file.rb +24 -0
  75. data/spec/ramaze/error.rb +28 -29
  76. data/spec/ramaze/helper/cgi.rb +43 -0
  77. data/spec/ramaze/helper/pager.rb +27 -0
  78. data/spec/ramaze/helper/partial.rb +38 -0
  79. data/spec/ramaze/helper/template/partial.xhtml +1 -0
  80. data/spec/ramaze/inform/informer.rb +1 -1
  81. data/spec/ramaze/localize.rb +1 -1
  82. data/spec/ramaze/morpher.rb +3 -3
  83. data/spec/ramaze/request.rb +1 -3
  84. data/spec/ramaze/template.rb +9 -7
  85. data/spec/ramaze/template/haml.rb +2 -1
  86. metadata +21 -7
  87. data/examples/todolist/public/404.jpg +0 -0
  88. data/examples/todolist/public/error.xhtml +0 -74
  89. data/lib/ramaze/controller/render.rb +0 -90
@@ -10,14 +10,32 @@ module Ramaze
10
10
 
11
11
  # shortcut for CGI.escape
12
12
 
13
- def escape(*args)
13
+ def url_encode(*args)
14
14
  CGI.escape(*args)
15
15
  end
16
16
 
17
17
  # shortcut for CGI.unescape
18
18
 
19
- def unescape(*args)
20
- CGI.escape(*args)
19
+ def url_decode(*args)
20
+ CGI.unescape(*args)
21
+ end
22
+
23
+ # shortcut for GCI.escapeHTML
24
+
25
+ def html_escape(string)
26
+ CGI.escapeHTML(string)
21
27
  end
28
+
29
+ # shortcut for GCI.unescapeHTML
30
+
31
+ def html_unescape(string)
32
+ CGI.unescapeHTML(string)
33
+ end
34
+
35
+ # one-letter versions help in case like #{h foo.inspect}
36
+ # ERb/ERuby/Rails compatible
37
+ alias h html_escape
38
+ alias u url_encode
39
+
22
40
  end
23
41
  end
@@ -6,6 +6,9 @@ require 'openid'
6
6
 
7
7
  module Ramaze
8
8
 
9
+ openid_store_file = File.join(Dir.tmpdir, 'openid-store')
10
+ OpenIDStore = OpenID::FilesystemStore.new(openid_store_file)
11
+
9
12
  # This is called Identity to avoid collisions with the original openid.rb
10
13
 
11
14
  module IdentityHelper
@@ -61,12 +64,7 @@ module Ramaze
61
64
  private
62
65
 
63
66
  def openid_consumer
64
- OpenID::Consumer.new(session, Ramaze::Global.openid_store)
67
+ OpenID::Consumer.new(session, Ramaze::OpenIDStore)
65
68
  end
66
69
  end
67
70
  end
68
-
69
-
70
- openid_store_file = File.join(Dir.tmpdir, 'openid-store')
71
-
72
- Ramaze::Global.openid_store ||= OpenID::FilesystemStore.new(openid_store_file)
@@ -22,7 +22,7 @@ module Ramaze
22
22
  # Usage:
23
23
  # A('title') #=> <a href="/title">title</a>
24
24
  # A('foo/bar') #=> <a href="/foo/bar">foo/bar</a>
25
- # A('Home' :href => Rs(:/)) #=> <a href="/foo/bar">foo/bar</a>
25
+ # A('Home', :href => Rs(:/)) #=> <a href="/foo/bar">Home</a>
26
26
 
27
27
  def A(title, hash = {})
28
28
  hash[:href] ||= Rs(title)
@@ -52,7 +52,7 @@ module Ramaze
52
52
  # R(MC, :foo, :bar => :x) #=> '/foo?bar=x'
53
53
 
54
54
  def R(*atoms)
55
- args, atoms = atoms.partition{|a| a.is_a?(Hash) }
55
+ args, atoms = atoms.flatten.partition{|a| a.is_a?(Hash) }
56
56
  args = args.flatten.inject{|s,v| s.merge!(v) }
57
57
 
58
58
  map = Global.mapping.invert
@@ -74,10 +74,10 @@ module Ramaze
74
74
  end
75
75
  end
76
76
 
77
- # Uses R with self as first element.
77
+ # Uses R with Controller.current as first element.
78
78
 
79
79
  def Rs(*atoms)
80
- R(self, *atoms)
80
+ R(Controller.current, *atoms)
81
81
  end
82
82
  end
83
83
  end
@@ -0,0 +1,316 @@
1
+ # The BSD License
2
+ #
3
+ # Copyright (c) 2004-2007, George K. Moschovitis. (http://www.gmosx.com)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are
8
+ # met:
9
+ #
10
+ # * Redistributions of source code must retain the above copyright
11
+ # notice, this list of conditions and the following disclaimer.
12
+ #
13
+ # * Redistributions in binary form must reproduce the above copyright
14
+ # notice, this list of conditions and the following disclaimer in the
15
+ # documentation and/or other materials provided with the distribution.
16
+ #
17
+ # * Neither the name of Nitro nor the names of its contributors may be
18
+ # used to endorse or promote products derived from this software
19
+ # without specific prior written permission.
20
+ #
21
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ #
33
+
34
+ module Ramaze
35
+
36
+ # Displays a collection of entitities in multiple pages.
37
+ #
38
+ # === Design
39
+ #
40
+ # This pager is carefully designed for scaleability. It stores
41
+ # only the items for one page. The key parameter is needed,
42
+ # multiple pagers can coexist in a single page. The pager
43
+ # leverages the SQL LIMIT option to optimize database
44
+ # interaction.
45
+
46
+ class Pager
47
+ include Ramaze::LinkHelper
48
+
49
+ # Items per page.
50
+
51
+ trait :limit => 10
52
+
53
+ # The request key.
54
+
55
+ trait :key => '_page'
56
+
57
+ # The current page.
58
+
59
+ attr_accessor :page
60
+
61
+ # Items per page.
62
+
63
+ attr_accessor :limit
64
+
65
+ # The total number of pages.
66
+
67
+ attr_accessor :page_count
68
+
69
+ # Total count of items.
70
+
71
+ attr_accessor :total_count
72
+
73
+ def initialize(request, limit, total_count, key = trait[:key])
74
+ raise 'limit should be > 0' unless limit > 0
75
+
76
+ @request, @key = request, key
77
+ @page = (request.params[key] || 1).to_i
78
+ @limit = limit
79
+ set_count(total_count)
80
+ @start_idx = (@page - 1) * limit
81
+ end
82
+
83
+ def set_count(total_count)
84
+ @total_count = total_count
85
+ @page_count = (@total_count.to_f / @limit).ceil
86
+ end
87
+
88
+ # Return the first page index.
89
+
90
+ def first_page
91
+ 1
92
+ end
93
+
94
+ # Is the first page displayed?
95
+
96
+ def first_page?
97
+ @page == 1
98
+ end
99
+
100
+ # Return the last page index.
101
+
102
+ def last_page
103
+ return @page_count
104
+ end
105
+
106
+ # Is the last page displayed?
107
+
108
+ def last_page?
109
+ @page == @page_count
110
+ end
111
+
112
+ # Return the index of the previous page.
113
+
114
+ def previous_page
115
+ [@page - 1, 1].max
116
+ end
117
+
118
+ # Return the index of the next page.
119
+
120
+ def next_page
121
+ [@page + 1, @page_count].min
122
+ end
123
+
124
+ # A set of helpers to create links to common pages.
125
+
126
+ for target in [:first, :last, :previous, :next]
127
+ eval %{
128
+ def link_#{target}_page
129
+ target_uri(#{target}_page)
130
+ end
131
+ alias_method :#{target}_page_uri, :link_#{target}_page
132
+ alias_method :#{target}_page_href, :link_#{target}_page
133
+ }
134
+ end
135
+
136
+ # Iterator
137
+
138
+ def each(&block)
139
+ @page_items.each(&block)
140
+ end
141
+
142
+ # Iterator
143
+ # Returns 1-based index.
144
+
145
+ def each_with_index
146
+ idx = @start_idx
147
+ for item in @page_items
148
+ yield(idx + 1, item)
149
+ idx += 1
150
+ end
151
+ end
152
+
153
+ # Is the pager empty, ie has one page only?
154
+
155
+ def empty?
156
+ @page_count < 1
157
+ end
158
+
159
+ # The items count.
160
+
161
+ def size
162
+ @total_count
163
+ end
164
+
165
+ # Returns the range of the current page.
166
+
167
+ def page_range
168
+ s = @idx
169
+ e = [@idx + @items_limit - 1, all_total_count].min
170
+
171
+ return [s, e]
172
+ end
173
+
174
+ # Override if needed.
175
+
176
+ def nav_range
177
+ # effective range = 10 pages.
178
+ s = [@page - 5, 1].max
179
+ e = [@page + 9, @page_count].min
180
+
181
+ d = 9 - (e - s)
182
+ e += d if d < 0
183
+
184
+ return (s..e)
185
+ end
186
+
187
+ # To be used with Og queries.
188
+
189
+ def limit
190
+ if @start_idx > 0
191
+ { :limit => @limit, :offset => @start_idx }
192
+ else
193
+ { :limit => @limit }
194
+ end
195
+ end
196
+
197
+ def offset
198
+ @start_idx
199
+ end
200
+
201
+ # Override this method in your application if needed.
202
+ #--
203
+ # TODO: better markup.
204
+ #++
205
+
206
+ def navigation
207
+ nav = ""
208
+
209
+ unless first_page?
210
+ nav << %{
211
+ <div class="first"><a href="#{first_page_href}">First</a></div>
212
+ <div class="previous"><a href="#{previous_page_href}">Previous</a></div>
213
+ }
214
+ end
215
+
216
+ unless last_page?
217
+ nav << %{
218
+ <div class="last"><a href="#{last_page_href}">Last</a></div>
219
+ <div class="next"><a href="#{next_page_href}">Next</a></div>
220
+ }
221
+ end
222
+
223
+ nav << %{<ul>}
224
+
225
+ for i in nav_range()
226
+ if i == @page
227
+ nav << %{
228
+ <li class="active">#{i}</li>
229
+ }
230
+ else
231
+ nav << %{
232
+ <li><a href="#{target_uri(i)}">#{i}</a></li>
233
+ }
234
+ end
235
+ end
236
+
237
+ nav << %{</ul>}
238
+
239
+ return nav
240
+ end
241
+
242
+ def navigation?
243
+ @page_count > 1
244
+ end
245
+
246
+ private
247
+
248
+ # Generate the target URI.
249
+
250
+ def target_uri(page)
251
+ params = Request.current.params.dup.update(@key => page)
252
+ Rs(Controller.current.action.method, params)
253
+ end
254
+
255
+ end
256
+
257
+ # Pager related helper methods.
258
+
259
+ module PagerHelper
260
+
261
+ private
262
+
263
+ # Helper method that generates a collection of items and the
264
+ # associated pager object.
265
+ #
266
+ # === Example
267
+ #
268
+ # entries, pager = paginate(Article, :where => 'title LIKE..', :limit => 10)
269
+ #
270
+ # or
271
+ #
272
+ # items = [ 'item1', 'item2', ... ]
273
+ # entries, pager = paginate(items, :limit => 10)
274
+ #
275
+ # or
276
+ #
277
+ # entries, pager = paginate(article.comments, :limit => 10)
278
+ #
279
+ # <ul>
280
+ # <?r for entry in entries ?>
281
+ # <li>#{entry.to_link}</li>
282
+ # <?r end ?>
283
+ # </ul>
284
+ # #{pager.navigation}
285
+
286
+ def paginate(items, options = {})
287
+ limit = options.delete(:limit) || options[:limit] || Pager.trait[:limit]
288
+ pager_key = options.delete(:pager_key) || Pager.trait[:key]
289
+
290
+ case items
291
+ when Array
292
+ pager = Pager.new(request, limit, items.size, pager_key)
293
+ items = items.slice(pager.offset, pager.limit[:limit])
294
+ return items, pager
295
+ end
296
+
297
+ if defined?(Og)
298
+ case items
299
+ when Og::Collection
300
+ pager = Pager.new(request, limit, items.count, pager_key)
301
+ options.update(pager.limit)
302
+ items = items.reload(options)
303
+ return items, pager
304
+
305
+ when Og::Mixin
306
+ pager = Pager.new(request, limit, items.count(options), pager_key)
307
+ options.update(pager.limit)
308
+ items = items.all(options)
309
+ return items, pager
310
+ end
311
+ end
312
+ end
313
+
314
+ end
315
+
316
+ end
@@ -0,0 +1,37 @@
1
+ # Copyright (c) 2006 Michael Fellinger m.fellinger@gmail.com
2
+ # All files in this distribution are subject to the terms of the Ruby license.
3
+
4
+ module Ramaze
5
+ module PartialHelper
6
+
7
+ private
8
+ module_function
9
+
10
+ # Renders a url 'inline'.
11
+ #
12
+ # url: normal URL, like you'd use for redirecting.
13
+ # options: optional, will be used as request parameters.
14
+
15
+ def render_partial(url, options = {})
16
+ saved = {}
17
+ options.keys.each {|x| saved[x] = request.params[x] }
18
+
19
+ request.params.update(options)
20
+
21
+ Controller.handle(url)
22
+ ensure
23
+ options.keys.each {|x| request.params[x] = saved[x] }
24
+ end
25
+
26
+ def render_template(file, options = {})
27
+ current = Action.current
28
+ options[:binding] ||= current.binding
29
+ options[:controller] ||= current.controller
30
+ options[:instance] ||= current.instance
31
+ options[:template] = (options[:controller].template_root/file)
32
+
33
+ action = Ramaze::Action(options)
34
+ action.render
35
+ end
36
+ end
37
+ end
@@ -47,7 +47,7 @@ module Ramaze
47
47
 
48
48
  def call this
49
49
  (session[:STACK] ||= []) << request.fullpath
50
- redirect(R(this))
50
+ redirect this
51
51
  end
52
52
 
53
53
  # return to the last location on session[:STACK]