actionview 4.1.0.rc1 → 4.1.0.rc2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07c7cfb02baa85d1be095df9bdf486932bae786d
4
- data.tar.gz: 43b83b9ee0eb0a2ac07f0a654c6e622bbe71861a
3
+ metadata.gz: 695b4fb4b7776377d61b06b2223992fa600389ff
4
+ data.tar.gz: f14b5a57eb0d1a81e524b09c99102e6c73157f2a
5
5
  SHA512:
6
- metadata.gz: bf072d8647e35ca744a19267a9478ed110fa637c1eded7faea8159b6376de476ad9621b857667a7469d152c69994f751b73bdd5541480e09c8d48da4162760d7
7
- data.tar.gz: b7e058105db2d0ab080608f1922b3d02ed686fa632e7f5dc8df495250e7896286d3562801dec4f93a3602f6189fcc0d0e6453f7acebdfe38b5f4441e37b47172
6
+ metadata.gz: db42dc979e0a866ba3ef9f168a784c19e41f48692cafeb430a91b71e26d97eadc133fd0e2415857dd9a9e29f7c4f3b88eb1ff4e355a9b9be7fd1e53fc5118fcd
7
+ data.tar.gz: 02fbe0ea74c6f5011c553a88c3655a10654e501247cd1574fd94c3ed2c49c0f906f6730f45755a13c1c363e1bd9caf6cb85ef267f93eef880c180b8fc6b38444
data/CHANGELOG.md CHANGED
@@ -1,3 +1,35 @@
1
+ * Fixed ActionView::Digestor template lookup to use the lookup_context exclusively, and not rely on the passed-in format.
2
+ This unfortunately means that the cache_key changed, so upgrading will invalidate all prior caches. Take note if you rely
3
+ heavily on caching in production when you push this live.
4
+
5
+ *DHH*
6
+
7
+ * `number_to_percentage` does not crash with `Float::NAN` or `Float::INFINITY`
8
+ as input.
9
+
10
+ Fixes #14405.
11
+
12
+ *Yves Senn*
13
+
14
+ * Take variants into account when calculating template digests in ActionView::Digestor.
15
+
16
+ The arguments to ActionView::Digestor#digest are now being passed as a hash
17
+ to support variants and allow more flexibility in the future. The support for
18
+ regular (required) arguments is deprecated and will be removed in Rails 5.0 or later.
19
+
20
+ *Piotr Chmolowski, Łukasz Strzałkowski*
21
+
22
+ * Fixed a problem where the default options for the `button_tag` helper is not
23
+ applied correctly.
24
+
25
+ Fixes #14255.
26
+
27
+ *Sergey Prikhodko*
28
+
29
+ * Fix ActionView label translation for more than 10 nested elements.
30
+
31
+ *Vladimir Krylov*
32
+
1
33
  * Added `:plain`, `:html` and `:body` option for `render` method. Please see
2
34
  Action Pack's release note for more detail.
3
35
 
@@ -320,7 +352,7 @@
320
352
 
321
353
  *Bryan Ricker*
322
354
 
323
- * First release, ActionView extracted from ActionPack
355
+ * First release, ActionView extracted from ActionPack.
324
356
 
325
357
  *Piotr Sarnacki*, *Łukasz Strzałkowski*
326
358
 
data/README.rdoc CHANGED
@@ -13,7 +13,7 @@ The latest version of Action View can be installed with RubyGems:
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/master/actionview
16
+ * https://github.com/rails/rails/tree/4-1-stable/actionview
17
17
 
18
18
 
19
19
  == License
@@ -9,54 +9,61 @@ module ActionView
9
9
  @@digest_monitor = Monitor.new
10
10
 
11
11
  class << self
12
- def digest(name, format, finder, options = {})
13
- details_key = finder.details_key.hash
14
- dependencies = Array.wrap(options[:dependencies])
15
- cache_key = ([name, details_key, format] + dependencies).join('.')
12
+ # Supported options:
13
+ #
14
+ # * <tt>name</tt> - Template name
15
+ # * <tt>finder</tt> - An instance of ActionView::LookupContext
16
+ # * <tt>dependencies</tt> - An array of dependent views
17
+ # * <tt>partial</tt> - Specifies whether the template is a partial
18
+ def digest(options)
19
+ options.assert_valid_keys(:name, :finder, :dependencies, :partial)
20
+
21
+ cache_key = ([ options[:name], options[:finder].details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
16
22
 
17
23
  # this is a correctly done double-checked locking idiom
18
24
  # (ThreadSafe::Cache's lookups have volatile semantics)
19
25
  @@cache[cache_key] || @@digest_monitor.synchronize do
20
26
  @@cache.fetch(cache_key) do # re-check under lock
21
- compute_and_store_digest(cache_key, name, format, finder, options)
27
+ compute_and_store_digest(cache_key, options)
22
28
  end
23
29
  end
24
30
  end
25
31
 
26
32
  private
27
- def compute_and_store_digest(cache_key, name, format, finder, options) # called under @@digest_monitor lock
28
- klass = if options[:partial] || name.include?("/_")
29
- # Prevent re-entry or else recursive templates will blow the stack.
30
- # There is no need to worry about other threads seeing the +false+ value,
31
- # as they will then have to wait for this thread to let go of the @@digest_monitor lock.
32
- pre_stored = @@cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
33
- PartialDigestor
34
- else
35
- Digestor
36
- end
33
+ def compute_and_store_digest(cache_key, options) # called under @@digest_monitor lock
34
+ klass = if options[:partial] || options[:name].include?("/_")
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
37
43
 
38
- digest = klass.new(name, format, finder, options).digest
39
- # Store the actual digest if config.cache_template_loading is true
40
- @@cache[cache_key] = stored_digest = digest if ActionView::Resolver.caching?
41
- digest
42
- ensure
43
- # something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
44
- @@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
45
- end
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
46
52
  end
47
53
 
48
- attr_reader :name, :format, :finder, :options
54
+ attr_reader :name, :finder, :options
49
55
 
50
- def initialize(name, format, finder, options={})
51
- @name, @format, @finder, @options = name, format, finder, options
56
+ def initialize(options)
57
+ @name, @finder = options.values_at(:name, :finder)
58
+ @options = options.except(:name, :finder)
52
59
  end
53
60
 
54
61
  def digest
55
62
  Digest::MD5.hexdigest("#{source}-#{dependency_digest}").tap do |digest|
56
- logger.try :info, "Cache digest for #{name}.#{format}: #{digest}"
63
+ logger.try :info, " Cache digest for #{template.inspect}: #{digest}"
57
64
  end
58
65
  rescue ActionView::MissingTemplate
59
- logger.try :error, "Couldn't find template for digesting: #{name}.#{format}"
66
+ logger.try :error, " Couldn't find template for digesting: #{name}"
60
67
  ''
61
68
  end
62
69
 
@@ -68,13 +75,12 @@ module ActionView
68
75
 
69
76
  def nested_dependencies
70
77
  dependencies.collect do |dependency|
71
- dependencies = PartialDigestor.new(dependency, format, finder).nested_dependencies
78
+ dependencies = PartialDigestor.new(name: dependency, finder: finder).nested_dependencies
72
79
  dependencies.any? ? { dependency => dependencies } : dependency
73
80
  end
74
81
  end
75
82
 
76
83
  private
77
-
78
84
  def logger
79
85
  ActionView::Base.logger
80
86
  end
@@ -88,7 +94,7 @@ module ActionView
88
94
  end
89
95
 
90
96
  def template
91
- @template ||= finder.find(logical_name, [], partial?, formats: [ format ])
97
+ @template ||= finder.disable_cache { finder.find(logical_name, [], partial?) }
92
98
  end
93
99
 
94
100
  def source
@@ -97,7 +103,7 @@ module ActionView
97
103
 
98
104
  def dependency_digest
99
105
  template_digests = dependencies.collect do |template_name|
100
- Digestor.digest(template_name, format, finder, partial: true)
106
+ Digestor.digest(name: template_name, finder: finder, partial: true)
101
107
  end
102
108
 
103
109
  (template_digests + injected_dependencies).join("-")
@@ -0,0 +1,15 @@
1
+ module ActionView
2
+ # Returns the version of the currently loaded ActionView as a <tt>Gem::Version</tt>
3
+ def self.gem_version
4
+ Gem::Version.new VERSION::STRING
5
+ end
6
+
7
+ module VERSION
8
+ MAJOR = 4
9
+ MINOR = 1
10
+ TINY = 0
11
+ PRE = "rc2"
12
+
13
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
+ end
15
+ end
@@ -165,10 +165,10 @@ module ActionView
165
165
 
166
166
  def fragment_name_with_digest(name) #:nodoc:
167
167
  if @virtual_path
168
- [
169
- *Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name),
170
- Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context, dependencies: view_cache_dependencies)
171
- ]
168
+ names = Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name)
169
+ digest = Digestor.digest name: @virtual_path, finder: lookup_context, dependencies: view_cache_dependencies
170
+
171
+ [ *names, digest ]
172
172
  else
173
173
  name
174
174
  end
@@ -465,17 +465,23 @@ module ActionView
465
465
  # # <strong>Ask me!</strong>
466
466
  # # </button>
467
467
  #
468
- # button_tag "Checkout", data: { :disable_with => "Please wait..." }
468
+ # button_tag "Checkout", data: { disable_with: "Please wait..." }
469
469
  # # => <button data-disable-with="Please wait..." name="button" type="submit">Checkout</button>
470
470
  #
471
471
  def button_tag(content_or_options = nil, options = nil, &block)
472
- options = content_or_options if block_given? && content_or_options.is_a?(Hash)
473
- options ||= {}
474
- options = options.stringify_keys
472
+ if content_or_options.is_a? Hash
473
+ options = content_or_options
474
+ else
475
+ options ||= {}
476
+ end
475
477
 
476
- options.reverse_merge! 'name' => 'button', 'type' => 'submit'
478
+ options = { 'name' => 'button', 'type' => 'submit' }.merge!(options.stringify_keys)
477
479
 
478
- content_tag :button, content_or_options || 'Button', options, &block
480
+ if block_given?
481
+ content_tag :button, options, &block
482
+ else
483
+ content_tag :button, content_or_options || 'Button', options
484
+ end
479
485
  end
480
486
 
481
487
  # Displays an image which when clicked will submit the form.
@@ -17,8 +17,9 @@ module ActionView
17
17
  # * <tt>:html</tt> - Renders the html safe string passed in out, otherwise
18
18
  # performs html escape on the string first. Setting the content type as
19
19
  # <tt>text/html</tt>.
20
- # * <tt>:body</tt> - Renders the text passed in, and does not set content
21
- # type in the response.
20
+ # * <tt>:body</tt> - Renders the text passed in, and inherits the content
21
+ # type of <tt>text/html</tt> from <tt>ActionDispatch::Response</tt>
22
+ # object.
22
23
  #
23
24
  # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter
24
25
  # as the locals hash.
@@ -36,7 +36,7 @@ module ActionView
36
36
  content = @template_object.capture(&block)
37
37
  else
38
38
  content = if @content.blank?
39
- @object_name.gsub!(/\[(.*)_attributes\]\[\d\]/, '.\1')
39
+ @object_name.gsub!(/\[(.*)_attributes\]\[\d+\]/, '.\1')
40
40
  method_and_value = tag_value.present? ? "#{@method_name}.#{tag_value}" : @method_name
41
41
 
42
42
  if object.respond_to?(:to_model)
@@ -82,7 +82,7 @@ module ActionView
82
82
  # to using GET. If <tt>href: '#'</tt> is used and the user has JavaScript
83
83
  # disabled clicking the link will have no effect. If you are relying on the
84
84
  # POST behavior, you should check for it in your controller's action by using
85
- # the request object's methods for <tt>post?</tt>, <tt>delete?</tt>, <tt>:patch</tt>, or <tt>put?</tt>.
85
+ # the request object's methods for <tt>post?</tt>, <tt>delete?</tt>, <tt>patch?</tt>, or <tt>put?</tt>.
86
86
  # * <tt>remote: true</tt> - This will allow the unobtrusive JavaScript
87
87
  # driver to make an Ajax request to the URL in question instead of following
88
88
  # the link. The drivers each provide mechanisms for listening for the
@@ -159,7 +159,14 @@ module ActionView
159
159
  def detail_args_for(options)
160
160
  return @details, details_key if options.empty? # most common path.
161
161
  user_details = @details.merge(options)
162
- [user_details, DetailsKey.get(user_details)]
162
+
163
+ if @cache
164
+ details_key = DetailsKey.get(user_details)
165
+ else
166
+ details_key = nil
167
+ end
168
+
169
+ [user_details, details_key]
163
170
  end
164
171
 
165
172
  # Support legacy foo.erb names even though we now ignore .erb
@@ -102,11 +102,6 @@ module ActionView
102
102
  # Assign the rendered format to lookup context.
103
103
  def _process_format(format, options = {}) #:nodoc:
104
104
  super
105
-
106
- if options[:body]
107
- self.no_content_type = true
108
- end
109
-
110
105
  lookup_context.formats = [format.to_sym]
111
106
  lookup_context.rendered_format = lookup_context.formats.first
112
107
  end
@@ -97,7 +97,7 @@ module ActionView
97
97
 
98
98
  extend Template::Handlers
99
99
 
100
- attr_accessor :locals, :formats, :virtual_path
100
+ attr_accessor :locals, :formats, :variants, :virtual_path
101
101
 
102
102
  attr_reader :source, :identifier, :handler, :original_encoding, :updated_at
103
103
 
@@ -123,6 +123,7 @@ module ActionView
123
123
  @virtual_path = details[:virtual_path]
124
124
  @updated_at = details[:updated_at] || Time.now
125
125
  @formats = Array(format).map { |f| f.respond_to?(:ref) ? f.ref : f }
126
+ @variants = [details[:variant]]
126
127
  @compile_mutex = Mutex.new
127
128
  end
128
129
 
@@ -154,7 +154,8 @@ module ActionView
154
154
  cached = nil
155
155
  templates.each do |t|
156
156
  t.locals = locals
157
- t.formats = details[:formats] || [:html] if t.formats.empty?
157
+ t.formats = details[:formats] || [:html] if t.formats.empty?
158
+ t.variants = details[:variants] || [] if t.variants.empty?
158
159
  t.virtual_path ||= (cached ||= build_path(*path_info))
159
160
  end
160
161
  end
@@ -189,13 +190,15 @@ module ActionView
189
190
  }
190
191
 
191
192
  template_paths.map { |template|
192
- handler, format = extract_handler_and_format(template, formats)
193
- contents = File.binread template
193
+ handler, format, variant = extract_handler_and_format_and_variant(template, formats)
194
+ contents = File.binread(template)
194
195
 
195
196
  Template.new(contents, File.expand_path(template), handler,
196
197
  :virtual_path => path.virtual,
197
198
  :format => format,
198
- :updated_at => mtime(template))
199
+ :variant => variant,
200
+ :updated_at => mtime(template)
201
+ )
199
202
  }
200
203
  end
201
204
 
@@ -228,7 +231,7 @@ module ActionView
228
231
  # Extract handler and formats from path. If a format cannot be a found neither
229
232
  # from the path, or the handler, we should return the array of formats given
230
233
  # to the resolver.
231
- def extract_handler_and_format(path, default_formats)
234
+ def extract_handler_and_format_and_variant(path, default_formats)
232
235
  pieces = File.basename(path).split(".")
233
236
  pieces.shift
234
237
 
@@ -240,10 +243,10 @@ module ActionView
240
243
  end
241
244
 
242
245
  handler = Template.handler_for_extension(extension)
243
- format = pieces.last && pieces.last.split(EXTENSIONS[:variants], 2).first # remove variant from format
246
+ format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
244
247
  format &&= Template::Types[format]
245
248
 
246
- [handler, format]
249
+ [handler, format, variant]
247
250
  end
248
251
  end
249
252
 
@@ -30,9 +30,13 @@ module ActionView #:nodoc:
30
30
  @hash.each do |_path, array|
31
31
  source, updated_at = array
32
32
  next unless _path =~ query
33
- handler, format = extract_handler_and_format(_path, formats)
33
+ handler, format, variant = extract_handler_and_format_and_variant(_path, formats)
34
34
  templates << Template.new(source, _path, handler,
35
- :virtual_path => path.virtual, :format => format, :updated_at => updated_at)
35
+ :virtual_path => path.virtual,
36
+ :format => format,
37
+ :variant => variant,
38
+ :updated_at => updated_at
39
+ )
36
40
  end
37
41
 
38
42
  templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
@@ -41,8 +45,8 @@ module ActionView #:nodoc:
41
45
 
42
46
  class NullResolver < PathResolver
43
47
  def query(path, exts, formats)
44
- handler, format = extract_handler_and_format(path, formats)
45
- [ActionView::Template.new("Template generated by Null Resolver", path, handler, :virtual_path => path, :format => format)]
48
+ handler, format, variant = extract_handler_and_format_and_variant(path, formats)
49
+ [ActionView::Template.new("Template generated by Null Resolver", path, handler, :virtual_path => path, :format => format, :variant => variant)]
46
50
  end
47
51
  end
48
52
 
@@ -1,11 +1,8 @@
1
+ require_relative 'gem_version'
2
+
1
3
  module ActionView
2
- # Returns the version of the currently loaded ActionView as a Gem::Version
4
+ # Returns the version of the currently loaded ActionView as a <tt>Gem::Version</tt>
3
5
  def self.version
4
- Gem::Version.new "4.1.0.rc1"
5
- end
6
-
7
- module VERSION #:nodoc:
8
- MAJOR, MINOR, TINY, PRE = ActionView.version.segments
9
- STRING = ActionView.version.to_s
6
+ gem_version
10
7
  end
11
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actionview
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.1.0.rc1
4
+ version: 4.1.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-18 00:00:00.000000000 Z
11
+ date: 2014-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.1.0.rc1
19
+ version: 4.1.0.rc2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.1.0.rc1
26
+ version: 4.1.0.rc2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: builder
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -58,28 +58,28 @@ dependencies:
58
58
  requirements:
59
59
  - - '='
60
60
  - !ruby/object:Gem::Version
61
- version: 4.1.0.rc1
61
+ version: 4.1.0.rc2
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - '='
67
67
  - !ruby/object:Gem::Version
68
- version: 4.1.0.rc1
68
+ version: 4.1.0.rc2
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: activemodel
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 4.1.0.rc1
75
+ version: 4.1.0.rc2
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 4.1.0.rc1
82
+ version: 4.1.0.rc2
83
83
  description: Simple, battle-tested conventions and helpers for building web pages.
84
84
  email: david@loudthinking.com
85
85
  executables: []
@@ -96,6 +96,7 @@ files:
96
96
  - lib/action_view/dependency_tracker.rb
97
97
  - lib/action_view/digestor.rb
98
98
  - lib/action_view/flows.rb
99
+ - lib/action_view/gem_version.rb
99
100
  - lib/action_view/helpers.rb
100
101
  - lib/action_view/helpers/active_model_helper.rb
101
102
  - lib/action_view/helpers/asset_tag_helper.rb