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
@@ -15,7 +15,7 @@ module ActionView
15
15
  # that new object is called in turn. This abstracts the setup and rendering
16
16
  # into a separate classes for partials and templates.
17
17
  class AbstractRenderer #:nodoc:
18
- delegate :find_template, :find_file, :template_exists?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
18
+ delegate :find_template, :find_file, :template_exists?, :any_templates?, :with_fallbacks, :with_layout_format, :formats, :to => :@lookup_context
19
19
 
20
20
  def initialize(lookup_context)
21
21
  @lookup_context = lookup_context
@@ -35,8 +35,12 @@ module ActionView
35
35
  end
36
36
  end
37
37
 
38
- def instrument(name, options={})
39
- ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield }
38
+ def instrument(name, **options)
39
+ options[:identifier] ||= (@template && @template.identifier) || @path
40
+
41
+ ActiveSupport::Notifications.instrument("render_#{name}.action_view", options) do |payload|
42
+ yield payload
43
+ end
40
44
  end
41
45
 
42
46
  def prepend_formats(formats)
@@ -1,4 +1,5 @@
1
- require 'thread_safe'
1
+ require 'action_view/renderer/partial_renderer/collection_caching'
2
+ require 'concurrent/map'
2
3
 
3
4
  module ActionView
4
5
  class PartialIteration
@@ -73,7 +74,7 @@ module ActionView
73
74
  #
74
75
  # <%= render partial: "account", locals: { user: @buyer } %>
75
76
  #
76
- # == Rendering a collection of partials
77
+ # == \Rendering a collection of partials
77
78
  #
78
79
  # The example of partial use describes a familiar pattern where a template needs to iterate over an array and
79
80
  # render a sub template for each of the elements. This pattern has been implemented as a single method that
@@ -105,7 +106,7 @@ module ActionView
105
106
  # NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also
106
107
  # just keep domain objects, like Active Records, in there.
107
108
  #
108
- # == Rendering shared partials
109
+ # == \Rendering shared partials
109
110
  #
110
111
  # Two controllers can share a set of partials and render them like this:
111
112
  #
@@ -113,7 +114,7 @@ module ActionView
113
114
  #
114
115
  # This will render the partial "advertisement/_ad.html.erb" regardless of which controller this is being called from.
115
116
  #
116
- # == Rendering objects that respond to `to_partial_path`
117
+ # == \Rendering objects that respond to `to_partial_path`
117
118
  #
118
119
  # Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work
119
120
  # and pick the proper path by checking `to_partial_path` method.
@@ -127,7 +128,7 @@ module ActionView
127
128
  # # <%= render partial: "posts/post", collection: @posts %>
128
129
  # <%= render partial: @posts %>
129
130
  #
130
- # == Rendering the default case
131
+ # == \Rendering the default case
131
132
  #
132
133
  # If you're not going to be using any of the options like collections or layouts, you can also use the short-hand
133
134
  # defaults of render to render partials. Examples:
@@ -147,29 +148,29 @@ module ActionView
147
148
  # # <%= render partial: "posts/post", collection: @posts %>
148
149
  # <%= render @posts %>
149
150
  #
150
- # == Rendering partials with layouts
151
+ # == \Rendering partials with layouts
151
152
  #
152
153
  # Partials can have their own layouts applied to them. These layouts are different than the ones that are
153
154
  # specified globally for the entire action, but they work in a similar fashion. Imagine a list with two types
154
155
  # of users:
155
156
  #
156
- # <%# app/views/users/index.html.erb &>
157
+ # <%# app/views/users/index.html.erb %>
157
158
  # Here's the administrator:
158
159
  # <%= render partial: "user", layout: "administrator", locals: { user: administrator } %>
159
160
  #
160
161
  # Here's the editor:
161
162
  # <%= render partial: "user", layout: "editor", locals: { user: editor } %>
162
163
  #
163
- # <%# app/views/users/_user.html.erb &>
164
+ # <%# app/views/users/_user.html.erb %>
164
165
  # Name: <%= user.name %>
165
166
  #
166
- # <%# app/views/users/_administrator.html.erb &>
167
+ # <%# app/views/users/_administrator.html.erb %>
167
168
  # <div id="administrator">
168
169
  # Budget: $<%= user.budget %>
169
170
  # <%= yield %>
170
171
  # </div>
171
172
  #
172
- # <%# app/views/users/_editor.html.erb &>
173
+ # <%# app/views/users/_editor.html.erb %>
173
174
  # <div id="editor">
174
175
  # Deadline: <%= user.deadline %>
175
176
  # <%= yield %>
@@ -232,7 +233,7 @@ module ActionView
232
233
  #
233
234
  # You can also apply a layout to a block within any template:
234
235
  #
235
- # <%# app/views/users/_chief.html.erb &>
236
+ # <%# app/views/users/_chief.html.erb %>
236
237
  # <%= render(layout: "administrator", locals: { user: chief }) do %>
237
238
  # Title: <%= chief.title %>
238
239
  # <% end %>
@@ -249,13 +250,13 @@ module ActionView
249
250
  # If you pass arguments to "yield" then this will be passed to the block. One way to use this is to pass
250
251
  # an array to layout and treat it as an enumerable.
251
252
  #
252
- # <%# app/views/users/_user.html.erb &>
253
+ # <%# app/views/users/_user.html.erb %>
253
254
  # <div class="user">
254
255
  # Budget: $<%= user.budget %>
255
256
  # <%= yield user %>
256
257
  # </div>
257
258
  #
258
- # <%# app/views/users/index.html.erb &>
259
+ # <%# app/views/users/index.html.erb %>
259
260
  # <%= render layout: @users do |user| %>
260
261
  # Title: <%= user.title %>
261
262
  # <% end %>
@@ -264,14 +265,14 @@ module ActionView
264
265
  #
265
266
  # You can also yield multiple times in one layout and use block arguments to differentiate the sections.
266
267
  #
267
- # <%# app/views/users/_user.html.erb &>
268
+ # <%# app/views/users/_user.html.erb %>
268
269
  # <div class="user">
269
270
  # <%= yield user, :header %>
270
271
  # Budget: $<%= user.budget %>
271
272
  # <%= yield user, :footer %>
272
273
  # </div>
273
274
  #
274
- # <%# app/views/users/index.html.erb &>
275
+ # <%# app/views/users/index.html.erb %>
275
276
  # <%= render layout: @users do |user, section| %>
276
277
  # <%- case section when :header -%>
277
278
  # Title: <%= user.title %>
@@ -280,8 +281,10 @@ module ActionView
280
281
  # <%- end -%>
281
282
  # <% end %>
282
283
  class PartialRenderer < AbstractRenderer
283
- PREFIXED_PARTIAL_NAMES = ThreadSafe::Cache.new do |h, k|
284
- h[k] = ThreadSafe::Cache.new
284
+ include CollectionCaching
285
+
286
+ PREFIXED_PARTIAL_NAMES = Concurrent::Map.new do |h, k|
287
+ h[k] = Concurrent::Map.new
285
288
  end
286
289
 
287
290
  def initialize(*)
@@ -291,7 +294,7 @@ module ActionView
291
294
 
292
295
  def render(context, options, block)
293
296
  setup(context, options, block)
294
- identifier = (@template = find_partial) ? @template.identifier : @path
297
+ @template = find_partial
295
298
 
296
299
  @lookup_context.rendered_format ||= begin
297
300
  if @template && @template.formats.present?
@@ -302,11 +305,9 @@ module ActionView
302
305
  end
303
306
 
304
307
  if @collection
305
- instrument(:collection, :identifier => identifier || "collection", :count => @collection.size) do
306
- render_collection
307
- end
308
+ render_collection
308
309
  else
309
- instrument(:partial, :identifier => identifier) do
310
+ instrument(:partial) do
310
311
  render_partial
311
312
  end
312
313
  end
@@ -315,14 +316,17 @@ module ActionView
315
316
  private
316
317
 
317
318
  def render_collection
318
- return nil if @collection.blank?
319
+ instrument(:collection, count: @collection.size) do |payload|
320
+ return nil if @collection.blank?
319
321
 
320
- if @options.key?(:spacer_template)
321
- spacer = find_template(@options[:spacer_template], @locals.keys).render(@view, @locals)
322
- end
322
+ if @options.key?(:spacer_template)
323
+ spacer = find_template(@options[:spacer_template], @locals.keys).render(@view, @locals)
324
+ end
323
325
 
324
- result = @template ? collection_with_template : collection_without_template
325
- result.join(spacer).html_safe
326
+ cache_collection_render(payload) do
327
+ @template ? collection_with_template : collection_without_template
328
+ end.join(spacer).html_safe
329
+ end
326
330
  end
327
331
 
328
332
  def render_partial
@@ -334,7 +338,7 @@ module ActionView
334
338
  end
335
339
 
336
340
  object = locals[as] if object.nil? # Respect object when object is false
337
- locals[as] = object
341
+ locals[as] = object if @has_object
338
342
 
339
343
  content = @template.render(view, locals) do |*name|
340
344
  view._layout_for(*name, &block)
@@ -344,8 +348,6 @@ module ActionView
344
348
  content
345
349
  end
346
350
 
347
- private
348
-
349
351
  # Sets up instance variables needed for rendering a partial. This method
350
352
  # finds the options and details and extracts them. The method also contains
351
353
  # logic that handles the type of object passed in as the partial.
@@ -401,7 +403,7 @@ module ActionView
401
403
  def collection_from_options
402
404
  if @options.key?(:collection)
403
405
  collection = @options[:collection]
404
- collection.respond_to?(:to_ary) ? collection.to_ary : []
406
+ collection ? collection.to_a : []
405
407
  end
406
408
  end
407
409
 
@@ -455,7 +457,7 @@ module ActionView
455
457
  locals[counter] = index
456
458
  locals[iteration] = partial_iteration
457
459
 
458
- template = (cache[path] ||= find_template(path, keys + [as, counter]))
460
+ template = (cache[path] ||= find_template(path, keys + [as, counter, iteration]))
459
461
  content = template.render(view, locals)
460
462
  partial_iteration.iterate!
461
463
  content
@@ -518,8 +520,8 @@ module ActionView
518
520
 
519
521
  def retrieve_variable(path, as)
520
522
  variable = as || begin
521
- base = path[-1] == "/" ? "" : File.basename(path)
522
- raise_invalid_identifier(path) unless base =~ /\A_?([a-z]\w*)(\.\w+)*\z/
523
+ base = path[-1] == "/".freeze ? "".freeze : File.basename(path)
524
+ raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
523
525
  $1.to_sym
524
526
  end
525
527
  if @collection
@@ -530,8 +532,7 @@ module ActionView
530
532
  end
531
533
 
532
534
  IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " +
533
- "make sure your partial name starts with underscore, " +
534
- "and is followed by any combination of letters, numbers and underscores."
535
+ "make sure your partial name starts with underscore."
535
536
 
536
537
  OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " +
537
538
  "make sure it starts with lowercase letter, " +
@@ -0,0 +1,49 @@
1
+ module ActionView
2
+ module CollectionCaching # :nodoc:
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ # Fallback cache store if Action View is used without Rails.
7
+ # Otherwise overridden in Railtie to use Rails.cache.
8
+ mattr_accessor(:collection_cache) { ActiveSupport::Cache::MemoryStore.new }
9
+ end
10
+
11
+ private
12
+ def cache_collection_render(instrumentation_payload)
13
+ return yield unless @options[:cached]
14
+
15
+ keyed_collection = collection_by_cache_keys
16
+ cached_partials = collection_cache.read_multi(*keyed_collection.keys)
17
+ instrumentation_payload[:cache_hits] = cached_partials.size
18
+
19
+ @collection = keyed_collection.reject { |key, _| cached_partials.key?(key) }.values
20
+ rendered_partials = @collection.empty? ? [] : yield
21
+
22
+ index = 0
23
+ fetch_or_cache_partial(cached_partials, order_by: keyed_collection.each_key) do
24
+ rendered_partials[index].tap { index += 1 }
25
+ end
26
+ end
27
+
28
+ def collection_by_cache_keys
29
+ @collection.each_with_object({}) do |item, hash|
30
+ hash[expanded_cache_key(item)] = item
31
+ end
32
+ end
33
+
34
+ def expanded_cache_key(key)
35
+ key = @view.fragment_cache_key(@view.cache_fragment_name(key, virtual_path: @template.virtual_path))
36
+ key.frozen? ? key.dup : key # #read_multi & #write may require mutability, Dalli 2.6.0.
37
+ end
38
+
39
+ def fetch_or_cache_partial(cached_partials, order_by:)
40
+ order_by.map do |cache_key|
41
+ cached_partials.fetch(cache_key) do
42
+ yield.tap do |rendered_partial|
43
+ collection_cache.write(cache_key, rendered_partial)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -15,12 +15,8 @@ module ActionView
15
15
  @lookup_context = lookup_context
16
16
  end
17
17
 
18
- # Main render entry point shared by AV and AC.
18
+ # Main render entry point shared by Action View and Action Controller.
19
19
  def render(context, options)
20
- if options.respond_to?(:permitted?) && !options.permitted?
21
- raise ArgumentError, "render parameters are not permitted"
22
- end
23
-
24
20
  if options.key?(:partial)
25
21
  render_partial(context, options)
26
22
  else
@@ -41,7 +37,7 @@ module ActionView
41
37
  end
42
38
  end
43
39
 
44
- # Direct accessor to template rendering.
40
+ # Direct access to template rendering.
45
41
  def render_template(context, options) #:nodoc:
46
42
  TemplateRenderer.new(@lookup_context).render(context, options)
47
43
  end
@@ -47,7 +47,7 @@ module ActionView
47
47
  return [super] unless layout_name && template.supports_streaming?
48
48
 
49
49
  locals ||= {}
50
- layout = layout_name && find_layout(layout_name, locals.keys)
50
+ layout = layout_name && find_layout(layout_name, locals.keys, [formats.first])
51
51
 
52
52
  Body.new do |buffer|
53
53
  delayed_render(buffer, template, layout, @view, locals)
@@ -40,7 +40,7 @@ module ActionView
40
40
  find_template(options[:template], options[:prefixes], false, keys, @details)
41
41
  end
42
42
  else
43
- raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :text or :body option."
43
+ raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file, :plain, :html, :text or :body option."
44
44
  end
45
45
  end
46
46
 
@@ -57,7 +57,7 @@ module ActionView
57
57
  end
58
58
 
59
59
  def render_with_layout(path, locals) #:nodoc:
60
- layout = path && find_layout(path, locals.keys)
60
+ layout = path && find_layout(path, locals.keys, [formats.first])
61
61
  content = yield(layout)
62
62
 
63
63
  if layout
@@ -72,27 +72,28 @@ module ActionView
72
72
  # This is the method which actually finds the layout using details in the lookup
73
73
  # context object. If no layout is found, it checks if at least a layout with
74
74
  # the given name exists across all details before raising the error.
75
- def find_layout(layout, keys)
76
- with_layout_format { resolve_layout(layout, keys) }
75
+ def find_layout(layout, keys, formats)
76
+ resolve_layout(layout, keys, formats)
77
77
  end
78
78
 
79
- def resolve_layout(layout, keys)
79
+ def resolve_layout(layout, keys, formats)
80
+ details = @details.dup
81
+ details[:formats] = formats
82
+
80
83
  case layout
81
84
  when String
82
85
  begin
83
86
  if layout =~ /^\//
84
- with_fallbacks { find_template(layout, nil, false, keys, @details) }
87
+ with_fallbacks { find_template(layout, nil, false, keys, details) }
85
88
  else
86
- find_template(layout, nil, false, keys, @details)
89
+ find_template(layout, nil, false, keys, details)
87
90
  end
88
91
  rescue ActionView::MissingTemplate
89
92
  all_details = @details.merge(:formats => @lookup_context.default_formats)
90
93
  raise unless template_exists?(layout, nil, false, keys, all_details)
91
94
  end
92
95
  when Proc
93
- resolve_layout(layout.call, keys)
94
- when FalseClass
95
- nil
96
+ resolve_layout(layout.call(formats), keys, formats)
96
97
  else
97
98
  layout
98
99
  end
@@ -59,7 +59,7 @@ module ActionView
59
59
  @_view_context_class ||= self.class.view_context_class
60
60
  end
61
61
 
62
- # An instance of a view class. The default view class is ActionView::Base
62
+ # An instance of a view class. The default view class is ActionView::Base.
63
63
  #
64
64
  # The view class must have the following methods:
65
65
  # View.new[lookup_context, assigns, controller]
@@ -84,7 +84,8 @@ module ActionView
84
84
  end
85
85
 
86
86
  def rendered_format
87
- Mime[lookup_context.rendered_format]
87
+ format = lookup_context.rendered_format
88
+ Template::Types[format] || format
88
89
  end
89
90
 
90
91
  private
@@ -92,16 +93,19 @@ module ActionView
92
93
  # Find and render a template based on the options given.
93
94
  # :api: private
94
95
  def _render_template(options) #:nodoc:
95
- variant = options[:variant]
96
+ variant = options.delete(:variant)
97
+ assigns = options.delete(:assigns)
98
+ context = view_context
96
99
 
100
+ context.assign assigns if assigns
97
101
  lookup_context.rendered_format = nil if options[:formats]
98
102
  lookup_context.variants = variant if variant
99
103
 
100
- view_renderer.render(view_context, options)
104
+ view_renderer.render(context, options)
101
105
  end
102
106
 
103
- # Assign the rendered format to lookup context.
104
- def _process_format(format, options = {}) #:nodoc:
107
+ # Assign the rendered format to look up context.
108
+ def _process_format(format) #:nodoc:
105
109
  super
106
110
  lookup_context.formats = [format.to_sym]
107
111
  lookup_context.rendered_format = lookup_context.formats.first
@@ -121,7 +125,11 @@ module ActionView
121
125
  key = action.include?(?/) ? :template : :action
122
126
  options[key] = action
123
127
  else
124
- options[:partial] = action
128
+ if action.respond_to?(:permitted?) && action.permitted?
129
+ options = action
130
+ else
131
+ options[:partial] = action
132
+ end
125
133
  end
126
134
 
127
135
  options
@@ -32,7 +32,7 @@ module ActionView
32
32
  #
33
33
  # ==== Examples
34
34
  # <%= url_for(action: 'index') %>
35
- # # => /blog/
35
+ # # => /blogs/
36
36
  #
37
37
  # <%= url_for(action: 'find', controller: 'books') %>
38
38
  # # => /books/find
@@ -84,11 +84,13 @@ module ActionView
84
84
  when Hash
85
85
  options = options.symbolize_keys
86
86
  unless options.key?(:only_path)
87
- if options[:host].nil?
88
- options[:only_path] = _generate_paths_by_default
89
- else
90
- options[:only_path] = false
91
- end
87
+ options[:only_path] = only_path?(options[:host])
88
+ end
89
+
90
+ super(options)
91
+ when ActionController::Parameters
92
+ unless options.key?(:only_path)
93
+ options[:only_path] = only_path?(options[:host])
92
94
  end
93
95
 
94
96
  super(options)
@@ -131,5 +133,15 @@ module ActionView
131
133
  controller.optimize_routes_generation? : super
132
134
  end
133
135
  protected :optimize_routes_generation?
136
+
137
+ private
138
+
139
+ def _generate_paths_by_default
140
+ true
141
+ end
142
+
143
+ def only_path?(host)
144
+ _generate_paths_by_default unless host
145
+ end
134
146
  end
135
147
  end