raw 0.49.0

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 (148) hide show
  1. data/doc/CONTRIBUTORS +106 -0
  2. data/doc/LICENSE +32 -0
  3. data/doc/coding_conventions.txt +11 -0
  4. data/lib/raw.rb +42 -0
  5. data/lib/raw/adapter.rb +113 -0
  6. data/lib/raw/adapter/cgi.rb +41 -0
  7. data/lib/raw/adapter/fastcgi.rb +48 -0
  8. data/lib/raw/adapter/mongrel.rb +146 -0
  9. data/lib/raw/adapter/script.rb +94 -0
  10. data/lib/raw/adapter/webrick.rb +144 -0
  11. data/lib/raw/adapter/webrick/vcr.rb +91 -0
  12. data/lib/raw/cgi.rb +323 -0
  13. data/lib/raw/cgi/cookie.rb +47 -0
  14. data/lib/raw/cgi/http.rb +62 -0
  15. data/lib/raw/compiler.rb +138 -0
  16. data/lib/raw/compiler/filter/cleanup.rb +21 -0
  17. data/lib/raw/compiler/filter/elements.rb +166 -0
  18. data/lib/raw/compiler/filter/elements/element.rb +210 -0
  19. data/lib/raw/compiler/filter/localization.rb +23 -0
  20. data/lib/raw/compiler/filter/markup.rb +32 -0
  21. data/lib/raw/compiler/filter/morph.rb +123 -0
  22. data/lib/raw/compiler/filter/morph/each.rb +34 -0
  23. data/lib/raw/compiler/filter/morph/for.rb +11 -0
  24. data/lib/raw/compiler/filter/morph/if.rb +26 -0
  25. data/lib/raw/compiler/filter/morph/selected_if.rb +43 -0
  26. data/lib/raw/compiler/filter/morph/standard.rb +55 -0
  27. data/lib/raw/compiler/filter/morph/times.rb +27 -0
  28. data/lib/raw/compiler/filter/script.rb +116 -0
  29. data/lib/raw/compiler/filter/squeeze.rb +16 -0
  30. data/lib/raw/compiler/filter/static_include.rb +74 -0
  31. data/lib/raw/compiler/filter/template.rb +121 -0
  32. data/lib/raw/compiler/reloader.rb +96 -0
  33. data/lib/raw/context.rb +154 -0
  34. data/lib/raw/context/flash.rb +157 -0
  35. data/lib/raw/context/global.rb +88 -0
  36. data/lib/raw/context/request.rb +338 -0
  37. data/lib/raw/context/response.rb +57 -0
  38. data/lib/raw/context/session.rb +198 -0
  39. data/lib/raw/context/session/drb.rb +11 -0
  40. data/lib/raw/context/session/file.rb +15 -0
  41. data/lib/raw/context/session/memcached.rb +13 -0
  42. data/lib/raw/context/session/memory.rb +12 -0
  43. data/lib/raw/context/session/og.rb +15 -0
  44. data/lib/raw/context/session/pstore.rb +13 -0
  45. data/lib/raw/control.rb +18 -0
  46. data/lib/raw/control/attribute.rb +91 -0
  47. data/lib/raw/control/attribute/checkbox.rb +25 -0
  48. data/lib/raw/control/attribute/datetime.rb +21 -0
  49. data/lib/raw/control/attribute/file.rb +20 -0
  50. data/lib/raw/control/attribute/fixnum.rb +26 -0
  51. data/lib/raw/control/attribute/float.rb +26 -0
  52. data/lib/raw/control/attribute/options.rb +38 -0
  53. data/lib/raw/control/attribute/password.rb +16 -0
  54. data/lib/raw/control/attribute/text.rb +16 -0
  55. data/lib/raw/control/attribute/textarea.rb +16 -0
  56. data/lib/raw/control/none.rb +16 -0
  57. data/lib/raw/control/relation.rb +59 -0
  58. data/lib/raw/control/relation/belongs_to.rb +0 -0
  59. data/lib/raw/control/relation/has_many.rb +97 -0
  60. data/lib/raw/control/relation/joins_many.rb +0 -0
  61. data/lib/raw/control/relation/many_to_many.rb +0 -0
  62. data/lib/raw/control/relation/refers_to.rb +29 -0
  63. data/lib/raw/controller.rb +37 -0
  64. data/lib/raw/controller/publishable.rb +160 -0
  65. data/lib/raw/dispatcher.rb +209 -0
  66. data/lib/raw/dispatcher/format.rb +108 -0
  67. data/lib/raw/dispatcher/format/atom.rb +31 -0
  68. data/lib/raw/dispatcher/format/css.rb +0 -0
  69. data/lib/raw/dispatcher/format/html.rb +42 -0
  70. data/lib/raw/dispatcher/format/json.rb +31 -0
  71. data/lib/raw/dispatcher/format/rss.rb +33 -0
  72. data/lib/raw/dispatcher/format/xoxo.rb +31 -0
  73. data/lib/raw/dispatcher/mounter.rb +60 -0
  74. data/lib/raw/dispatcher/router.rb +111 -0
  75. data/lib/raw/errors.rb +19 -0
  76. data/lib/raw/helper.rb +86 -0
  77. data/lib/raw/helper/benchmark.rb +23 -0
  78. data/lib/raw/helper/buffer.rb +60 -0
  79. data/lib/raw/helper/cookie.rb +32 -0
  80. data/lib/raw/helper/debug.rb +28 -0
  81. data/lib/raw/helper/default.rb +16 -0
  82. data/lib/raw/helper/feed.rb +451 -0
  83. data/lib/raw/helper/form.rb +284 -0
  84. data/lib/raw/helper/javascript.rb +59 -0
  85. data/lib/raw/helper/layout.rb +40 -0
  86. data/lib/raw/helper/navigation.rb +87 -0
  87. data/lib/raw/helper/pager.rb +305 -0
  88. data/lib/raw/helper/table.rb +247 -0
  89. data/lib/raw/helper/xhtml.rb +218 -0
  90. data/lib/raw/helper/xml.rb +125 -0
  91. data/lib/raw/mixin/magick.rb +35 -0
  92. data/lib/raw/mixin/sweeper.rb +71 -0
  93. data/lib/raw/mixin/thumbnails.rb +1 -0
  94. data/lib/raw/mixin/webfile.rb +165 -0
  95. data/lib/raw/render.rb +271 -0
  96. data/lib/raw/render/builder.rb +26 -0
  97. data/lib/raw/render/caching.rb +81 -0
  98. data/lib/raw/render/call.rb +43 -0
  99. data/lib/raw/render/send_file.rb +46 -0
  100. data/lib/raw/render/stream.rb +39 -0
  101. data/lib/raw/scaffold.rb +13 -0
  102. data/lib/raw/scaffold/controller.rb +25 -0
  103. data/lib/raw/scaffold/model.rb +157 -0
  104. data/lib/raw/test.rb +5 -0
  105. data/lib/raw/test/assertions.rb +169 -0
  106. data/lib/raw/test/context.rb +55 -0
  107. data/lib/raw/test/testcase.rb +79 -0
  108. data/lib/raw/util/attr.rb +128 -0
  109. data/lib/raw/util/encode_uri.rb +149 -0
  110. data/lib/raw/util/html_filter.rb +538 -0
  111. data/lib/raw/util/markup.rb +130 -0
  112. data/test/glue/tc_webfile.rb +1 -0
  113. data/test/nitro/CONFIG.rb +3 -0
  114. data/test/nitro/adapter/raw_post1.bin +9 -0
  115. data/test/nitro/adapter/tc_webrick.rb +16 -0
  116. data/test/nitro/cgi/tc_cookie.rb +14 -0
  117. data/test/nitro/cgi/tc_request.rb +61 -0
  118. data/test/nitro/compiler/tc_client_morpher.rb +47 -0
  119. data/test/nitro/compiler/tc_compiler.rb +25 -0
  120. data/test/nitro/dispatcher/tc_mounter.rb +47 -0
  121. data/test/nitro/helper/tc_feed.rb +135 -0
  122. data/test/nitro/helper/tc_navbar.rb +74 -0
  123. data/test/nitro/helper/tc_pager.rb +35 -0
  124. data/test/nitro/helper/tc_table.rb +68 -0
  125. data/test/nitro/helper/tc_xhtml.rb +19 -0
  126. data/test/nitro/tc_caching.rb +19 -0
  127. data/test/nitro/tc_cgi.rb +222 -0
  128. data/test/nitro/tc_context.rb +17 -0
  129. data/test/nitro/tc_controller.rb +103 -0
  130. data/test/nitro/tc_controller_aspect.rb +32 -0
  131. data/test/nitro/tc_controller_params.rb +885 -0
  132. data/test/nitro/tc_dispatcher.rb +109 -0
  133. data/test/nitro/tc_element.rb +85 -0
  134. data/test/nitro/tc_flash.rb +59 -0
  135. data/test/nitro/tc_helper.rb +47 -0
  136. data/test/nitro/tc_render.rb +119 -0
  137. data/test/nitro/tc_router.rb +61 -0
  138. data/test/nitro/tc_server.rb +35 -0
  139. data/test/nitro/tc_session.rb +66 -0
  140. data/test/nitro/tc_template.rb +71 -0
  141. data/test/nitro/util/tc_encode_url.rb +87 -0
  142. data/test/nitro/util/tc_markup.rb +31 -0
  143. data/test/public/blog/another/very_litle/index.xhtml +1 -0
  144. data/test/public/blog/inc1.xhtml +2 -0
  145. data/test/public/blog/inc2.xhtml +1 -0
  146. data/test/public/blog/list.xhtml +9 -0
  147. data/test/public/dummy_mailer/registration.xhtml +5 -0
  148. metadata +244 -0
@@ -0,0 +1 @@
1
+ require "raw/mixin/magick"
@@ -0,0 +1,165 @@
1
+ require "fileutils"
2
+
3
+ require "facets/more/inheritor"
4
+
5
+ module Raw::Mixin
6
+
7
+ # A Web File.
8
+ #
9
+ # You can customize the path where the uploaded file will be
10
+ # by defining a webfile_path class method *before* the property:
11
+ #
12
+ # class Icon
13
+ # def self.webfile_path request, name
14
+ # File.join(Uploads.public_root, request.user.name, 'icon.png')
15
+ # end
16
+ #
17
+ # attr_accessor :file, WebFile, :magick => { :small => '64x64', :medium => '96x96' }
18
+ # end
19
+ #--
20
+ # TODO: webfile_path customization sucks, should be improved!
21
+ #++
22
+
23
+ class WebFile
24
+
25
+ # The directory where uploaded files are stored. Typically
26
+ # this is a symlink to another directory outside of the
27
+ # webapp dir for easier updates.
28
+
29
+ setting :upload_root, :default => 'upload', :doc => 'The directory where upload files are stored'
30
+
31
+ # Override files by default?
32
+
33
+ setting :override_files, :default => true, :doc => 'Override files by default?'
34
+
35
+ # Modify the base class when this class is included as a
36
+ # property
37
+ #--
38
+ # TODO: find a better name.
39
+ #++
40
+
41
+ def self.included_as_property(base, args)
42
+ if args.last.is_a?(Hash)
43
+ options = args.pop
44
+ else
45
+ options = Hash.new
46
+ end
47
+
48
+ args.pop if args.last.is_a?(Class)
49
+
50
+ if thumbnails = (options[:thumbnail] || options[:thumbnails] || options[:magick]) or self.name == 'WebImage'
51
+ require 'glue/thumbnails'
52
+ base.send :include, Thumbnails
53
+ thumbnails = { :small => :thumbnails } if thumbnails.is_a?(String)
54
+ end
55
+
56
+ for name in args
57
+ base.module_eval do
58
+ # The 'web' path to the file (relative to the public
59
+ # root directory. Uses the original property name
60
+ # or the #{name}_path alias.
61
+
62
+ attr_accessor name.to_sym, String, :control => :file
63
+ alias_method "#{name}_path".to_sym, name.to_sym
64
+
65
+ # The file size.
66
+
67
+ attr_accessor "#{name}_size".to_sym, Fixnum, :control => :none
68
+
69
+ # The mime type.
70
+
71
+ attr_accessor "#{name}_mime_type".to_sym, String , :control => :none
72
+
73
+ # Assignment callbacks.
74
+ #--
75
+ # gmosx, FIXME: this is a hack!! better implementation
76
+ # is needed (generalized property assigners).
77
+
78
+ inheritor(:assign_callbacks, [], :merge) unless @assign_callbacks
79
+ end
80
+
81
+ if thumbnails
82
+ for tname in thumbnails.keys
83
+ base.module_eval do
84
+ attr_accessor "#{name}_#{tname}_thumbnail".to_sym, String, :control => :none
85
+ end
86
+ end
87
+ end
88
+
89
+ code = %{
90
+ def #{name}_real_path
91
+ File.join(Nitro::Server.public_root, @#{name})
92
+ end
93
+
94
+ def #{name}_from_request(request)
95
+ param = request['#{name}']
96
+
97
+ return if param.nil? or param.original_filename.blank?
98
+ }
99
+ if base.respond_to? :webfile_path
100
+ code << %{
101
+ path = #{base}.webfile_path(request, '#{name}')
102
+ }
103
+ else
104
+ code << %{
105
+ path = File.join(WebFile.upload_root, WebFile.sanitize(param.original_filename))
106
+ }
107
+ end
108
+
109
+ code << %{
110
+ @#{name} = path
111
+ @#{name}_size = param.size
112
+
113
+ real_path = #{name}_real_path
114
+ raise 'file exists' if !WebFile.override_files and File.exists?(real_path)
115
+ FileUtils.mkdir_p(File.dirname(real_path))
116
+ if param.path
117
+ FileUtils.cp(param.path, real_path)
118
+ else
119
+ # gmosx FIXME: this is a hack!!
120
+ param.rewind
121
+ File.open(real_path, 'wb') { |f| f << param.read }
122
+ end
123
+ FileUtils.chmod(0664, real_path)
124
+ }
125
+
126
+ if thumbnails
127
+ for tname, geostring in thumbnails
128
+ code << %{
129
+ @#{name}_#{tname}_thumbnail = Thumbnails.generate_thumbnail(path, '#{tname}', '#{geostring}')
130
+ }
131
+ end
132
+ end
133
+
134
+ code << %{
135
+ end
136
+
137
+ def delete_#{name}
138
+ FileUtils.rm(#{name}_real_path)
139
+ end
140
+
141
+ assign_callbacks! << proc { |obj, values, options|
142
+ obj.#{name}_from_request(values)
143
+ }
144
+ }
145
+
146
+ base.module_eval(code)
147
+ end
148
+ end
149
+
150
+ # Sanitize a filename. You can override this method to make
151
+ # this suit your needs.
152
+
153
+ def self.sanitize(filename)
154
+ ext = File::extname(filename)
155
+ base = File::basename(filename, ext).gsub(/[\\\/\? !@$\(\)]/, '-')[0..64]
156
+ return "#{base}.#{ext}"
157
+ end
158
+
159
+ end
160
+
161
+ # An alias, implies thumbnailing.
162
+
163
+ WebImage = WebFile
164
+
165
+ end
@@ -0,0 +1,271 @@
1
+ require "stringio"
2
+
3
+ require "facets/core/string/blank"
4
+ require "facets/more/settings"
5
+
6
+ require "raw/render/builder"
7
+ require "raw/render/call"
8
+
9
+ module Raw
10
+
11
+ #--
12
+ # Raise or Throw this exception to stop the current action.
13
+ # Typically called to skip the template. This is considerered
14
+ # a low level tactic. Prefer to use the exit method.
15
+ #++
16
+
17
+ class ActionExit < Exception # :nodoc: all
18
+ end
19
+
20
+ #--
21
+ # Raise or Throw this exception to stop rendering altogether.
22
+ # Typically called by redirects.
23
+ #++
24
+
25
+ class RenderExit < Exception # :nodoc: all
26
+ end
27
+
28
+ #--
29
+ # The output buffer. The output of a contoller action is
30
+ # accumulated in this buffer before sending this to the client
31
+ # as a HTTP Response.
32
+ #
33
+ # TODO: Implement a FAST string (maybe in C)
34
+ #++
35
+
36
+ class OutputBuffer < String # :nodoc: all
37
+ end
38
+
39
+ # The rendering mixin. This module is typically included in
40
+ # published objects and/or controllers to provide rendering
41
+ # functionality.
42
+
43
+ module Render
44
+
45
+ # The output buffer. The output of a script/action is
46
+ # accumulated in this buffer.
47
+
48
+ attr_accessor :out
49
+ alias_method :body, :out
50
+
51
+ # The context.
52
+
53
+ attr_accessor :context
54
+ alias_method :request, :context
55
+ alias_method :response, :context
56
+
57
+ # The name of the currently executing action.
58
+
59
+ attr_accessor :action_name
60
+
61
+ # The current controller class.
62
+
63
+ attr_accessor :controller
64
+
65
+ # Initialize the render.
66
+ #
67
+ # [+context+]
68
+ # A parent render/controller acts as the context.
69
+
70
+ def initialize(context)
71
+ @context = context
72
+ @out = context.output_buffer
73
+ end
74
+
75
+ # Renders the action denoted by path. The path
76
+ # is resolved by the dispatcher to get the correct
77
+ # controller.
78
+ #
79
+ # Both relative and absolute paths are supported. Relative
80
+ # paths are converted to absolute by prepending the mount path
81
+ # of the controller.
82
+
83
+ def render(*args)
84
+ path = encode_uri(*args)
85
+ debug "Rendering '#{path}'" if $DBG
86
+
87
+ @controller, action, query, params, ext = @context.dispatcher.dispatch(path)
88
+ @context.content_type = @context.format.content_type
89
+
90
+ @context.level += 1
91
+ old_controller = Controller.replace_current(@controller)
92
+
93
+ if self.class == @controller
94
+ self.send(action, params)
95
+ else
96
+ @controller.new(@context).send(action, params)
97
+ end
98
+
99
+ Controller.replace_current(old_controller)
100
+ @context.level -= 1
101
+
102
+ rescue RenderExit, ActionExit => e1
103
+ # Just stop rendering.
104
+
105
+ rescue ActionError => e2
106
+ # Client Error family of errors, typically send 4XX
107
+ # status code.
108
+ handle_error(e2, 404)
109
+ error e2.to_s
110
+
111
+ rescue Object => e3
112
+ # Server Error family of errors, typically send 5XX
113
+ # status code.
114
+ # puts "--------", pp_exception(e3)
115
+
116
+ handle_error(e3, 500)
117
+ error "Error while handling '#{path}'"
118
+ error pp_exception(e3)
119
+ end
120
+
121
+ private
122
+ RADIUS = 3
123
+
124
+ # Extract the offending source code for a server error.
125
+
126
+ def extract_source_from(error)
127
+ extract = []
128
+
129
+ code = error.backtrace[1]
130
+ md = code.match(%r{:(\d+):in `(.*)'$})
131
+ line_num = md[1].to_i
132
+
133
+ code.split("\n")[(line_num - RADIUS)..(line_num + RADIUS)].each_with_index do |line, idx|
134
+ lidx = line_num - RADIUS + idx
135
+ extract << "#{lidx}: #{line}"
136
+ end
137
+
138
+ return extract
139
+ end
140
+
141
+ # Helper method to exit the current action, typically used
142
+ # to skip the template rendering.
143
+ #
144
+ # === Example
145
+ #
146
+ # def my_action
147
+ # ...
148
+ # exit unless user.admin?
149
+ # end
150
+
151
+ def exit
152
+ raise ActionExit.new
153
+ end
154
+
155
+ # Flush the IO object (OutputBuffer) if we are in streaming
156
+ # mode.
157
+
158
+ def flush
159
+ @out.flush if @out.is_a?(IO)
160
+ end
161
+
162
+ # :section: Redirection methods.
163
+
164
+ # Send a redirect response.
165
+ #
166
+ # If the URI (path) starts with '/' it is considered absolute, else
167
+ # the URI is considered relative to the current controller and
168
+ # the controller base is prepended.
169
+ #
170
+ # The parameters are passed to the R operator (encode_uri)
171
+ # to actually build the URI. So the following forms (among
172
+ # others) are allowed:
173
+ #
174
+ # redirect 'home/login'
175
+ # redirect ForaController, :post, :title, 'The title'
176
+ # redirect :welcome
177
+ # redirect article # => article.to_href
178
+ #
179
+ # You can also pass optional hash parameters at the end,
180
+ # for example:
181
+ #
182
+ # redirect :welcome, :status => 307
183
+ #
184
+ # The default redirect status is 303.
185
+ #
186
+ #--
187
+ # TODO: add a check for redirect to self (infinite loop)
188
+ #++
189
+
190
+ def redirect(*args)
191
+ # If this is an ajax and/or rpc request skip the redirect.
192
+ # Allows to write more reusable code.
193
+
194
+ return if request.script?
195
+
196
+ if args.last.is_a? Hash
197
+ status = args.last.fetch(:status, 303)
198
+ else
199
+ status = 303
200
+ end
201
+
202
+ uri = encode_uri(*args)
203
+
204
+ # gmosx, THINK: this may be unnecessary!
205
+
206
+ unless uri =~ /^http/
207
+ uri = "#{@context.host_uri}/#{uri.gsub(/^\//, '')}"
208
+ end
209
+
210
+ @context.status = status
211
+ @out = "<html><a href=\"#{uri}\">#{uri}</a>.</html>\n"
212
+ @context.response_headers['location'] = uri
213
+
214
+ raise RenderExit
215
+ end
216
+ alias_method :redirect_to, :redirect
217
+
218
+ # Redirect to the referer.
219
+
220
+ def redirect_referer(postfix = nil, status = 303)
221
+ redirect "#{@context.referer}#{postfix}", :status => status
222
+ end
223
+ alias_method :redirect_to_referer, :redirect_referer
224
+ alias_method :redirect_referrer, :redirect_referer
225
+ alias_method :redirect_to_referrer, :redirect_referer
226
+
227
+ # Redirect to home.
228
+
229
+ def redirect_home(status = 303)
230
+ redirect "/", :status => status
231
+ end
232
+ alias_method :redirect_to_home, :redirect_home
233
+
234
+ # Handle an error.
235
+ #--
236
+ # gmosx, TODO: add check for infinite loops here.
237
+ #++
238
+
239
+ def handle_error(exception, error_status = 500)
240
+ @context.status = error_status
241
+ @out = ""
242
+
243
+ session[:RENDERING_ERROR] = exception
244
+
245
+ render("/status_#{error_status}")
246
+ end
247
+
248
+ # Convenience method to lookup the session.
249
+
250
+ def session
251
+ @context.session
252
+ end
253
+
254
+ # Add some text to the output buffer.
255
+
256
+ def render_text(text)
257
+ @out << text
258
+ end
259
+ alias_method :print, :render_text
260
+
261
+ # Render a template into the output buffer.
262
+ # HACK FIX, will be removed.
263
+
264
+ def render_template(path)
265
+ render(path)
266
+ exit
267
+ end
268
+
269
+ end
270
+
271
+ end
@@ -0,0 +1,26 @@
1
+ require "glue/builder/xml"
2
+
3
+ module Raw
4
+
5
+ module Render
6
+
7
+ # Access the programmatic renderer (builder).
8
+
9
+ def build(&block)
10
+ if block.arity == 1
11
+ yield XmlBuilder.new(@out)
12
+ else
13
+ XmlBuilder.new(@out).instance_eval(&block)
14
+ end
15
+ end
16
+
17
+ # Return a programmatic renderer that targets the
18
+ # output buffer.
19
+
20
+ def builder
21
+ XmlBuilder.new(@out)
22
+ end
23
+
24
+ end
25
+
26
+ end