actionpack 3.0.0.beta → 3.0.0.beta2

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 (118) hide show
  1. data/CHANGELOG +291 -260
  2. data/lib/abstract_controller.rb +5 -2
  3. data/lib/abstract_controller/assigns.rb +21 -0
  4. data/lib/abstract_controller/base.rb +13 -5
  5. data/lib/abstract_controller/collector.rb +2 -0
  6. data/lib/abstract_controller/helpers.rb +4 -14
  7. data/lib/abstract_controller/layouts.rb +50 -99
  8. data/lib/abstract_controller/logger.rb +2 -2
  9. data/lib/abstract_controller/rendering.rb +105 -173
  10. data/lib/abstract_controller/view_paths.rb +69 -0
  11. data/lib/action_controller.rb +1 -2
  12. data/lib/action_controller/base.rb +10 -32
  13. data/lib/action_controller/caching.rb +19 -18
  14. data/lib/action_controller/caching/actions.rb +17 -11
  15. data/lib/action_controller/caching/fragments.rb +5 -17
  16. data/lib/action_controller/caching/pages.rb +24 -24
  17. data/lib/action_controller/caching/sweeping.rb +1 -3
  18. data/lib/action_controller/deprecated.rb +0 -2
  19. data/lib/action_controller/deprecated/base.rb +143 -0
  20. data/lib/action_controller/metal.rb +29 -26
  21. data/lib/action_controller/metal/compatibility.rb +18 -87
  22. data/lib/action_controller/metal/cookies.rb +0 -1
  23. data/lib/action_controller/metal/head.rb +1 -0
  24. data/lib/action_controller/metal/helpers.rb +2 -2
  25. data/lib/action_controller/metal/hide_actions.rb +4 -6
  26. data/lib/action_controller/metal/http_authentication.rb +18 -33
  27. data/lib/action_controller/metal/implicit_render.rb +21 -0
  28. data/lib/action_controller/metal/instrumentation.rb +1 -1
  29. data/lib/action_controller/metal/mime_responds.rb +2 -1
  30. data/lib/action_controller/metal/rack_delegation.rb +3 -8
  31. data/lib/action_controller/metal/redirecting.rb +2 -1
  32. data/lib/action_controller/metal/renderers.rb +4 -2
  33. data/lib/action_controller/metal/rendering.rb +31 -44
  34. data/lib/action_controller/metal/request_forgery_protection.rb +41 -4
  35. data/lib/action_controller/metal/responder.rb +2 -0
  36. data/lib/action_controller/metal/session_management.rb +0 -36
  37. data/lib/action_controller/metal/streaming.rb +20 -47
  38. data/lib/action_controller/metal/testing.rb +0 -1
  39. data/lib/action_controller/metal/url_for.rb +11 -148
  40. data/lib/action_controller/middleware.rb +2 -1
  41. data/lib/action_controller/polymorphic_routes.rb +1 -2
  42. data/lib/action_controller/railtie.rb +63 -10
  43. data/lib/action_controller/railties/{subscriber.rb → log_subscriber.rb} +5 -12
  44. data/lib/action_controller/railties/url_helpers.rb +14 -0
  45. data/lib/action_controller/record_identifier.rb +20 -1
  46. data/lib/action_controller/test_case.rb +123 -12
  47. data/lib/action_dispatch.rb +1 -0
  48. data/lib/action_dispatch/http/cache.rb +20 -3
  49. data/lib/action_dispatch/http/filter_parameters.rb +40 -25
  50. data/lib/action_dispatch/http/mime_negotiation.rb +6 -17
  51. data/lib/action_dispatch/http/mime_type.rb +2 -7
  52. data/lib/action_dispatch/http/request.rb +12 -33
  53. data/lib/action_dispatch/http/response.rb +35 -15
  54. data/lib/action_dispatch/http/upload.rb +2 -0
  55. data/lib/action_dispatch/http/url.rb +5 -32
  56. data/lib/action_dispatch/middleware/callbacks.rb +1 -1
  57. data/lib/action_dispatch/middleware/cookies.rb +4 -3
  58. data/lib/action_dispatch/middleware/params_parser.rb +4 -3
  59. data/lib/action_dispatch/middleware/remote_ip.rb +51 -0
  60. data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -0
  61. data/lib/action_dispatch/middleware/session/cookie_store.rb +6 -8
  62. data/lib/action_dispatch/middleware/show_exceptions.rb +0 -14
  63. data/lib/action_dispatch/middleware/stack.rb +6 -2
  64. data/lib/action_dispatch/railtie.rb +3 -1
  65. data/lib/action_dispatch/routing.rb +2 -0
  66. data/lib/action_dispatch/routing/deprecated_mapper.rb +35 -7
  67. data/lib/action_dispatch/routing/mapper.rb +134 -48
  68. data/lib/action_dispatch/routing/route.rb +2 -2
  69. data/lib/action_dispatch/routing/route_set.rb +217 -158
  70. data/lib/action_dispatch/routing/url_for.rb +139 -0
  71. data/lib/action_dispatch/testing/assertions/response.rb +14 -61
  72. data/lib/action_dispatch/testing/assertions/routing.rb +25 -14
  73. data/lib/action_dispatch/testing/integration.rb +32 -50
  74. data/lib/action_dispatch/testing/performance_test.rb +3 -1
  75. data/lib/action_dispatch/testing/test_process.rb +2 -0
  76. data/lib/action_dispatch/testing/test_request.rb +2 -0
  77. data/lib/action_pack/version.rb +4 -3
  78. data/lib/action_view.rb +11 -6
  79. data/lib/action_view/base.rb +33 -121
  80. data/lib/action_view/context.rb +0 -2
  81. data/lib/action_view/helpers.rb +26 -23
  82. data/lib/action_view/helpers/active_model_helper.rb +28 -18
  83. data/lib/action_view/helpers/asset_tag_helper.rb +109 -54
  84. data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
  85. data/lib/action_view/helpers/cache_helper.rb +22 -1
  86. data/lib/action_view/helpers/capture_helper.rb +22 -22
  87. data/lib/action_view/helpers/date_helper.rb +6 -5
  88. data/lib/action_view/helpers/form_helper.rb +78 -63
  89. data/lib/action_view/helpers/form_options_helper.rb +6 -4
  90. data/lib/action_view/helpers/form_tag_helper.rb +26 -15
  91. data/lib/action_view/helpers/javascript_helper.rb +90 -10
  92. data/lib/action_view/helpers/number_helper.rb +315 -118
  93. data/lib/action_view/helpers/prototype_helper.rb +19 -46
  94. data/lib/action_view/helpers/record_tag_helper.rb +4 -4
  95. data/lib/action_view/helpers/tag_helper.rb +7 -24
  96. data/lib/action_view/helpers/text_helper.rb +8 -7
  97. data/lib/action_view/helpers/translation_helper.rb +7 -5
  98. data/lib/action_view/helpers/url_helper.rb +19 -16
  99. data/lib/action_view/locale/en.yml +45 -6
  100. data/lib/action_view/lookup_context.rb +190 -0
  101. data/lib/action_view/paths.rb +22 -63
  102. data/lib/action_view/railtie.rb +14 -4
  103. data/lib/action_view/railties/{subscriber.rb → log_subscriber.rb} +1 -1
  104. data/lib/action_view/render/layouts.rb +73 -0
  105. data/lib/action_view/render/partials.rb +15 -41
  106. data/lib/action_view/render/rendering.rb +27 -78
  107. data/lib/action_view/template.rb +20 -24
  108. data/lib/action_view/template/error.rb +22 -2
  109. data/lib/action_view/template/handlers/erb.rb +33 -9
  110. data/lib/action_view/template/handlers/rjs.rb +1 -2
  111. data/lib/action_view/template/resolver.rb +46 -104
  112. data/lib/action_view/template/text.rb +5 -12
  113. data/lib/action_view/test_case.rb +14 -23
  114. metadata +83 -40
  115. data/lib/abstract_controller/compatibility.rb +0 -18
  116. data/lib/abstract_controller/localized_cache.rb +0 -49
  117. data/lib/action_controller/metal/configuration.rb +0 -28
  118. data/lib/action_controller/url_rewriter.rb +0 -76
@@ -1,5 +1,6 @@
1
1
  require "date"
2
2
  require 'action_view/helpers/tag_helper'
3
+ require 'active_support/core_ext/hash/slice'
3
4
 
4
5
  module ActionView
5
6
  module Helpers
@@ -815,7 +816,7 @@ module ActionView
815
816
  tag_options[:selected] = "selected" if selected == i
816
817
  select_options << content_tag(:option, value, tag_options)
817
818
  end
818
- select_options.join("\n") + "\n"
819
+ (select_options.join("\n") + "\n").html_safe
819
820
  end
820
821
 
821
822
  # Builds select tag from date type and html select options
@@ -833,9 +834,9 @@ module ActionView
833
834
  select_html = "\n"
834
835
  select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank]
835
836
  select_html << prompt_option_tag(type, @options[:prompt]) + "\n" if @options[:prompt]
836
- select_html << select_options_as_html.to_s
837
+ select_html << select_options_as_html
837
838
 
838
- (content_tag(:select, select_html, select_options) + "\n").html_safe
839
+ (content_tag(:select, select_html.html_safe, select_options) + "\n").html_safe
839
840
  end
840
841
 
841
842
  # Builds a prompt option tag with supplied options or from default options
@@ -865,7 +866,7 @@ module ActionView
865
866
  :id => input_id_from_type(type),
866
867
  :name => input_name_from_type(type),
867
868
  :value => value
868
- }) + "\n").html_safe
869
+ }.merge(@html_options.slice(:disabled))) + "\n").html_safe
869
870
  end
870
871
 
871
872
  # Returns the name attribute for the input tag
@@ -907,7 +908,7 @@ module ActionView
907
908
  when :hour
908
909
  (@options[:discard_year] && @options[:discard_day]) ? "" : @options[:datetime_separator]
909
910
  when :minute
910
- @options[:time_separator]
911
+ @options[:discard_minute] ? "" : @options[:time_separator]
911
912
  when :second
912
913
  @options[:include_seconds] ? @options[:time_separator] : ""
913
914
  end
@@ -4,6 +4,7 @@ require 'action_view/helpers/tag_helper'
4
4
  require 'action_view/helpers/form_tag_helper'
5
5
  require 'active_support/core_ext/class/inheritable_attributes'
6
6
  require 'active_support/core_ext/hash/slice'
7
+ require 'active_support/core_ext/object/blank'
7
8
 
8
9
  module ActionView
9
10
  module Helpers
@@ -28,7 +29,7 @@ module ActionView
28
29
  #
29
30
  # # Note: a @person variable will have been created in the controller.
30
31
  # # For example: @person = Person.new
31
- # <% form_for :person, @person, :url => { :action => "create" } do |f| %>
32
+ # <%= form_for :person, @person, :url => { :action => "create" } do |f| %>
32
33
  # <%= f.text_field :first_name %>
33
34
  # <%= f.text_field :last_name %>
34
35
  # <%= submit_tag 'Create' %>
@@ -44,7 +45,7 @@ module ActionView
44
45
  #
45
46
  # If you are using a partial for your form fields, you can use this shortcut:
46
47
  #
47
- # <% form_for :person, @person, :url => { :action => "create" } do |f| %>
48
+ # <%= form_for :person, @person, :url => { :action => "create" } do |f| %>
48
49
  # <%= render :partial => f %>
49
50
  # <%= submit_tag 'Create' %>
50
51
  # <% end %>
@@ -92,13 +93,17 @@ module ActionView
92
93
  # link:classes/ActionView/Helpers/DateHelper.html, and
93
94
  # link:classes/ActionView/Helpers/ActiveRecordHelper.html
94
95
  module FormHelper
96
+ extend ActiveSupport::Concern
97
+
98
+ include FormTagHelper
99
+
95
100
  # Creates a form and a scope around a specific model object that is used
96
101
  # as a base for questioning about values for the fields.
97
102
  #
98
103
  # Rails provides succinct resource-oriented form generation with +form_for+
99
104
  # like this:
100
105
  #
101
- # <% form_for @offer do |f| %>
106
+ # <%= form_for @offer do |f| %>
102
107
  # <%= f.label :version, 'Version' %>:
103
108
  # <%= f.text_field :version %><br />
104
109
  # <%= f.label :author, 'Author' %>:
@@ -115,7 +120,7 @@ module ActionView
115
120
  # The generic way to call +form_for+ yields a form builder around a
116
121
  # model:
117
122
  #
118
- # <% form_for :person, :url => { :action => "update" } do |f| %>
123
+ # <%= form_for :person, :url => { :action => "update" } do |f| %>
119
124
  # <%= f.error_messages %>
120
125
  # First name: <%= f.text_field :first_name %><br />
121
126
  # Last name : <%= f.text_field :last_name %><br />
@@ -139,7 +144,7 @@ module ActionView
139
144
  # If the instance variable is not <tt>@person</tt> you can pass the actual
140
145
  # record as the second argument:
141
146
  #
142
- # <% form_for :person, person, :url => { :action => "update" } do |f| %>
147
+ # <%= form_for :person, person, :url => { :action => "update" } do |f| %>
143
148
  # ...
144
149
  # <% end %>
145
150
  #
@@ -171,7 +176,7 @@ module ActionView
171
176
  # possible to use both the stand-alone FormHelper methods and methods
172
177
  # from FormTagHelper. For example:
173
178
  #
174
- # <% form_for :person, @person, :url => { :action => "update" } do |f| %>
179
+ # <%= form_for :person, @person, :url => { :action => "update" } do |f| %>
175
180
  # First name: <%= f.text_field :first_name %>
176
181
  # Last name : <%= f.text_field :last_name %>
177
182
  # Biography : <%= text_area :person, :biography %>
@@ -191,37 +196,37 @@ module ActionView
191
196
  #
192
197
  # For example, if <tt>@post</tt> is an existing record you want to edit
193
198
  #
194
- # <% form_for @post do |f| %>
199
+ # <%= form_for @post do |f| %>
195
200
  # ...
196
201
  # <% end %>
197
202
  #
198
203
  # is equivalent to something like:
199
204
  #
200
- # <% form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
205
+ # <%= form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
201
206
  # ...
202
207
  # <% end %>
203
208
  #
204
209
  # And for new records
205
210
  #
206
- # <% form_for(Post.new) do |f| %>
211
+ # <%= form_for(Post.new) do |f| %>
207
212
  # ...
208
213
  # <% end %>
209
214
  #
210
215
  # expands to
211
216
  #
212
- # <% form_for :post, Post.new, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
217
+ # <%= form_for :post, Post.new, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
213
218
  # ...
214
219
  # <% end %>
215
220
  #
216
221
  # You can also overwrite the individual conventions, like this:
217
222
  #
218
- # <% form_for(@post, :url => super_post_path(@post)) do |f| %>
223
+ # <%= form_for(@post, :url => super_post_path(@post)) do |f| %>
219
224
  # ...
220
225
  # <% end %>
221
226
  #
222
227
  # And for namespaced routes, like +admin_post_url+:
223
228
  #
224
- # <% form_for([:admin, @post]) do |f| %>
229
+ # <%= form_for([:admin, @post]) do |f| %>
225
230
  # ...
226
231
  # <% end %>
227
232
  #
@@ -239,7 +244,7 @@ module ActionView
239
244
  #
240
245
  # Example:
241
246
  #
242
- # <% form_for(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| %>
247
+ # <%= form_for(:post, @post, :remote => true, :html => { :id => 'create-post', :method => :put }) do |f| %>
243
248
  # ...
244
249
  # <% end %>
245
250
  #
@@ -259,7 +264,7 @@ module ActionView
259
264
  # custom builder. For example, let's say you made a helper to
260
265
  # automatically add labels to form inputs.
261
266
  #
262
- # <% form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
267
+ # <%= form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
263
268
  # <%= f.text_field :first_name %>
264
269
  # <%= f.text_field :last_name %>
265
270
  # <%= text_area :person, :biography %>
@@ -309,21 +314,20 @@ module ActionView
309
314
 
310
315
  options[:html][:remote] = true if options.delete(:remote)
311
316
 
312
- concat(form_tag(options.delete(:url) || {}, options.delete(:html) || {}))
313
- fields_for(object_name, *(args << options), &proc)
314
- safe_concat('</form>')
317
+ output = form_tag(options.delete(:url) || {}, options.delete(:html) || {})
318
+ output << fields_for(object_name, *(args << options), &proc)
319
+ output.safe_concat('</form>')
315
320
  end
316
321
 
317
322
  def apply_form_for_options!(object_or_array, options) #:nodoc:
318
323
  object = object_or_array.is_a?(Array) ? object_or_array.last : object_or_array
319
-
320
324
  object = convert_to_model(object)
321
325
 
322
326
  html_options =
323
- if object.respond_to?(:new_record?) && object.new_record?
324
- { :class => dom_class(object, :new), :id => dom_id(object), :method => :post }
325
- else
327
+ if object.respond_to?(:persisted?) && object.persisted?
326
328
  { :class => dom_class(object, :edit), :id => dom_id(object, :edit), :method => :put }
329
+ else
330
+ { :class => dom_class(object, :new), :id => dom_id(object), :method => :post }
327
331
  end
328
332
 
329
333
  options[:html] ||= {}
@@ -337,11 +341,11 @@ module ActionView
337
341
  #
338
342
  # === Generic Examples
339
343
  #
340
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
344
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
341
345
  # First name: <%= person_form.text_field :first_name %>
342
346
  # Last name : <%= person_form.text_field :last_name %>
343
347
  #
344
- # <% fields_for @person.permission do |permission_fields| %>
348
+ # <%= fields_for @person.permission do |permission_fields| %>
345
349
  # Admin? : <%= permission_fields.check_box :admin %>
346
350
  # <% end %>
347
351
  # <% end %>
@@ -349,13 +353,13 @@ module ActionView
349
353
  # ...or if you have an object that needs to be represented as a different
350
354
  # parameter, like a Client that acts as a Person:
351
355
  #
352
- # <% fields_for :person, @client do |permission_fields| %>
356
+ # <%= fields_for :person, @client do |permission_fields| %>
353
357
  # Admin?: <%= permission_fields.check_box :admin %>
354
358
  # <% end %>
355
359
  #
356
360
  # ...or if you don't have an object, just a name of the parameter:
357
361
  #
358
- # <% fields_for :person do |permission_fields| %>
362
+ # <%= fields_for :person do |permission_fields| %>
359
363
  # Admin?: <%= permission_fields.check_box :admin %>
360
364
  # <% end %>
361
365
  #
@@ -399,9 +403,9 @@ module ActionView
399
403
  #
400
404
  # This model can now be used with a nested fields_for, like so:
401
405
  #
402
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
406
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
403
407
  # ...
404
- # <% person_form.fields_for :address do |address_fields| %>
408
+ # <%= person_form.fields_for :address do |address_fields| %>
405
409
  # Street : <%= address_fields.text_field :street %>
406
410
  # Zip code: <%= address_fields.text_field :zip_code %>
407
411
  # <% end %>
@@ -424,15 +428,15 @@ module ActionView
424
428
  # accepts_nested_attributes_for :address, :allow_destroy => true
425
429
  # end
426
430
  #
427
- # Now, when you use a form element with the <tt>_delete</tt> parameter,
431
+ # Now, when you use a form element with the <tt>_destroy</tt> parameter,
428
432
  # with a value that evaluates to +true+, you will destroy the associated
429
433
  # model (eg. 1, '1', true, or 'true'):
430
434
  #
431
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
435
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
432
436
  # ...
433
- # <% person_form.fields_for :address do |address_fields| %>
437
+ # <%= person_form.fields_for :address do |address_fields| %>
434
438
  # ...
435
- # Delete: <%= address_fields.check_box :_delete %>
439
+ # Delete: <%= address_fields.check_box :_destroy %>
436
440
  # <% end %>
437
441
  # <% end %>
438
442
  #
@@ -456,9 +460,9 @@ module ActionView
456
460
  # the nested fields_for call will be repeated for each instance in the
457
461
  # collection:
458
462
  #
459
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
463
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
460
464
  # ...
461
- # <% person_form.fields_for :projects do |project_fields| %>
465
+ # <%= person_form.fields_for :projects do |project_fields| %>
462
466
  # <% if project_fields.object.active? %>
463
467
  # Name: <%= project_fields.text_field :name %>
464
468
  # <% end %>
@@ -467,11 +471,11 @@ module ActionView
467
471
  #
468
472
  # It's also possible to specify the instance to be used:
469
473
  #
470
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
474
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
471
475
  # ...
472
476
  # <% @person.projects.each do |project| %>
473
477
  # <% if project.active? %>
474
- # <% person_form.fields_for :projects, project do |project_fields| %>
478
+ # <%= person_form.fields_for :projects, project do |project_fields| %>
475
479
  # Name: <%= project_fields.text_field :name %>
476
480
  # <% end %>
477
481
  # <% end %>
@@ -480,9 +484,9 @@ module ActionView
480
484
  #
481
485
  # Or a collection to be used:
482
486
  #
483
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
487
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
484
488
  # ...
485
- # <% person_form.fields_for :projects, @active_projects do |project_fields| %>
489
+ # <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
486
490
  # Name: <%= project_fields.text_field :name %>
487
491
  # <% end %>
488
492
  # <% end %>
@@ -505,14 +509,14 @@ module ActionView
505
509
  # end
506
510
  #
507
511
  # This will allow you to specify which models to destroy in the
508
- # attributes hash by adding a form element for the <tt>_delete</tt>
512
+ # attributes hash by adding a form element for the <tt>_destroy</tt>
509
513
  # parameter with a value that evaluates to +true+
510
514
  # (eg. 1, '1', true, or 'true'):
511
515
  #
512
- # <% form_for @person, :url => { :action => "update" } do |person_form| %>
516
+ # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
513
517
  # ...
514
- # <% person_form.fields_for :projects do |project_fields| %>
515
- # Delete: <%= project_fields.check_box :_delete %>
518
+ # <%= person_form.fields_for :projects do |project_fields| %>
519
+ # Delete: <%= project_fields.check_box :_destroy %>
516
520
  # <% end %>
517
521
  # <% end %>
518
522
  def fields_for(record_or_name_or_array, *args, &block)
@@ -529,7 +533,10 @@ module ActionView
529
533
  end
530
534
 
531
535
  builder = options[:builder] || ActionView::Base.default_form_builder
532
- yield builder.new(object_name, object, self, options, block)
536
+
537
+ with_output_buffer do
538
+ yield builder.new(object_name, object, self, options, block)
539
+ end
533
540
  end
534
541
 
535
542
  # Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
@@ -719,7 +726,7 @@ module ActionView
719
726
  # Unfortunately that workaround does not work when the check box goes
720
727
  # within an array-like parameter, as in
721
728
  #
722
- # <% fields_for "project[invoice_attributes][]", invoice, :index => nil do |form| %>
729
+ # <%= fields_for "project[invoice_attributes][]", invoice, :index => nil do |form| %>
723
730
  # <%= form.check_box :paid %>
724
731
  # ...
725
732
  # <% end %>
@@ -1008,7 +1015,7 @@ module ActionView
1008
1015
  class FormBuilder #:nodoc:
1009
1016
  # The methods which wrap a form helper call.
1010
1017
  class_inheritable_accessor :field_helpers
1011
- self.field_helpers = (FormHelper.instance_methods - ['form_for'])
1018
+ self.field_helpers = (FormHelper.instance_method_names - ['form_for'])
1012
1019
 
1013
1020
  attr_accessor :object_name, :object, :options
1014
1021
 
@@ -1034,7 +1041,7 @@ module ActionView
1034
1041
  end
1035
1042
 
1036
1043
  (field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector|
1037
- src = <<-end_src
1044
+ src, file, line = <<-end_src, __FILE__, __LINE__ + 1
1038
1045
  def #{selector}(method, options = {}) # def text_field(method, options = {})
1039
1046
  @template.send( # @template.send(
1040
1047
  #{selector.inspect}, # "text_field",
@@ -1043,7 +1050,7 @@ module ActionView
1043
1050
  objectify_options(options)) # objectify_options(options))
1044
1051
  end # end
1045
1052
  end_src
1046
- class_eval src, __FILE__, __LINE__
1053
+ class_eval src, file, line
1047
1054
  end
1048
1055
 
1049
1056
  def fields_for(record_or_name_or_array, *args, &block)
@@ -1109,7 +1116,7 @@ module ActionView
1109
1116
  # Add the submit button for the given form. When no value is given, it checks
1110
1117
  # if the object is a new resource or not to create the proper label:
1111
1118
  #
1112
- # <% form_for @post do |f| %>
1119
+ # <%= form_for @post do |f| %>
1113
1120
  # <%= f.submit %>
1114
1121
  # <% end %>
1115
1122
  #
@@ -1150,7 +1157,7 @@ module ActionView
1150
1157
 
1151
1158
  def submit_default_value
1152
1159
  object = @object.respond_to?(:to_model) ? @object.to_model : @object
1153
- key = object ? (object.new_record? ? :create : :update) : :submit
1160
+ key = object ? (object.persisted? ? :update : :create) : :submit
1154
1161
 
1155
1162
  model = if object.class.respond_to?(:model_name)
1156
1163
  object.class.model_name.human
@@ -1172,32 +1179,38 @@ module ActionView
1172
1179
 
1173
1180
  def fields_for_with_nested_attributes(association_name, args, block)
1174
1181
  name = "#{object_name}[#{association_name}_attributes]"
1175
- association = args.first.to_model if args.first.respond_to?(:to_model)
1182
+ options = args.extract_options!
1183
+ association = args.shift
1184
+ association = association.to_model if association.respond_to?(:to_model)
1176
1185
 
1177
- if association.respond_to?(:new_record?)
1186
+ if association.respond_to?(:persisted?)
1178
1187
  association = [association] if @object.send(association_name).is_a?(Array)
1179
1188
  elsif !association.is_a?(Array)
1180
1189
  association = @object.send(association_name)
1181
1190
  end
1182
1191
 
1183
1192
  if association.is_a?(Array)
1184
- explicit_child_index = args.last[:child_index] if args.last.is_a?(Hash)
1185
- association.map do |child|
1186
- fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, args, block)
1187
- end.join
1193
+ explicit_child_index = options[:child_index]
1194
+ output = ActiveSupport::SafeBuffer.new
1195
+ association.each do |child|
1196
+ output << fields_for_nested_model("#{name}[#{explicit_child_index || nested_child_index(name)}]", child, options, block)
1197
+ end
1198
+ output
1188
1199
  elsif association
1189
- fields_for_nested_model(name, association, args, block)
1200
+ fields_for_nested_model(name, association, options, block)
1190
1201
  end
1191
1202
  end
1192
1203
 
1193
- def fields_for_nested_model(name, object, args, block)
1194
- if object.new_record?
1195
- @template.fields_for(name, object, *args, &block)
1196
- else
1197
- @template.fields_for(name, object, *args) do |builder|
1204
+ def fields_for_nested_model(name, object, options, block)
1205
+ object = object.to_model if object.respond_to?(:to_model)
1206
+
1207
+ if object.persisted?
1208
+ @template.fields_for(name, object, options) do |builder|
1198
1209
  block.call(builder)
1199
1210
  @template.concat builder.hidden_field(:id) unless builder.emitted_hidden_id?
1200
1211
  end
1212
+ else
1213
+ @template.fields_for(name, object, options, &block)
1201
1214
  end
1202
1215
  end
1203
1216
 
@@ -1208,8 +1221,10 @@ module ActionView
1208
1221
  end
1209
1222
  end
1210
1223
 
1211
- class Base
1212
- cattr_accessor :default_form_builder
1213
- @@default_form_builder = ::ActionView::Helpers::FormBuilder
1224
+ ActiveSupport.on_load(:action_view) do
1225
+ class ActionView::Base
1226
+ cattr_accessor :default_form_builder
1227
+ @@default_form_builder = ::ActionView::Helpers::FormBuilder
1228
+ end
1214
1229
  end
1215
1230
  end
@@ -1,6 +1,7 @@
1
1
  require 'cgi'
2
2
  require 'erb'
3
3
  require 'action_view/helpers/form_helper'
4
+ require 'active_support/core_ext/object/blank'
4
5
 
5
6
  module ActionView
6
7
  module Helpers
@@ -97,7 +98,9 @@ module ActionView
97
98
  # </select>
98
99
  #
99
100
  module FormOptionsHelper
101
+ # ERB::Util can mask some helpers like textilize. Make sure to include them.
100
102
  include ERB::Util
103
+ include TextHelper
101
104
 
102
105
  # Create a select tag and a series of contained option tags for the provided object and method.
103
106
  # The option currently held by the object will be selected, provided that the object is available.
@@ -149,7 +152,7 @@ module ActionView
149
152
  # end
150
153
  #
151
154
  # Sample usage (selecting the associated Author for an instance of Post, <tt>@post</tt>):
152
- # collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
155
+ # collection_select(:post, :author_id, Author.all, :id, :name_with_initial, :prompt => true)
153
156
  #
154
157
  # If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return:
155
158
  # <select name="post[author_id]">
@@ -572,10 +575,9 @@ module ActionView
572
575
  end
573
576
  if value.blank? && options[:prompt]
574
577
  prompt = options[:prompt].kind_of?(String) ? options[:prompt] : I18n.translate('helpers.select.prompt', :default => 'Please select')
575
- "<option value=\"\">#{prompt}</option>\n" + option_tags
576
- else
577
- option_tags
578
+ option_tags = "<option value=\"\">#{prompt}</option>\n" + option_tags
578
579
  end
580
+ option_tags.html_safe
579
581
  end
580
582
  end
581
583