actionview 6.0.0
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 +7 -0
- data/CHANGELOG.md +271 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +40 -0
- data/lib/action_view.rb +98 -0
- data/lib/action_view/base.rb +312 -0
- data/lib/action_view/buffers.rb +67 -0
- data/lib/action_view/cache_expiry.rb +54 -0
- data/lib/action_view/context.rb +32 -0
- data/lib/action_view/dependency_tracker.rb +175 -0
- data/lib/action_view/digestor.rb +126 -0
- data/lib/action_view/flows.rb +76 -0
- data/lib/action_view/gem_version.rb +17 -0
- data/lib/action_view/helpers.rb +66 -0
- data/lib/action_view/helpers/active_model_helper.rb +55 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +488 -0
- data/lib/action_view/helpers/asset_url_helper.rb +470 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +205 -0
- data/lib/action_view/helpers/cache_helper.rb +271 -0
- data/lib/action_view/helpers/capture_helper.rb +216 -0
- data/lib/action_view/helpers/controller_helper.rb +36 -0
- data/lib/action_view/helpers/csp_helper.rb +26 -0
- data/lib/action_view/helpers/csrf_helper.rb +35 -0
- data/lib/action_view/helpers/date_helper.rb +1200 -0
- data/lib/action_view/helpers/debug_helper.rb +36 -0
- data/lib/action_view/helpers/form_helper.rb +2569 -0
- data/lib/action_view/helpers/form_options_helper.rb +896 -0
- data/lib/action_view/helpers/form_tag_helper.rb +920 -0
- data/lib/action_view/helpers/javascript_helper.rb +95 -0
- data/lib/action_view/helpers/number_helper.rb +456 -0
- data/lib/action_view/helpers/output_safety_helper.rb +70 -0
- data/lib/action_view/helpers/rendering_helper.rb +101 -0
- data/lib/action_view/helpers/sanitize_helper.rb +171 -0
- data/lib/action_view/helpers/tag_helper.rb +314 -0
- data/lib/action_view/helpers/tags.rb +44 -0
- data/lib/action_view/helpers/tags/base.rb +196 -0
- data/lib/action_view/helpers/tags/check_box.rb +66 -0
- data/lib/action_view/helpers/tags/checkable.rb +18 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +36 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +119 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +31 -0
- data/lib/action_view/helpers/tags/collection_select.rb +30 -0
- data/lib/action_view/helpers/tags/color_field.rb +27 -0
- data/lib/action_view/helpers/tags/date_field.rb +15 -0
- data/lib/action_view/helpers/tags/date_select.rb +74 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +32 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +21 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +10 -0
- data/lib/action_view/helpers/tags/email_field.rb +10 -0
- data/lib/action_view/helpers/tags/file_field.rb +10 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +31 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +10 -0
- data/lib/action_view/helpers/tags/label.rb +81 -0
- data/lib/action_view/helpers/tags/month_field.rb +15 -0
- data/lib/action_view/helpers/tags/number_field.rb +20 -0
- data/lib/action_view/helpers/tags/password_field.rb +14 -0
- data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
- data/lib/action_view/helpers/tags/radio_button.rb +33 -0
- data/lib/action_view/helpers/tags/range_field.rb +10 -0
- data/lib/action_view/helpers/tags/search_field.rb +27 -0
- data/lib/action_view/helpers/tags/select.rb +43 -0
- data/lib/action_view/helpers/tags/tel_field.rb +10 -0
- data/lib/action_view/helpers/tags/text_area.rb +24 -0
- data/lib/action_view/helpers/tags/text_field.rb +34 -0
- data/lib/action_view/helpers/tags/time_field.rb +15 -0
- data/lib/action_view/helpers/tags/time_select.rb +10 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +22 -0
- data/lib/action_view/helpers/tags/translator.rb +39 -0
- data/lib/action_view/helpers/tags/url_field.rb +10 -0
- data/lib/action_view/helpers/tags/week_field.rb +15 -0
- data/lib/action_view/helpers/text_helper.rb +486 -0
- data/lib/action_view/helpers/translation_helper.rb +145 -0
- data/lib/action_view/helpers/url_helper.rb +676 -0
- data/lib/action_view/layouts.rb +433 -0
- data/lib/action_view/locale/en.yml +56 -0
- data/lib/action_view/log_subscriber.rb +96 -0
- data/lib/action_view/lookup_context.rb +316 -0
- data/lib/action_view/model_naming.rb +14 -0
- data/lib/action_view/path_set.rb +95 -0
- data/lib/action_view/railtie.rb +105 -0
- data/lib/action_view/record_identifier.rb +112 -0
- data/lib/action_view/renderer/abstract_renderer.rb +108 -0
- data/lib/action_view/renderer/partial_renderer.rb +563 -0
- data/lib/action_view/renderer/partial_renderer/collection_caching.rb +103 -0
- data/lib/action_view/renderer/renderer.rb +68 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +105 -0
- data/lib/action_view/renderer/template_renderer.rb +108 -0
- data/lib/action_view/rendering.rb +171 -0
- data/lib/action_view/routing_url_for.rb +146 -0
- data/lib/action_view/tasks/cache_digests.rake +25 -0
- data/lib/action_view/template.rb +393 -0
- data/lib/action_view/template/error.rb +161 -0
- data/lib/action_view/template/handlers.rb +92 -0
- data/lib/action_view/template/handlers/builder.rb +25 -0
- data/lib/action_view/template/handlers/erb.rb +84 -0
- data/lib/action_view/template/handlers/erb/erubi.rb +87 -0
- data/lib/action_view/template/handlers/html.rb +11 -0
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/html.rb +43 -0
- data/lib/action_view/template/inline.rb +22 -0
- data/lib/action_view/template/raw_file.rb +28 -0
- data/lib/action_view/template/resolver.rb +394 -0
- data/lib/action_view/template/sources.rb +13 -0
- data/lib/action_view/template/sources/file.rb +17 -0
- data/lib/action_view/template/text.rb +35 -0
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/test_case.rb +300 -0
- data/lib/action_view/testing/resolvers.rb +67 -0
- data/lib/action_view/unbound_template.rb +32 -0
- data/lib/action_view/version.rb +10 -0
- data/lib/action_view/view_paths.rb +129 -0
- data/lib/assets/compiled/rails-ujs.js +746 -0
- metadata +260 -0
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/log_subscriber"
|
4
|
+
|
5
|
+
module ActionView
|
6
|
+
# = Action View Log Subscriber
|
7
|
+
#
|
8
|
+
# Provides functionality so that Rails can output logs from Action View.
|
9
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
10
|
+
VIEWS_PATTERN = /^app\/views\//
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@root = nil
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def render_template(event)
|
18
|
+
info do
|
19
|
+
message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
|
20
|
+
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
21
|
+
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def render_partial(event)
|
26
|
+
info do
|
27
|
+
message = +" Rendered #{from_rails_root(event.payload[:identifier])}"
|
28
|
+
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
29
|
+
message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
30
|
+
message << " #{cache_message(event.payload)}" unless event.payload[:cache_hit].nil?
|
31
|
+
message
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_collection(event)
|
36
|
+
identifier = event.payload[:identifier] || "templates"
|
37
|
+
|
38
|
+
info do
|
39
|
+
" Rendered collection of #{from_rails_root(identifier)}" \
|
40
|
+
" #{render_count(event.payload)} (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def start(name, id, payload)
|
45
|
+
if name == "render_template.action_view"
|
46
|
+
log_rendering_start(payload)
|
47
|
+
end
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def logger
|
53
|
+
ActionView::Base.logger
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
EMPTY = ""
|
59
|
+
def from_rails_root(string) # :doc:
|
60
|
+
string = string.sub(rails_root, EMPTY)
|
61
|
+
string.sub!(VIEWS_PATTERN, EMPTY)
|
62
|
+
string
|
63
|
+
end
|
64
|
+
|
65
|
+
def rails_root # :doc:
|
66
|
+
@root ||= "#{Rails.root}/"
|
67
|
+
end
|
68
|
+
|
69
|
+
def render_count(payload) # :doc:
|
70
|
+
if payload[:cache_hits]
|
71
|
+
"[#{payload[:cache_hits]} / #{payload[:count]} cache hits]"
|
72
|
+
else
|
73
|
+
"[#{payload[:count]} times]"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def cache_message(payload) # :doc:
|
78
|
+
case payload[:cache_hit]
|
79
|
+
when :hit
|
80
|
+
"[cache hit]"
|
81
|
+
when :miss
|
82
|
+
"[cache miss]"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def log_rendering_start(payload)
|
87
|
+
info do
|
88
|
+
message = +" Rendering #{from_rails_root(payload[:identifier])}"
|
89
|
+
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
90
|
+
message
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
ActionView::LogSubscriber.attach_to :action_view
|
@@ -0,0 +1,316 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
require "active_support/core_ext/module/remove_method"
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "active_support/deprecation"
|
7
|
+
require "action_view/template/resolver"
|
8
|
+
|
9
|
+
module ActionView
|
10
|
+
# = Action View Lookup Context
|
11
|
+
#
|
12
|
+
# <tt>LookupContext</tt> is the object responsible for holding all information
|
13
|
+
# required for looking up templates, i.e. view paths and details.
|
14
|
+
# <tt>LookupContext</tt> is also responsible for generating a key, given to
|
15
|
+
# view paths, used in the resolver cache lookup. Since this key is generated
|
16
|
+
# only once during the request, it speeds up all cache accesses.
|
17
|
+
class LookupContext #:nodoc:
|
18
|
+
attr_accessor :prefixes, :rendered_format
|
19
|
+
deprecate :rendered_format
|
20
|
+
deprecate :rendered_format=
|
21
|
+
|
22
|
+
mattr_accessor :fallbacks, default: FallbackFileSystemResolver.instances
|
23
|
+
|
24
|
+
mattr_accessor :registered_details, default: []
|
25
|
+
|
26
|
+
def self.register_detail(name, &block)
|
27
|
+
registered_details << name
|
28
|
+
Accessors::DEFAULT_PROCS[name] = block
|
29
|
+
|
30
|
+
Accessors.define_method(:"default_#{name}", &block)
|
31
|
+
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
32
|
+
def #{name}
|
33
|
+
@details.fetch(:#{name}, [])
|
34
|
+
end
|
35
|
+
|
36
|
+
def #{name}=(value)
|
37
|
+
value = value.present? ? Array(value) : default_#{name}
|
38
|
+
_set_detail(:#{name}, value) if value != @details[:#{name}]
|
39
|
+
end
|
40
|
+
METHOD
|
41
|
+
end
|
42
|
+
|
43
|
+
# Holds accessors for the registered details.
|
44
|
+
module Accessors #:nodoc:
|
45
|
+
DEFAULT_PROCS = {}
|
46
|
+
end
|
47
|
+
|
48
|
+
register_detail(:locale) do
|
49
|
+
locales = [I18n.locale]
|
50
|
+
locales.concat(I18n.fallbacks[I18n.locale]) if I18n.respond_to? :fallbacks
|
51
|
+
locales << I18n.default_locale
|
52
|
+
locales.uniq!
|
53
|
+
locales
|
54
|
+
end
|
55
|
+
register_detail(:formats) { ActionView::Base.default_formats || [:html, :text, :js, :css, :xml, :json] }
|
56
|
+
register_detail(:variants) { [] }
|
57
|
+
register_detail(:handlers) { Template::Handlers.extensions }
|
58
|
+
|
59
|
+
class DetailsKey #:nodoc:
|
60
|
+
alias :eql? :equal?
|
61
|
+
|
62
|
+
@details_keys = Concurrent::Map.new
|
63
|
+
@digest_cache = Concurrent::Map.new
|
64
|
+
|
65
|
+
def self.digest_cache(details)
|
66
|
+
@digest_cache[details_cache_key(details)] ||= Concurrent::Map.new
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.details_cache_key(details)
|
70
|
+
if details[:formats]
|
71
|
+
details = details.dup
|
72
|
+
details[:formats] &= Template::Types.symbols
|
73
|
+
end
|
74
|
+
@details_keys[details] ||= Object.new
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.clear
|
78
|
+
ActionView::ViewPaths.all_view_paths.each do |path_set|
|
79
|
+
path_set.each(&:clear_cache)
|
80
|
+
end
|
81
|
+
ActionView::LookupContext.fallbacks.each(&:clear_cache)
|
82
|
+
@view_context_class = nil
|
83
|
+
@details_keys.clear
|
84
|
+
@digest_cache.clear
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.digest_caches
|
88
|
+
@digest_cache.values
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.view_context_class(klass)
|
92
|
+
@view_context_class ||= klass.with_empty_template_cache
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Add caching behavior on top of Details.
|
97
|
+
module DetailsCache
|
98
|
+
attr_accessor :cache
|
99
|
+
|
100
|
+
# Calculate the details key. Remove the handlers from calculation to improve performance
|
101
|
+
# since the user cannot modify it explicitly.
|
102
|
+
def details_key #:nodoc:
|
103
|
+
@details_key ||= DetailsKey.details_cache_key(@details) if @cache
|
104
|
+
end
|
105
|
+
|
106
|
+
# Temporary skip passing the details_key forward.
|
107
|
+
def disable_cache
|
108
|
+
old_value, @cache = @cache, false
|
109
|
+
yield
|
110
|
+
ensure
|
111
|
+
@cache = old_value
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def _set_detail(key, value) # :doc:
|
117
|
+
@details = @details.dup if @digest_cache || @details_key
|
118
|
+
@digest_cache = nil
|
119
|
+
@details_key = nil
|
120
|
+
@details[key] = value
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Helpers related to template lookup using the lookup context information.
|
125
|
+
module ViewPaths
|
126
|
+
attr_reader :view_paths, :html_fallback_for_js
|
127
|
+
|
128
|
+
def find(name, prefixes = [], partial = false, keys = [], options = {})
|
129
|
+
@view_paths.find(*args_for_lookup(name, prefixes, partial, keys, options))
|
130
|
+
end
|
131
|
+
alias :find_template :find
|
132
|
+
|
133
|
+
alias :find_file :find
|
134
|
+
deprecate :find_file
|
135
|
+
|
136
|
+
def find_all(name, prefixes = [], partial = false, keys = [], options = {})
|
137
|
+
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
138
|
+
end
|
139
|
+
|
140
|
+
def exists?(name, prefixes = [], partial = false, keys = [], **options)
|
141
|
+
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys, options))
|
142
|
+
end
|
143
|
+
alias :template_exists? :exists?
|
144
|
+
|
145
|
+
def any?(name, prefixes = [], partial = false)
|
146
|
+
@view_paths.exists?(*args_for_any(name, prefixes, partial))
|
147
|
+
end
|
148
|
+
alias :any_templates? :any?
|
149
|
+
|
150
|
+
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
151
|
+
# a :file.
|
152
|
+
def with_fallbacks
|
153
|
+
view_paths = build_view_paths((@view_paths.paths + self.class.fallbacks).uniq)
|
154
|
+
|
155
|
+
if block_given?
|
156
|
+
ActiveSupport::Deprecation.warn <<~eowarn.squish
|
157
|
+
Calling `with_fallbacks` with a block is deprecated. Call methods on
|
158
|
+
the lookup context returned by `with_fallbacks` instead.
|
159
|
+
eowarn
|
160
|
+
|
161
|
+
begin
|
162
|
+
_view_paths = @view_paths
|
163
|
+
@view_paths = view_paths
|
164
|
+
yield
|
165
|
+
ensure
|
166
|
+
@view_paths = _view_paths
|
167
|
+
end
|
168
|
+
else
|
169
|
+
ActionView::LookupContext.new(view_paths, @details, @prefixes)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
private
|
174
|
+
|
175
|
+
# Whenever setting view paths, makes a copy so that we can manipulate them in
|
176
|
+
# instance objects as we wish.
|
177
|
+
def build_view_paths(paths)
|
178
|
+
ActionView::PathSet.new(Array(paths))
|
179
|
+
end
|
180
|
+
|
181
|
+
def args_for_lookup(name, prefixes, partial, keys, details_options)
|
182
|
+
name, prefixes = normalize_name(name, prefixes)
|
183
|
+
details, details_key = detail_args_for(details_options)
|
184
|
+
[name, prefixes, partial || false, details, details_key, keys]
|
185
|
+
end
|
186
|
+
|
187
|
+
# Compute details hash and key according to user options (e.g. passed from #render).
|
188
|
+
def detail_args_for(options) # :doc:
|
189
|
+
return @details, details_key if options.empty? # most common path.
|
190
|
+
user_details = @details.merge(options)
|
191
|
+
|
192
|
+
if @cache
|
193
|
+
details_key = DetailsKey.details_cache_key(user_details)
|
194
|
+
else
|
195
|
+
details_key = nil
|
196
|
+
end
|
197
|
+
|
198
|
+
[user_details, details_key]
|
199
|
+
end
|
200
|
+
|
201
|
+
def args_for_any(name, prefixes, partial)
|
202
|
+
name, prefixes = normalize_name(name, prefixes)
|
203
|
+
details, details_key = detail_args_for_any
|
204
|
+
[name, prefixes, partial || false, details, details_key]
|
205
|
+
end
|
206
|
+
|
207
|
+
def detail_args_for_any
|
208
|
+
@detail_args_for_any ||= begin
|
209
|
+
details = {}
|
210
|
+
|
211
|
+
registered_details.each do |k|
|
212
|
+
if k == :variants
|
213
|
+
details[k] = :any
|
214
|
+
else
|
215
|
+
details[k] = Accessors::DEFAULT_PROCS[k].call
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
if @cache
|
220
|
+
[details, DetailsKey.details_cache_key(details)]
|
221
|
+
else
|
222
|
+
[details, nil]
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Support legacy foo.erb names even though we now ignore .erb
|
228
|
+
# as well as incorrectly putting part of the path in the template
|
229
|
+
# name instead of the prefix.
|
230
|
+
def normalize_name(name, prefixes)
|
231
|
+
prefixes = prefixes.presence
|
232
|
+
parts = name.to_s.split("/")
|
233
|
+
parts.shift if parts.first.empty?
|
234
|
+
name = parts.pop
|
235
|
+
|
236
|
+
return name, prefixes || [""] if parts.empty?
|
237
|
+
|
238
|
+
parts = parts.join("/")
|
239
|
+
prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts]
|
240
|
+
|
241
|
+
return name, prefixes
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
include Accessors
|
246
|
+
include DetailsCache
|
247
|
+
include ViewPaths
|
248
|
+
|
249
|
+
def initialize(view_paths, details = {}, prefixes = [])
|
250
|
+
@details_key = nil
|
251
|
+
@digest_cache = nil
|
252
|
+
@cache = true
|
253
|
+
@prefixes = prefixes
|
254
|
+
|
255
|
+
@details = initialize_details({}, details)
|
256
|
+
@view_paths = build_view_paths(view_paths)
|
257
|
+
end
|
258
|
+
|
259
|
+
def digest_cache
|
260
|
+
@digest_cache ||= DetailsKey.digest_cache(@details)
|
261
|
+
end
|
262
|
+
|
263
|
+
def with_prepended_formats(formats)
|
264
|
+
details = @details.dup
|
265
|
+
details[:formats] = formats
|
266
|
+
|
267
|
+
self.class.new(@view_paths, details, @prefixes)
|
268
|
+
end
|
269
|
+
|
270
|
+
def initialize_details(target, details)
|
271
|
+
registered_details.each do |k|
|
272
|
+
target[k] = details[k] || Accessors::DEFAULT_PROCS[k].call
|
273
|
+
end
|
274
|
+
target
|
275
|
+
end
|
276
|
+
private :initialize_details
|
277
|
+
|
278
|
+
# Override formats= to expand ["*/*"] values and automatically
|
279
|
+
# add :html as fallback to :js.
|
280
|
+
def formats=(values)
|
281
|
+
if values
|
282
|
+
values = values.dup
|
283
|
+
values.concat(default_formats) if values.delete "*/*"
|
284
|
+
values.uniq!
|
285
|
+
|
286
|
+
invalid_values = (values - Template::Types.symbols)
|
287
|
+
unless invalid_values.empty?
|
288
|
+
raise ArgumentError, "Invalid formats: #{invalid_values.map(&:inspect).join(", ")}"
|
289
|
+
end
|
290
|
+
|
291
|
+
if values == [:js]
|
292
|
+
values << :html
|
293
|
+
@html_fallback_for_js = true
|
294
|
+
end
|
295
|
+
end
|
296
|
+
super(values)
|
297
|
+
end
|
298
|
+
|
299
|
+
# Override locale to return a symbol instead of array.
|
300
|
+
def locale
|
301
|
+
@details[:locale].first
|
302
|
+
end
|
303
|
+
|
304
|
+
# Overload locale= to also set the I18n.locale. If the current I18n.config object responds
|
305
|
+
# to original_config, it means that it has a copy of the original I18n configuration and it's
|
306
|
+
# acting as proxy, which we need to skip.
|
307
|
+
def locale=(value)
|
308
|
+
if value
|
309
|
+
config = I18n.config.respond_to?(:original_config) ? I18n.config.original_config : I18n.config
|
310
|
+
config.locale = value
|
311
|
+
end
|
312
|
+
|
313
|
+
super(default_locale)
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
module ModelNaming #:nodoc:
|
5
|
+
# Converts the given object to an ActiveModel compliant one.
|
6
|
+
def convert_to_model(object)
|
7
|
+
object.respond_to?(:to_model) ? object.to_model : object
|
8
|
+
end
|
9
|
+
|
10
|
+
def model_name_from_record_or_class(record_or_class)
|
11
|
+
convert_to_model(record_or_class).model_name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
# = Action View PathSet
|
5
|
+
#
|
6
|
+
# This class is used to store and access paths in Action View. A number of
|
7
|
+
# operations are defined so that you can search among the paths in this
|
8
|
+
# set and also perform operations on other +PathSet+ objects.
|
9
|
+
#
|
10
|
+
# A +LookupContext+ will use a +PathSet+ to store the paths in its context.
|
11
|
+
class PathSet #:nodoc:
|
12
|
+
include Enumerable
|
13
|
+
|
14
|
+
attr_reader :paths
|
15
|
+
|
16
|
+
delegate :[], :include?, :pop, :size, :each, to: :paths
|
17
|
+
|
18
|
+
def initialize(paths = [])
|
19
|
+
@paths = typecast paths
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize_copy(other)
|
23
|
+
@paths = other.paths.dup
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_ary
|
28
|
+
paths.dup
|
29
|
+
end
|
30
|
+
|
31
|
+
def compact
|
32
|
+
PathSet.new paths.compact
|
33
|
+
end
|
34
|
+
|
35
|
+
def +(array)
|
36
|
+
PathSet.new(paths + array)
|
37
|
+
end
|
38
|
+
|
39
|
+
%w(<< concat push insert unshift).each do |method|
|
40
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
41
|
+
def #{method}(*args)
|
42
|
+
paths.#{method}(*typecast(args))
|
43
|
+
end
|
44
|
+
METHOD
|
45
|
+
end
|
46
|
+
|
47
|
+
def find(*args)
|
48
|
+
find_all(*args).first || raise(MissingTemplate.new(self, *args))
|
49
|
+
end
|
50
|
+
|
51
|
+
alias :find_file :find
|
52
|
+
deprecate :find_file
|
53
|
+
|
54
|
+
def find_all(path, prefixes = [], *args)
|
55
|
+
_find_all path, prefixes, args
|
56
|
+
end
|
57
|
+
|
58
|
+
def exists?(path, prefixes, *args)
|
59
|
+
find_all(path, prefixes, *args).any?
|
60
|
+
end
|
61
|
+
|
62
|
+
def find_all_with_query(query) # :nodoc:
|
63
|
+
paths.each do |resolver|
|
64
|
+
templates = resolver.find_all_with_query(query)
|
65
|
+
return templates unless templates.empty?
|
66
|
+
end
|
67
|
+
|
68
|
+
[]
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def _find_all(path, prefixes, args)
|
74
|
+
prefixes = [prefixes] if String === prefixes
|
75
|
+
prefixes.each do |prefix|
|
76
|
+
paths.each do |resolver|
|
77
|
+
templates = resolver.find_all(path, prefix, *args)
|
78
|
+
return templates unless templates.empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
[]
|
82
|
+
end
|
83
|
+
|
84
|
+
def typecast(paths)
|
85
|
+
paths.map do |path|
|
86
|
+
case path
|
87
|
+
when Pathname, String
|
88
|
+
OptimizedFileSystemResolver.new path.to_s
|
89
|
+
else
|
90
|
+
path
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|