ramaze 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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]