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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +304 -184
- 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 +51 -18
- data/lib/action_view/digestor.rb +83 -81
- data/lib/action_view/flows.rb +4 -5
- data/lib/action_view/gem_version.rb +3 -3
- 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 +6 -5
- data/lib/action_view/helpers/cache_helper.rb +62 -21
- data/lib/action_view/helpers/capture_helper.rb +5 -4
- data/lib/action_view/helpers/controller_helper.rb +11 -2
- data/lib/action_view/helpers/date_helper.rb +59 -13
- data/lib/action_view/helpers/debug_helper.rb +1 -1
- data/lib/action_view/helpers/form_helper.rb +74 -72
- data/lib/action_view/helpers/form_options_helper.rb +79 -39
- data/lib/action_view/helpers/form_tag_helper.rb +74 -44
- data/lib/action_view/helpers/javascript_helper.rb +4 -4
- data/lib/action_view/helpers/number_helper.rb +28 -13
- data/lib/action_view/helpers/output_safety_helper.rb +32 -2
- 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 +19 -11
- data/lib/action_view/helpers/tags/base.rb +45 -29
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +4 -28
- data/lib/action_view/helpers/tags/collection_helpers.rb +32 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +1 -9
- data/lib/action_view/helpers/tags/datetime_field.rb +1 -1
- 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 +27 -11
- data/lib/action_view/helpers/translation_helper.rb +56 -26
- data/lib/action_view/helpers/url_helper.rb +108 -79
- data/lib/action_view/layouts.rb +11 -10
- data/lib/action_view/log_subscriber.rb +35 -1
- data/lib/action_view/lookup_context.rb +69 -48
- data/lib/action_view/model_naming.rb +1 -1
- data/lib/action_view/path_set.rb +9 -0
- data/lib/action_view/railtie.rb +18 -3
- data/lib/action_view/record_identifier.rb +45 -19
- data/lib/action_view/renderer/abstract_renderer.rb +7 -3
- data/lib/action_view/renderer/partial_renderer.rb +38 -37
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +49 -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 +11 -10
- data/lib/action_view/rendering.rb +15 -7
- data/lib/action_view/routing_url_for.rb +18 -6
- data/lib/action_view/tasks/{dependencies.rake → cache_digests.rake} +2 -2
- data/lib/action_view/template.rb +36 -12
- data/lib/action_view/template/error.rb +20 -9
- data/lib/action_view/template/handlers.rb +6 -4
- data/lib/action_view/template/handlers/html.rb +9 -0
- data/lib/action_view/template/handlers/raw.rb +1 -3
- data/lib/action_view/template/resolver.rb +49 -42
- data/lib/action_view/template/types.rb +14 -16
- data/lib/action_view/test_case.rb +15 -9
- data/lib/action_view/testing/resolvers.rb +1 -2
- data/lib/action_view/view_paths.rb +6 -24
- metadata +16 -20
data/MIT-LICENSE
CHANGED
data/README.rdoc
CHANGED
@@ -9,11 +9,11 @@ used to inline short Ruby snippets inside HTML), and XML Builder.
|
|
9
9
|
|
10
10
|
The latest version of Action View can be installed with RubyGems:
|
11
11
|
|
12
|
-
|
12
|
+
$ gem install actionview
|
13
13
|
|
14
14
|
Source code can be downloaded as part of the Rails project on GitHub
|
15
15
|
|
16
|
-
* https://github.com/rails/rails/tree/
|
16
|
+
* https://github.com/rails/rails/tree/5-0-stable/actionview
|
17
17
|
|
18
18
|
|
19
19
|
== License
|
@@ -36,4 +36,3 @@ Bug reports can be filed for the Ruby on Rails project here:
|
|
36
36
|
Feature requests should be discussed on the rails-core mailing list here:
|
37
37
|
|
38
38
|
* https://groups.google.com/forum/?fromgroups#!forum/rubyonrails-core
|
39
|
-
|
data/lib/action_view.rb
CHANGED
data/lib/action_view/base.rb
CHANGED
@@ -70,6 +70,14 @@ module ActionView #:nodoc:
|
|
70
70
|
# Headline: <%= headline %>
|
71
71
|
# First name: <%= person.first_name %>
|
72
72
|
#
|
73
|
+
# The local variables passed to sub templates can be accessed as a hash using the <tt>local_assigns</tt> hash. This lets you access the
|
74
|
+
# variables as:
|
75
|
+
#
|
76
|
+
# Headline: <%= local_assigns[:headline] %>
|
77
|
+
#
|
78
|
+
# This is useful in cases where you aren't sure if the local variable has been assigned. Alternatively, you could also use
|
79
|
+
# <tt>defined? headline</tt> to first check if the variable has been assigned before using it.
|
80
|
+
#
|
73
81
|
# === Template caching
|
74
82
|
#
|
75
83
|
# By default, Rails will compile each template to a method in order to render it. When you alter a template,
|
@@ -126,8 +134,8 @@ module ActionView #:nodoc:
|
|
126
134
|
# end
|
127
135
|
# end
|
128
136
|
#
|
129
|
-
# For more information on Builder please consult the
|
130
|
-
# code
|
137
|
+
# For more information on Builder please consult the {source
|
138
|
+
# code}[https://github.com/jimweirich/builder].
|
131
139
|
class Base
|
132
140
|
include Helpers, ::ERB::Util, Context
|
133
141
|
|
@@ -153,6 +161,10 @@ module ActionView #:nodoc:
|
|
153
161
|
cattr_accessor :raise_on_missing_translations
|
154
162
|
@@raise_on_missing_translations = false
|
155
163
|
|
164
|
+
# Specify whether submit_tag should automatically disable on click
|
165
|
+
cattr_accessor :automatically_disable_submit_tag
|
166
|
+
@@automatically_disable_submit_tag = true
|
167
|
+
|
156
168
|
class_attribute :_routes
|
157
169
|
class_attribute :logger
|
158
170
|
|
@@ -1,22 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'concurrent/map'
|
2
|
+
require 'action_view/path_set'
|
2
3
|
|
3
4
|
module ActionView
|
4
5
|
class DependencyTracker # :nodoc:
|
5
|
-
@trackers =
|
6
|
+
@trackers = Concurrent::Map.new
|
6
7
|
|
7
|
-
def self.find_dependencies(name, template)
|
8
|
+
def self.find_dependencies(name, template, view_paths = nil)
|
8
9
|
tracker = @trackers[template.handler]
|
10
|
+
return [] unless tracker
|
9
11
|
|
10
|
-
|
11
|
-
tracker.call(name, template)
|
12
|
-
else
|
13
|
-
[]
|
14
|
-
end
|
12
|
+
tracker.call(name, template, view_paths)
|
15
13
|
end
|
16
14
|
|
17
15
|
def self.register_tracker(extension, tracker)
|
18
16
|
handler = Template.handler_for_extension(extension)
|
19
|
-
|
17
|
+
if tracker.respond_to?(:supports_view_paths?)
|
18
|
+
@trackers[handler] = tracker
|
19
|
+
else
|
20
|
+
@trackers[handler] = lambda { |name, template, _|
|
21
|
+
tracker.call(name, template)
|
22
|
+
}
|
23
|
+
end
|
20
24
|
end
|
21
25
|
|
22
26
|
def self.remove_tracker(handler)
|
@@ -76,12 +80,22 @@ module ActionView
|
|
76
80
|
(?:#{STRING}|#{VARIABLE_OR_METHOD_CHAIN}) # finally, the dependency name of interest
|
77
81
|
/xm
|
78
82
|
|
79
|
-
|
80
|
-
|
83
|
+
LAYOUT_DEPENDENCY = /\A
|
84
|
+
(?:\s*\(?\s*) # optional opening paren surrounded by spaces
|
85
|
+
(?:.*?#{LAYOUT_HASH_KEY}) # check if the line has layout key declaration
|
86
|
+
(?:#{STRING}|#{VARIABLE_OR_METHOD_CHAIN}) # finally, the dependency name of interest
|
87
|
+
/xm
|
88
|
+
|
89
|
+
def self.supports_view_paths? # :nodoc:
|
90
|
+
true
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.call(name, template, view_paths = nil)
|
94
|
+
new(name, template, view_paths).dependencies
|
81
95
|
end
|
82
96
|
|
83
|
-
def initialize(name, template)
|
84
|
-
@name, @template = name, template
|
97
|
+
def initialize(name, template, view_paths = nil)
|
98
|
+
@name, @template, @view_paths = name, template, view_paths
|
85
99
|
end
|
86
100
|
|
87
101
|
def dependencies
|
@@ -106,15 +120,20 @@ module ActionView
|
|
106
120
|
render_calls = source.split(/\brender\b/).drop(1)
|
107
121
|
|
108
122
|
render_calls.each do |arguments|
|
109
|
-
arguments
|
110
|
-
|
111
|
-
add_static_dependency(render_dependencies, Regexp.last_match[:static])
|
112
|
-
end
|
123
|
+
add_dependencies(render_dependencies, arguments, LAYOUT_DEPENDENCY)
|
124
|
+
add_dependencies(render_dependencies, arguments, RENDER_ARGUMENTS)
|
113
125
|
end
|
114
126
|
|
115
127
|
render_dependencies.uniq
|
116
128
|
end
|
117
129
|
|
130
|
+
def add_dependencies(render_dependencies, arguments, pattern)
|
131
|
+
arguments.scan(pattern) do
|
132
|
+
add_dynamic_dependency(render_dependencies, Regexp.last_match[:dynamic])
|
133
|
+
add_static_dependency(render_dependencies, Regexp.last_match[:static])
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
118
137
|
def add_dynamic_dependency(dependencies, dependency)
|
119
138
|
if dependency
|
120
139
|
dependencies << "#{dependency.pluralize}/#{dependency.singularize}"
|
@@ -131,8 +150,22 @@ module ActionView
|
|
131
150
|
end
|
132
151
|
end
|
133
152
|
|
153
|
+
def resolve_directories(wildcard_dependencies)
|
154
|
+
return [] unless @view_paths
|
155
|
+
|
156
|
+
wildcard_dependencies.flat_map { |query, templates|
|
157
|
+
@view_paths.find_all_with_query(query).map do |template|
|
158
|
+
"#{File.dirname(query)}/#{File.basename(template).split('.').first}"
|
159
|
+
end
|
160
|
+
}.sort
|
161
|
+
end
|
162
|
+
|
134
163
|
def explicit_dependencies
|
135
|
-
source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
|
164
|
+
dependencies = source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
|
165
|
+
|
166
|
+
wildcards, explicits = dependencies.partition { |dependency| dependency[-1] == '*' }
|
167
|
+
|
168
|
+
(explicits + resolve_directories(wildcards)).uniq
|
136
169
|
end
|
137
170
|
end
|
138
171
|
|
data/lib/action_view/digestor.rb
CHANGED
@@ -1,123 +1,125 @@
|
|
1
|
-
require '
|
1
|
+
require 'concurrent/map'
|
2
2
|
require 'action_view/dependency_tracker'
|
3
3
|
require 'monitor'
|
4
4
|
|
5
5
|
module ActionView
|
6
6
|
class Digestor
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
@@digest_mutex = Mutex.new
|
8
|
+
|
9
|
+
module PerExecutionDigestCacheExpiry
|
10
|
+
def self.before(target)
|
11
|
+
ActionView::LookupContext::DetailsKey.clear
|
12
|
+
end
|
13
|
+
end
|
10
14
|
|
11
15
|
class << self
|
12
16
|
# Supported options:
|
13
17
|
#
|
14
18
|
# * <tt>name</tt> - Template name
|
15
|
-
# * <tt>finder</tt> - An instance of ActionView::LookupContext
|
19
|
+
# * <tt>finder</tt> - An instance of <tt>ActionView::LookupContext</tt>
|
16
20
|
# * <tt>dependencies</tt> - An array of dependent views
|
17
21
|
# * <tt>partial</tt> - Specifies whether the template is a partial
|
18
|
-
def digest(
|
19
|
-
|
20
|
-
|
21
|
-
cache_key = ([ options[:name], options[:finder].details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
|
22
|
+
def digest(name:, finder:, dependencies: [])
|
23
|
+
dependencies ||= []
|
24
|
+
cache_key = [ name, finder.rendered_format, dependencies ].flatten.compact.join('.')
|
22
25
|
|
23
26
|
# this is a correctly done double-checked locking idiom
|
24
|
-
# (
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
# (Concurrent::Map's lookups have volatile semantics)
|
28
|
+
finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
|
29
|
+
finder.digest_cache.fetch(cache_key) do # re-check under lock
|
30
|
+
partial = name.include?("/_")
|
31
|
+
root = tree(name, finder, partial)
|
32
|
+
dependencies.each do |injected_dep|
|
33
|
+
root.children << Injected.new(injected_dep, nil, nil)
|
34
|
+
end
|
35
|
+
finder.digest_cache[cache_key] = root.digest(finder)
|
28
36
|
end
|
29
37
|
end
|
30
38
|
end
|
31
39
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
# Prevent re-entry or else recursive templates will blow the stack.
|
36
|
-
# There is no need to worry about other threads seeing the +false+ value,
|
37
|
-
# as they will then have to wait for this thread to let go of the @@digest_monitor lock.
|
38
|
-
pre_stored = @@cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
|
39
|
-
PartialDigestor
|
40
|
-
else
|
41
|
-
Digestor
|
42
|
-
end
|
43
|
-
|
44
|
-
digest = klass.new(options).digest
|
45
|
-
# Store the actual digest if config.cache_template_loading is true
|
46
|
-
@@cache[cache_key] = stored_digest = digest if ActionView::Resolver.caching?
|
47
|
-
digest
|
48
|
-
ensure
|
49
|
-
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
|
50
|
-
@@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
|
51
|
-
end
|
52
|
-
end
|
40
|
+
def logger
|
41
|
+
ActionView::Base.logger || NullLogger
|
42
|
+
end
|
53
43
|
|
54
|
-
|
44
|
+
# Create a dependency tree for template named +name+.
|
45
|
+
def tree(name, finder, partial = false, seen = {})
|
46
|
+
logical_name = name.gsub(%r|/_|, "/")
|
55
47
|
|
56
|
-
|
57
|
-
|
58
|
-
@options = options.except(:name, :finder)
|
59
|
-
end
|
48
|
+
options = {}
|
49
|
+
options[:formats] = [finder.rendered_format] if finder.rendered_format
|
60
50
|
|
61
|
-
|
62
|
-
|
63
|
-
logger.try :debug, " Cache digest for #{template.inspect}: #{digest}"
|
64
|
-
end
|
65
|
-
rescue ActionView::MissingTemplate
|
66
|
-
logger.try :error, " Couldn't find template for digesting: #{name}"
|
67
|
-
''
|
68
|
-
end
|
51
|
+
if template = finder.disable_cache { finder.find_all(logical_name, [], partial, [], options).first }
|
52
|
+
finder.rendered_format ||= template.formats.first
|
69
53
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
[]
|
75
|
-
end
|
54
|
+
if node = seen[template.identifier] # handle cycles in the tree
|
55
|
+
node
|
56
|
+
else
|
57
|
+
node = seen[template.identifier] = Node.create(name, logical_name, template, partial)
|
76
58
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
59
|
+
deps = DependencyTracker.find_dependencies(name, template, finder.view_paths)
|
60
|
+
deps.uniq { |n| n.gsub(%r|/_|, "/") }.each do |dep_file|
|
61
|
+
node.children << tree(dep_file, finder, true, seen)
|
62
|
+
end
|
63
|
+
node
|
64
|
+
end
|
65
|
+
else
|
66
|
+
logger.error " '#{name}' file doesn't exist, so no dependencies"
|
67
|
+
logger.error " Couldn't find template for digesting: #{name}"
|
68
|
+
seen[name] ||= Missing.new(name, logical_name, nil)
|
69
|
+
end
|
81
70
|
end
|
82
71
|
end
|
83
72
|
|
84
|
-
|
85
|
-
|
86
|
-
|
73
|
+
class Node
|
74
|
+
attr_reader :name, :logical_name, :template, :children
|
75
|
+
|
76
|
+
def self.create(name, logical_name, template, partial)
|
77
|
+
klass = partial ? Partial : Node
|
78
|
+
klass.new(name, logical_name, template, [])
|
87
79
|
end
|
88
80
|
|
89
|
-
def logical_name
|
90
|
-
name
|
81
|
+
def initialize(name, logical_name, template, children = [])
|
82
|
+
@name = name
|
83
|
+
@logical_name = logical_name
|
84
|
+
@template = template
|
85
|
+
@children = children
|
91
86
|
end
|
92
87
|
|
93
|
-
def
|
94
|
-
|
88
|
+
def digest(finder, stack = [])
|
89
|
+
Digest::MD5.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
|
95
90
|
end
|
96
91
|
|
97
|
-
def
|
98
|
-
|
92
|
+
def dependency_digest(finder, stack)
|
93
|
+
children.map do |node|
|
94
|
+
if stack.include?(node)
|
95
|
+
false
|
96
|
+
else
|
97
|
+
finder.digest_cache[node.name] ||= begin
|
98
|
+
stack.push node
|
99
|
+
node.digest(finder, stack).tap { stack.pop }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end.join("-")
|
99
103
|
end
|
100
104
|
|
101
|
-
def
|
102
|
-
|
105
|
+
def to_dep_map
|
106
|
+
children.any? ? { name => children.map(&:to_dep_map) } : name
|
103
107
|
end
|
108
|
+
end
|
104
109
|
|
105
|
-
|
106
|
-
template_digests = dependencies.collect do |template_name|
|
107
|
-
Digestor.digest(name: template_name, finder: finder, partial: true)
|
108
|
-
end
|
110
|
+
class Partial < Node; end
|
109
111
|
|
110
|
-
|
111
|
-
end
|
112
|
+
class Missing < Node
|
113
|
+
def digest(finder, _ = []) '' end
|
114
|
+
end
|
112
115
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
116
|
+
class Injected < Node
|
117
|
+
def digest(finder, _ = []) name end
|
118
|
+
end
|
117
119
|
|
118
|
-
|
119
|
-
|
120
|
-
|
120
|
+
class NullLogger
|
121
|
+
def self.debug(_); end
|
122
|
+
def self.error(_); end
|
121
123
|
end
|
122
124
|
end
|
123
125
|
end
|
data/lib/action_view/flows.rb
CHANGED
@@ -37,9 +37,8 @@ module ActionView
|
|
37
37
|
end
|
38
38
|
|
39
39
|
# Try to get stored content. If the content
|
40
|
-
# is not available and we
|
41
|
-
#
|
42
|
-
# key and yield.
|
40
|
+
# is not available and we're inside the layout fiber,
|
41
|
+
# then it will begin waiting for the given key and yield.
|
43
42
|
def get(key)
|
44
43
|
return super if @content.key?(key)
|
45
44
|
|
@@ -60,8 +59,8 @@ module ActionView
|
|
60
59
|
end
|
61
60
|
|
62
61
|
# Appends the contents for the given key. This is called
|
63
|
-
# by
|
64
|
-
# the key it
|
62
|
+
# by providing and resuming back to the fiber,
|
63
|
+
# if that's the key it's waiting for.
|
65
64
|
def append!(key, value)
|
66
65
|
super
|
67
66
|
@fiber.resume if @waiting_for == key
|
@@ -55,12 +55,12 @@ module ActionView
|
|
55
55
|
# # => <script src="http://www.example.com/xmlhr.js"></script>
|
56
56
|
def javascript_include_tag(*sources)
|
57
57
|
options = sources.extract_options!.stringify_keys
|
58
|
-
path_options = options.extract!('protocol', 'extname').symbolize_keys
|
58
|
+
path_options = options.extract!('protocol', 'extname', 'host').symbolize_keys
|
59
59
|
sources.uniq.map { |source|
|
60
60
|
tag_options = {
|
61
61
|
"src" => path_to_javascript(source, path_options)
|
62
62
|
}.merge!(options)
|
63
|
-
content_tag(
|
63
|
+
content_tag("script".freeze, "", tag_options)
|
64
64
|
}.join("\n").html_safe
|
65
65
|
end
|
66
66
|
|
@@ -91,7 +91,7 @@ module ActionView
|
|
91
91
|
# # <link href="/css/stylish.css" media="screen" rel="stylesheet" />
|
92
92
|
def stylesheet_link_tag(*sources)
|
93
93
|
options = sources.extract_options!.stringify_keys
|
94
|
-
path_options = options.extract!('protocol').symbolize_keys
|
94
|
+
path_options = options.extract!('protocol', 'host').symbolize_keys
|
95
95
|
|
96
96
|
sources.uniq.map { |source|
|
97
97
|
tag_options = {
|
@@ -136,7 +136,7 @@ module ActionView
|
|
136
136
|
tag(
|
137
137
|
"link",
|
138
138
|
"rel" => tag_options[:rel] || "alternate",
|
139
|
-
"type" => tag_options[:type] ||
|
139
|
+
"type" => tag_options[:type] || Template::Types[type].to_s,
|
140
140
|
"title" => tag_options[:title] || type.to_s.upcase,
|
141
141
|
"href" => url_options.is_a?(Hash) ? url_for(url_options.merge(:only_path => false)) : url_options
|
142
142
|
)
|
@@ -205,8 +205,11 @@ module ActionView
|
|
205
205
|
# # => <img alt="Icon" height="32" src="/icons/icon.gif" width="32" />
|
206
206
|
# image_tag("/icons/icon.gif", class: "menu_icon")
|
207
207
|
# # => <img alt="Icon" class="menu_icon" src="/icons/icon.gif" />
|
208
|
+
# image_tag("/icons/icon.gif", data: { title: 'Rails Application' })
|
209
|
+
# # => <img data-title="Rails Application" src="/icons/icon.gif" />
|
208
210
|
def image_tag(source, options={})
|
209
211
|
options = options.symbolize_keys
|
212
|
+
check_for_image_tag_errors(options)
|
210
213
|
|
211
214
|
src = options[:src] = path_to_image(source)
|
212
215
|
|
@@ -236,7 +239,7 @@ module ActionView
|
|
236
239
|
# image_alt('underscored_file_name.png')
|
237
240
|
# # => Underscored file name
|
238
241
|
def image_alt(src)
|
239
|
-
File.basename(src, '.*').sub(/-[[:xdigit:]]{32,64}\z/, '').tr('-_', ' ').capitalize
|
242
|
+
File.basename(src, '.*'.freeze).sub(/-[[:xdigit:]]{32,64}\z/, ''.freeze).tr('-_'.freeze, ' '.freeze).capitalize
|
240
243
|
end
|
241
244
|
|
242
245
|
# Returns an HTML video tag for the +sources+. If +sources+ is a string,
|
@@ -318,12 +321,19 @@ module ActionView
|
|
318
321
|
end
|
319
322
|
|
320
323
|
def extract_dimensions(size)
|
324
|
+
size = size.to_s
|
321
325
|
if size =~ %r{\A\d+x\d+\z}
|
322
326
|
size.split('x')
|
323
327
|
elsif size =~ %r{\A\d+\z}
|
324
328
|
[size, size]
|
325
329
|
end
|
326
330
|
end
|
331
|
+
|
332
|
+
def check_for_image_tag_errors(options)
|
333
|
+
if options[:size] && (options[:height] || options[:width])
|
334
|
+
raise ArgumentError, "Cannot pass a :size option with a :height or :width option"
|
335
|
+
end
|
336
|
+
end
|
327
337
|
end
|
328
338
|
end
|
329
339
|
end
|