actionview 4.1.13 → 6.1.3.1
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 +181 -359
- data/MIT-LICENSE +1 -1
- data/README.rdoc +12 -6
- data/lib/action_view/base.rb +115 -43
- data/lib/action_view/buffers.rb +22 -4
- data/lib/action_view/cache_expiry.rb +52 -0
- data/lib/action_view/context.rb +8 -12
- data/lib/action_view/dependency_tracker.rb +61 -21
- data/lib/action_view/digestor.rb +89 -84
- data/lib/action_view/flows.rb +12 -13
- data/lib/action_view/gem_version.rb +6 -4
- data/lib/action_view/helpers/active_model_helper.rb +16 -11
- data/lib/action_view/helpers/asset_tag_helper.rb +311 -105
- data/lib/action_view/helpers/asset_url_helper.rb +197 -80
- data/lib/action_view/helpers/atom_feed_helper.rb +20 -17
- data/lib/action_view/helpers/cache_helper.rb +109 -45
- data/lib/action_view/helpers/capture_helper.rb +20 -22
- data/lib/action_view/helpers/controller_helper.rb +15 -4
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +8 -6
- data/lib/action_view/helpers/date_helper.rb +245 -140
- data/lib/action_view/helpers/debug_helper.rb +14 -17
- data/lib/action_view/helpers/form_helper.rb +875 -148
- data/lib/action_view/helpers/form_options_helper.rb +128 -82
- data/lib/action_view/helpers/form_tag_helper.rb +253 -91
- data/lib/action_view/helpers/javascript_helper.rb +37 -15
- data/lib/action_view/helpers/number_helper.rb +100 -77
- data/lib/action_view/helpers/output_safety_helper.rb +42 -10
- data/lib/action_view/helpers/rendering_helper.rb +26 -15
- data/lib/action_view/helpers/sanitize_helper.rb +79 -164
- data/lib/action_view/helpers/tag_helper.rb +277 -64
- data/lib/action_view/helpers/tags/base.rb +143 -92
- data/lib/action_view/helpers/tags/check_box.rb +20 -19
- data/lib/action_view/helpers/tags/checkable.rb +4 -2
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +12 -30
- data/lib/action_view/helpers/tags/collection_helpers.rb +69 -36
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +6 -12
- data/lib/action_view/helpers/tags/collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/color_field.rb +4 -3
- data/lib/action_view/helpers/tags/date_field.rb +3 -2
- data/lib/action_view/helpers/tags/date_select.rb +38 -37
- data/lib/action_view/helpers/tags/datetime_field.rb +14 -5
- data/lib/action_view/helpers/tags/datetime_local_field.rb +3 -2
- data/lib/action_view/helpers/tags/datetime_select.rb +2 -0
- data/lib/action_view/helpers/tags/email_field.rb +2 -0
- data/lib/action_view/helpers/tags/file_field.rb +2 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +4 -2
- data/lib/action_view/helpers/tags/hidden_field.rb +2 -0
- data/lib/action_view/helpers/tags/label.rb +41 -22
- data/lib/action_view/helpers/tags/month_field.rb +3 -2
- data/lib/action_view/helpers/tags/number_field.rb +2 -0
- data/lib/action_view/helpers/tags/password_field.rb +3 -1
- data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
- data/lib/action_view/helpers/tags/radio_button.rb +7 -6
- data/lib/action_view/helpers/tags/range_field.rb +2 -0
- data/lib/action_view/helpers/tags/search_field.rb +3 -0
- data/lib/action_view/helpers/tags/select.rb +11 -10
- data/lib/action_view/helpers/tags/tel_field.rb +2 -0
- data/lib/action_view/helpers/tags/text_area.rb +7 -1
- data/lib/action_view/helpers/tags/text_field.rb +11 -7
- data/lib/action_view/helpers/tags/time_field.rb +3 -2
- data/lib/action_view/helpers/tags/time_select.rb +2 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +3 -1
- data/lib/action_view/helpers/tags/translator.rb +39 -0
- data/lib/action_view/helpers/tags/url_field.rb +2 -0
- data/lib/action_view/helpers/tags/week_field.rb +3 -2
- data/lib/action_view/helpers/tags.rb +4 -1
- data/lib/action_view/helpers/text_helper.rb +80 -45
- data/lib/action_view/helpers/translation_helper.rb +148 -67
- data/lib/action_view/helpers/url_helper.rb +289 -147
- data/lib/action_view/helpers.rb +5 -3
- data/lib/action_view/layouts.rb +68 -63
- data/lib/action_view/log_subscriber.rb +80 -13
- data/lib/action_view/lookup_context.rb +137 -92
- data/lib/action_view/model_naming.rb +4 -2
- data/lib/action_view/path_set.rb +30 -16
- data/lib/action_view/railtie.rb +62 -13
- data/lib/action_view/record_identifier.rb +53 -26
- data/lib/action_view/renderer/abstract_renderer.rb +152 -13
- data/lib/action_view/renderer/collection_renderer.rb +196 -0
- data/lib/action_view/renderer/object_renderer.rb +34 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +102 -0
- data/lib/action_view/renderer/partial_renderer.rb +61 -261
- data/lib/action_view/renderer/renderer.rb +67 -6
- data/lib/action_view/renderer/streaming_template_renderer.rb +58 -54
- data/lib/action_view/renderer/template_renderer.rb +83 -75
- data/lib/action_view/rendering.rb +73 -46
- data/lib/action_view/routing_url_for.rb +54 -17
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template/error.rb +44 -29
- data/lib/action_view/template/handlers/builder.rb +12 -13
- data/lib/action_view/template/handlers/erb/erubi.rb +89 -0
- data/lib/action_view/template/handlers/erb.rb +23 -89
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +4 -4
- data/lib/action_view/template/handlers.rb +22 -9
- data/lib/action_view/template/html.rb +10 -11
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +25 -0
- data/lib/action_view/template/renderable.rb +24 -0
- data/lib/action_view/template/resolver.rb +267 -181
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/text.rb +8 -10
- data/lib/action_view/template/types.rb +18 -18
- data/lib/action_view/template.rb +109 -99
- data/lib/action_view/test_case.rb +73 -53
- data/lib/action_view/testing/resolvers.rb +24 -33
- data/lib/action_view/unbound_template.rb +31 -0
- data/lib/action_view/version.rb +3 -1
- data/lib/action_view/view_paths.rb +74 -44
- data/lib/action_view.rb +14 -9
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +71 -26
- data/lib/action_view/helpers/record_tag_helper.rb +0 -108
- data/lib/action_view/tasks/dependencies.rake +0 -23
- data/lib/action_view/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_view/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +0 -188
- data/lib/action_view/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_view/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_view/vendor/html-scanner.rb +0 -20
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView
|
2
|
-
module ModelNaming
|
4
|
+
module ModelNaming #:nodoc:
|
3
5
|
# Converts the given object to an ActiveModel compliant one.
|
4
6
|
def convert_to_model(object)
|
5
7
|
object.respond_to?(:to_model) ? object.to_model : object
|
6
8
|
end
|
7
9
|
|
8
10
|
def model_name_from_record_or_class(record_or_class)
|
9
|
-
|
11
|
+
convert_to_model(record_or_class).model_name
|
10
12
|
end
|
11
13
|
end
|
12
14
|
end
|
data/lib/action_view/path_set.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActionView #:nodoc:
|
2
4
|
# = Action View PathSet
|
3
5
|
#
|
@@ -47,31 +49,43 @@ module ActionView #:nodoc:
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def find_all(path, prefixes = [], *args)
|
50
|
-
|
51
|
-
prefixes.each do |prefix|
|
52
|
-
paths.each do |resolver|
|
53
|
-
templates = resolver.find_all(path, prefix, *args)
|
54
|
-
return templates unless templates.empty?
|
55
|
-
end
|
56
|
-
end
|
57
|
-
[]
|
52
|
+
_find_all path, prefixes, args
|
58
53
|
end
|
59
54
|
|
60
55
|
def exists?(path, prefixes, *args)
|
61
56
|
find_all(path, prefixes, *args).any?
|
62
57
|
end
|
63
58
|
|
59
|
+
def find_all_with_query(query) # :nodoc:
|
60
|
+
paths.each do |resolver|
|
61
|
+
templates = resolver.find_all_with_query(query)
|
62
|
+
return templates unless templates.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
[]
|
66
|
+
end
|
67
|
+
|
64
68
|
private
|
69
|
+
def _find_all(path, prefixes, args)
|
70
|
+
prefixes = [prefixes] if String === prefixes
|
71
|
+
prefixes.each do |prefix|
|
72
|
+
paths.each do |resolver|
|
73
|
+
templates = resolver.find_all(path, prefix, *args)
|
74
|
+
return templates unless templates.empty?
|
75
|
+
end
|
76
|
+
end
|
77
|
+
[]
|
78
|
+
end
|
65
79
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
80
|
+
def typecast(paths)
|
81
|
+
paths.map do |path|
|
82
|
+
case path
|
83
|
+
when Pathname, String
|
84
|
+
OptimizedFileSystemResolver.new path.to_s
|
85
|
+
else
|
86
|
+
path
|
87
|
+
end
|
73
88
|
end
|
74
89
|
end
|
75
|
-
end
|
76
90
|
end
|
77
91
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -1,33 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "action_view"
|
2
4
|
require "rails"
|
3
5
|
|
4
6
|
module ActionView
|
5
7
|
# = Action View Railtie
|
6
|
-
class Railtie < Rails::
|
8
|
+
class Railtie < Rails::Engine # :nodoc:
|
7
9
|
config.action_view = ActiveSupport::OrderedOptions.new
|
8
|
-
config.action_view.embed_authenticity_token_in_remote_forms =
|
10
|
+
config.action_view.embed_authenticity_token_in_remote_forms = nil
|
11
|
+
config.action_view.debug_missing_translation = true
|
12
|
+
config.action_view.default_enforce_utf8 = nil
|
9
13
|
|
10
14
|
config.eager_load_namespaces << ActionView
|
11
15
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
config.after_initialize do |app|
|
17
|
+
ActionView::Helpers::FormTagHelper.embed_authenticity_token_in_remote_forms =
|
18
|
+
app.config.action_view.delete(:embed_authenticity_token_in_remote_forms)
|
19
|
+
end
|
20
|
+
|
21
|
+
config.after_initialize do |app|
|
22
|
+
form_with_generates_remote_forms = app.config.action_view.delete(:form_with_generates_remote_forms)
|
23
|
+
ActionView::Helpers::FormHelper.form_with_generates_remote_forms = form_with_generates_remote_forms
|
24
|
+
end
|
25
|
+
|
26
|
+
config.after_initialize do |app|
|
27
|
+
form_with_generates_ids = app.config.action_view.delete(:form_with_generates_ids)
|
28
|
+
unless form_with_generates_ids.nil?
|
29
|
+
ActionView::Helpers::FormHelper.form_with_generates_ids = form_with_generates_ids
|
16
30
|
end
|
17
31
|
end
|
18
32
|
|
19
|
-
|
20
|
-
|
33
|
+
config.after_initialize do |app|
|
34
|
+
default_enforce_utf8 = app.config.action_view.delete(:default_enforce_utf8)
|
35
|
+
unless default_enforce_utf8.nil?
|
36
|
+
ActionView::Helpers::FormTagHelper.default_enforce_utf8 = default_enforce_utf8
|
37
|
+
end
|
21
38
|
end
|
22
39
|
|
23
|
-
|
40
|
+
config.after_initialize do |app|
|
41
|
+
ActionView::Helpers::AssetTagHelper.preload_links_header = app.config.action_view.delete(:preload_links_header)
|
42
|
+
end
|
43
|
+
|
44
|
+
config.after_initialize do |app|
|
24
45
|
ActiveSupport.on_load(:action_view) do
|
25
|
-
app.config.action_view.each do |k,v|
|
46
|
+
app.config.action_view.each do |k, v|
|
47
|
+
if k == :raise_on_missing_translations
|
48
|
+
ActiveSupport::Deprecation.warn \
|
49
|
+
"action_view.raise_on_missing_translations is deprecated and will be removed in Rails 6.2. " \
|
50
|
+
"Set i18n.raise_on_missing_translations instead. " \
|
51
|
+
"Note that this new setting also affects how missing translations are handled in controllers."
|
52
|
+
end
|
26
53
|
send "#{k}=", v
|
27
54
|
end
|
28
55
|
end
|
29
56
|
end
|
30
57
|
|
58
|
+
initializer "action_view.logger" do
|
59
|
+
ActiveSupport.on_load(:action_view) { self.logger ||= Rails.logger }
|
60
|
+
end
|
61
|
+
|
31
62
|
initializer "action_view.caching" do |app|
|
32
63
|
ActiveSupport.on_load(:action_view) do
|
33
64
|
if app.config.action_view.cache_template_loading.nil?
|
@@ -38,12 +69,30 @@ module ActionView
|
|
38
69
|
|
39
70
|
initializer "action_view.setup_action_pack" do |app|
|
40
71
|
ActiveSupport.on_load(:action_controller) do
|
41
|
-
ActionView::RoutingUrlFor.
|
72
|
+
ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor)
|
42
73
|
end
|
43
74
|
end
|
44
75
|
|
45
|
-
|
46
|
-
|
76
|
+
initializer "action_view.collection_caching", after: "action_controller.set_configs" do |app|
|
77
|
+
PartialRenderer.collection_cache = app.config.action_controller.cache_store
|
78
|
+
end
|
79
|
+
|
80
|
+
config.after_initialize do |app|
|
81
|
+
enable_caching = if app.config.action_view.cache_template_loading.nil?
|
82
|
+
app.config.cache_classes
|
83
|
+
else
|
84
|
+
app.config.action_view.cache_template_loading
|
85
|
+
end
|
86
|
+
|
87
|
+
unless enable_caching
|
88
|
+
app.executor.to_run ActionView::CacheExpiry::Executor.new(watcher: app.config.file_watcher)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
rake_tasks do |app|
|
93
|
+
unless app.config.api_only
|
94
|
+
load "action_view/tasks/cache_digests.rake"
|
95
|
+
end
|
47
96
|
end
|
48
97
|
end
|
49
98
|
end
|
@@ -1,38 +1,66 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module"
|
4
|
+
require "action_view/model_naming"
|
3
5
|
|
4
6
|
module ActionView
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# a higher logical level.
|
7
|
+
# RecordIdentifier encapsulates methods used by various ActionView helpers
|
8
|
+
# to associate records with DOM elements.
|
8
9
|
#
|
9
|
-
#
|
10
|
-
# resources :posts
|
10
|
+
# Consider for example the following code that form of post:
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# <% end %> </div>
|
12
|
+
# <%= form_for(post) do |f| %>
|
13
|
+
# <%= f.text_field :body %>
|
14
|
+
# <% end %>
|
16
15
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# post = Post.find(params[:id])
|
20
|
-
# post.update(params[:post])
|
16
|
+
# When +post+ is a new, unsaved ActiveRecord::Base instance, the resulting HTML
|
17
|
+
# is:
|
21
18
|
#
|
22
|
-
#
|
23
|
-
#
|
19
|
+
# <form class="new_post" id="new_post" action="/posts" accept-charset="UTF-8" method="post">
|
20
|
+
# <input type="text" name="post[body]" id="post_body" />
|
21
|
+
# </form>
|
22
|
+
#
|
23
|
+
# When +post+ is a persisted ActiveRecord::Base instance, the resulting HTML
|
24
|
+
# is:
|
25
|
+
#
|
26
|
+
# <form class="edit_post" id="edit_post_42" action="/posts/42" accept-charset="UTF-8" method="post">
|
27
|
+
# <input type="text" value="What a wonderful world!" name="post[body]" id="post_body" />
|
28
|
+
# </form>
|
29
|
+
#
|
30
|
+
# In both cases, the +id+ and +class+ of the wrapping DOM element are
|
31
|
+
# automatically generated, following naming conventions encapsulated by the
|
32
|
+
# RecordIdentifier methods #dom_id and #dom_class:
|
33
|
+
#
|
34
|
+
# dom_id(Post.new) # => "new_post"
|
35
|
+
# dom_class(Post.new) # => "post"
|
36
|
+
# dom_id(Post.find 42) # => "post_42"
|
37
|
+
# dom_class(Post.find 42) # => "post"
|
24
38
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
39
|
+
# Note that these methods do not strictly require +Post+ to be a subclass of
|
40
|
+
# ActiveRecord::Base.
|
41
|
+
# Any +Post+ class will work as long as its instances respond to +to_key+
|
42
|
+
# and +model_name+, given that +model_name+ responds to +param_key+.
|
43
|
+
# For instance:
|
44
|
+
#
|
45
|
+
# class Post
|
46
|
+
# attr_accessor :to_key
|
47
|
+
#
|
48
|
+
# def model_name
|
49
|
+
# OpenStruct.new param_key: 'post'
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# def self.find(id)
|
53
|
+
# new.tap { |post| post.to_key = [id] }
|
54
|
+
# end
|
55
|
+
# end
|
28
56
|
module RecordIdentifier
|
29
57
|
extend self
|
30
58
|
extend ModelNaming
|
31
59
|
|
32
60
|
include ModelNaming
|
33
61
|
|
34
|
-
JOIN =
|
35
|
-
NEW =
|
62
|
+
JOIN = "_"
|
63
|
+
NEW = "new"
|
36
64
|
|
37
65
|
# The DOM class convention is to use the singular form of an object or class.
|
38
66
|
#
|
@@ -66,8 +94,7 @@ module ActionView
|
|
66
94
|
end
|
67
95
|
end
|
68
96
|
|
69
|
-
|
70
|
-
|
97
|
+
private
|
71
98
|
# Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id.
|
72
99
|
# This can be overwritten to customize the default generated string representation if desired.
|
73
100
|
# If you need to read back a key from a dom_id in order to query for the underlying database record,
|
@@ -76,9 +103,9 @@ module ActionView
|
|
76
103
|
# overwritten version of the method. By default, this implementation passes the key string through a
|
77
104
|
# method that replaces all characters that are invalid inside DOM ids, with valid ones. You need to
|
78
105
|
# make sure yourself that your dom ids are valid, in case you overwrite this method.
|
79
|
-
def record_key_for_dom_id(record)
|
106
|
+
def record_key_for_dom_id(record) # :doc:
|
80
107
|
key = convert_to_model(record).to_key
|
81
|
-
key ? key.join(
|
108
|
+
key ? key.join(JOIN) : key
|
82
109
|
end
|
83
110
|
end
|
84
111
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
|
1
5
|
module ActionView
|
2
6
|
# This class defines the interface for a renderer. Each class that
|
3
7
|
# subclasses +AbstractRenderer+ is used by the base +Renderer+ class to
|
@@ -12,10 +16,10 @@ module ActionView
|
|
12
16
|
#
|
13
17
|
# Whenever the +render+ method is called on the base +Renderer+ class, a new
|
14
18
|
# renderer object of the correct type is created, and the +render+ method on
|
15
|
-
# that new object is called in turn. This abstracts the
|
19
|
+
# that new object is called in turn. This abstracts the set up and rendering
|
16
20
|
# into a separate classes for partials and templates.
|
17
21
|
class AbstractRenderer #:nodoc:
|
18
|
-
delegate :
|
22
|
+
delegate :template_exists?, :any_templates?, :formats, to: :@lookup_context
|
19
23
|
|
20
24
|
def initialize(lookup_context)
|
21
25
|
@lookup_context = lookup_context
|
@@ -25,23 +29,158 @@ module ActionView
|
|
25
29
|
raise NotImplementedError
|
26
30
|
end
|
27
31
|
|
28
|
-
|
32
|
+
module ObjectRendering # :nodoc:
|
33
|
+
PREFIXED_PARTIAL_NAMES = Concurrent::Map.new do |h, k|
|
34
|
+
h[k] = Concurrent::Map.new
|
35
|
+
end
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
details[key] = Array(value)
|
37
|
+
def initialize(lookup_context, options)
|
38
|
+
super
|
39
|
+
@context_prefix = lookup_context.prefixes.first
|
34
40
|
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def local_variable(path)
|
44
|
+
if as = @options[:as]
|
45
|
+
raise_invalid_option_as(as) unless /\A[a-z_]\w*\z/.match?(as.to_s)
|
46
|
+
as.to_sym
|
47
|
+
else
|
48
|
+
base = path.end_with?("/") ? "" : File.basename(path)
|
49
|
+
raise_invalid_identifier(path) unless base =~ /\A_?(.*?)(?:\.\w+)*\z/
|
50
|
+
$1.to_sym
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
IDENTIFIER_ERROR_MESSAGE = "The partial name (%s) is not a valid Ruby identifier; " \
|
55
|
+
"make sure your partial name starts with underscore."
|
56
|
+
|
57
|
+
OPTION_AS_ERROR_MESSAGE = "The value (%s) of the option `as` is not a valid Ruby identifier; " \
|
58
|
+
"make sure it starts with lowercase letter, " \
|
59
|
+
"and is followed by any combination of letters, numbers and underscores."
|
60
|
+
|
61
|
+
def raise_invalid_identifier(path)
|
62
|
+
raise ArgumentError, IDENTIFIER_ERROR_MESSAGE % path
|
63
|
+
end
|
64
|
+
|
65
|
+
def raise_invalid_option_as(as)
|
66
|
+
raise ArgumentError, OPTION_AS_ERROR_MESSAGE % as
|
67
|
+
end
|
68
|
+
|
69
|
+
# Obtains the path to where the object's partial is located. If the object
|
70
|
+
# responds to +to_partial_path+, then +to_partial_path+ will be called and
|
71
|
+
# will provide the path. If the object does not respond to +to_partial_path+,
|
72
|
+
# then an +ArgumentError+ is raised.
|
73
|
+
#
|
74
|
+
# If +prefix_partial_path_with_controller_namespace+ is true, then this
|
75
|
+
# method will prefix the partial paths with a namespace.
|
76
|
+
def partial_path(object, view)
|
77
|
+
object = object.to_model if object.respond_to?(:to_model)
|
78
|
+
|
79
|
+
path = if object.respond_to?(:to_partial_path)
|
80
|
+
object.to_partial_path
|
81
|
+
else
|
82
|
+
raise ArgumentError.new("'#{object.inspect}' is not an ActiveModel-compatible object. It must implement :to_partial_path.")
|
83
|
+
end
|
84
|
+
|
85
|
+
if view.prefix_partial_path_with_controller_namespace
|
86
|
+
PREFIXED_PARTIAL_NAMES[@context_prefix][path] ||= merge_prefix_into_object_path(@context_prefix, path.dup)
|
87
|
+
else
|
88
|
+
path
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def merge_prefix_into_object_path(prefix, object_path)
|
93
|
+
if prefix.include?(?/) && object_path.include?(?/)
|
94
|
+
prefixes = []
|
95
|
+
prefix_array = File.dirname(prefix).split("/")
|
96
|
+
object_path_array = object_path.split("/")[0..-3] # skip model dir & partial
|
97
|
+
|
98
|
+
prefix_array.each_with_index do |dir, index|
|
99
|
+
break if dir == object_path_array[index]
|
100
|
+
prefixes << dir
|
101
|
+
end
|
102
|
+
|
103
|
+
(prefixes << object_path).join("/")
|
104
|
+
else
|
105
|
+
object_path
|
106
|
+
end
|
107
|
+
end
|
35
108
|
end
|
36
109
|
|
37
|
-
|
38
|
-
|
110
|
+
class RenderedCollection # :nodoc:
|
111
|
+
def self.empty(format)
|
112
|
+
EmptyCollection.new format
|
113
|
+
end
|
114
|
+
|
115
|
+
attr_reader :rendered_templates
|
116
|
+
|
117
|
+
def initialize(rendered_templates, spacer)
|
118
|
+
@rendered_templates = rendered_templates
|
119
|
+
@spacer = spacer
|
120
|
+
end
|
121
|
+
|
122
|
+
def body
|
123
|
+
@rendered_templates.map(&:body).join(@spacer.body).html_safe
|
124
|
+
end
|
125
|
+
|
126
|
+
def format
|
127
|
+
rendered_templates.first.format
|
128
|
+
end
|
129
|
+
|
130
|
+
class EmptyCollection
|
131
|
+
attr_reader :format
|
132
|
+
|
133
|
+
def initialize(format)
|
134
|
+
@format = format
|
135
|
+
end
|
136
|
+
|
137
|
+
def body; nil; end
|
138
|
+
end
|
39
139
|
end
|
40
140
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
141
|
+
class RenderedTemplate # :nodoc:
|
142
|
+
attr_reader :body, :template
|
143
|
+
|
144
|
+
def initialize(body, template)
|
145
|
+
@body = body
|
146
|
+
@template = template
|
147
|
+
end
|
148
|
+
|
149
|
+
def format
|
150
|
+
template.format
|
151
|
+
end
|
152
|
+
|
153
|
+
EMPTY_SPACER = Struct.new(:body).new
|
45
154
|
end
|
155
|
+
|
156
|
+
private
|
157
|
+
NO_DETAILS = {}.freeze
|
158
|
+
|
159
|
+
def extract_details(options) # :doc:
|
160
|
+
details = nil
|
161
|
+
@lookup_context.registered_details.each do |key|
|
162
|
+
value = options[key]
|
163
|
+
|
164
|
+
if value
|
165
|
+
(details ||= {})[key] = Array(value)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
details || NO_DETAILS
|
169
|
+
end
|
170
|
+
|
171
|
+
def prepend_formats(formats) # :doc:
|
172
|
+
formats = Array(formats)
|
173
|
+
return if formats.empty? || @lookup_context.html_fallback_for_js
|
174
|
+
|
175
|
+
@lookup_context.formats = formats | @lookup_context.formats
|
176
|
+
end
|
177
|
+
|
178
|
+
def build_rendered_template(content, template)
|
179
|
+
RenderedTemplate.new content, template
|
180
|
+
end
|
181
|
+
|
182
|
+
def build_rendered_collection(templates, spacer)
|
183
|
+
RenderedCollection.new templates, spacer
|
184
|
+
end
|
46
185
|
end
|
47
186
|
end
|