actionview 4.2.11 → 5.0.7

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.

Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +304 -184
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +2 -3
  5. data/lib/action_view.rb +1 -1
  6. data/lib/action_view/base.rb +14 -2
  7. data/lib/action_view/dependency_tracker.rb +51 -18
  8. data/lib/action_view/digestor.rb +83 -81
  9. data/lib/action_view/flows.rb +4 -5
  10. data/lib/action_view/gem_version.rb +3 -3
  11. data/lib/action_view/helpers/asset_tag_helper.rb +15 -5
  12. data/lib/action_view/helpers/asset_url_helper.rb +51 -12
  13. data/lib/action_view/helpers/atom_feed_helper.rb +6 -5
  14. data/lib/action_view/helpers/cache_helper.rb +62 -21
  15. data/lib/action_view/helpers/capture_helper.rb +5 -4
  16. data/lib/action_view/helpers/controller_helper.rb +11 -2
  17. data/lib/action_view/helpers/date_helper.rb +59 -13
  18. data/lib/action_view/helpers/debug_helper.rb +1 -1
  19. data/lib/action_view/helpers/form_helper.rb +74 -72
  20. data/lib/action_view/helpers/form_options_helper.rb +79 -39
  21. data/lib/action_view/helpers/form_tag_helper.rb +74 -44
  22. data/lib/action_view/helpers/javascript_helper.rb +4 -4
  23. data/lib/action_view/helpers/number_helper.rb +28 -13
  24. data/lib/action_view/helpers/output_safety_helper.rb +32 -2
  25. data/lib/action_view/helpers/record_tag_helper.rb +12 -99
  26. data/lib/action_view/helpers/rendering_helper.rb +2 -2
  27. data/lib/action_view/helpers/sanitize_helper.rb +1 -2
  28. data/lib/action_view/helpers/tag_helper.rb +19 -11
  29. data/lib/action_view/helpers/tags/base.rb +45 -29
  30. data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -28
  31. data/lib/action_view/helpers/tags/collection_helpers.rb +32 -0
  32. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -9
  33. data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
  34. data/lib/action_view/helpers/tags/label.rb +1 -1
  35. data/lib/action_view/helpers/tags/placeholderable.rb +1 -1
  36. data/lib/action_view/helpers/tags/search_field.rb +12 -9
  37. data/lib/action_view/helpers/tags/text_field.rb +0 -1
  38. data/lib/action_view/helpers/tags/translator.rb +1 -1
  39. data/lib/action_view/helpers/text_helper.rb +27 -11
  40. data/lib/action_view/helpers/translation_helper.rb +56 -26
  41. data/lib/action_view/helpers/url_helper.rb +108 -79
  42. data/lib/action_view/layouts.rb +11 -10
  43. data/lib/action_view/log_subscriber.rb +35 -1
  44. data/lib/action_view/lookup_context.rb +69 -48
  45. data/lib/action_view/model_naming.rb +1 -1
  46. data/lib/action_view/path_set.rb +9 -0
  47. data/lib/action_view/railtie.rb +18 -3
  48. data/lib/action_view/record_identifier.rb +45 -19
  49. data/lib/action_view/renderer/abstract_renderer.rb +7 -3
  50. data/lib/action_view/renderer/partial_renderer.rb +38 -37
  51. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +49 -0
  52. data/lib/action_view/renderer/renderer.rb +2 -6
  53. data/lib/action_view/renderer/streaming_template_renderer.rb +1 -1
  54. data/lib/action_view/renderer/template_renderer.rb +11 -10
  55. data/lib/action_view/rendering.rb +15 -7
  56. data/lib/action_view/routing_url_for.rb +18 -6
  57. data/lib/action_view/tasks/{dependencies.rake → cache_digests.rake} +2 -2
  58. data/lib/action_view/template.rb +36 -12
  59. data/lib/action_view/template/error.rb +20 -9
  60. data/lib/action_view/template/handlers.rb +6 -4
  61. data/lib/action_view/template/handlers/html.rb +9 -0
  62. data/lib/action_view/template/handlers/raw.rb +1 -3
  63. data/lib/action_view/template/resolver.rb +49 -42
  64. data/lib/action_view/template/types.rb +14 -16
  65. data/lib/action_view/test_case.rb +15 -9
  66. data/lib/action_view/testing/resolvers.rb +1 -2
  67. data/lib/action_view/view_paths.rb +6 -24
  68. metadata +16 -20
@@ -2,13 +2,13 @@ namespace :cache_digests do
2
2
  desc 'Lookup nested dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
3
3
  task :nested_dependencies => :environment do
4
4
  abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
5
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).nested_dependencies
5
+ puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:to_dep_map)
6
6
  end
7
7
 
8
8
  desc 'Lookup first-level dependencies for TEMPLATE (like messages/show or comments/_comment.html)'
9
9
  task :dependencies => :environment do
10
10
  abort 'You must provide TEMPLATE for the task to run' unless ENV['TEMPLATE'].present?
11
- puts JSON.pretty_generate ActionView::Digestor.new(name: CacheDigests.template_name, finder: CacheDigests.finder).dependencies
11
+ puts JSON.pretty_generate ActionView::Digestor.tree(CacheDigests.template_name, CacheDigests.finder).children.map(&:name)
12
12
  end
13
13
 
14
14
  class CacheDigests
@@ -1,6 +1,7 @@
1
- require 'active_support/core_ext/object/try'
2
- require 'active_support/core_ext/kernel/singleton_class'
3
- require 'thread'
1
+ require "active_support/core_ext/object/try"
2
+ require "active_support/core_ext/kernel/singleton_class"
3
+ require "active_support/core_ext/module/delegation"
4
+ require "thread"
4
5
 
5
6
  module ActionView
6
7
  # = Action View Template
@@ -87,6 +88,19 @@ module ActionView
87
88
  # expected_encoding
88
89
  # )
89
90
 
91
+ ##
92
+ # :method: local_assigns
93
+ #
94
+ # Returns a hash with the defined local variables.
95
+ #
96
+ # Given this sub template rendering:
97
+ #
98
+ # <%= render "shared/header", { headline: "Welcome", person: person } %>
99
+ #
100
+ # You can use +local_assigns+ in the sub templates to access the local variables:
101
+ #
102
+ # local_assigns[:headline] # => "Welcome"
103
+
90
104
  eager_autoload do
91
105
  autoload :Error
92
106
  autoload :Handlers
@@ -103,7 +117,7 @@ module ActionView
103
117
 
104
118
  # This finalizer is needed (and exactly with a proc inside another proc)
105
119
  # otherwise templates leak in development.
106
- Finalizer = proc do |method_name, mod|
120
+ Finalizer = proc do |method_name, mod| # :nodoc:
107
121
  proc do
108
122
  mod.module_eval do
109
123
  remove_possible_method method_name
@@ -127,7 +141,7 @@ module ActionView
127
141
  @compile_mutex = Mutex.new
128
142
  end
129
143
 
130
- # Returns if the underlying handler supports streaming. If so,
144
+ # Returns whether the underlying handler supports streaming. If so,
131
145
  # a streaming buffer *may* be passed when it start rendering.
132
146
  def supports_streaming?
133
147
  handler.respond_to?(:supports_streaming?) && handler.supports_streaming?
@@ -140,7 +154,7 @@ module ActionView
140
154
  # we use a bang in this instrumentation because you don't want to
141
155
  # consume this in production. This is only slow if it's being listened to.
142
156
  def render(view, locals, buffer=nil, &block)
143
- instrument("!render_template") do
157
+ instrument("!render_template".freeze) do
144
158
  compile!(view)
145
159
  view.send(method_name, locals, buffer, &block)
146
160
  end
@@ -172,7 +186,7 @@ module ActionView
172
186
  end
173
187
 
174
188
  def inspect
175
- @inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", '') : identifier
189
+ @inspect ||= defined?(Rails.root) ? identifier.sub("#{Rails.root}/", ''.freeze) : identifier
176
190
  end
177
191
 
178
192
  # This method is responsible for properly setting the encoding of the
@@ -307,30 +321,40 @@ module ActionView
307
321
  template = refresh(view)
308
322
  template.encode!
309
323
  end
310
- raise Template::Error.new(template, e)
324
+ raise Template::Error.new(template)
311
325
  end
312
326
  end
313
327
 
314
328
  def locals_code #:nodoc:
329
+ # Only locals with valid variable names get set directly. Others will
330
+ # still be available in local_assigns.
331
+ locals = @locals - Module::RUBY_RESERVED_KEYWORDS
332
+ locals = locals.grep(/\A@?(?![A-Z0-9])(?:[[:alnum:]_]|[^\0-\177])+\z/)
333
+
315
334
  # Double assign to suppress the dreaded 'assigned but unused variable' warning
316
- @locals.each_with_object('') { |key, code| code << "#{key} = #{key} = local_assigns[:#{key}];" }
335
+ locals.each_with_object("") { |key, code| code << "#{key} = #{key} = local_assigns[:#{key}];" }
317
336
  end
318
337
 
319
338
  def method_name #:nodoc:
320
339
  @method_name ||= begin
321
340
  m = "_#{identifier_method_name}__#{@identifier.hash}_#{__id__}"
322
- m.tr!('-', '_')
341
+ m.tr!('-'.freeze, '_'.freeze)
323
342
  m
324
343
  end
325
344
  end
326
345
 
327
346
  def identifier_method_name #:nodoc:
328
- inspect.tr('^a-z_', '_')
347
+ inspect.tr('^a-z_'.freeze, '_'.freeze)
329
348
  end
330
349
 
331
350
  def instrument(action, &block)
332
351
  payload = { virtual_path: @virtual_path, identifier: @identifier }
333
- ActiveSupport::Notifications.instrument("#{action}.action_view", payload, &block)
352
+ case action
353
+ when "!render_template".freeze
354
+ ActiveSupport::Notifications.instrument("!render_template.action_view".freeze, payload, &block)
355
+ else
356
+ ActiveSupport::Notifications.instrument("#{action}.action_view".freeze, payload, &block)
357
+ end
334
358
  end
335
359
  end
336
360
  end
@@ -59,13 +59,24 @@ module ActionView
59
59
  class Error < ActionViewError #:nodoc:
60
60
  SOURCE_CODE_RADIUS = 3
61
61
 
62
- attr_reader :original_exception
62
+ # Override to prevent #cause resetting during re-raise.
63
+ attr_reader :cause
63
64
 
64
- def initialize(template, original_exception)
65
- super(original_exception.message)
66
- @template, @original_exception = template, original_exception
67
- @sub_templates = nil
68
- set_backtrace(original_exception.backtrace)
65
+ def initialize(template, original_exception = nil)
66
+ if original_exception
67
+ ActiveSupport::Deprecation.warn("Passing #original_exception is deprecated and has no effect. " \
68
+ "Exceptions will automatically capture the original exception.", caller)
69
+ end
70
+
71
+ super($!.message)
72
+ set_backtrace($!.backtrace)
73
+ @cause = $!
74
+ @template, @sub_templates = template, nil
75
+ end
76
+
77
+ def original_exception
78
+ ActiveSupport::Deprecation.warn("#original_exception is deprecated. Use #cause instead.", caller)
79
+ cause
69
80
  end
70
81
 
71
82
  def file_name
@@ -75,7 +86,7 @@ module ActionView
75
86
  def sub_template_message
76
87
  if @sub_templates
77
88
  "Trace of template inclusion: " +
78
- @sub_templates.collect { |template| template.inspect }.join(", ")
89
+ @sub_templates.collect(&:inspect).join(", ")
79
90
  else
80
91
  ""
81
92
  end
@@ -124,13 +135,13 @@ module ActionView
124
135
  end
125
136
 
126
137
  def formatted_code_for(source_code, line_counter, indent, output)
127
- start_value = (output == :html) ? {} : ""
138
+ start_value = (output == :html) ? {} : []
128
139
  source_code.inject(start_value) do |result, line|
129
140
  line_counter += 1
130
141
  if output == :html
131
142
  result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
132
143
  else
133
- result << "%#{indent}s: %s\n" % [line_counter, line]
144
+ result << "%#{indent}s: %s" % [line_counter, line]
134
145
  end
135
146
  end
136
147
  end
@@ -2,14 +2,16 @@ module ActionView #:nodoc:
2
2
  # = Action View Template Handlers
3
3
  class Template
4
4
  module Handlers #:nodoc:
5
+ autoload :Raw, 'action_view/template/handlers/raw'
5
6
  autoload :ERB, 'action_view/template/handlers/erb'
7
+ autoload :Html, 'action_view/template/handlers/html'
6
8
  autoload :Builder, 'action_view/template/handlers/builder'
7
- autoload :Raw, 'action_view/template/handlers/raw'
8
9
 
9
10
  def self.extended(base)
10
- base.register_default_template_handler :erb, ERB.new
11
+ base.register_default_template_handler :raw, Raw.new
12
+ base.register_template_handler :erb, ERB.new
13
+ base.register_template_handler :html, Html.new
11
14
  base.register_template_handler :builder, Builder.new
12
- base.register_template_handler :raw, Raw.new
13
15
  base.register_template_handler :ruby, :source.to_proc
14
16
  end
15
17
 
@@ -42,7 +44,7 @@ module ActionView #:nodoc:
42
44
  end
43
45
 
44
46
  def template_handler_extensions
45
- @@template_handlers.keys.map {|key| key.to_s }.sort
47
+ @@template_handlers.keys.map(&:to_s).sort
46
48
  end
47
49
 
48
50
  def registered_template_handler(extension)
@@ -0,0 +1,9 @@
1
+ module ActionView
2
+ module Template::Handlers
3
+ class Html < Raw
4
+ def call(template)
5
+ "ActionView::OutputBuffer.new #{super}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -2,9 +2,7 @@ module ActionView
2
2
  module Template::Handlers
3
3
  class Raw
4
4
  def call(template)
5
- escaped = template.source.gsub(/:/, '\:')
6
-
7
- '%q:' + escaped + ':;'
5
+ "#{template.source.inspect}.html_safe;"
8
6
  end
9
7
  end
10
8
  end
@@ -1,10 +1,9 @@
1
1
  require "pathname"
2
2
  require "active_support/core_ext/class"
3
3
  require "active_support/core_ext/module/attribute_accessors"
4
- require 'active_support/core_ext/string/filters'
5
4
  require "action_view/template"
6
5
  require "thread"
7
- require "thread_safe"
6
+ require "concurrent/map"
8
7
 
9
8
  module ActionView
10
9
  # = Action View Resolver
@@ -36,7 +35,7 @@ module ActionView
36
35
 
37
36
  # Threadsafe template cache
38
37
  class Cache #:nodoc:
39
- class SmallCache < ThreadSafe::Cache
38
+ class SmallCache < Concurrent::Map
40
39
  def initialize(options = {})
41
40
  super(options.merge(:initial_capacity => 2))
42
41
  end
@@ -53,6 +52,11 @@ module ActionView
53
52
 
54
53
  def initialize
55
54
  @data = SmallCache.new(&KEY_BLOCK)
55
+ @query_cache = SmallCache.new
56
+ end
57
+
58
+ def inspect
59
+ "#<#{self.class.name}:0x#{(object_id << 1).to_s(16)} keys=#{@data.size} queries=#{@query_cache.size}>"
56
60
  end
57
61
 
58
62
  # Cache the templates returned by the block
@@ -71,8 +75,17 @@ module ActionView
71
75
  end
72
76
  end
73
77
 
78
+ def cache_query(query) # :nodoc:
79
+ if Resolver.caching?
80
+ @query_cache[query] ||= canonical_no_templates(yield)
81
+ else
82
+ yield
83
+ end
84
+ end
85
+
74
86
  def clear
75
87
  @data.clear
88
+ @query_cache.clear
76
89
  end
77
90
 
78
91
  private
@@ -113,7 +126,7 @@ module ActionView
113
126
  # Normalizes the arguments and passes it on to find_templates.
114
127
  def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
115
128
  cached(key, [name, prefix, partial], details, locals) do
116
- find_templates(name, prefix, partial, details, false)
129
+ find_templates(name, prefix, partial, details)
117
130
  end
118
131
  end
119
132
 
@@ -123,6 +136,10 @@ module ActionView
123
136
  end
124
137
  end
125
138
 
139
+ def find_all_with_query(query) # :nodoc:
140
+ @cache.cache_query(query) { find_template_paths(File.join(@path, query)) }
141
+ end
142
+
126
143
  private
127
144
 
128
145
  delegate :caching?, to: :class
@@ -130,8 +147,8 @@ module ActionView
130
147
  # This is what child classes implement. No defaults are needed
131
148
  # because Resolver guarantees that the arguments are present and
132
149
  # normalized.
133
- def find_templates(name, prefix, partial, details, outside_app_allowed)
134
- raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed) method"
150
+ def find_templates(name, prefix, partial, details, outside_app_allowed = false)
151
+ raise NotImplementedError, "Subclasses must implement a find_templates(name, prefix, partial, details, outside_app_allowed = false) method"
135
152
  end
136
153
 
137
154
  # Helpers that builds a path. Useful for building virtual paths.
@@ -145,7 +162,7 @@ module ActionView
145
162
  # resolver is fresher before returning it.
146
163
  def cached(key, path_info, details, locals) #:nodoc:
147
164
  name, prefix, partial = path_info
148
- locals = locals.map { |x| x.to_s }.sort!
165
+ locals = locals.map(&:to_s).sort!
149
166
 
150
167
  if key
151
168
  @cache.cache(key, name, prefix, partial, locals) do
@@ -188,10 +205,10 @@ module ActionView
188
205
  def query(path, details, formats, outside_app_allowed)
189
206
  query = build_query(path, details)
190
207
 
191
- template_paths = find_template_paths query
208
+ template_paths = find_template_paths(query)
192
209
  template_paths = reject_files_external_to_app(template_paths) unless outside_app_allowed
193
210
 
194
- template_paths.map { |template|
211
+ template_paths.map do |template|
195
212
  handler, format, variant = extract_handler_and_format_and_variant(template, formats)
196
213
  contents = File.binread(template)
197
214
 
@@ -201,30 +218,18 @@ module ActionView
201
218
  :variant => variant,
202
219
  :updated_at => mtime(template)
203
220
  )
204
- }
221
+ end
205
222
  end
206
223
 
207
224
  def reject_files_external_to_app(files)
208
225
  files.reject { |filename| !inside_path?(@path, filename) }
209
226
  end
210
227
 
211
- if RUBY_VERSION >= '2.2.0'
212
- def find_template_paths(query)
213
- Dir[query].reject { |filename|
214
- File.directory?(filename) ||
215
- # deals with case-insensitive file systems.
216
- !File.fnmatch(query, filename, File::FNM_EXTGLOB)
217
- }
218
- end
219
- else
220
- def find_template_paths(query)
221
- # deals with case-insensitive file systems.
222
- sanitizer = Hash.new { |h,dir| h[dir] = Dir["#{dir}/*"] }
223
-
224
- Dir[query].reject { |filename|
225
- File.directory?(filename) ||
226
- !sanitizer[File.dirname(filename)].include?(filename)
227
- }
228
+ def find_template_paths(query)
229
+ Dir[query].uniq.reject do |filename|
230
+ File.directory?(filename) ||
231
+ # deals with case-insensitive file systems.
232
+ !File.fnmatch(query, filename, File::FNM_EXTGLOB)
228
233
  end
229
234
  end
230
235
 
@@ -238,21 +243,25 @@ module ActionView
238
243
  def build_query(path, details)
239
244
  query = @pattern.dup
240
245
 
241
- prefix = path.prefix.empty? ? "" : "#{escape_entry(path.prefix)}\\1"
242
- query.gsub!(/\:prefix(\/)?/, prefix)
246
+ prefix = path.prefix.empty? ? '' : "#{escape_entry(path.prefix)}\\1"
247
+ query.gsub!(/:prefix(\/)?/, prefix)
243
248
 
244
249
  partial = escape_entry(path.partial? ? "_#{path.name}" : path.name)
245
- query.gsub!(/\:action/, partial)
250
+ query.gsub!(/:action/, partial)
246
251
 
247
- details.each do |ext, variants|
248
- query.gsub!(/\:#{ext}/, "{#{variants.compact.uniq.join(',')}}")
252
+ details.each do |ext, candidates|
253
+ if ext == :variants && candidates == :any
254
+ query.gsub!(/:#{ext}/, "*")
255
+ else
256
+ query.gsub!(/:#{ext}/, "{#{candidates.compact.uniq.join(',')}}")
257
+ end
249
258
  end
250
259
 
251
260
  File.expand_path(query, @path)
252
261
  end
253
262
 
254
263
  def escape_entry(entry)
255
- entry.gsub(/[*?{}\[\]]/, '\\\\\\&')
264
+ entry.gsub(/[*?{}\[\]]/, '\\\\\\&'.freeze)
256
265
  end
257
266
 
258
267
  # Returns the file mtime from the filesystem.
@@ -264,16 +273,10 @@ module ActionView
264
273
  # from the path, or the handler, we should return the array of formats given
265
274
  # to the resolver.
266
275
  def extract_handler_and_format_and_variant(path, default_formats)
267
- pieces = File.basename(path).split(".")
276
+ pieces = File.basename(path).split('.'.freeze)
268
277
  pieces.shift
269
278
 
270
279
  extension = pieces.pop
271
- unless extension
272
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
273
- The file #{path} did not specify a template handler. The default is
274
- currently ERB, but will change to RAW in the future.
275
- MSG
276
- end
277
280
 
278
281
  handler = Template.handler_for_extension(extension)
279
282
  format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
@@ -306,7 +309,7 @@ module ActionView
306
309
  #
307
310
  # ActionController::Base.view_paths = FileSystemResolver.new(
308
311
  # Rails.root.join("app/views"),
309
- # ":prefix{/:locale}/:action{.:formats,}{+:variants,}{.:handlers,}"
312
+ # ":prefix/:action{.:locale,}{.:formats,}{+:variants,}{.:handlers,}",
310
313
  # )
311
314
  #
312
315
  # ==== Pattern format and variables
@@ -345,7 +348,11 @@ module ActionView
345
348
  query = escape_entry(File.join(@path, path))
346
349
 
347
350
  exts = EXTENSIONS.map do |ext, prefix|
348
- "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
351
+ if ext == :variants && details[ext] == :any
352
+ "{#{prefix}*,}"
353
+ else
354
+ "{#{details[ext].compact.uniq.map { |e| "#{prefix}#{e}," }.join}}"
355
+ end
349
356
  end.join
350
357
 
351
358
  query + exts
@@ -1,23 +1,15 @@
1
- require 'set'
2
1
  require 'active_support/core_ext/module/attribute_accessors'
3
2
 
4
3
  module ActionView
5
4
  class Template
6
5
  class Types
7
6
  class Type
8
- cattr_accessor :types
9
- self.types = Set.new
10
-
11
- def self.register(*t)
12
- types.merge(t.map { |type| type.to_s })
13
- end
14
-
15
- register :html, :text, :js, :css, :xml, :json
7
+ SET = Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
16
8
 
17
9
  def self.[](type)
18
- return type if type.is_a?(self)
19
-
20
- if type.is_a?(Symbol) || types.member?(type.to_s)
10
+ if type.is_a?(self)
11
+ type
12
+ else
21
13
  new(type)
22
14
  end
23
15
  end
@@ -28,16 +20,18 @@ module ActionView
28
20
  @symbol = symbol.to_sym
29
21
  end
30
22
 
31
- delegate :to_s, :to_sym, :to => :symbol
23
+ def to_s
24
+ @symbol.to_s
25
+ end
32
26
  alias to_str to_s
33
27
 
34
28
  def ref
35
- to_sym || to_s
29
+ @symbol
36
30
  end
31
+ alias to_sym ref
37
32
 
38
33
  def ==(type)
39
- return false if type.blank?
40
- symbol.to_sym == type.to_sym
34
+ @symbol == type.to_sym unless type.blank?
41
35
  end
42
36
  end
43
37
 
@@ -52,6 +46,10 @@ module ActionView
52
46
  def self.[](type)
53
47
  type_klass[type]
54
48
  end
49
+
50
+ def self.symbols
51
+ type_klass::SET.symbols
52
+ end
55
53
  end
56
54
  end
57
55
  end