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,57 @@
1
+ module Raw
2
+
3
+ # HTTP Response. This module is included in Context.
4
+
5
+ module Response
6
+
7
+ # The Response status.
8
+
9
+ attr_accessor :status
10
+
11
+ # The Response headers.
12
+
13
+ attr_accessor :response_headers
14
+
15
+ # The Response cookies.
16
+
17
+ attr_accessor :response_cookies
18
+
19
+ # Return the content type for this response.
20
+
21
+ def content_type
22
+ @response_headers["Content-Type"]
23
+ end
24
+
25
+ # Set the content type for this response.
26
+
27
+ def content_type=(ctype)
28
+ @response_headers["Content-Type"] = ctype
29
+ end
30
+
31
+ # Add a cookie to the response. Better use this
32
+ # method to avoid precreating the cookies array
33
+ # for every request.
34
+ #
35
+ # === Examples
36
+ #
37
+ # add_cookie('nsid', 'gmosx')
38
+ # add_cookie(Cookie.new('nsid', 'gmosx')
39
+
40
+ def add_cookie(cookie, value = nil)
41
+ if value
42
+ (@response_cookies ||= []) << Cookie.new(cookie, value)
43
+ else
44
+ (@response_cookies ||= []) << cookie
45
+ end
46
+ end
47
+ alias_method :send_cookie, :add_cookie
48
+
49
+ # Return the output buffer.
50
+
51
+ def body
52
+ @output_buffer
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,198 @@
1
+ require "md5"
2
+
3
+ require "facets/core/class/cattr"
4
+ require "facets/more/synchash"
5
+ require "facets/more/times"
6
+ require "facets/more/expirable"
7
+ require "facets/more/settings"
8
+
9
+ require "raw/cgi/cookie"
10
+
11
+ module Raw
12
+
13
+ # A web application session.
14
+ #
15
+ # State is a neccessary evil but session variables
16
+ # should be avoided as much as possible. Session state
17
+ # is typically distributed to many servers so avoid
18
+ # storing complete objects in session variables, only
19
+ # store oids and small integer/strings.
20
+ #
21
+ # The session should be persistable to survive server
22
+ # shutdowns.
23
+ #
24
+ # The session can be considered as a Hash where key-value
25
+ # pairs are stored. Typically symbols are used as keys. By
26
+ # convention uppercase symbols are used for internal Nitro
27
+ # session variables (ie :FLASH, :USER, etc). User applications
28
+ # typically use lowercase symbols (ie :cart, :history, etc).
29
+ #
30
+ #--
31
+ # TODO: rehash of the session cookie
32
+ # TODO: store -> cache, reimplement helpers.
33
+ #++
34
+
35
+ class Session < Hash
36
+ include Expirable
37
+
38
+ # Session id salt.
39
+
40
+ setting :session_id_salt, :default => 'SALT', :doc => 'Session id salt'
41
+
42
+ # The name of the cookie that stores the session id.
43
+
44
+ setting :cookie_name, :default => 'nsid', :doc => 'The name of the cookie that stores the session id'
45
+
46
+ # useful with persistents sessions stores
47
+
48
+ setting :cookie_expires, :default => false, :doc => 'Set expires parameter of session cookie equal to the keepalive setting?'
49
+
50
+ # The session keepalive time. The session is eligable for
51
+ # garbage collection after this time passes.
52
+
53
+ setting :keepalive, :default => 30.minutes, :doc => 'The session keepalive time'
54
+
55
+ # The type of the session cache. The generalized caching
56
+ # system in Glue is used. The following options are available:
57
+ #
58
+ # * :memory [default]
59
+ # * :drb
60
+ # * :og
61
+ # * :file
62
+ # * :memcached
63
+
64
+ setting :cache_type, :default => :memory, :doc => 'The type of session cache'
65
+
66
+ # The address of the cache store.
67
+
68
+ setting :cache_address, :default => '127.0.0.1', :doc => 'The address of the cache store'
69
+
70
+ # The port of the cache store.
71
+
72
+ setting :cache_port, :default => 9069, :doc => 'The port of the cache store'
73
+
74
+ class << self
75
+
76
+ # The sessions cache (store).
77
+
78
+ attr_accessor :cache
79
+ alias_method :store, :cache
80
+
81
+ # Load the correct Session specialization according to the
82
+ # cache type.
83
+
84
+ def setup(type = Session.cache_type)
85
+ # gmosx: RDoc friendly.
86
+ require "raw/context/session/" + type.to_s
87
+ end
88
+
89
+ # Lookup the session in the cache by using the session
90
+ # cookie value as a key. If the session does not exist
91
+ # creates a new session, inserts it in the cache and
92
+ # appends a new session cookie in the response.
93
+
94
+ def lookup(context)
95
+ if session_id = context.cookies[Session.cookie_name]
96
+ session = Session.cache[session_id]
97
+ end
98
+
99
+ unless session
100
+ # Create new session.
101
+ session = Session.new(context)
102
+ cookie = Cookie.new(Session.cookie_name, session.session_id)
103
+ if Session.cookie_expires
104
+ cookie.expires = Time.now + Session.keepalive
105
+ end
106
+ context.add_cookie(cookie)
107
+ Session.cache[session.session_id] = session
108
+ else
109
+ # Access ('touch') the existing session.
110
+ session.touch!
111
+ end
112
+
113
+ return session
114
+ end
115
+
116
+ # The number of active (online) sessions.
117
+ # DON'T use yet!
118
+
119
+ def count
120
+ Session.cache.size
121
+ end
122
+
123
+ # Perform Session garbage collection. You may call this
124
+ # method from a cron job.
125
+
126
+ def garbage_collect
127
+ expired = []
128
+ for s in Session.cache.all
129
+ expired << s.session_id if s.expired?
130
+ end
131
+ for sid in expired
132
+ Session.cache.delete(sid)
133
+ end
134
+ end
135
+ alias_method :gc!, :garbage_collect
136
+
137
+ # Returns the current session from the context thread local
138
+ # variable.
139
+
140
+ def current
141
+ Context.current.session
142
+ end
143
+
144
+ end
145
+
146
+ # The unique id of this session.
147
+
148
+ attr_reader :session_id
149
+
150
+ # Create the session for the given context.
151
+ # If the hook method 'created' is defined it is called
152
+ # at the end. Typically used to initialize the session
153
+ # hash.
154
+
155
+ def initialize(context = nil)
156
+ @session_id = create_id
157
+ expires_after(Session.keepalive)
158
+ created if respond_to?(:created)
159
+ end
160
+
161
+ # Synchronize the session store, by
162
+ # restoring this session. Especially useful
163
+ # in distributed and/or multiprocess setups.
164
+
165
+ def sync
166
+ Session.cache[@session_id] = self
167
+ end
168
+ alias_method :restore, :sync
169
+
170
+ def touch!
171
+ expires_after(Session.keepalive)
172
+ end
173
+
174
+ protected
175
+
176
+ # Calculates a unique id.
177
+ #
178
+ # The session id must be unique, a monotonically
179
+ # increasing function like time is appropriate.
180
+ # Random may produce equal ids? add a prefix
181
+ # (SALT) to stop hackers from creating session_ids.
182
+ #--
183
+ # THINK: Is MD5 slow??? Allow for pluggable hashes.
184
+ #++
185
+
186
+ def create_id
187
+ now = Time.now
188
+ md5 = Digest::MD5.new
189
+ md5.update(now.to_s)
190
+ md5.update(now.usec.to_s)
191
+ md5.update(rand(0).to_s)
192
+ md5.update(Session.session_id_salt)
193
+ md5.hexdigest
194
+ end
195
+
196
+ end
197
+
198
+ end
@@ -0,0 +1,11 @@
1
+ require "glue/cache/drb"
2
+
3
+ require "raw/context/session"
4
+
5
+ module Raw
6
+
7
+ Logger.info "Using DRb sessions at #{Session.cache_address}:#{Session.cache_port}." if defined?(Logger) && $DBG
8
+
9
+ Session.cache = Glue::DrbCache.new(Session.cache_address, Session.cache_port)
10
+
11
+ end
@@ -0,0 +1,15 @@
1
+ require "glue/cache/file"
2
+
3
+ require "raw/context/session"
4
+
5
+ module Raw
6
+
7
+ # A Session manager that persists sessions on disk.
8
+
9
+ Logger.info "Using File sessions." if defined?(Logger) && $DBG
10
+
11
+ Session.cache = Glue::FileCache.new("session_#{Session.cookie_name}", Session.keepalive)
12
+
13
+ end
14
+
15
+ # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
@@ -0,0 +1,13 @@
1
+ require "glue/cache/memcached"
2
+
3
+ require "raw/context/session"
4
+
5
+ module Raw
6
+
7
+ # A Session manager that persists sessions on disk.
8
+
9
+ Logger.debug "Using MemCached sessions." if defined?(Logger) && $DBG
10
+
11
+ Session.cache = Glue::MemCached.new("session_#{Session.cookie_name}", Session.keepalive)
12
+
13
+ end
@@ -0,0 +1,12 @@
1
+ require "glue/cache/memory"
2
+ require "glue/logger"
3
+
4
+ require "raw/context/session"
5
+
6
+ module Raw
7
+
8
+ Logger.info "Using Memory sessions." if defined?(Logger) && $DBG
9
+
10
+ Session.cache = Glue::MemoryCache.new
11
+
12
+ end
@@ -0,0 +1,15 @@
1
+ require "glue/cache/og"
2
+
3
+ require "raw/context/session"
4
+
5
+ module Raw
6
+
7
+ # A Session manager that persists sessions on an Og store.
8
+
9
+ Logger.debug "Using Og sessions." if defined?(Logger) && $DBG
10
+
11
+ Session.cache = OgCache.new("session_#{Session.cookie_name}", Session.keepalive)
12
+
13
+ end
14
+
15
+ # * Guillaume Pierronnet <guillaume.pierronnet@gmail.com>
@@ -0,0 +1,13 @@
1
+ require "glue/cache/pstore"
2
+
3
+ require "raw/context/session"
4
+
5
+ module Raw
6
+
7
+ # A Session manager that is using PStore to store state
8
+
9
+ Logger.info "Using PStore sessions." if defined?(Logger) && $DBG
10
+
11
+ Session.cache = Glue::PStoreCache.new(Session.keepalive)
12
+
13
+ end
@@ -0,0 +1,18 @@
1
+ require "raw/compiler/filter/elements/element"
2
+ require "raw/helper/xhtml"
3
+
4
+ module Raw
5
+
6
+ # A specialized kind of element used for implementing UI
7
+ # controls.
8
+ #--
9
+ # TODO: add support for the singleton pattern to avoid excessive
10
+ # memory usage.
11
+ #++
12
+
13
+ class Control < Element
14
+ # THINK: maybe include this in element too?
15
+ include XhtmlHelper
16
+ end
17
+
18
+ end
@@ -0,0 +1,91 @@
1
+ require "raw/control"
2
+
3
+ module Raw
4
+
5
+ # The base class for controls used to inspect object
6
+ # attributes.
7
+ #--
8
+ # TODO: find a better name.
9
+ #++
10
+
11
+ class AttributeControl < Control
12
+
13
+ # The attribute that this control renders.
14
+
15
+ attr_accessor :attribute
16
+
17
+ # The annotations used for rendering
18
+
19
+ attr_accessor :anno
20
+
21
+ # The value
22
+
23
+ attr_accessor :value
24
+ alias_method :values, :value
25
+
26
+ # === Input
27
+ #
28
+ # * object = the object to inspect
29
+ # * a = the attribute to inspect
30
+ # * options = additional options
31
+
32
+ def initialize(object, a, options)
33
+ @object = object
34
+ @attribute = a
35
+ @anno = @object.class.ann(@attribute)
36
+ @value = @object.send(@attribute)
37
+ @options = options
38
+ end
39
+
40
+ private
41
+
42
+ # Used as id attribute in HTML markup.
43
+ def control_id
44
+ "#{@attribute}_ctl"
45
+ end
46
+
47
+ # Emit the label for this control.
48
+ # The label is skipped if the control is created with the
49
+ # option :no_label set to true.
50
+
51
+ def emit_label
52
+ return "" if @options[:no_label]
53
+ title = @anno[:title] || @options[:label] || @attribute.to_s.humanize
54
+ %{<label for="#{control_id}">#{title}</label>}
55
+ end
56
+
57
+ # Emit the css style for this control.
58
+ # This mehtod takes into account the passed options (first)
59
+ # and then the attribute annotations.
60
+
61
+ def emit_style
62
+ unless style = (@options[:style] || @anno[:control_style])
63
+ if self.class.respond_to? :style
64
+ style = self.class.style
65
+ else
66
+ style = nil
67
+ end
68
+ end
69
+ style ? %{ style="#{style}"} : ''
70
+ end
71
+
72
+ # Add support to your controls for being disabled
73
+ # by including an emit_disabled on form items
74
+ # or testing for is_disabled? on more complex controls.
75
+
76
+ def emit_disabled
77
+ is_disabled? ? %{ disabled="disabled"} : ''
78
+ end
79
+
80
+ #--
81
+ # FIXME
82
+ #++
83
+
84
+ def is_disabled?
85
+ return false if @options[:all]
86
+ @options[:disable_controls] || @anno[:disable_control]
87
+ end
88
+
89
+ end
90
+
91
+ end