actionpack 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (101) hide show
  1. data/CHANGELOG +309 -16
  2. data/README +1 -1
  3. data/lib/action_controller.rb +5 -0
  4. data/lib/action_controller/assertions.rb +57 -12
  5. data/lib/action_controller/auto_complete.rb +47 -0
  6. data/lib/action_controller/base.rb +288 -258
  7. data/lib/action_controller/benchmarking.rb +8 -3
  8. data/lib/action_controller/caching.rb +88 -42
  9. data/lib/action_controller/cgi_ext/cgi_ext.rb +1 -1
  10. data/lib/action_controller/cgi_ext/cgi_methods.rb +41 -11
  11. data/lib/action_controller/cgi_ext/multipart_progress.rb +169 -0
  12. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +30 -12
  13. data/lib/action_controller/cgi_process.rb +39 -11
  14. data/lib/action_controller/code_generation.rb +235 -0
  15. data/lib/action_controller/cookies.rb +14 -8
  16. data/lib/action_controller/deprecated_renders_and_redirects.rb +76 -0
  17. data/lib/action_controller/filters.rb +8 -7
  18. data/lib/action_controller/helpers.rb +41 -6
  19. data/lib/action_controller/layout.rb +45 -16
  20. data/lib/action_controller/request.rb +86 -23
  21. data/lib/action_controller/rescue.rb +1 -0
  22. data/lib/action_controller/response.rb +1 -1
  23. data/lib/action_controller/routing.rb +536 -272
  24. data/lib/action_controller/scaffolding.rb +30 -25
  25. data/lib/action_controller/session/active_record_store.rb +251 -50
  26. data/lib/action_controller/streaming.rb +133 -0
  27. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +0 -7
  28. data/lib/action_controller/templates/scaffolds/edit.rhtml +2 -2
  29. data/lib/action_controller/templates/scaffolds/layout.rhtml +22 -18
  30. data/lib/action_controller/templates/scaffolds/list.rhtml +3 -3
  31. data/lib/action_controller/templates/scaffolds/new.rhtml +2 -2
  32. data/lib/action_controller/templates/scaffolds/show.rhtml +1 -1
  33. data/lib/action_controller/test_process.rb +68 -47
  34. data/lib/action_controller/upload_progress.rb +421 -0
  35. data/lib/action_controller/url_rewriter.rb +8 -11
  36. data/lib/action_controller/vendor/html-scanner/html/document.rb +6 -5
  37. data/lib/action_controller/vendor/html-scanner/html/node.rb +70 -14
  38. data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +17 -10
  39. data/lib/action_controller/vendor/html-scanner/html/version.rb +3 -3
  40. data/lib/action_controller/vendor/xml_simple.rb +1019 -0
  41. data/lib/action_controller/verification.rb +36 -30
  42. data/lib/action_view/base.rb +21 -14
  43. data/lib/action_view/helpers/active_record_helper.rb +15 -13
  44. data/lib/action_view/helpers/asset_tag_helper.rb +26 -9
  45. data/lib/action_view/helpers/benchmark_helper.rb +24 -0
  46. data/lib/action_view/helpers/capture_helper.rb +7 -5
  47. data/lib/action_view/helpers/date_helper.rb +63 -46
  48. data/lib/action_view/helpers/form_helper.rb +7 -1
  49. data/lib/action_view/helpers/form_options_helper.rb +19 -11
  50. data/lib/action_view/helpers/form_tag_helper.rb +5 -1
  51. data/lib/action_view/helpers/javascript_helper.rb +403 -35
  52. data/lib/action_view/helpers/javascripts/controls.js +261 -0
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +476 -0
  54. data/lib/action_view/helpers/javascripts/effects.js +570 -0
  55. data/lib/action_view/helpers/javascripts/prototype.js +633 -371
  56. data/lib/action_view/helpers/number_helper.rb +11 -13
  57. data/lib/action_view/helpers/tag_helper.rb +1 -2
  58. data/lib/action_view/helpers/text_helper.rb +69 -6
  59. data/lib/action_view/helpers/upload_progress_helper.rb +433 -0
  60. data/lib/action_view/helpers/url_helper.rb +98 -3
  61. data/lib/action_view/partials.rb +14 -8
  62. data/lib/action_view/vendor/builder/xmlmarkup.rb +11 -0
  63. data/rakefile +13 -5
  64. data/test/abstract_unit.rb +1 -1
  65. data/test/controller/action_pack_assertions_test.rb +52 -9
  66. data/test/controller/active_record_assertions_test.rb +119 -120
  67. data/test/controller/active_record_store_test.rb +111 -0
  68. data/test/controller/addresses_render_test.rb +45 -0
  69. data/test/controller/caching_filestore.rb +92 -0
  70. data/test/controller/capture_test.rb +39 -0
  71. data/test/controller/cgi_test.rb +40 -3
  72. data/test/controller/helper_test.rb +65 -13
  73. data/test/controller/multipart_progress_testx.rb +365 -0
  74. data/test/controller/new_render_test.rb +263 -0
  75. data/test/controller/redirect_test.rb +64 -0
  76. data/test/controller/render_test.rb +20 -21
  77. data/test/controller/request_test.rb +83 -3
  78. data/test/controller/routing_test.rb +702 -0
  79. data/test/controller/send_file_test.rb +2 -0
  80. data/test/controller/test_test.rb +44 -8
  81. data/test/controller/upload_progress_testx.rb +89 -0
  82. data/test/controller/verification_test.rb +94 -29
  83. data/test/fixtures/addresses/list.rhtml +1 -0
  84. data/test/fixtures/test/capturing.rhtml +4 -0
  85. data/test/fixtures/test/list.rhtml +1 -1
  86. data/test/fixtures/test/update_element_with_capture.rhtml +9 -0
  87. data/test/template/active_record_helper_test.rb +30 -15
  88. data/test/template/asset_tag_helper_test.rb +12 -5
  89. data/test/template/benchmark_helper_test.rb +72 -0
  90. data/test/template/date_helper_test.rb +69 -0
  91. data/test/template/form_helper_test.rb +18 -10
  92. data/test/template/form_options_helper_test.rb +40 -5
  93. data/test/template/javascript_helper.rb +149 -2
  94. data/test/template/number_helper_test.rb +2 -0
  95. data/test/template/tag_helper_test.rb +4 -0
  96. data/test/template/text_helper_test.rb +36 -0
  97. data/test/template/upload_progress_helper_testx.rb +272 -0
  98. data/test/template/url_helper_test.rb +30 -0
  99. metadata +30 -6
  100. data/test/controller/layout_test.rb +0 -49
  101. data/test/controller/routing_tests.rb +0 -543
@@ -6,6 +6,8 @@ class CGI #:nodoc:
6
6
  # Handles multipart forms (in particular, forms that involve file uploads).
7
7
  # Reads query parameters in the @params field, and cookies into @cookies.
8
8
  def initialize_query()
9
+ @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] || env_table['COOKIE']))
10
+
9
11
  if boundary = multipart_form_boundary
10
12
  @multipart = true
11
13
  @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
@@ -13,12 +15,12 @@ class CGI #:nodoc:
13
15
  @multipart = false
14
16
  @params = CGI::parse(read_query_params || "")
15
17
  end
16
-
17
- @cookies = CGI::Cookie::parse((env_table['HTTP_COOKIE'] || env_table['COOKIE']))
18
18
  end
19
19
 
20
20
  private
21
- MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #"
21
+ unless defined?(MULTIPART_FORM_BOUNDARY_RE)
22
+ MULTIPART_FORM_BOUNDARY_RE = %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?|n #"
23
+ end
22
24
 
23
25
  def multipart_form_boundary
24
26
  if env_table['REQUEST_METHOD'] == 'POST'
@@ -26,17 +28,33 @@ class CGI #:nodoc:
26
28
  end
27
29
  end
28
30
 
31
+ def read_params_from_query
32
+ if defined? MOD_RUBY
33
+ Apache::request.args || ''
34
+ else
35
+ # fixes CGI querystring parsing for POSTs
36
+ if env_table['QUERY_STRING'].blank? && !env_table['REQUEST_URI'].blank?
37
+ env_table['QUERY_STRING'] = env_table['REQUEST_URI'].split('?', 2)[1] || ''
38
+ end
39
+ env_table['QUERY_STRING']
40
+ end
41
+ end
42
+
43
+ def read_params_from_post
44
+ stdinput.binmode if stdinput.respond_to?(:binmode)
45
+ content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || ''
46
+ env_table['RAW_POST_DATA'] = content.split("&_").first.to_s.freeze # &_ is a fix for Safari Ajax postings that always append \000
47
+ end
48
+
29
49
  def read_query_params
30
- case env_table['REQUEST_METHOD']
31
- when 'GET', 'HEAD', 'DELETE', 'OPTIONS'
32
- (defined?(MOD_RUBY) ? Apache::request.args : env_table['QUERY_STRING']) || ''
33
- when 'POST', 'PUT'
34
- stdinput.binmode if stdinput.respond_to?(:binmode)
35
- content = stdinput.read(Integer(env_table['CONTENT_LENGTH'])) || ''
36
- env_table['RAW_POST_DATA'] = content.split("&_").first.to_s.freeze # &_ is a fix for Safari Ajax postings that always append \000
37
- else
50
+ case env_table['REQUEST_METHOD'].to_s.upcase
51
+ when 'CMD'
38
52
  read_from_cmdline
39
- end
53
+ when 'POST', 'PUT'
54
+ read_params_from_post
55
+ else # when 'GET', 'HEAD', 'DELETE', 'OPTIONS'
56
+ read_params_from_query
57
+ end
40
58
  end
41
59
  end # module QueryExtension
42
60
  end
@@ -2,8 +2,10 @@ require 'action_controller/cgi_ext/cgi_ext'
2
2
  require 'action_controller/cgi_ext/cookie_performance_fix'
3
3
  require 'action_controller/cgi_ext/raw_post_data_fix'
4
4
  require 'action_controller/session/drb_store'
5
- require 'action_controller/session/active_record_store'
6
5
  require 'action_controller/session/mem_cache_store'
6
+ if Object.const_defined?(:ActiveRecord)
7
+ require 'action_controller/session/active_record_store'
8
+ end
7
9
 
8
10
  module ActionController #:nodoc:
9
11
  class Base
@@ -37,8 +39,11 @@ module ActionController #:nodoc:
37
39
  class CgiRequest < AbstractRequest #:nodoc:
38
40
  attr_accessor :cgi
39
41
 
40
- DEFAULT_SESSION_OPTIONS =
41
- { :database_manager => CGI::Session::PStore, :prefix => "ruby_sess.", :session_path => "/" }
42
+ DEFAULT_SESSION_OPTIONS = {
43
+ :database_manager => CGI::Session::PStore,
44
+ :prefix => "ruby_sess.",
45
+ :session_path => "/"
46
+ } unless const_defined?(:DEFAULT_SESSION_OPTIONS)
42
47
 
43
48
  def initialize(cgi, session_options = {})
44
49
  @cgi = cgi
@@ -63,7 +68,11 @@ module ActionController #:nodoc:
63
68
  end
64
69
 
65
70
  def request_parameters
66
- CGIMethods.parse_request_parameters(@cgi.params)
71
+ if formatted_post?
72
+ CGIMethods.parse_formatted_request_parameters(post_format, env['RAW_POST_DATA'])
73
+ else
74
+ CGIMethods.parse_request_parameters(@cgi.params)
75
+ end
67
76
  end
68
77
 
69
78
  def env
@@ -80,17 +89,34 @@ module ActionController #:nodoc:
80
89
 
81
90
  def session
82
91
  return @session unless @session.nil?
92
+
83
93
  begin
84
94
  @session = (@session_options == false ? {} : CGI::Session.new(@cgi, session_options_with_string_keys))
85
95
  @session["__valid_session"]
86
96
  return @session
87
97
  rescue ArgumentError => e
88
- @session.delete if @session
98
+ # TODO: Uncomment this on 0.13.1
99
+ # if e.message =~ %r{undefined class/module (\w+)}
100
+ # begin
101
+ # Module.const_missing($1)
102
+ # rescue LoadError, NameError => e
103
+ # raise(
104
+ # ActionController::SessionRestoreError,
105
+ # "Session contained objects where the class definition wasn't available. " +
106
+ # "Remember to require classes for all objects kept in the session. " +
107
+ # "(Original exception: #{e.message} [#{e.class}])"
108
+ # )
109
+ # end
110
+ #
111
+ # retry
112
+ # else
113
+ # raise
114
+ # end
89
115
  raise(
90
116
  ActionController::SessionRestoreError,
91
117
  "Session contained objects where the class definition wasn't available. " +
92
118
  "Remember to require classes for all objects kept in the session. " +
93
- "The session has been deleted. (Original exception: #{e.message} [#{e.class}])"
119
+ "(Original exception: #{e.message} [#{e.class}])"
94
120
  )
95
121
  end
96
122
  end
@@ -120,21 +146,23 @@ module ActionController #:nodoc:
120
146
  super()
121
147
  end
122
148
 
123
- def out
149
+ def out(output = $stdout)
124
150
  convert_content_type!(@headers)
125
- $stdout.binmode if $stdout.respond_to?(:binmode)
126
- $stdout.sync = false
151
+ output.binmode if output.respond_to?(:binmode)
152
+ output.sync = false if output.respond_to?(:sync=)
127
153
 
128
154
  begin
129
- print @cgi.header(@headers)
155
+ output.write(@cgi.header(@headers))
130
156
 
131
157
  if @cgi.send(:env_table)['REQUEST_METHOD'] == 'HEAD'
132
158
  return
133
159
  elsif @body.respond_to?(:call)
134
160
  @body.call(self)
135
161
  else
136
- print @body
162
+ output.write(@body)
137
163
  end
164
+
165
+ output.flush if output.respond_to?(:flush)
138
166
  rescue Errno::EPIPE => e
139
167
  # lost connection to the FCGI process -- ignore the output, then
140
168
  end
@@ -0,0 +1,235 @@
1
+ module ActionController
2
+ module CodeGeneration #:nodoc:
3
+ class GenerationError < StandardError #:nodoc:
4
+ end
5
+
6
+ class Source #:nodoc:
7
+ attr_reader :lines, :indentation_level
8
+ IndentationString = ' '
9
+ def initialize
10
+ @lines, @indentation_level = [], 0
11
+ end
12
+ def line(line)
13
+ @lines << (IndentationString * @indentation_level + line)
14
+ end
15
+ alias :<< :line
16
+
17
+ def indent
18
+ @indentation_level += 1
19
+ yield
20
+ ensure
21
+ @indentation_level -= 1
22
+ end
23
+
24
+ def to_s() lines.join("\n") end
25
+ end
26
+
27
+ class CodeGenerator #:nodoc:
28
+ attr_accessor :source, :locals
29
+ def initialize(source = nil)
30
+ @locals = []
31
+ @source = source || Source.new
32
+ end
33
+
34
+ BeginKeywords = %w(if unless begin until while def).collect {|kw| kw.to_sym}
35
+ ResumeKeywords = %w(elsif else rescue).collect {|kw| kw.to_sym}
36
+ Keywords = BeginKeywords + ResumeKeywords
37
+
38
+ def method_missing(keyword, *text)
39
+ if Keywords.include? keyword
40
+ if ResumeKeywords.include? keyword
41
+ raise GenerationError, "Can only resume with #{keyword} immediately after an end" unless source.lines.last =~ /^\s*end\s*$/
42
+ source.lines.pop # Remove the 'end'
43
+ end
44
+
45
+ line "#{keyword} #{text.join ' '}"
46
+ begin source.indent { yield(self.dup) }
47
+ ensure line 'end'
48
+ end
49
+ else
50
+ super(keyword, *text)
51
+ end
52
+ end
53
+
54
+ def line(*args) self.source.line(*args) end
55
+ alias :<< :line
56
+ def indent(*args, &block) source(*args, &block) end
57
+ def to_s() source.to_s end
58
+
59
+ def share_locals_with(other)
60
+ other.locals = self.locals = (other.locals | locals)
61
+ end
62
+
63
+ FieldsToDuplicate = [:locals]
64
+ def dup
65
+ copy = self.class.new(source)
66
+ self.class::FieldsToDuplicate.each do |sym|
67
+ value = self.send(sym)
68
+ value = value.dup unless value.nil? || value.is_a?(Numeric)
69
+ copy.send("#{sym}=", value)
70
+ end
71
+ return copy
72
+ end
73
+ end
74
+
75
+ class RecognitionGenerator < CodeGenerator #:nodoc:
76
+ Attributes = [:after, :before, :current, :results, :constants, :depth, :move_ahead, :finish_statement]
77
+ attr_accessor(*Attributes)
78
+ FieldsToDuplicate = CodeGenerator::FieldsToDuplicate + Attributes
79
+
80
+ def initialize(*args)
81
+ super(*args)
82
+ @after, @before = [], []
83
+ @current = nil
84
+ @results, @constants = {}, {}
85
+ @depth = 0
86
+ @move_ahead = nil
87
+ @finish_statement = Proc.new {|hash_expr| hash_expr}
88
+ end
89
+
90
+ def if_next_matches(string, &block)
91
+ test = Routing.test_condition(next_segment(true), string)
92
+ self.if(test, &block)
93
+ end
94
+
95
+ def move_forward(places = 1)
96
+ dup = self.dup
97
+ dup.depth += 1
98
+ dup.move_ahead = places
99
+ yield dup
100
+ end
101
+
102
+ def next_segment(assign_inline = false, default = nil)
103
+ if locals.include?(segment_name)
104
+ code = segment_name
105
+ else
106
+ code = "#{segment_name} = #{path_name}[#{index_name}]"
107
+ if assign_inline
108
+ code = "(#{code})"
109
+ else
110
+ line(code)
111
+ code = segment_name
112
+ end
113
+
114
+ locals << segment_name
115
+ end
116
+ code = "(#{code} || #{default.inspect})" if default
117
+
118
+ return code.to_s
119
+ end
120
+
121
+ def segment_name() "segment#{depth}".to_sym end
122
+ def path_name() :path end
123
+ def index_name
124
+ move_ahead, @move_ahead = @move_ahead, nil
125
+ move_ahead ? "index += #{move_ahead}" : 'index'
126
+ end
127
+
128
+ def continue
129
+ dup = self.dup
130
+ dup.before << dup.current
131
+ dup.current = dup.after.shift
132
+ dup.go
133
+ end
134
+
135
+ def go
136
+ if current then current.write_recognition(self)
137
+ else self.finish
138
+ end
139
+ end
140
+
141
+ def result(key, expression, delay = false)
142
+ unless delay
143
+ line "#{key}_value = #{expression}"
144
+ expression = "#{key}_value"
145
+ end
146
+ results[key] = expression
147
+ end
148
+ def constant_result(key, object)
149
+ constants[key] = object
150
+ end
151
+
152
+ def finish(ensure_traversal_finished = true)
153
+ pairs = []
154
+ (results.keys + constants.keys).uniq.each do |key|
155
+ pairs << "#{key.to_s.inspect} => #{results[key] ? results[key] : constants[key].inspect}"
156
+ end
157
+ hash_expr = "{#{pairs.join(', ')}}"
158
+
159
+ statement = finish_statement.call(hash_expr)
160
+ if ensure_traversal_finished then self.if("! #{next_segment(true)}") {|gp| gp << statement}
161
+ else self << statement
162
+ end
163
+ end
164
+ end
165
+
166
+ class GenerationGenerator < CodeGenerator #:nodoc:
167
+ Attributes = [:after, :before, :current, :segments]
168
+ attr_accessor(*Attributes)
169
+ FieldsToDuplicate = CodeGenerator::FieldsToDuplicate + Attributes
170
+
171
+ def initialize(*args)
172
+ super(*args)
173
+ @after, @before = [], []
174
+ @current = nil
175
+ @segments = []
176
+ end
177
+
178
+ def hash_name() 'hash' end
179
+ def local_name(key) "#{key}_value" end
180
+
181
+ def hash_value(key, assign = true, default = nil)
182
+ if locals.include?(local_name(key)) then code = local_name(key)
183
+ else
184
+ code = "hash[#{key.to_sym.inspect}]"
185
+ if assign
186
+ code = "(#{local_name(key)} = #{code})"
187
+ locals << local_name(key)
188
+ end
189
+ end
190
+ code = "(#{code} || (#{default.inspect}))" if default
191
+ return code
192
+ end
193
+
194
+ def expire_for_keys(*keys)
195
+ return if keys.empty?
196
+ conds = keys.collect {|key| "expire_on[#{key.to_sym.inspect}]"}
197
+ line "not_expired, #{hash_name} = false, options if not_expired && #{conds.join(' && ')}"
198
+ end
199
+
200
+ def add_segment(*segments)
201
+ d = dup
202
+ d.segments.concat segments
203
+ yield d
204
+ end
205
+
206
+ def go
207
+ if current then current.write_generation(self)
208
+ else self.finish
209
+ end
210
+ end
211
+
212
+ def continue
213
+ d = dup
214
+ d.before << d.current
215
+ d.current = d.after.shift
216
+ d.go
217
+ end
218
+
219
+ def finish
220
+ line %("/#{segments.join('/')}")
221
+ end
222
+
223
+ def check_conditions(conditions)
224
+ tests = []
225
+ generator = nil
226
+ conditions.each do |key, condition|
227
+ tests << (generator || self).hash_value(key, true) if condition.is_a? Regexp
228
+ tests << Routing.test_condition((generator || self).hash_value(key, false), condition)
229
+ generator = self.dup unless generator
230
+ end
231
+ return tests.join(' && ')
232
+ end
233
+ end
234
+ end
235
+ end
@@ -3,17 +3,17 @@ module ActionController #:nodoc:
3
3
  # the cookies being written is what will be sent out will the response. Cookies are read by value (so you won't get the cookie object
4
4
  # itself back -- just the value it holds). Examples for writing:
5
5
  #
6
- # cookies["user_name"] = "david" # => Will set a simple session cookie
7
- # cookies["login"] = { :value => "XJ-122", :expires => Time.now + 360} # => Will set a cookie that expires in 1 hour
6
+ # cookies[:user_name] = "david" # => Will set a simple session cookie
7
+ # cookies[:login] = { :value => "XJ-122", :expires => Time.now + 360} # => Will set a cookie that expires in 1 hour
8
8
  #
9
9
  # Examples for reading:
10
10
  #
11
- # cookies["user_name"] # => "david"
11
+ # cookies[:user_name] # => "david"
12
12
  # cookies.size # => 2
13
13
  #
14
14
  # Example for deleting:
15
15
  #
16
- # cookies.delete "user_name"
16
+ # cookies.delete :user_name
17
17
  #
18
18
  # All the option symbols for setting cookies are:
19
19
  #
@@ -24,10 +24,16 @@ module ActionController #:nodoc:
24
24
  # * <tt>secure</tt> - whether this cookie is a secure cookie or not (default to false).
25
25
  # Secure cookies are only transmitted to HTTPS servers.
26
26
  module Cookies
27
- # Returns the cookie container, which operates as described above.
28
- def cookies
29
- CookieJar.new(self)
30
- end
27
+ protected
28
+ # Returns the cookie container, which operates as described above.
29
+ def cookies
30
+ CookieJar.new(self)
31
+ end
32
+
33
+ # Deprecated cookie writer method
34
+ def cookie(*options)
35
+ @response.headers["cookie"] << CGI::Cookie.new(*options)
36
+ end
31
37
  end
32
38
 
33
39
  class CookieJar < Hash #:nodoc:
@@ -0,0 +1,76 @@
1
+ module ActionController
2
+ class Base
3
+ protected
4
+ # Works like render, but instead of requiring a full template name, you can get by with specifying the action name. So calling
5
+ # <tt>render_action "show_many"</tt> in WeblogController#display will render "#{template_root}/weblog/show_many.rhtml" or
6
+ # "#{template_root}/weblog/show_many.rxml".
7
+ def render_action(action_name, status = nil)
8
+ render :action => action_name, :status => status
9
+ end
10
+
11
+ # Works like render, but disregards the template_root and requires a full path to the template that needs to be rendered. Can be
12
+ # used like <tt>render_file "/Users/david/Code/Ruby/template"</tt> to render "/Users/david/Code/Ruby/template.rhtml" or
13
+ # "/Users/david/Code/Ruby/template.rxml".
14
+ def render_file(template_path, status = nil, use_full_path = false)
15
+ render :file => template_path, :status => status, :use_full_path => use_full_path
16
+ end
17
+
18
+ # Renders the +template+ string, which is useful for rendering short templates you don't want to bother having a file for. So
19
+ # you'd call <tt>render_template "Hello, <%= @user.name %>"</tt> to greet the current user. Or if you want to render as Builder
20
+ # template, you could do <tt>render_template "xml.h1 @user.name", nil, "rxml"</tt>.
21
+ def render_template(template, status = nil, type = "rhtml")
22
+ render :inline => template, :status => status, :type => type
23
+ end
24
+
25
+ # Renders the +text+ string without parsing it through any template engine. Useful for rendering static information as it's
26
+ # considerably faster than rendering through the template engine.
27
+ # Use block for response body if provided (useful for deferred rendering or streaming output).
28
+ def render_text(text = nil, status = nil)
29
+ render :text => text, :status => status
30
+ end
31
+
32
+ # Renders an empty response that can be used when the request is only interested in triggering an effect. Do note that good
33
+ # HTTP manners mandate that you don't use GET requests to trigger data changes.
34
+ def render_nothing(status = nil)
35
+ render :nothing => true, :status => status
36
+ end
37
+
38
+ # Renders the partial specified by <tt>partial_path</tt>, which by default is the name of the action itself. Example:
39
+ #
40
+ # class WeblogController < ActionController::Base
41
+ # def show
42
+ # render_partial # renders "weblog/_show.r(xml|html)"
43
+ # end
44
+ # end
45
+ def render_partial(partial_path = default_template_name, object = nil, local_assigns = {})
46
+ render :partial => partial_path, :object => object, :locals => local_assigns
47
+ end
48
+
49
+ # Renders a collection of partials using <tt>partial_name</tt> to iterate over the +collection+.
50
+ def render_partial_collection(partial_name, collection, partial_spacer_template = nil, local_assigns = {})
51
+ render :partial => partial_name, :collection => collection, :spacer_template => partial_spacer_template, :locals => local_assigns
52
+ end
53
+
54
+ def render_with_layout(template_name = default_template_name, status = nil, layout = nil)
55
+ render :template => template_name, :status => status, :layout => layout
56
+ end
57
+
58
+ def render_without_layout(template_name = default_template_name, status = nil)
59
+ render :template => template_name, :status => status, :layout => false
60
+ end
61
+
62
+
63
+ # Deprecated in favor of calling redirect_to directly with the path.
64
+ def redirect_to_path(path)
65
+ redirect_to(path)
66
+ end
67
+
68
+ # Deprecated in favor of calling redirect_to directly with the url. If the resource has moved permanently, it's possible to pass
69
+ # true as the second parameter and the browser will get "301 Moved Permanently" instead of "302 Found". This can also be done through
70
+ # just setting the headers["Status"] to "301 Moved Permanently" before using the redirect_to.
71
+ def redirect_to_url(url, permanently = false)
72
+ headers["Status"] = "301 Moved Permanently" if permanently
73
+ redirect_to(url)
74
+ end
75
+ end
76
+ end