actionview 4.2.11.3 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of actionview might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +136 -255
- data/MIT-LICENSE +1 -1
- data/README.rdoc +2 -3
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +14 -2
- data/lib/action_view/dependency_tracker.rb +46 -15
- data/lib/action_view/digestor.rb +13 -9
- data/lib/action_view/flows.rb +1 -1
- data/lib/action_view/gem_version.rb +4 -4
- data/lib/action_view/helpers/asset_tag_helper.rb +15 -5
- data/lib/action_view/helpers/asset_url_helper.rb +51 -12
- data/lib/action_view/helpers/atom_feed_helper.rb +5 -4
- data/lib/action_view/helpers/cache_helper.rb +75 -20
- data/lib/action_view/helpers/capture_helper.rb +3 -2
- data/lib/action_view/helpers/controller_helper.rb +1 -0
- data/lib/action_view/helpers/date_helper.rb +39 -10
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +81 -35
- data/lib/action_view/helpers/form_options_helper.rb +74 -35
- data/lib/action_view/helpers/form_tag_helper.rb +46 -19
- data/lib/action_view/helpers/javascript_helper.rb +4 -4
- data/lib/action_view/helpers/number_helper.rb +10 -12
- data/lib/action_view/helpers/record_tag_helper.rb +12 -99
- data/lib/action_view/helpers/rendering_helper.rb +2 -2
- data/lib/action_view/helpers/sanitize_helper.rb +1 -2
- data/lib/action_view/helpers/tag_helper.rb +20 -13
- data/lib/action_view/helpers/tags/base.rb +33 -28
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +2 -30
- data/lib/action_view/helpers/tags/collection_helpers.rb +28 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -9
- data/lib/action_view/helpers/tags/file_field.rb +15 -0
- data/lib/action_view/helpers/tags/label.rb +1 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
- data/lib/action_view/helpers/tags/search_field.rb +12 -9
- data/lib/action_view/helpers/tags/text_field.rb +0 -1
- data/lib/action_view/helpers/tags/translator.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +25 -9
- data/lib/action_view/helpers/translation_helper.rb +56 -26
- data/lib/action_view/helpers/url_helper.rb +40 -65
- data/lib/action_view/layouts.rb +11 -10
- data/lib/action_view/lookup_context.rb +14 -40
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +15 -18
- data/lib/action_view/railtie.rb +20 -3
- data/lib/action_view/record_identifier.rb +44 -19
- data/lib/action_view/renderer/abstract_renderer.rb +1 -1
- data/lib/action_view/renderer/partial_renderer.rb +27 -26
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +70 -0
- data/lib/action_view/renderer/renderer.rb +2 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +1 -1
- data/lib/action_view/renderer/template_renderer.rb +12 -11
- data/lib/action_view/rendering.rb +8 -5
- data/lib/action_view/routing_url_for.rb +18 -6
- data/lib/action_view/template.rb +50 -13
- data/lib/action_view/template/error.rb +14 -7
- data/lib/action_view/template/handlers.rb +3 -3
- data/lib/action_view/template/handlers/erb.rb +25 -0
- data/lib/action_view/template/handlers/raw.rb +1 -1
- data/lib/action_view/template/resolver.rb +36 -58
- data/lib/action_view/template/types.rb +1 -1
- data/lib/action_view/test_case.rb +13 -8
- data/lib/action_view/testing/resolvers.rb +3 -4
- data/lib/action_view/view_paths.rb +6 -22
- metadata +17 -14
@@ -1,108 +1,21 @@
|
|
1
|
-
require 'action_view/record_identifier'
|
2
|
-
|
3
1
|
module ActionView
|
4
|
-
# = Action View Record Tag Helpers
|
5
2
|
module Helpers
|
6
3
|
module RecordTagHelper
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# <%= @person.name %>
|
14
|
-
# <% end %>
|
15
|
-
#
|
16
|
-
# produces:
|
17
|
-
#
|
18
|
-
# <div id="person_123" class="person foo"> Joe Bloggs </div>
|
19
|
-
#
|
20
|
-
# You can also pass an array of Active Record objects, which will then
|
21
|
-
# get iterated over and yield each record as an argument for the block.
|
22
|
-
# For example:
|
23
|
-
#
|
24
|
-
# <%= div_for(@people, class: "foo") do |person| %>
|
25
|
-
# <%= person.name %>
|
26
|
-
# <% end %>
|
27
|
-
#
|
28
|
-
# produces:
|
29
|
-
#
|
30
|
-
# <div id="person_123" class="person foo"> Joe Bloggs </div>
|
31
|
-
# <div id="person_124" class="person foo"> Jane Bloggs </div>
|
32
|
-
#
|
33
|
-
def div_for(record, *args, &block)
|
34
|
-
content_tag_for(:div, record, *args, &block)
|
4
|
+
def div_for(*)
|
5
|
+
raise NoMethodError, "The `div_for` method has been removed from " \
|
6
|
+
"Rails. To continue using it, add the `record_tag_helper` gem to " \
|
7
|
+
"your Gemfile:\n" \
|
8
|
+
" gem 'record_tag_helper', '~> 1.0'\n" \
|
9
|
+
"Consult the Rails upgrade guide for details."
|
35
10
|
end
|
36
11
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
# <% end %>
|
44
|
-
#
|
45
|
-
# would produce the following HTML (assuming @person is an instance of
|
46
|
-
# a Person object, with an id value of 123):
|
47
|
-
#
|
48
|
-
# <tr id="person_123" class="person">....</tr>
|
49
|
-
#
|
50
|
-
# If you require the HTML id attribute to have a prefix, you can specify it:
|
51
|
-
#
|
52
|
-
# <%= content_tag_for(:tr, @person, :foo) do %> ...
|
53
|
-
#
|
54
|
-
# produces:
|
55
|
-
#
|
56
|
-
# <tr id="foo_person_123" class="person">...
|
57
|
-
#
|
58
|
-
# You can also pass an array of objects which this method will loop through
|
59
|
-
# and yield the current object to the supplied block, reducing the need for
|
60
|
-
# having to iterate through the object (using <tt>each</tt>) beforehand.
|
61
|
-
# For example (assuming @people is an array of Person objects):
|
62
|
-
#
|
63
|
-
# <%= content_tag_for(:tr, @people) do |person| %>
|
64
|
-
# <td><%= person.first_name %></td>
|
65
|
-
# <td><%= person.last_name %></td>
|
66
|
-
# <% end %>
|
67
|
-
#
|
68
|
-
# produces:
|
69
|
-
#
|
70
|
-
# <tr id="person_123" class="person">...</tr>
|
71
|
-
# <tr id="person_124" class="person">...</tr>
|
72
|
-
#
|
73
|
-
# content_tag_for also accepts a hash of options, which will be converted to
|
74
|
-
# additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined
|
75
|
-
# with the default class name for your object. For example:
|
76
|
-
#
|
77
|
-
# <%= content_tag_for(:li, @person, class: "bar") %>...
|
78
|
-
#
|
79
|
-
# produces:
|
80
|
-
#
|
81
|
-
# <li id="person_123" class="person bar">...
|
82
|
-
#
|
83
|
-
def content_tag_for(tag_name, single_or_multiple_records, prefix = nil, options = nil, &block)
|
84
|
-
options, prefix = prefix, nil if prefix.is_a?(Hash)
|
85
|
-
|
86
|
-
Array(single_or_multiple_records).map do |single_record|
|
87
|
-
content_tag_for_single_record(tag_name, single_record, prefix, options, &block)
|
88
|
-
end.join("\n").html_safe
|
12
|
+
def content_tag_for(*)
|
13
|
+
raise NoMethodError, "The `content_tag_for` method has been removed from " \
|
14
|
+
"Rails. To continue using it, add the `record_tag_helper` gem to " \
|
15
|
+
"your Gemfile:\n" \
|
16
|
+
" gem 'record_tag_helper', '~> 1.0'\n" \
|
17
|
+
"Consult the Rails upgrade guide for details."
|
89
18
|
end
|
90
|
-
|
91
|
-
private
|
92
|
-
|
93
|
-
# Called by <tt>content_tag_for</tt> internally to render a content tag
|
94
|
-
# for each record.
|
95
|
-
def content_tag_for_single_record(tag_name, record, prefix, options, &block)
|
96
|
-
options = options ? options.dup : {}
|
97
|
-
options[:class] = [ dom_class(record, prefix), options[:class] ].compact
|
98
|
-
options[:id] = dom_id(record, prefix)
|
99
|
-
|
100
|
-
if block_given?
|
101
|
-
content_tag(tag_name, capture(record, &block), options)
|
102
|
-
else
|
103
|
-
content_tag(tag_name, "", options)
|
104
|
-
end
|
105
|
-
end
|
106
19
|
end
|
107
20
|
end
|
108
21
|
end
|
@@ -18,7 +18,7 @@ module ActionView
|
|
18
18
|
# performs HTML escape on the string first. Setting the content type as
|
19
19
|
# <tt>text/html</tt>.
|
20
20
|
# * <tt>:body</tt> - Renders the text passed in, and inherits the content
|
21
|
-
# type of <tt>text/
|
21
|
+
# type of <tt>text/plain</tt> from <tt>ActionDispatch::Response</tt>
|
22
22
|
# object.
|
23
23
|
#
|
24
24
|
# If no options hash is passed or :update specified, the default is to render a partial and use the second parameter
|
@@ -32,7 +32,7 @@ module ActionView
|
|
32
32
|
view_renderer.render(self, options)
|
33
33
|
end
|
34
34
|
else
|
35
|
-
view_renderer.render_partial(self, :partial => options, :locals => locals)
|
35
|
+
view_renderer.render_partial(self, :partial => options, :locals => locals, &block)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'active_support/core_ext/object/try'
|
2
|
-
require 'active_support/deprecation'
|
3
2
|
require 'rails-html-sanitizer'
|
4
3
|
|
5
4
|
module ActionView
|
@@ -121,7 +120,7 @@ module ActionView
|
|
121
120
|
attr_writer :full_sanitizer, :link_sanitizer, :white_list_sanitizer
|
122
121
|
|
123
122
|
# Vendors the full, link and white list sanitizers.
|
124
|
-
# Provided strictly for
|
123
|
+
# Provided strictly for compatibility and can be removed in Rails 5.
|
125
124
|
def sanitizer_vendor
|
126
125
|
Rails::Html::Sanitizer
|
127
126
|
end
|
@@ -18,13 +18,14 @@ module ActionView
|
|
18
18
|
itemscope allowfullscreen default inert sortable
|
19
19
|
truespeed typemustmatch).to_set
|
20
20
|
|
21
|
-
BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map
|
21
|
+
BOOLEAN_ATTRIBUTES.merge(BOOLEAN_ATTRIBUTES.map(&:to_sym))
|
22
22
|
|
23
23
|
TAG_PREFIXES = ['aria', 'data', :aria, :data].to_set
|
24
24
|
|
25
|
-
PRE_CONTENT_STRINGS
|
26
|
-
|
27
|
-
|
25
|
+
PRE_CONTENT_STRINGS = Hash.new { "".freeze }
|
26
|
+
PRE_CONTENT_STRINGS[:textarea] = "\n"
|
27
|
+
PRE_CONTENT_STRINGS["textarea"] = "\n"
|
28
|
+
|
28
29
|
|
29
30
|
# Returns an empty HTML tag of type +name+ which by default is XHTML
|
30
31
|
# compliant. Set +open+ to true to create an open tag compatible
|
@@ -143,24 +144,30 @@ module ActionView
|
|
143
144
|
def content_tag_string(name, content, options, escape = true)
|
144
145
|
tag_options = tag_options(options, escape) if options
|
145
146
|
content = ERB::Util.unwrapped_html_escape(content) if escape
|
146
|
-
"<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name
|
147
|
+
"<#{name}#{tag_options}>#{PRE_CONTENT_STRINGS[name]}#{content}</#{name}>".html_safe
|
147
148
|
end
|
148
149
|
|
149
150
|
def tag_options(options, escape = true)
|
150
151
|
return if options.blank?
|
151
|
-
|
152
|
+
output = ""
|
153
|
+
sep = " ".freeze
|
152
154
|
options.each_pair do |key, value|
|
153
155
|
if TAG_PREFIXES.include?(key) && value.is_a?(Hash)
|
154
156
|
value.each_pair do |k, v|
|
155
|
-
|
157
|
+
output << sep
|
158
|
+
output << prefix_tag_option(key, k, v, escape)
|
156
159
|
end
|
157
160
|
elsif BOOLEAN_ATTRIBUTES.include?(key)
|
158
|
-
|
161
|
+
if value
|
162
|
+
output << sep
|
163
|
+
output << boolean_tag_option(key)
|
164
|
+
end
|
159
165
|
elsif !value.nil?
|
160
|
-
|
166
|
+
output << sep
|
167
|
+
output << tag_option(key, value, escape)
|
161
168
|
end
|
162
169
|
end
|
163
|
-
|
170
|
+
output unless output.empty?
|
164
171
|
end
|
165
172
|
|
166
173
|
def prefix_tag_option(prefix, key, value, escape)
|
@@ -177,11 +184,11 @@ module ActionView
|
|
177
184
|
|
178
185
|
def tag_option(key, value, escape)
|
179
186
|
if value.is_a?(Array)
|
180
|
-
value = escape ? safe_join(value, " ") : value.join(" ")
|
187
|
+
value = escape ? safe_join(value, " ".freeze) : value.join(" ".freeze)
|
181
188
|
else
|
182
|
-
value = escape ? ERB::Util.unwrapped_html_escape(value) : value
|
189
|
+
value = escape ? ERB::Util.unwrapped_html_escape(value) : value
|
183
190
|
end
|
184
|
-
%(#{key}="#{value
|
191
|
+
%(#{key}="#{value}")
|
185
192
|
end
|
186
193
|
end
|
187
194
|
end
|
@@ -14,7 +14,7 @@ module ActionView
|
|
14
14
|
@object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]")
|
15
15
|
@object = retrieve_object(options.delete(:object))
|
16
16
|
@options = options
|
17
|
-
@auto_index = retrieve_autoindex(Regexp.last_match.pre_match)
|
17
|
+
@auto_index = Regexp.last_match ? retrieve_autoindex(Regexp.last_match.pre_match) : nil
|
18
18
|
end
|
19
19
|
|
20
20
|
# This is what child classes implement.
|
@@ -79,35 +79,30 @@ module ActionView
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def add_default_name_and_id(options)
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
options["name"] ||= options.fetch("name"){ tag_name_with_index(@auto_index, options["multiple"]) }
|
88
|
-
options["id"] = options.fetch("id"){ tag_id_with_index(@auto_index) }
|
89
|
-
else
|
90
|
-
options["name"] ||= options.fetch("name"){ tag_name(options["multiple"]) }
|
91
|
-
options["id"] = options.fetch("id"){ tag_id }
|
82
|
+
index = name_and_id_index(options)
|
83
|
+
options["name"] = options.fetch("name"){ tag_name(options["multiple"], index) }
|
84
|
+
options["id"] = options.fetch("id"){ tag_id(index) }
|
85
|
+
if namespace = options.delete("namespace")
|
86
|
+
options['id'] = options['id'] ? "#{namespace}_#{options['id']}" : namespace
|
92
87
|
end
|
93
|
-
|
94
|
-
options["id"] = [options.delete('namespace'), options["id"]].compact.join("_").presence
|
95
|
-
end
|
96
|
-
|
97
|
-
def tag_name(multiple = false)
|
98
|
-
"#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
|
99
88
|
end
|
100
89
|
|
101
|
-
def
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
90
|
+
def tag_name(multiple = false, index = nil)
|
91
|
+
# a little duplication to construct less strings
|
92
|
+
if index
|
93
|
+
"#{@object_name}[#{index}][#{sanitized_method_name}]#{"[]" if multiple}"
|
94
|
+
else
|
95
|
+
"#{@object_name}[#{sanitized_method_name}]#{"[]" if multiple}"
|
96
|
+
end
|
107
97
|
end
|
108
98
|
|
109
|
-
def
|
110
|
-
|
99
|
+
def tag_id(index = nil)
|
100
|
+
# a little duplication to construct less strings
|
101
|
+
if index
|
102
|
+
"#{sanitized_object_name}_#{index}_#{sanitized_method_name}"
|
103
|
+
else
|
104
|
+
"#{sanitized_object_name}_#{sanitized_method_name}"
|
105
|
+
end
|
111
106
|
end
|
112
107
|
|
113
108
|
def sanitized_object_name
|
@@ -125,7 +120,12 @@ module ActionView
|
|
125
120
|
def select_content_tag(option_tags, options, html_options)
|
126
121
|
html_options = html_options.stringify_keys
|
127
122
|
add_default_name_and_id(html_options)
|
128
|
-
|
123
|
+
|
124
|
+
if placeholder_required?(html_options)
|
125
|
+
raise ArgumentError, "include_blank cannot be false for a required field." if options[:include_blank] == false
|
126
|
+
options[:include_blank] ||= true unless options[:prompt]
|
127
|
+
end
|
128
|
+
|
129
129
|
value = options.fetch(:selected) { value(object) }
|
130
130
|
select = content_tag("select", add_options(option_tags, options, value), html_options)
|
131
131
|
|
@@ -136,8 +136,9 @@ module ActionView
|
|
136
136
|
end
|
137
137
|
end
|
138
138
|
|
139
|
-
def
|
140
|
-
|
139
|
+
def placeholder_required?(html_options)
|
140
|
+
# See https://html.spec.whatwg.org/multipage/forms.html#attr-select-required
|
141
|
+
html_options["required"] && !html_options["multiple"] && html_options.fetch("size", 1).to_i == 1
|
141
142
|
end
|
142
143
|
|
143
144
|
def add_options(option_tags, options, value = nil)
|
@@ -149,6 +150,10 @@ module ActionView
|
|
149
150
|
end
|
150
151
|
option_tags
|
151
152
|
end
|
153
|
+
|
154
|
+
def name_and_id_index(options)
|
155
|
+
options.key?("index") ? options.delete("index") || "" : @auto_index
|
156
|
+
end
|
152
157
|
end
|
153
158
|
end
|
154
159
|
end
|
@@ -9,29 +9,13 @@ module ActionView
|
|
9
9
|
class CheckBoxBuilder < Builder # :nodoc:
|
10
10
|
def check_box(extra_html_options={})
|
11
11
|
html_options = extra_html_options.merge(@input_html_options)
|
12
|
+
html_options[:multiple] = true
|
12
13
|
@template_object.check_box(@object_name, @method_name, html_options, @value, nil)
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
17
|
def render(&block)
|
17
|
-
|
18
|
-
default_html_options[:multiple] = true
|
19
|
-
builder = instantiate_builder(CheckBoxBuilder, item, value, text, default_html_options)
|
20
|
-
|
21
|
-
if block_given?
|
22
|
-
@template_object.capture(builder, &block)
|
23
|
-
else
|
24
|
-
render_component(builder)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# Append a hidden field to make sure something will be sent back to the
|
29
|
-
# server if all check boxes are unchecked.
|
30
|
-
if @options.fetch(:include_hidden, true)
|
31
|
-
rendered_collection + hidden_field
|
32
|
-
else
|
33
|
-
rendered_collection
|
34
|
-
end
|
18
|
+
render_collection_for(CheckBoxBuilder, &block)
|
35
19
|
end
|
36
20
|
|
37
21
|
private
|
@@ -39,18 +23,6 @@ module ActionView
|
|
39
23
|
def render_component(builder)
|
40
24
|
builder.check_box + builder.label
|
41
25
|
end
|
42
|
-
|
43
|
-
def hidden_field
|
44
|
-
hidden_name = @html_options[:name]
|
45
|
-
|
46
|
-
hidden_name ||= if @options.has_key?(:index)
|
47
|
-
"#{tag_name_with_index(@options[:index])}[]"
|
48
|
-
else
|
49
|
-
"#{tag_name}[]"
|
50
|
-
end
|
51
|
-
|
52
|
-
@template_object.hidden_field_tag(hidden_name, "", id: nil)
|
53
|
-
end
|
54
26
|
end
|
55
27
|
end
|
56
28
|
end
|
@@ -19,6 +19,8 @@ module ActionView
|
|
19
19
|
|
20
20
|
def label(label_html_options={}, &block)
|
21
21
|
html_options = @input_html_options.slice(:index, :namespace).merge(label_html_options)
|
22
|
+
html_options[:for] ||= @input_html_options[:id] if @input_html_options[:id]
|
23
|
+
|
22
24
|
@template_object.label(@object_name, @sanitized_attribute_name, @text, html_options, &block)
|
23
25
|
end
|
24
26
|
end
|
@@ -79,6 +81,32 @@ module ActionView
|
|
79
81
|
yield item, value, text, default_html_options.merge(additional_html_options)
|
80
82
|
end.join.html_safe
|
81
83
|
end
|
84
|
+
|
85
|
+
def render_collection_for(builder_class, &block) #:nodoc:
|
86
|
+
options = @options.stringify_keys
|
87
|
+
rendered_collection = render_collection do |item, value, text, default_html_options|
|
88
|
+
builder = instantiate_builder(builder_class, item, value, text, default_html_options)
|
89
|
+
|
90
|
+
if block_given?
|
91
|
+
@template_object.capture(builder, &block)
|
92
|
+
else
|
93
|
+
render_component(builder)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Append a hidden field to make sure something will be sent back to the
|
98
|
+
# server if all radio buttons are unchecked.
|
99
|
+
if options.fetch('include_hidden', true)
|
100
|
+
rendered_collection + hidden_field
|
101
|
+
else
|
102
|
+
rendered_collection
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def hidden_field #:nodoc:
|
107
|
+
hidden_name = @html_options[:name] || "#{tag_name(false, @options[:index])}[]"
|
108
|
+
@template_object.hidden_field_tag(hidden_name, "", id: nil)
|
109
|
+
end
|
82
110
|
end
|
83
111
|
end
|
84
112
|
end
|
@@ -14,15 +14,7 @@ module ActionView
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def render(&block)
|
17
|
-
|
18
|
-
builder = instantiate_builder(RadioButtonBuilder, item, value, text, default_html_options)
|
19
|
-
|
20
|
-
if block_given?
|
21
|
-
@template_object.capture(builder, &block)
|
22
|
-
else
|
23
|
-
render_component(builder)
|
24
|
-
end
|
25
|
-
end
|
17
|
+
render_collection_for(RadioButtonBuilder, &block)
|
26
18
|
end
|
27
19
|
|
28
20
|
private
|
@@ -2,6 +2,21 @@ module ActionView
|
|
2
2
|
module Helpers
|
3
3
|
module Tags # :nodoc:
|
4
4
|
class FileField < TextField # :nodoc:
|
5
|
+
|
6
|
+
def render
|
7
|
+
options = @options.stringify_keys
|
8
|
+
|
9
|
+
if options.fetch("include_hidden", true)
|
10
|
+
add_default_name_and_id(options)
|
11
|
+
options[:type] = "file"
|
12
|
+
tag("input", name: options["name"], type: "hidden", value: "") + tag("input", options)
|
13
|
+
else
|
14
|
+
options.delete("include_hidden")
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
5
20
|
end
|
6
21
|
end
|
7
22
|
end
|