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.
- data/CHANGELOG +291 -260
- data/lib/abstract_controller.rb +5 -2
- data/lib/abstract_controller/assigns.rb +21 -0
- data/lib/abstract_controller/base.rb +13 -5
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -14
- data/lib/abstract_controller/layouts.rb +50 -99
- data/lib/abstract_controller/logger.rb +2 -2
- data/lib/abstract_controller/rendering.rb +105 -173
- data/lib/abstract_controller/view_paths.rb +69 -0
- data/lib/action_controller.rb +1 -2
- data/lib/action_controller/base.rb +10 -32
- data/lib/action_controller/caching.rb +19 -18
- data/lib/action_controller/caching/actions.rb +17 -11
- data/lib/action_controller/caching/fragments.rb +5 -17
- data/lib/action_controller/caching/pages.rb +24 -24
- data/lib/action_controller/caching/sweeping.rb +1 -3
- data/lib/action_controller/deprecated.rb +0 -2
- data/lib/action_controller/deprecated/base.rb +143 -0
- data/lib/action_controller/metal.rb +29 -26
- data/lib/action_controller/metal/compatibility.rb +18 -87
- data/lib/action_controller/metal/cookies.rb +0 -1
- data/lib/action_controller/metal/head.rb +1 -0
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/hide_actions.rb +4 -6
- data/lib/action_controller/metal/http_authentication.rb +18 -33
- data/lib/action_controller/metal/implicit_render.rb +21 -0
- data/lib/action_controller/metal/instrumentation.rb +1 -1
- data/lib/action_controller/metal/mime_responds.rb +2 -1
- data/lib/action_controller/metal/rack_delegation.rb +3 -8
- data/lib/action_controller/metal/redirecting.rb +2 -1
- data/lib/action_controller/metal/renderers.rb +4 -2
- data/lib/action_controller/metal/rendering.rb +31 -44
- data/lib/action_controller/metal/request_forgery_protection.rb +41 -4
- data/lib/action_controller/metal/responder.rb +2 -0
- data/lib/action_controller/metal/session_management.rb +0 -36
- data/lib/action_controller/metal/streaming.rb +20 -47
- data/lib/action_controller/metal/testing.rb +0 -1
- data/lib/action_controller/metal/url_for.rb +11 -148
- data/lib/action_controller/middleware.rb +2 -1
- data/lib/action_controller/polymorphic_routes.rb +1 -2
- data/lib/action_controller/railtie.rb +63 -10
- data/lib/action_controller/railties/{subscriber.rb → log_subscriber.rb} +5 -12
- data/lib/action_controller/railties/url_helpers.rb +14 -0
- data/lib/action_controller/record_identifier.rb +20 -1
- data/lib/action_controller/test_case.rb +123 -12
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/cache.rb +20 -3
- data/lib/action_dispatch/http/filter_parameters.rb +40 -25
- data/lib/action_dispatch/http/mime_negotiation.rb +6 -17
- data/lib/action_dispatch/http/mime_type.rb +2 -7
- data/lib/action_dispatch/http/request.rb +12 -33
- data/lib/action_dispatch/http/response.rb +35 -15
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +5 -32
- data/lib/action_dispatch/middleware/callbacks.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +4 -3
- data/lib/action_dispatch/middleware/params_parser.rb +4 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +51 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +6 -8
- data/lib/action_dispatch/middleware/show_exceptions.rb +0 -14
- data/lib/action_dispatch/middleware/stack.rb +6 -2
- data/lib/action_dispatch/railtie.rb +3 -1
- data/lib/action_dispatch/routing.rb +2 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +35 -7
- data/lib/action_dispatch/routing/mapper.rb +134 -48
- data/lib/action_dispatch/routing/route.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +217 -158
- data/lib/action_dispatch/routing/url_for.rb +139 -0
- data/lib/action_dispatch/testing/assertions/response.rb +14 -61
- data/lib/action_dispatch/testing/assertions/routing.rb +25 -14
- data/lib/action_dispatch/testing/integration.rb +32 -50
- data/lib/action_dispatch/testing/performance_test.rb +3 -1
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +2 -0
- data/lib/action_pack/version.rb +4 -3
- data/lib/action_view.rb +11 -6
- data/lib/action_view/base.rb +33 -121
- data/lib/action_view/context.rb +0 -2
- data/lib/action_view/helpers.rb +26 -23
- data/lib/action_view/helpers/active_model_helper.rb +28 -18
- data/lib/action_view/helpers/asset_tag_helper.rb +109 -54
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +22 -1
- data/lib/action_view/helpers/capture_helper.rb +22 -22
- data/lib/action_view/helpers/date_helper.rb +6 -5
- data/lib/action_view/helpers/form_helper.rb +78 -63
- data/lib/action_view/helpers/form_options_helper.rb +6 -4
- data/lib/action_view/helpers/form_tag_helper.rb +26 -15
- data/lib/action_view/helpers/javascript_helper.rb +90 -10
- data/lib/action_view/helpers/number_helper.rb +315 -118
- data/lib/action_view/helpers/prototype_helper.rb +19 -46
- data/lib/action_view/helpers/record_tag_helper.rb +4 -4
- data/lib/action_view/helpers/tag_helper.rb +7 -24
- data/lib/action_view/helpers/text_helper.rb +8 -7
- data/lib/action_view/helpers/translation_helper.rb +7 -5
- data/lib/action_view/helpers/url_helper.rb +19 -16
- data/lib/action_view/locale/en.yml +45 -6
- data/lib/action_view/lookup_context.rb +190 -0
- data/lib/action_view/paths.rb +22 -63
- data/lib/action_view/railtie.rb +14 -4
- data/lib/action_view/railties/{subscriber.rb → log_subscriber.rb} +1 -1
- data/lib/action_view/render/layouts.rb +73 -0
- data/lib/action_view/render/partials.rb +15 -41
- data/lib/action_view/render/rendering.rb +27 -78
- data/lib/action_view/template.rb +20 -24
- data/lib/action_view/template/error.rb +22 -2
- data/lib/action_view/template/handlers/erb.rb +33 -9
- data/lib/action_view/template/handlers/rjs.rb +1 -2
- data/lib/action_view/template/resolver.rb +46 -104
- data/lib/action_view/template/text.rb +5 -12
- data/lib/action_view/test_case.rb +14 -23
- metadata +83 -40
- data/lib/abstract_controller/compatibility.rb +0 -18
- data/lib/abstract_controller/localized_cache.rb +0 -49
- data/lib/action_controller/metal/configuration.rb +0 -28
- 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
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
199
|
+
# <%= form_for @post do |f| %>
|
195
200
|
# ...
|
196
201
|
# <% end %>
|
197
202
|
#
|
198
203
|
# is equivalent to something like:
|
199
204
|
#
|
200
|
-
#
|
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
|
-
#
|
211
|
+
# <%= form_for(Post.new) do |f| %>
|
207
212
|
# ...
|
208
213
|
# <% end %>
|
209
214
|
#
|
210
215
|
# expands to
|
211
216
|
#
|
212
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
|
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?(:
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
406
|
+
# <%= form_for @person, :url => { :action => "update" } do |person_form| %>
|
403
407
|
# ...
|
404
|
-
#
|
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>
|
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
|
-
#
|
435
|
+
# <%= form_for @person, :url => { :action => "update" } do |person_form| %>
|
432
436
|
# ...
|
433
|
-
#
|
437
|
+
# <%= person_form.fields_for :address do |address_fields| %>
|
434
438
|
# ...
|
435
|
-
# Delete: <%= address_fields.check_box :
|
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
|
-
#
|
463
|
+
# <%= form_for @person, :url => { :action => "update" } do |person_form| %>
|
460
464
|
# ...
|
461
|
-
#
|
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
|
-
#
|
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
|
-
#
|
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
|
-
#
|
487
|
+
# <%= form_for @person, :url => { :action => "update" } do |person_form| %>
|
484
488
|
# ...
|
485
|
-
#
|
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>
|
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
|
-
#
|
516
|
+
# <%= form_for @person, :url => { :action => "update" } do |person_form| %>
|
513
517
|
# ...
|
514
|
-
#
|
515
|
-
# Delete: <%= project_fields.check_box :
|
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
|
-
|
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
|
-
#
|
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.
|
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,
|
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
|
-
#
|
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.
|
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
|
-
|
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?(:
|
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 =
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
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,
|
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,
|
1194
|
-
if object.
|
1195
|
-
|
1196
|
-
|
1197
|
-
@template.fields_for(name, object,
|
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
|
-
|
1212
|
-
|
1213
|
-
|
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,
|
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
|
|