ramaze 2008.11 → 2009.01

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/README.markdown +7 -7
  2. data/benchmark/run.rb +1 -1
  3. data/doc/CHANGELOG +662 -0
  4. data/examples/app/blog/model/entry.rb +8 -1
  5. data/examples/app/blog/spec/blog.rb +2 -2
  6. data/examples/app/rapaste/spec/rapaste.rb +1 -1
  7. data/examples/app/rapaste/start.rb +2 -2
  8. data/examples/app/rapaste/view/view.xhtml +3 -0
  9. data/examples/app/todolist/spec/todolist.rb +1 -1
  10. data/examples/app/whywiki/spec/whywiki.rb +1 -1
  11. data/examples/app/wikore/spec/wikore.rb +1 -1
  12. data/examples/app/wikore/src/model.rb +8 -2
  13. data/examples/app/wiktacular/spec/wiktacular.rb +1 -1
  14. data/examples/app/wiktacular/src/model.rb +1 -1
  15. data/examples/basic/partial.rb +28 -0
  16. data/examples/helpers/httpdigest.rb +68 -10
  17. data/examples/misc/ramaise.rb +2 -2
  18. data/examples/templates/template_amrita2.rb +1 -1
  19. data/examples/templates/template_erubis.rb +1 -1
  20. data/examples/templates/template_ezamar.rb +1 -1
  21. data/examples/templates/template_haml.rb +2 -2
  22. data/examples/templates/template_liquid.rb +1 -1
  23. data/examples/templates/template_markaby.rb +2 -2
  24. data/examples/templates/template_nagoro.rb +1 -1
  25. data/examples/templates/template_redcloth.rb +1 -1
  26. data/examples/templates/template_remarkably.rb +2 -2
  27. data/examples/templates/template_tenjin.rb +1 -1
  28. data/examples/templates/template_xslt.rb +1 -1
  29. data/lib/proto/controller/init.rb +2 -1
  30. data/lib/proto/model/init.rb +3 -3
  31. data/lib/proto/public/dispatch.fcgi +2 -2
  32. data/lib/proto/spec/main.rb +3 -3
  33. data/lib/proto/start.rb +4 -0
  34. data/lib/ramaze.rb +6 -0
  35. data/lib/ramaze/action.rb +7 -1
  36. data/lib/ramaze/action/render.rb +6 -5
  37. data/lib/ramaze/cache.rb +1 -0
  38. data/lib/ramaze/cache/file.rb +71 -0
  39. data/lib/ramaze/contrib.rb +1 -1
  40. data/lib/ramaze/contrib/email.rb +2 -0
  41. data/lib/ramaze/contrib/facebook.rb +2 -2
  42. data/lib/ramaze/contrib/file_cache.rb +2 -64
  43. data/lib/ramaze/contrib/sequel/image.rb +1 -1
  44. data/lib/ramaze/controller.rb +9 -1
  45. data/lib/ramaze/controller/resolve.rb +10 -5
  46. data/lib/ramaze/current/request.rb +87 -70
  47. data/lib/ramaze/current/session.rb +3 -5
  48. data/lib/ramaze/current/session/hash.rb +7 -11
  49. data/lib/ramaze/dispatcher/action.rb +2 -0
  50. data/lib/ramaze/dispatcher/file.rb +6 -1
  51. data/lib/ramaze/helper.rb +12 -4
  52. data/lib/ramaze/helper/aspect.rb +2 -2
  53. data/lib/ramaze/helper/bench.rb +43 -0
  54. data/lib/ramaze/helper/form.rb +5 -2
  55. data/lib/ramaze/helper/formatting.rb +4 -0
  56. data/lib/ramaze/helper/gravatar.rb +18 -1
  57. data/lib/ramaze/helper/httpdigest.rb +55 -28
  58. data/lib/ramaze/helper/markaby.rb +1 -1
  59. data/lib/ramaze/helper/maruku.rb +2 -0
  60. data/lib/ramaze/helper/paginate.rb +1 -1
  61. data/lib/ramaze/helper/partial.rb +1 -1
  62. data/lib/ramaze/helper/redirect.rb +22 -4
  63. data/lib/ramaze/helper/user.rb +4 -4
  64. data/lib/ramaze/option.rb +1 -1
  65. data/lib/ramaze/option/holder.rb +3 -3
  66. data/lib/ramaze/reloader.rb +25 -41
  67. data/lib/ramaze/reloader/watch_inotify.rb +85 -0
  68. data/lib/ramaze/reloader/watch_stat.rb +58 -0
  69. data/lib/ramaze/snippets/divide.rb +2 -0
  70. data/lib/ramaze/snippets/numeric/time.rb +1 -1
  71. data/lib/ramaze/snippets/object/__dir__.rb +3 -3
  72. data/lib/ramaze/snippets/object/acquire.rb +3 -6
  73. data/lib/ramaze/snippets/ramaze/acquire.rb +31 -0
  74. data/lib/ramaze/snippets/ramaze/deprecated.rb +2 -1
  75. data/lib/ramaze/spec/helper/mock_http.rb +6 -5
  76. data/lib/ramaze/template/ezamar/render_partial.rb +8 -0
  77. data/lib/ramaze/tool/mime.rb +1 -1
  78. data/lib/ramaze/tool/project_creator.rb +2 -1
  79. data/lib/ramaze/version.rb +2 -2
  80. data/rake_tasks/coverage.rake +4 -5
  81. data/rake_tasks/spec.rake +6 -6
  82. data/ramaze-2008.11.gem +0 -0
  83. data/ramaze.gemspec +759 -758
  84. data/spec/contrib/profiling.rb +2 -2
  85. data/spec/ramaze/action/file_cache.rb +1 -1
  86. data/spec/ramaze/action/layout.rb +1 -1
  87. data/spec/ramaze/controller/actionless_templates.rb +1 -1
  88. data/spec/ramaze/controller/resolve.rb +1 -1
  89. data/spec/ramaze/controller/template_resolving.rb +1 -1
  90. data/spec/ramaze/dispatcher/directory.rb +3 -3
  91. data/spec/ramaze/helper/aspect.rb +1 -1
  92. data/spec/ramaze/helper/partial.rb +1 -1
  93. data/spec/ramaze/localize.rb +1 -1
  94. data/spec/ramaze/rewrite.rb +1 -1
  95. data/spec/ramaze/template.rb +3 -3
  96. data/spec/ramaze/template/amrita2.rb +1 -1
  97. data/spec/ramaze/template/erubis.rb +1 -1
  98. data/spec/ramaze/template/ezamar.rb +1 -1
  99. data/spec/ramaze/template/haml.rb +2 -2
  100. data/spec/ramaze/template/nagoro.rb +1 -1
  101. data/spec/ramaze/template/redcloth.rb +1 -1
  102. data/spec/ramaze/template/sass.rb +1 -1
  103. data/spec/ramaze/template/tenjin.rb +1 -1
  104. data/spec/snippets/object/__dir__.rb +6 -0
  105. data/spec/snippets/{object → ramaze}/acquire.rb +24 -18
  106. metadata +18 -16
  107. data/lib/ramaze/contrib/auto_params.rb +0 -135
  108. data/lib/ramaze/contrib/auto_params/get_args.rb +0 -58
  109. data/spec/contrib/auto_params.rb +0 -121
  110. data/spec/snippets/divide.rb +0 -19
@@ -4,8 +4,8 @@ require 'rubygems'
4
4
  require 'ramaze'
5
5
 
6
6
  # FCGI doesn't like you writing to stdout
7
- Ramaze::Log.loggers = [ Ramaze::Logger::Informer.new( File.join(__DIR__, '..', 'ramaze.fcgi.log') ) ]
7
+ Ramaze::Log.loggers = [ Ramaze::Logger::Informer.new( __DIR__("../ramaze.fcgi.log") ) ]
8
8
  Ramaze::Global.adapter = :fcgi
9
9
 
10
- $0 = File.join(__DIR__, '..', 'start.rb')
10
+ $0 = __DIR__("../start.rb")
11
11
  require $0
@@ -1,12 +1,12 @@
1
1
  require 'ramaze'
2
2
  require 'ramaze/spec/helper'
3
3
 
4
- require __DIR__/'../start'
4
+ require __DIR__('../start')
5
5
 
6
6
  describe MainController do
7
7
  behaves_like 'http', 'xpath'
8
- ramaze :view_root => __DIR__/'../view',
9
- :public_root => __DIR__/'../public'
8
+ ramaze :view_root => __DIR__('../view'),
9
+ :public_root => __DIR__('../public')
10
10
 
11
11
  it 'should show start page' do
12
12
  got = get('/')
@@ -1,6 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'ramaze'
3
3
 
4
+ # Add directory start.rb is in to the load path, so you can run the app from
5
+ # any other working path
6
+ $LOAD_PATH.unshift(__DIR__)
7
+
4
8
  # Initialize controllers and models
5
9
  require 'controller/init'
6
10
  require 'model/init'
@@ -79,6 +79,8 @@ module Ramaze
79
79
  # each class in trait[:essentials] by calling ::startup on them.
80
80
 
81
81
  def startup options = {}
82
+ options = options.to_hash
83
+
82
84
  force = options.delete(:force)
83
85
  force ||= !trait[:started]
84
86
 
@@ -97,10 +99,14 @@ module Ramaze
97
99
  end
98
100
  end
99
101
 
102
+ # A shortcut for setting Ramaze.trait[:started] = true.
103
+
100
104
  def skip_start
101
105
  trait[:started] = true
102
106
  end
103
107
 
108
+ # Forces the startup of Ramaze regardless if trait[:started] is set.
109
+
104
110
  def start!(options = {})
105
111
  trait[:started] = false
106
112
  startup(options)
@@ -110,17 +110,21 @@ module Ramaze
110
110
  end
111
111
 
112
112
  # Try to figure out a sane name for current action.
113
+
113
114
  def name
114
115
  File.basename((self[:method] || self[:template]).to_s).split('.').first
115
116
  end
116
117
 
117
118
  # combined path to current action, from path and params
119
+
118
120
  def extended_path
119
121
  (path == "index" && !params.empty? ? params : Array[path, *params]).join('/')
120
122
  end
121
123
 
124
+ # same as Ramaze::Action#extended_path, with mapping of the current controller prepended.
125
+
122
126
  def full_path
123
- self.controller.mapping/extended_path
127
+ File.join(self.controller.mapping, extended_path)
124
128
  end
125
129
 
126
130
  # Hook for AspectHelper
@@ -133,6 +137,8 @@ module Ramaze
133
137
  def after_process
134
138
  end
135
139
 
140
+ # Returns true if current request is valid REST request.
141
+
136
142
  def valid_rest?
137
143
  return true unless rest = controller.trait[:REST]
138
144
  meth = Request.current.request_method
@@ -49,8 +49,8 @@ module Ramaze
49
49
  # true.
50
50
 
51
51
  def cached_render
52
- if Global.file_cache
53
- cached_render_file
52
+ if cache_root = Global.file_cache
53
+ cached_render_file(cache_root)
54
54
  else
55
55
  cached_render_memory
56
56
  end
@@ -59,12 +59,13 @@ module Ramaze
59
59
  # Uses files in the Global.public_root to provide a static ressource on
60
60
  # next request and returns the rendered action
61
61
 
62
- def cached_render_file
62
+ def cached_render_file(cache_root)
63
63
  rendered = uncached_render
64
64
 
65
- global_epath = Global.public_root/self.controller.mapping/extended_path
65
+ cr = cache_root.respond_to?(:to_str) ? cache_root.to_str : Global.public_root
66
+ global_epath = File.join(cr, self.controller.mapping, extended_path)
66
67
  FileUtils.mkdir_p(File.dirname(global_epath))
67
- File.open(global_epath, 'w+') {|fp| fp.print(rendered) }
68
+ File.open(global_epath, 'w+'){|fp| fp.print(rendered) }
68
69
 
69
70
  rendered
70
71
  end
@@ -6,6 +6,7 @@ require 'ramaze/cache/memory'
6
6
  module Ramaze
7
7
  autoload :YAMLStoreCache, "ramaze/cache/yaml_store.rb"
8
8
  autoload :MemcachedCache, "ramaze/cache/memcached.rb"
9
+ autoload :FileCache, "ramaze/cache/file.rb"
9
10
 
10
11
  # This is the wrapper of all caches, providing mechanism
11
12
  # for switching caching from one adapter to another.
@@ -0,0 +1,71 @@
1
+ module Ramaze
2
+ # Persist cache contents to the filesystem.
3
+ # By default this will create a `/cache` directory in your APPDIR
4
+ #
5
+ # Usage for sessions only:
6
+ #
7
+ # Ramaze::Global::cache_alternative[:sessions] = Ramaze::FileCache
8
+ #
9
+ # Usage for everything:
10
+ #
11
+ # Ramaze::Global::cache = Ramaze::FileCache
12
+
13
+ class FileCache
14
+ attr_accessor :root, :subdir
15
+ attr_reader :host, :pid
16
+
17
+ def initialize(root = Ramaze::Global.root, subdir = 'cache')
18
+ @root, @subdir = root, subdir
19
+ @host = Socket.gethostname
20
+ @pid = $$
21
+
22
+ FileUtils.mkdir_p(dir)
23
+ end
24
+
25
+ def dir(*further)
26
+ File.join(root, subdir, *further)
27
+ end
28
+
29
+ def [](key)
30
+ Marshal.load(File.read(dir(key.to_s, 'data')))
31
+ rescue
32
+ nil
33
+ end
34
+
35
+ def []=(key, value)
36
+ key = key.to_s
37
+ tmp_name = dir(key, "data.#{host}.#{pid}")
38
+ key_name = dir(key, 'data')
39
+ dir_name = dir(key)
40
+
41
+ data = Marshal.dump(value)
42
+
43
+ FileUtils.rm_rf(dir_name)
44
+ FileUtils.mkdir_p(dir_name)
45
+
46
+ File.open(tmp_name, 'w'){|fd| fd.write(data) }
47
+
48
+ FileUtils.mv(tmp_name, key_name)
49
+
50
+ return value
51
+ end
52
+
53
+ def values_at(*keys)
54
+ keys.map{|key| self[key] }
55
+ end
56
+
57
+ def delete(*keys)
58
+ keys.map do |key|
59
+ FileUtils.rm_rf(dir(key.to_s))
60
+ end
61
+ end
62
+
63
+ def clear
64
+ Dir[dir('*')].each{|entry| FileUtils.rm_rf(entry) }
65
+ end
66
+
67
+ def to_sym
68
+ name.split('::').last.to_sym
69
+ end
70
+ end
71
+ end
@@ -49,7 +49,7 @@ module Ramaze
49
49
  const.startup if const.respond_to?(:startup)
50
50
  Log.dev "Loaded contrib: #{const}"
51
51
  rescue NameError
52
- files = Dir["{contrib,#{BASEDIR/:ramaze/:contrib}}/#{name}.{so,bundle,rb}"]
52
+ files = Dir["{contrib,#{BASEDIR}/ramaze/contrib}/#{name}.{so,bundle,rb}"]
53
53
  raise LoadError, "#{mod_name} not found" unless files.any?
54
54
  require(files.first) ? retry : raise
55
55
  end
@@ -67,6 +67,8 @@ Message-Id: #{id}
67
67
  send_smtp( email, recipient, subject )
68
68
  end
69
69
 
70
+ # the raw mail sending method used by Ramaze::EmailHelper
71
+
70
72
  def send_smtp( email, recipient, subject )
71
73
  options = trait.values_at(:smtp_server, :smtp_port, :smtp_helo_domain,
72
74
  :smtp_username, :smtp_password, :smtp_auth_type)
@@ -1,4 +1,4 @@
1
- require __DIR__/:facebook/:facebook
1
+ require __DIR__('facebook/facebook')
2
2
 
3
3
  module Ramaze
4
4
  module Helper::Facebook
@@ -20,4 +20,4 @@ module Ramaze
20
20
  end
21
21
  alias fb facebook
22
22
  end
23
- end
23
+ end
@@ -1,65 +1,3 @@
1
- #
2
- # drop-in replacement for Ramaze's built-in MemoryCache built on the
3
- # filesystem. # to use with sessions do
4
- #
5
- # Ramaze::Global::cache_alternative[:sessions] = Ramaze::FileCache
6
- #
7
- # to use with everything do
8
- #
9
- # Ramaze::Global::cache = Ramaze::FileCache
10
- #
1
+ Ramaze::Log.warn("ramaze/contrib/file_cache is now ramaze/cache/file")
11
2
 
12
- module Ramaze::FileCache
13
- require "fileutils"
14
- require "socket"
15
-
16
- Host = Socket.gethostname
17
- Pid = Process.pid
18
- Fu = FileUtils
19
- Root = File.join Ramaze::APPDIR, "cache"
20
-
21
- Fu.mkdir_p(Root) rescue nil
22
-
23
- def self.[] key
24
- path = File.join Root, key, "data"
25
- Marshal.load(IO.read(path))
26
- rescue
27
- nil
28
- end
29
-
30
- def self.[]= key, value
31
- tmp = File.join Root, key, "data.#{ Host }.#{ Pid }"
32
- dirname = File.join Root, key
33
- path = File.join Root, key, "data"
34
- data = Marshal.dump value
35
- Fu.rm_rf dirname rescue nil
36
- Fu.mkdir_p dirname rescue nil
37
- open(tmp, 'w'){|fd| fd.write data}
38
- Fu.mv tmp, path
39
- rescue
40
- nil
41
- end
42
-
43
- def self.values_at *keys
44
- keys.map{|key| self[key]}
45
- end
46
-
47
- def self.delete *keys
48
- keys.map do |key|
49
- dirname = File.join Root, key
50
- Fu.rm_rf dirname rescue next
51
- end
52
- end
53
-
54
- def self.clear
55
- Dir["#{ Root }/*"].each{|entry| Fu.rm_rf entry}
56
- end
57
-
58
- def self.new
59
- self
60
- end
61
-
62
- def self.to_sym
63
- name.split(%r/::/).last.to_sym
64
- end
65
- end
3
+ require 'ramaze/cache/file'
@@ -31,7 +31,7 @@
31
31
  # # Creates a square thumbnail of the image cropping the longest edge
32
32
  # # to match the shortest edge, resizes to +size+.
33
33
  #
34
- # :agorithm => :thumbnail,
34
+ # :algorithm => :thumbnail,
35
35
  #
36
36
  #
37
37
  # # Key specifies the filename and accessors, value are arguments to the
@@ -67,13 +67,17 @@ module Ramaze
67
67
 
68
68
  # if trait[:automap] is set and controller is not in Global.mapping yet
69
69
  # this will build a new default mapping-point, MainController is put
70
- # at '/' by default.
70
+ # at '/' by default. For other Class names, String#snake_case is called,
71
+ # e.g. FooBarController is mapped at '/foo_bar'.
71
72
 
72
73
  def mapping
73
74
  global_mapping = Global.mapping.invert[self]
75
+
74
76
  return global_mapping if global_mapping
77
+
75
78
  if ancestral_trait[:automap] && self.to_s !~ /#<Class:/
76
79
  name = self.to_s.gsub('Controller', '').gsub('::', '/').clone
80
+ return if name.empty?
77
81
  name == 'Main' ? '/' : "/#{name.snake_case}"
78
82
  end
79
83
  end
@@ -262,6 +266,10 @@ module Ramaze
262
266
  action.render
263
267
  end
264
268
 
269
+ # By default, returns all ancestors of current Controller that have
270
+ # Ramaze::Controller as their ancestor. Optional argument parent
271
+ # can be used return ancestors that have parent as an ancestor.
272
+
265
273
  def relevant_ancestors(parent = Ramaze::Controller)
266
274
  ancestors.select do |anc|
267
275
  anc.ancestors.include?(parent)
@@ -16,7 +16,7 @@ module Ramaze
16
16
  # instead, in either case with path as argument.
17
17
 
18
18
  def resolve(path, routed = false)
19
- @routed = routed
19
+ Thread.current[:routed] = routed
20
20
 
21
21
  FILTER.each do |filter|
22
22
  answer = if filter.respond_to?(:call)
@@ -90,7 +90,7 @@ module Ramaze
90
90
  end
91
91
  end
92
92
 
93
- if !@routed and new_path = Route.resolve(path)
93
+ if !Thread.current[:routed] and new_path = Route.resolve(path)
94
94
  Log.dev("Routing from `#{path}' to `#{new_path}'")
95
95
  return resolve(new_path, true)
96
96
  end
@@ -136,10 +136,15 @@ module Ramaze
136
136
 
137
137
  def resolve_template(path)
138
138
  path = path.to_s
139
- path_converted = path.split('__').inject{|s,v| s/v}
139
+ path_converted = path.split('__').inject{|s,v| File.join(s, v) }
140
140
  possible_paths = [path, path_converted].compact
141
141
 
142
- paths = template_paths.map{|pa| possible_paths.map{|a| pa/a } }.flatten.uniq
142
+ paths = template_paths.map{|pa|
143
+ possible_paths.map{|a|
144
+ File.join(pa, a)
145
+ }
146
+ }.flatten.uniq
147
+
143
148
  glob = "{#{paths.join(',')}}.{#{extension_order.join(',')}}"
144
149
 
145
150
  Dir[glob].first
@@ -153,7 +158,7 @@ module Ramaze
153
158
  if paths = view_root
154
159
  paths
155
160
  else
156
- view_root(Global.view_root / Global.mapping.invert[self])
161
+ view_root(File.join(Global.view_root, Global.mapping.invert[self]))
157
162
  end
158
163
  end
159
164
 
@@ -28,10 +28,14 @@ module Ramaze
28
28
  super
29
29
  end
30
30
 
31
+ # the full request URI provided by Rack::Request e.g. http://localhost:7000/controller/action?foo=bar.xhtml
32
+
31
33
  def request_uri
32
34
  env['REQUEST_URI'] || path_info
33
35
  end
34
36
 
37
+ # the IP address(s) making the request provided by Rack::Request. You shouldn't trust it
38
+
35
39
  def ip
36
40
  if addr = env['HTTP_X_FORWARDED_FOR']
37
41
  addr.split(',').last.strip
@@ -47,9 +51,8 @@ module Ramaze
47
51
  ipv6 = %w[ fc00::/7 fe80::/10 fec0::/10 ::1 ]
48
52
  LOCAL = (ipv4 + ipv6).map{|a| IPAddr.new(a)} unless defined?(LOCAL)
49
53
 
50
- # --
51
- # Mongrel somehow puts together multiple IPs when proxy is involved.
52
- # ++
54
+ # returns true if the IP address making the request is from local network.
55
+ # Optional argument address can be used to check any IP address.
53
56
 
54
57
  def local_net?(address = ip)
55
58
  addr = IPAddr.new(address)
@@ -63,6 +66,15 @@ module Ramaze
63
66
  [key, *rest].map{|k| params[k.to_s] }
64
67
  end
65
68
 
69
+ # Sets any arguments passed as @instance_variables for the current action.
70
+ #
71
+ # Usage:
72
+ # request.params # => {'name' => 'manveru', 'q' => 'google', 'lang' => 'de'}
73
+ # to_ivs(:name, :q)
74
+ # @q # => 'google'
75
+ # @name # => 'manveru'
76
+ # @lang # => nil
77
+
66
78
  def to_ivs(*args)
67
79
  instance = Action.current.instance
68
80
  args.each do |arg|
@@ -71,81 +83,77 @@ module Ramaze
71
83
  end
72
84
  end
73
85
 
74
- unless method_defined?(:rack_params)
75
- alias rack_params params
76
-
77
- # Wrapping Request#params to support a one-level hash notation.
78
- # It doesn't support anything really fancy, so be conservative in its use.
79
- #
80
- # See if following provides something useful for us:
81
- # http://redhanded.hobix.com/2006/01/25.html
82
- #
83
- # Example Usage:
84
- #
85
- # # Template:
86
- #
87
- # <form action="/paste">
88
- # <input type="text" name="paste[name]" />
89
- # <input type="text" name="paste[syntax]" />
90
- # <input type="submit" />
91
- # </form>
92
- #
93
- # # In your Controller:
94
- #
95
- # def paste
96
- # name, syntax = request['paste'].values_at('name', 'syntax')
97
- # paste = Paste.create_with(:name => name, :syntax => syntax)
98
- # redirect '/'
99
- # end
100
- #
101
- # # Or, easier:
102
- #
103
- # def paste
104
- # paste = Paste.create_with(request['paste'])
105
- # redirect '/'
106
- # end
107
-
108
- def params
109
- return {} if put?
110
- return @ramaze_params if @ramaze_params
111
-
112
- begin
113
- @rack_params ||= rack_params
114
- rescue EOFError => ex
115
- @rack_params = {}
116
- Log.error(ex)
117
- end
86
+ # Wrapping Request#params to support a one-level hash notation.
87
+ # It doesn't support anything really fancy, so be conservative in its use.
88
+ #
89
+ # See if following provides something useful for us:
90
+ # http://redhanded.hobix.com/2006/01/25.html
91
+ #
92
+ # Example Usage:
93
+ #
94
+ # # Template:
95
+ #
96
+ # <form action="/paste">
97
+ # <input type="text" name="paste[name]" />
98
+ # <input type="text" name="paste[syntax]" />
99
+ # <input type="submit" />
100
+ # </form>
101
+ #
102
+ # # In your Controller:
103
+ #
104
+ # def paste
105
+ # name, syntax = request['paste'].values_at('name', 'syntax')
106
+ # paste = Paste.create_with(:name => name, :syntax => syntax)
107
+ # redirect '/'
108
+ # end
109
+ #
110
+ # # Or, easier:
111
+ #
112
+ # def paste
113
+ # paste = Paste.create_with(request['paste'])
114
+ # redirect '/'
115
+ # end
116
+
117
+ def params
118
+ return {} if put?
119
+ return @ramaze_params if @ramaze_params
120
+
121
+ begin
122
+ @rack_params ||= super
123
+ rescue EOFError => ex
124
+ @rack_params = {}
125
+ Log.error(ex)
126
+ end
118
127
 
119
- @ramaze_params = {}
128
+ @ramaze_params = {}
120
129
 
121
- @rack_params.each do |key, value|
122
- if key =~ /^(.*?)(\[.*\])/
123
- prim, nested = $~.captures
124
- ref = @ramaze_params
130
+ @rack_params.each do |key, value|
131
+ if key =~ /^(.*?)(\[.*\])/
132
+ prim, nested = $~.captures
133
+ ref = @ramaze_params
125
134
 
126
- keys = nested.scan(/\[([^\]]+)\]/).flatten
127
- keys.unshift prim
135
+ keys = nested.scan(/\[([^\]]+)\]/).flatten
136
+ keys.unshift prim
128
137
 
129
- keys.each_with_index do |k, i|
130
- if i + 1 >= keys.size
131
- ref[k] = value
138
+ keys.each_with_index do |k, i|
139
+ if i + 1 >= keys.size
140
+ ref[k] = value
141
+ else
142
+ # in case the value is a string we cannot let it be ref next
143
+ # time, so throw it away
144
+ if ref[k].is_a?(String)
145
+ ref = ref[k] = {}
132
146
  else
133
- # in case the value is a string we cannot let it be ref next
134
- # time, so throw it away
135
- if ref[k].is_a?(String)
136
- ref = ref[k] = {}
137
- else
138
- ref = ref[k] ||= {}
139
- end
147
+ ref = ref[k] ||= {}
140
148
  end
141
149
  end
142
- else
143
- @ramaze_params[key] = value
144
150
  end
151
+ else
152
+ @ramaze_params[key] = value
145
153
  end
146
-
147
- @ramaze_params
148
154
  end
155
+
156
+ @ramaze_params
149
157
  end
150
158
 
151
159
  # Interesting HTTP variables from env
@@ -156,12 +164,18 @@ module Ramaze
156
164
  }
157
165
  end
158
166
 
167
+ # Returns a string presentation of the request, useful for debugging
168
+ # parameters of the action.
169
+
159
170
  def to_s
160
171
  p, c, e = params.inspect, cookies.inspect, http_vars.inspect
161
172
  %{#<Ramaze::Request params=#{p} cookies=#{c} env=#{e}>}
162
173
  end
163
174
  alias inspect to_s
164
175
 
176
+ # Pretty prints current action with parameters, cookies and
177
+ # enviroment variables.
178
+
165
179
  def pretty_print pp
166
180
  p, c, e = params, cookies, http_vars
167
181
  pp.object_group(self){
@@ -182,9 +196,9 @@ module Ramaze
182
196
  # Example:
183
197
  # request.params
184
198
  # # => {'name' => 'jason', 'age' => '45', 'job' => 'lumberjack'}
185
- # request.sub('name')
199
+ # request.subset('name')
186
200
  # # => {'name' => 'jason'}
187
- # request.sub(:name, :job)
201
+ # request.subset(:name, :job)
188
202
  # # => {'name' => 'jason', 'job' => 'lumberjack'}
189
203
 
190
204
  def subset(*keys)
@@ -198,6 +212,9 @@ module Ramaze
198
212
  URI("#{scheme}://#{host}#{path}")
199
213
  end
200
214
 
215
+ # Returns and array of locales from env['HTTP_ACCEPT_LANGUAGE].
216
+ # e.g. ["fi", "en", "ja", "fr", "de", "es", "it", "nl", "sv"]
217
+
201
218
  def locales
202
219
  env['HTTP_ACCEPT_LANGUAGE'].to_s.split(/(?:,|;q=[\d.,]+)/)
203
220
  end