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,157 @@
1
+ require "nitro/aspects"
2
+
3
+ module Raw
4
+
5
+ # This module adds flashing support to the Controllers.
6
+
7
+ module Flashing
8
+
9
+ def self.included(base)
10
+ super
11
+ base.before(:call => :init_flash)
12
+ base.after(:call => :clean_flash)
13
+ end
14
+
15
+ # A Flash is a special hash object that lives in the session.
16
+ # The values stored in the Flash are typically maintained
17
+ # for the duration of one request. After the request is over,
18
+ # the Hash is cleared.
19
+ #
20
+ # You may want to use the Flash to pass error messages or
21
+ # other short lived objects.
22
+ #
23
+ # Use capitalized keys to denote system variables. Reserve
24
+ # lower case keys for user application variables.
25
+
26
+ class Flash < Hash
27
+
28
+ def initialize
29
+ super
30
+ @dirty = {}
31
+ end
32
+
33
+ def []=(key, val)
34
+ super
35
+ keep(key)
36
+ end
37
+
38
+ # Keep the specific key or the whole Flash.
39
+
40
+ def keep(key = nil)
41
+ set_dirty(key, false)
42
+ end
43
+
44
+ # Discard the specific key or the whole Flash.
45
+
46
+ def discard(key = nil)
47
+ set_dirty(key)
48
+ end
49
+
50
+ def clean # :nodoc:
51
+ keys.each do |k|
52
+ unless @dirty[k]
53
+ set_dirty(k)
54
+ else
55
+ delete(k)
56
+ @dirty.delete(k)
57
+ end
58
+ end
59
+
60
+ # remove externaly updated keys.
61
+
62
+ (@dirty.keys - keys).each { |k| @dirty.delete k }
63
+ end
64
+
65
+ # :section: Helpers
66
+
67
+ # Push a value in an array flash variable.
68
+ #
69
+ # === Example
70
+ #
71
+ # flash.push :ERRORS, 'This is the first error'
72
+ # flash.push :ERRORS, 'This is the second error'
73
+ #
74
+ # flash[:ERRORS] # => []
75
+
76
+ def push(key, *values)
77
+ val = self[key]
78
+ val ||= []
79
+ if values.size == 1
80
+ val << values[0]
81
+ else
82
+ val << values
83
+ end
84
+ self[key] = val
85
+ end
86
+
87
+ # Pop a value from an array flash variable.
88
+
89
+ def pop(key)
90
+ if arr = self[key]
91
+ if arr.is_a? Array
92
+ return arr.pop
93
+ else
94
+ return arr
95
+ end
96
+ end
97
+ return nil
98
+ end
99
+
100
+ # Another helper, concats a whole array to the given flash
101
+ # key.
102
+
103
+ def concat(key, arr)
104
+ for val in arr.to_a
105
+ push key, val
106
+ end
107
+ end
108
+
109
+ # Join helper
110
+
111
+ def join(key, sep = ', ')
112
+ value = self[key]
113
+
114
+ if value.is_a? Array
115
+ return value.join(sep)
116
+ else
117
+ return value
118
+ end
119
+ end
120
+
121
+ private
122
+
123
+ def set_dirty(key = nil, flag = true)
124
+ if key
125
+ @dirty[key] = flag
126
+ else
127
+ keys.each { |k| @dirty[k] = flag }
128
+ end
129
+ end
130
+
131
+ end
132
+
133
+ private
134
+
135
+ def flash
136
+ session[:FLASH] ||= Flash.new
137
+ end
138
+
139
+ # Some useful aspects.
140
+
141
+ # Marks flash entries as used and expose the flash to the
142
+ # view.
143
+
144
+ def init_flash
145
+ flash.discard
146
+ end
147
+
148
+ # Deletes the flash entries that were not marked for
149
+ # keeping.
150
+
151
+ def clean_flash
152
+ flash.clean
153
+ end
154
+
155
+ end
156
+
157
+ end
@@ -0,0 +1,88 @@
1
+ # Global scoped variables. This is backed by a Cache store.
2
+ #--
3
+ # TODO: implement as a refactoring of session?
4
+ #++
5
+
6
+ class Global
7
+
8
+ # The type of the global cache. The generalized caching
9
+ # system in Glue is used. The following options are available:
10
+ #
11
+ # * :memory [default]
12
+ # * :drb
13
+ # * :og
14
+ # * :file
15
+ # * :memcached
16
+
17
+ setting :cache_type, :default => :memory, :doc => 'The type of global cache'
18
+
19
+ # The address of the store.
20
+
21
+ setting :cache_address, :default => '127.0.0.1', :doc => 'The address of the global cache'
22
+
23
+ # The port of the store.
24
+
25
+ setting :cache_port, :default => 9079, :doc => 'The port of the global cache'
26
+
27
+ class << self
28
+ # The global cache (store).
29
+
30
+ attr_accessor :cache
31
+
32
+ # Init the correct Global cache.
33
+
34
+ def setup(type = Global.cache_type)
35
+ return if Global.cache
36
+
37
+ case type
38
+ when :memory
39
+ require 'glue/cache/memory'
40
+ Global.cache = Glue::MemoryCache.new
41
+
42
+ when :drb
43
+ require 'glue/cache/drb'
44
+ Global.cache = DrbCache.new(Global.cache_address, Global.cache_port)
45
+ end
46
+ end
47
+
48
+ # Initialize a global value once.
49
+
50
+ def init(key, value)
51
+ unless Global[key]
52
+ Global[key] = value
53
+ end
54
+ end
55
+
56
+ def set(key, value)
57
+ Global.cache[key] = value
58
+ end
59
+ alias_method :[]=, :set
60
+
61
+ def get(key)
62
+ return Global.cache[key]
63
+ end
64
+ alias_method :[], :get
65
+
66
+ # If block is given it acts as an update methods,
67
+ # that transparently handles distributed stores.
68
+ #
69
+ # Global.update(:USERS) do |users|
70
+ # users << 'gmosx'
71
+ # end
72
+
73
+ def update(key)
74
+ if block_given?
75
+ # update, also handles distributed stores.
76
+ val = Global.cache[key]
77
+ yield val
78
+ Global.cache[key] = val
79
+ end
80
+ end
81
+
82
+ def delete(key)
83
+ Global.cache.delete(key)
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,338 @@
1
+ module Raw
2
+
3
+ # Encapsulates a request. This is an abstract request
4
+ # typically extended by sub-classes. This module
5
+ # is included in Context.
6
+
7
+ module Request
8
+
9
+ # The request input stream.
10
+
11
+ attr_accessor :in
12
+
13
+ # The request headers collection. Also called
14
+ # the request environment (env).
15
+
16
+ attr_accessor :headers
17
+ alias_method :env, :headers
18
+ alias_method :env=, :headers=
19
+ alias_method :env_table, :headers
20
+
21
+ attr_accessor :post_params
22
+ attr_accessor :get_params
23
+
24
+ # The parsed query parameters collection.
25
+
26
+ def params
27
+ if method == :post
28
+ @post_params
29
+ else
30
+ @get_params
31
+ end
32
+ end
33
+
34
+ def params=(pa)
35
+ if method == :post
36
+ @post_params = pa
37
+ else
38
+ @get_params = pa
39
+ end
40
+ end
41
+
42
+ alias_method :query, :params
43
+ alias_method :parameters, :params
44
+
45
+ # The request cookies.
46
+
47
+ attr_accessor :cookies
48
+ alias_method :cookie, :cookies
49
+
50
+ # The request protocol.
51
+
52
+ def protocol
53
+ @headers['HTTPS'] == "on" ? "https://" : "http://"
54
+ end
55
+
56
+ # Is this an ssl request?
57
+
58
+ def ssl?
59
+ @headers["HTTPS"] == "on"
60
+ end
61
+
62
+ # The request uri.
63
+
64
+ def uri
65
+ @headers["REQUEST_URI"]
66
+ end
67
+
68
+ # The path info. Typically this is the rewritten uri without
69
+ # the query string.
70
+
71
+ def path_info
72
+ @headers["PATH_INFO"]
73
+ end
74
+ alias_method :path, :path_info
75
+
76
+ # Returns the domain part of a host.
77
+ #
78
+ # === Examples
79
+ #
80
+ # www.nitroproject.org: request.domain # => 'nitroproject.org'
81
+ # www.nitroproject.co.uk: request.domain(2) # => 'nitroproject.co.uk'
82
+
83
+ def domain tld_length = 1
84
+ host.split('.').last(1 + tld_length).join('.')
85
+ end
86
+
87
+ # Returns all the subdomains as an array.
88
+ #
89
+ # === Examples
90
+ #
91
+ # my.name.nitroproject.org: request.subdomains # => ['my', 'name']
92
+
93
+ def subdomains tld_length = 1
94
+ parts = host.split('.')
95
+ parts[0..-(tld_length+2)]
96
+ end
97
+
98
+ # The request query string.
99
+
100
+ def query_string
101
+ headers["QUERY_STRING"]
102
+ end
103
+
104
+ # The request method. Alternatively you could use the
105
+ # request method predicates.
106
+ #
107
+ # === Examples
108
+ #
109
+ # if request.method == :get
110
+ # if request.get?
111
+
112
+ def method
113
+ @headers["REQUEST_METHOD"].downcase.to_sym
114
+ end
115
+
116
+ #--
117
+ # Define a set of helpers to determine the request
118
+ # method (get?, post?, put?, delete?, head?)
119
+ #++
120
+
121
+ for m in [:get, :post, :put, :delete, :head]
122
+ eval %{
123
+ def #{m}?; method == :#{m}; end
124
+ }
125
+ end
126
+
127
+ # Determine whether the body of a POST request is URL-encoded
128
+ # (default), XML, or YAML by checking the Content-Type HTTP
129
+ # header:
130
+ #
131
+ # Content-Type Post Format
132
+ # application/xml :xml
133
+ # text/xml :xml
134
+ # application/x-yaml :yaml
135
+ # text/x-yaml :yaml
136
+ # * :url_encoded
137
+
138
+ def post_format
139
+ @post_format ||= if @headers['HTTP_X_POST_DATA_FORMAT']
140
+ @headers['HTTP_X_POST_DATA_FORMAT'].downcase.to_sym
141
+ else
142
+ case @headers['CONTENT_TYPE'].to_s.downcase
143
+ when 'application/xml', 'text/xml' then :xml
144
+ when 'application/x-yaml', 'text/x-yaml' then :yaml
145
+ else :url_encoded
146
+ end
147
+ end
148
+ end
149
+
150
+ # Is this a POST request formatted as XML or YAML?
151
+
152
+ def formatted_post?
153
+ post? && (post_format == :xml || post_format == :yaml)
154
+ end
155
+
156
+ # Is this a POST request formatted as XML?
157
+
158
+ def xml_post?
159
+ post? && post_format == :xml
160
+ end
161
+
162
+ # Is this a POST request formatted as YAML?
163
+
164
+ def yaml_post?
165
+ post? && post_format == :yaml
166
+ end
167
+
168
+ # Is this an XhtmlRpcRequest?
169
+ # Returns true if the request's 'X-Requested-With' header
170
+ # contains 'XMLHttpRequest'. Compatible with the Prototype
171
+ # Javascript library.
172
+
173
+ def xml_http_request?
174
+ not /XMLHttpRequest/i.match(@headers['HTTP_X_REQUESTED_WITH']).nil?
175
+ end
176
+ alias_method :xhr?, :xml_http_request?
177
+ alias_method :script?, :xml_http_request?
178
+
179
+ # Return the referer. For the initial page in the
180
+ # clickstream there is no referer, set "/" by default.
181
+
182
+ def referer
183
+ @headers["HTTP_REFERER"] || "/"
184
+ end
185
+ alias_method :referrer, :referer
186
+
187
+ # The content_length
188
+
189
+ def content_length
190
+ @headers["CONTENT_LENGTH"].to_i
191
+ end
192
+
193
+ # The remote IP address. REMOTE_ADDR is the standard
194
+ # but will fail if the user is behind a proxy.
195
+ # HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR are set by
196
+ # proxies so check for these before falling back to
197
+ # REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma-delimited
198
+ # list in the case of multiple chained proxies; the first
199
+ # is the originating IP.
200
+
201
+ def remote_ip
202
+ return @headers['HTTP_CLIENT_IP'] if @headers.include?('HTTP_CLIENT_IP')
203
+
204
+ if @headers.include?('HTTP_X_FORWARDED_FOR') then
205
+ remote_ips = @headers['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip|
206
+ ip =~ /^unknown$/i or local_net?(ip)
207
+ end
208
+
209
+ return remote_ips.first.strip unless remote_ips.empty?
210
+ end
211
+
212
+ return @headers['REMOTE_ADDR']
213
+ end
214
+
215
+ # Request is from a local network? (RFC1918 + localhost)
216
+
217
+ def local_net?(ip = remote_ip)
218
+ bip = ip.split('.').map{ |x| x.to_i }.pack('C4').unpack('N')[0]
219
+
220
+ # 127.0.0.1/32 => 2130706433
221
+ # 192.168.0.0/16 => 49320
222
+ # 172.16.0.0/12 => 2753
223
+ # 10.0.0.0/8 => 10
224
+
225
+ { 0 => 2130706433, 16 => 49320, 20 => 2753, 24 => 10}.each do |s,c|
226
+ return true if (bip >> s) == c
227
+ end
228
+
229
+ return false
230
+ end
231
+
232
+ # Request comming from local?
233
+
234
+ def local?(ip = remote_ip)
235
+ # TODO: should check if requesting machine is the one the server is running
236
+ return true if ip == '127.0.0.1'
237
+ end
238
+
239
+ # The server port.
240
+
241
+ def port
242
+ @headers['SERVER_PORT'].to_i
243
+ end
244
+
245
+ # The server host name.
246
+ # Also handles proxy forwarding.
247
+
248
+ def host
249
+ @headers['HTTP_X_FORWARDED_HOST'] || @headers['HTTP_HOST']
250
+ end
251
+
252
+ # The host uri.
253
+
254
+ def host_uri
255
+ "#{protocol}#{host}"
256
+ end
257
+ alias_method :server_uri, :host_uri
258
+ # This is deprecated.
259
+ alias_method :host_url, :host_uri
260
+
261
+ # Different servers hold user agent in differnet
262
+ # strings (unify this).
263
+
264
+ def user_agent
265
+ headers["HTTP_USER_AGENT"] || headers["USER-AGENT"]
266
+ end
267
+
268
+ # The raw data of the request.
269
+ # Useful to implement Webservices.
270
+ #--
271
+ # FIXME: better name and implementation.
272
+ #++
273
+
274
+ def raw_body
275
+ unless @raw_body
276
+ @in.rewind
277
+ @raw_body = @in.read(content_length)
278
+ end
279
+
280
+ @raw_body
281
+ end
282
+
283
+ # Lookup a query parameter.
284
+ #--
285
+ # TODO: Check if unescape is needed.
286
+ #++
287
+
288
+ def [](param)
289
+ params[param]
290
+ end
291
+
292
+ # Set a query parameter.
293
+
294
+ def []=(param, value)
295
+ params[param] = value
296
+ end
297
+
298
+ # Check if a boolean param (checkbox) is true.
299
+
300
+ def true?(param)
301
+ params[param] == 'on'
302
+ end
303
+ alias_method :enabled?, :true?
304
+ alias_method :boolean, :true?
305
+
306
+ # Check if a boolean param (checkbox) is false.
307
+
308
+ def false?(param)
309
+ !true?(param)
310
+ end
311
+
312
+ # Fetch a parameter with default value.
313
+
314
+ def fetch param, default = nil
315
+ params.fetch(param, default)
316
+ end
317
+
318
+ # Check if a param is available.
319
+ #--
320
+ # gmosx: use instead of nil test to be more robust.
321
+ # (nil can be a hash element !)
322
+ #++
323
+
324
+ def has_key?(key)
325
+ params.keys.include?(key)
326
+ end
327
+ alias_method :has_param?, :has_key?
328
+ alias_method :param?, :has_key?
329
+ alias_method :has?, :has_key?
330
+ alias_method :is?, :has_key?
331
+
332
+ def keys
333
+ params.keys
334
+ end
335
+
336
+ end
337
+
338
+ end