actionpack 1.12.3 → 1.12.4

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.

@@ -27,7 +27,7 @@ module ActionController #:nodoc:
27
27
  # that the header and footer are only mentioned in one place, like this:
28
28
  #
29
29
  # <!-- The header part of this layout -->
30
- # <%= @content_for_layout %>
30
+ # <%= yield %>
31
31
  # <!-- The footer part of this layout -->
32
32
  #
33
33
  # And then you have content pages that look like this:
@@ -47,7 +47,7 @@ module ActionController #:nodoc:
47
47
  # references that won't materialize before rendering time:
48
48
  #
49
49
  # <h1><%= @page_title %></h1>
50
- # <%= @content_for_layout %>
50
+ # <%= yield %>
51
51
  #
52
52
  # ...and content pages that fulfill these references _at_ rendering time:
53
53
  #
@@ -159,10 +159,12 @@ module ActionController #:nodoc:
159
159
  #
160
160
  # As you can see, you pass the template as the first parameter, the status code as the second ("200" is OK), and the layout
161
161
  # as the third.
162
+ #
163
+ # NOTE: The old notation for rendering the view from a layout was to expose the magic <tt>@content_for_layout</tt> instance
164
+ # variable. The preferred notation now is to use <tt>yield</tt>, as documented above.
162
165
  module ClassMethods
163
- # If a layout is specified, all actions rendered through render and render_action will have their result assigned
164
- # to <tt>@content_for_layout</tt>, which can then be used by the layout to insert their contents with
165
- # <tt><%= @content_for_layout %></tt>. This layout can itself depend on instance variables assigned during action
166
+ # If a layout is specified, all rendered actions will have their result rendered
167
+ # when the layout<tt>yield</tt>'s. This layout can itself depend on instance variables assigned during action
166
168
  # performance and have access to them as any normal template would.
167
169
  def layout(template_name, conditions = {})
168
170
  add_layout_conditions(conditions)
@@ -92,6 +92,12 @@ module ActionController #:nodoc:
92
92
  # Note that you can define your own XML parameter parser which would allow you to describe multiple entities
93
93
  # in a single request (i.e., by wrapping them all in a single root note), but if you just go with the flow
94
94
  # and accept Rails' defaults, life will be much easier.
95
+ #
96
+ # If you need to use a MIME type which isn't supported by default, you can register your own handlers in
97
+ # environment.rb as follows.
98
+ #
99
+ # Mime::Type.register "image/jpg", :jpg
100
+ #
95
101
  def respond_to(*types, &block)
96
102
  raise ArgumentError, "respond_to takes either types or a block, never bot" unless types.any? ^ block
97
103
  block ||= lambda { |responder| types.each { |type| responder.send(type) } }
@@ -160,4 +166,4 @@ module ActionController #:nodoc:
160
166
  end
161
167
  end
162
168
  end
163
- end
169
+ end
@@ -31,7 +31,7 @@ module ActionController
31
31
  # instance variable, which is an ordered collection of model objects for the
32
32
  # current page (at most 20, sorted by last name and first name), and a
33
33
  # <tt>@person_pages</tt> Paginator instance. The current page is determined
34
- # by the <tt>@params['page']</tt> variable.
34
+ # by the <tt>params[:page]</tt> variable.
35
35
  #
36
36
  # ==== Pagination for a single action
37
37
  #
@@ -47,7 +47,7 @@ module ActionController
47
47
  # ==== Custom/"classic" pagination
48
48
  #
49
49
  # def list
50
- # @person_pages = Paginator.new self, Person.count, 10, @params['page']
50
+ # @person_pages = Paginator.new self, Person.count, 10, params[:page]
51
51
  # @people = Person.find :all, :order => 'last_name, first_name',
52
52
  # :limit => @person_pages.items_per_page,
53
53
  # :offset => @person_pages.current.offset
@@ -1,5 +1,6 @@
1
1
  module ActionController
2
- # These methods are available in both the production and test Request objects.
2
+ # Subclassing AbstractRequest makes these methods available to the request objects used in production and testing,
3
+ # CgiRequest and TestRequest
3
4
  class AbstractRequest
4
5
  cattr_accessor :relative_url_root
5
6
 
@@ -65,6 +66,7 @@ module ActionController
65
66
  end
66
67
  end
67
68
 
69
+ # Returns the accepted MIME type for the request
68
70
  def accepts
69
71
  @accepts ||=
70
72
  if @env['HTTP_ACCEPT'].to_s.strip.empty?
@@ -202,15 +204,21 @@ module ActionController
202
204
  host + port_string
203
205
  end
204
206
 
205
- def path_parameters=(parameters)
207
+ def path_parameters=(parameters) #:nodoc:
206
208
  @path_parameters = parameters
207
209
  @symbolized_path_parameters = @parameters = nil
208
210
  end
209
211
 
210
- def symbolized_path_parameters
212
+ # The same as <tt>path_parameters</tt> with explicitly symbolized keys
213
+ def symbolized_path_parameters
211
214
  @symbolized_path_parameters ||= path_parameters.symbolize_keys
212
215
  end
213
216
 
217
+ # Returns a hash with the parameters used to form the path of the request
218
+ #
219
+ # Example:
220
+ #
221
+ # {:action => 'my_action', :controller => 'my_controller'}
214
222
  def path_parameters
215
223
  @path_parameters ||= {}
216
224
  end
@@ -218,7 +218,11 @@ module ActionController
218
218
  expr = "::#{controller.split('/').collect {|c| c.camelize}.join('::')}Controller"
219
219
  g.result :controller, expr, true
220
220
  end
221
-
221
+
222
+ def file_kinds(kind)
223
+ ((@file_kinds ||= []) << kind).uniq! || @file_kinds
224
+ end
225
+
222
226
  def traverse_to_controller(segments, start_at = 0)
223
227
  mod = ::Object
224
228
  length = segments.length
@@ -228,6 +232,7 @@ module ActionController
228
232
  return nil unless /\A[A-Za-z][A-Za-z\d_]*\Z/ =~ (segment = segments[index])
229
233
  index += 1
230
234
 
235
+ file_kinds :app
231
236
  mod_name = segment.camelize
232
237
  controller_name = "#{mod_name}Controller"
233
238
  path_suffix = File.join(segments[start_at..(index - 1)])
@@ -268,7 +273,7 @@ module ActionController
268
273
  $LOAD_PATH.select do |base|
269
274
  base = File.expand_path(base)
270
275
  extended_root = File.expand_path(RAILS_ROOT)
271
- base[0, extended_root.length] == extended_root || base =~ %r{rails-[\d.]+/builtin}
276
+ base.match(/\A#{Regexp.escape(extended_root)}\/*#{file_kinds(:lib) * '|'}/) || base =~ %r{rails-[\d.]+/builtin}
272
277
  end
273
278
  else
274
279
  $LOAD_PATH
@@ -14,7 +14,7 @@ module ActionController #:nodoc:
14
14
  # it feasible to send even large files.
15
15
  #
16
16
  # Be careful to sanitize the path parameter if it coming from a web
17
- # page. send_file(@params['path']) allows a malicious user to
17
+ # page. send_file(params[:path]) allows a malicious user to
18
18
  # download any file on your server.
19
19
  #
20
20
  # Options:
@@ -28,6 +28,7 @@ module ActionController #:nodoc:
28
28
  # or to read the entire file before sending (false). Defaults to true.
29
29
  # * <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream the file.
30
30
  # Defaults to 4096.
31
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
31
32
  #
32
33
  # The default Content-Type and Content-Disposition headers are
33
34
  # set to download arbitrary binary files in as many browsers as
@@ -37,9 +38,12 @@ module ActionController #:nodoc:
37
38
  # Simple download:
38
39
  # send_file '/path/to.zip'
39
40
  #
40
- # Show a JPEG in browser:
41
+ # Show a JPEG in the browser:
41
42
  # send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
42
43
  #
44
+ # Show a 404 page in the browser:
45
+ # send_file '/path/to/404.html, :type => 'text/html; charset=utf-8', :status => 404
46
+ #
43
47
  # Read about the other Content-* HTTP headers if you'd like to
44
48
  # provide the user with more information (such as Content-Description).
45
49
  # http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
@@ -61,7 +65,7 @@ module ActionController #:nodoc:
61
65
  @performed_render = false
62
66
 
63
67
  if options[:stream]
64
- render :text => Proc.new { |response, output|
68
+ render :status => options[:status], :text => Proc.new { |response, output|
65
69
  logger.info "Streaming file #{path}" unless logger.nil?
66
70
  len = options[:buffer_size] || 4096
67
71
  File.open(path, 'rb') do |file|
@@ -81,7 +85,7 @@ module ActionController #:nodoc:
81
85
  }
82
86
  else
83
87
  logger.info "Sending file #{path}" unless logger.nil?
84
- File.open(path, 'rb') { |file| render :text => file.read }
88
+ File.open(path, 'rb') { |file| render :status => options[:status], :text => file.read }
85
89
  end
86
90
  end
87
91
 
@@ -93,6 +97,7 @@ module ActionController #:nodoc:
93
97
  # * <tt>:type</tt> - specifies an HTTP content type.
94
98
  # Defaults to 'application/octet-stream'.
95
99
  # * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
100
+ # * <tt>:status</tt> - specifies the status code to send with the response. Defaults to '200 OK'.
96
101
  # Valid values are 'inline' and 'attachment' (default).
97
102
  #
98
103
  # Generic data download:
@@ -109,7 +114,7 @@ module ActionController #:nodoc:
109
114
  logger.info "Sending data #{options[:filename]}" unless logger.nil?
110
115
  send_file_headers! options.merge(:length => data.size)
111
116
  @performed_render = false
112
- render :text => data
117
+ render :status => options[:status], :text => data
113
118
  end
114
119
 
115
120
  private
@@ -139,4 +144,4 @@ module ActionController #:nodoc:
139
144
  @headers['Cache-Control'] = 'private' if @headers['Cache-Control'] == 'no-cache'
140
145
  end
141
146
  end
142
- end
147
+ end
@@ -63,7 +63,7 @@
63
63
 
64
64
  <p style="color: green"><%= flash[:notice] %></p>
65
65
 
66
- <%= @content_for_layout %>
66
+ <%= yield %>
67
67
 
68
68
  </body>
69
69
  </html>
@@ -37,7 +37,7 @@ module ActionController #:nodoc:
37
37
  # is a hash consisting of the following key/value pairs:
38
38
  #
39
39
  # * <tt>:params</tt>: a single key or an array of keys that must
40
- # be in the @params hash in order for the action(s) to be safely
40
+ # be in the <tt>params</tt> hash in order for the action(s) to be safely
41
41
  # called.
42
42
  # * <tt>:session</tt>: a single key or an array of keys that must
43
43
  # be in the @session in order for the action(s) to be safely called.
@@ -2,7 +2,7 @@ module ActionPack #:nodoc:
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 12
5
- TINY = 3
5
+ TINY = 4
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -11,7 +11,7 @@ module ActionView #:nodoc:
11
11
  #
12
12
  # = ERb
13
13
  #
14
- # You trigger ERb by using embeddings such as <% %> and <%= %>. The difference is whether you want output or not. Consider the
14
+ # You trigger ERb by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the
15
15
  # following loop for names:
16
16
  #
17
17
  # <b>Names of all the people</b>
@@ -19,12 +19,14 @@ module ActionView #:nodoc:
19
19
  # Name: <%= person.name %><br/>
20
20
  # <% end %>
21
21
  #
22
- # The loop is setup in regular embedding tags (<% %>) and the name is written using the output embedding tag (<%= %>). Note that this
22
+ # The loop is setup in regular embedding tags <% %> and the name is written using the output embedding tag <%= %>. Note that this
23
23
  # is not just a usage suggestion. Regular output functions like print or puts won't work with ERb templates. So this would be wrong:
24
24
  #
25
25
  # Hi, Mr. <% puts "Frodo" %>
26
26
  #
27
- # (If you absolutely must write from within a function, you can use the TextHelper#concat)
27
+ # If you absolutely must write from within a function, you can use the TextHelper#concat
28
+ #
29
+ # <%- and -%> suppress leading and trailing whitespace, including the trailing newline, and can be used interchangeably with <% and %>.
28
30
  #
29
31
  # == Using sub templates
30
32
  #
@@ -425,7 +427,8 @@ module ActionView #:nodoc:
425
427
 
426
428
  if @@compile_time[render_symbol] && supports_local_assigns?(render_symbol, local_assigns)
427
429
  if file_name && !@@cache_template_loading
428
- @@compile_time[render_symbol] < File.mtime(file_name)
430
+ @@compile_time[render_symbol] < File.mtime(file_name) || (File.symlink?(file_name) ?
431
+ @@compile_time[render_symbol] < File.lstat(file_name).mtime : false)
429
432
  end
430
433
  else
431
434
  true
@@ -1,6 +1,6 @@
1
1
  module ActionView
2
2
  module Helpers
3
- # Capture lets you extract parts of code into instance variables which
3
+ # Capture lets you extract parts of code which
4
4
  # can be used in other points of the template or even layout file.
5
5
  #
6
6
  # == Capturing a block into an instance variable
@@ -8,12 +8,11 @@ module ActionView
8
8
  # <% @script = capture do %>
9
9
  # [some html...]
10
10
  # <% end %>
11
- #
12
11
  #
13
12
  # == Add javascript to header using content_for
14
13
  #
15
- # content_for("name") is a wrapper for capture which will store the
16
- # fragment in a instance variable similar to @content_for_layout.
14
+ # content_for("name") is a wrapper for capture which will
15
+ # make the fragment available by name to a yielding layout or template.
17
16
  #
18
17
  # layout.rhtml:
19
18
  #
@@ -21,11 +20,11 @@ module ActionView
21
20
  # <head>
22
21
  # <title>layout with js</title>
23
22
  # <script type="text/javascript">
24
- # <%= @content_for_script %>
25
- # </script>
23
+ # <%= yield :script %>
24
+ # </script>
26
25
  # </head>
27
26
  # <body>
28
- # <%= @content_for_layout %>
27
+ # <%= yield %>
29
28
  # </body>
30
29
  # </html>
31
30
  #
@@ -69,13 +68,9 @@ module ActionView
69
68
  end
70
69
  end
71
70
 
72
- # Content_for will store the given block
73
- # in an instance variable for later use in another template
74
- # or in the layout.
75
- #
76
- # The name of the instance variable is content_for_<name>
77
- # to stay consistent with @content_for_layout which is used
78
- # by ActionView's layouts
71
+ # Calling content_for stores the block of markup for later use.
72
+ # Subsequently, you can make calls to it by name with <tt>yield</tt>
73
+ # in another template or in the layout.
79
74
  #
80
75
  # Example:
81
76
  #
@@ -83,10 +78,17 @@ module ActionView
83
78
  # alert('hello world')
84
79
  # <% end %>
85
80
  #
86
- # You can use @content_for_header anywhere in your templates.
81
+ # You can use yield :header anywhere in your templates.
82
+ #
83
+ # <%= yield :header %>
87
84
  #
88
85
  # NOTE: Beware that content_for is ignored in caches. So you shouldn't use it
89
- # for elements that are going to be fragment cached.
86
+ # for elements that are going to be fragment cached.
87
+ #
88
+ # The deprecated way of accessing a content_for block was to use a instance variable
89
+ # named @@content_for_#{name_of_the_content_block}@. So <tt><%= content_for('footer') %></tt>
90
+ # would be avaiable as <tt><%= @content_for_footer %></tt>. The preferred notation now is
91
+ # <tt><%= yield :footer %></tt>.
90
92
  def content_for(name, &block)
91
93
  eval "@content_for_#{name} = (@content_for_#{name} || '') + capture(&block)"
92
94
  end
@@ -27,6 +27,7 @@ module ActionView
27
27
  # <tt>:url</tt>:: Specifies the url where the updated value should
28
28
  # be sent after the user presses "ok".
29
29
  #
30
+ #
30
31
  # Addtional +options+ are:
31
32
  # <tt>:rows</tt>:: Number of rows (more than 1 will use a TEXTAREA)
32
33
  # <tt>:cols</tt>:: Number of characters the text input should span (works for both INPUT and TEXTAREA)
@@ -122,10 +123,10 @@ module ActionView
122
123
  # <tt>:on_show</tt>:: Like on_hide, only now the expression is called
123
124
  # then the div is shown.
124
125
  # <tt>:after_update_element</tt>:: A Javascript expression that is called when the
125
- # user has selected one of the proposed values.
126
- # The expression should take two variables: element and value.
127
- # Element is a DOM element for the field, value
128
- # is the value selected by the user.
126
+ # user has selected one of the proposed values.
127
+ # The expression should take two variables: element and value.
128
+ # Element is a DOM element for the field, value
129
+ # is the value selected by the user.
129
130
  # <tt>:select</tt>:: Pick the class of the element from which the value for
130
131
  # insertion should be extracted. If this is not specified,
131
132
  # the entire element is used.
@@ -143,7 +143,7 @@ module ActionView
143
143
  # background instead of the regular reloading POST arrangement. Even
144
144
  # though it's using JavaScript to serialize the form elements, the form
145
145
  # submission will work just like a regular submission as viewed by the
146
- # receiving side (all elements available in @params). The options for
146
+ # receiving side (all elements available in <tt>params</tt>). The options for
147
147
  # specifying the target with :url and defining callbacks is the same as
148
148
  # link_to_remote.
149
149
  #
@@ -171,9 +171,10 @@ module ActionView
171
171
  end
172
172
 
173
173
  # Works like form_remote_tag, but uses form_for semantics.
174
- def remote_form_for(object_name, object, options = {}, &proc)
174
+ def remote_form_for(object_name, *args, &proc)
175
+ options = args.last.is_a?(Hash) ? args.pop : {}
175
176
  concat(form_remote_tag(options), proc.binding)
176
- fields_for(object_name, object, options, &proc)
177
+ fields_for(object_name, *(args << options), &proc)
177
178
  concat('</form>', proc.binding)
178
179
  end
179
180
  alias_method :form_remote_for, :remote_form_for
@@ -77,7 +77,7 @@ module ActionView
77
77
  end
78
78
 
79
79
  begin
80
- require_library_or_gem "redcloth"
80
+ require_library_or_gem "redcloth" unless Object.const_defined?(:RedCloth)
81
81
 
82
82
  # Returns the text with all the Textile codes turned into HTML-tags.
83
83
  # <i>This method is only available if RedCloth can be required</i>.
@@ -104,7 +104,7 @@ module ActionView
104
104
  end
105
105
 
106
106
  begin
107
- require_library_or_gem "bluecloth"
107
+ require_library_or_gem "bluecloth" unless Object.const_defined?(:BlueCloth)
108
108
 
109
109
  # Returns the text with all the Markdown codes turned into HTML-tags.
110
110
  # <i>This method is only available if BlueCloth can be required</i>.
@@ -116,7 +116,7 @@ module ActionView
116
116
  end
117
117
 
118
118
  # Returns +text+ transformed into HTML using very simple formatting rules
119
- # Surrounds paragraphs with <tt>&lt;p&gt;</tt> tags, and converts line breaks into <tt>&lt;br /&gt;</tt>
119
+ # Surrounds paragraphs with <tt><p></tt> tags, and converts line breaks into <tt><br/></tt>
120
120
  # Two consecutive newlines(<tt>\n\n</tt>) are considered as a paragraph, one newline (<tt>\n</tt>) is
121
121
  # considered a linebreak, three or more consecutive newlines are turned into two newlines
122
122
  def simple_format(text)
@@ -129,7 +129,7 @@ module ActionView
129
129
  end
130
130
 
131
131
  # Turns all urls and email addresses into clickable links. The +link+ parameter can limit what should be linked.
132
- # Options are :all (default), :email_addresses, and :urls.
132
+ # Options are <tt>:all</tt> (default), <tt>:email_addresses</tt>, and <tt>:urls</tt>.
133
133
  #
134
134
  # Example:
135
135
  # auto_link("Go to http://www.rubyonrails.com and say hello to david@loudthinking.com") =>
@@ -235,28 +235,28 @@ module ActionView
235
235
  # array every time it is called. This can be used to alternate classes
236
236
  # for table rows:
237
237
  #
238
- # <%- for item in @items do -%>
239
- # <tr class="<%= cycle("even", "odd") %>">
240
- # ... use item ...
241
- # </tr>
242
- # <%- end -%>
238
+ # <%- for item in @items do -%>
239
+ # <tr class="<%= cycle("even", "odd") %>">
240
+ # ... use item ...
241
+ # </tr>
242
+ # <%- end -%>
243
243
  #
244
244
  # You can use named cycles to prevent clashes in nested loops. You'll
245
245
  # have to reset the inner cycle, manually:
246
246
  #
247
- # <%- for item in @items do -%>
248
- # <tr class="<%= cycle("even", "odd", :name => "row_class")
249
- # <td>
250
- # <%- for value in item.values do -%>
251
- # <span style="color:'<%= cycle("red", "green", "blue"
252
- # :name => "colors") %>'">
253
- # item
254
- # </span>
255
- # <%- end -%>
256
- # <%- reset_cycle("colors") -%>
257
- # </td>
258
- # </tr>
259
- # <%- end -%>
247
+ # <%- for item in @items do -%>
248
+ # <tr class="<%= cycle("even", "odd", :name => "row_class")
249
+ # <td>
250
+ # <%- for value in item.values do -%>
251
+ # <span style="color:'<%= cycle("red", "green", "blue"
252
+ # :name => "colors") %>'">
253
+ # item
254
+ # </span>
255
+ # <%- end -%>
256
+ # <%- reset_cycle("colors") -%>
257
+ # </td>
258
+ # </tr>
259
+ # <%- end -%>
260
260
  def cycle(first_value, *values)
261
261
  if (values.last.instance_of? Hash)
262
262
  params = values.pop