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/lib/action_view/layouts.rb
CHANGED
@@ -228,7 +228,7 @@ module ActionView
|
|
228
228
|
# set by the <tt>layout</tt> method.
|
229
229
|
#
|
230
230
|
# ==== Returns
|
231
|
-
# * <tt>
|
231
|
+
# * <tt>Boolean</tt> - True if the action has a layout definition, false otherwise.
|
232
232
|
def _conditional_layout?
|
233
233
|
return unless super
|
234
234
|
|
@@ -262,7 +262,7 @@ module ActionView
|
|
262
262
|
def layout(layout, conditions = {})
|
263
263
|
include LayoutConditions unless conditions.empty?
|
264
264
|
|
265
|
-
conditions.each {|k, v| conditions[k] = Array(v).map
|
265
|
+
conditions.each {|k, v| conditions[k] = Array(v).map(&:to_s) }
|
266
266
|
self._layout_conditions = conditions
|
267
267
|
|
268
268
|
self._layout = layout
|
@@ -277,7 +277,7 @@ module ActionView
|
|
277
277
|
remove_possible_method(:_layout)
|
278
278
|
|
279
279
|
prefixes = _implied_layout_name =~ /\blayouts/ ? [] : ["layouts"]
|
280
|
-
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}).first || super"
|
280
|
+
default_behavior = "lookup_context.find_all('#{_implied_layout_name}', #{prefixes.inspect}, false, [], { formats: formats }).first || super"
|
281
281
|
name_clause = if name
|
282
282
|
default_behavior
|
283
283
|
else
|
@@ -316,7 +316,7 @@ module ActionView
|
|
316
316
|
end
|
317
317
|
|
318
318
|
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
319
|
-
def _layout
|
319
|
+
def _layout(formats)
|
320
320
|
if _conditional_layout?
|
321
321
|
#{layout_definition}
|
322
322
|
else
|
@@ -372,7 +372,7 @@ module ActionView
|
|
372
372
|
end
|
373
373
|
|
374
374
|
# This will be overwritten by _write_layout_method
|
375
|
-
def _layout; end
|
375
|
+
def _layout(*); end
|
376
376
|
|
377
377
|
# Determine the layout for a given name, taking into account the name type.
|
378
378
|
#
|
@@ -382,8 +382,8 @@ module ActionView
|
|
382
382
|
case name
|
383
383
|
when String then _normalize_layout(name)
|
384
384
|
when Proc then name
|
385
|
-
when true then Proc.new { _default_layout(true) }
|
386
|
-
when :default then Proc.new { _default_layout(false) }
|
385
|
+
when true then Proc.new { |formats| _default_layout(formats, true) }
|
386
|
+
when :default then Proc.new { |formats| _default_layout(formats, false) }
|
387
387
|
when false, nil then nil
|
388
388
|
else
|
389
389
|
raise ArgumentError,
|
@@ -399,14 +399,15 @@ module ActionView
|
|
399
399
|
# Optionally raises an exception if the layout could not be found.
|
400
400
|
#
|
401
401
|
# ==== Parameters
|
402
|
+
# * <tt>formats</tt> - The formats accepted to this layout
|
402
403
|
# * <tt>require_layout</tt> - If set to true and layout is not found,
|
403
|
-
# an ArgumentError exception is raised (defaults to false)
|
404
|
+
# an +ArgumentError+ exception is raised (defaults to false)
|
404
405
|
#
|
405
406
|
# ==== Returns
|
406
407
|
# * <tt>template</tt> - The template object for the default layout (or nil)
|
407
|
-
def _default_layout(require_layout = false)
|
408
|
+
def _default_layout(formats, require_layout = false)
|
408
409
|
begin
|
409
|
-
value = _layout if action_has_layout?
|
410
|
+
value = _layout(formats) if action_has_layout?
|
410
411
|
rescue NameError => e
|
411
412
|
raise e, "Could not render layout: #{e.message}"
|
412
413
|
end
|
@@ -20,7 +20,23 @@ module ActionView
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
alias :render_partial :render_template
|
23
|
-
|
23
|
+
|
24
|
+
def render_collection(event)
|
25
|
+
identifier = event.payload[:identifier] || 'templates'
|
26
|
+
|
27
|
+
info do
|
28
|
+
" Rendered collection of #{from_rails_root(identifier)}" \
|
29
|
+
" #{render_count(event.payload)} (#{event.duration.round(1)}ms)"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def start(name, id, payload)
|
34
|
+
if name == "render_template.action_view"
|
35
|
+
log_rendering_start(payload)
|
36
|
+
end
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
24
40
|
|
25
41
|
def logger
|
26
42
|
ActionView::Base.logger
|
@@ -38,6 +54,24 @@ module ActionView
|
|
38
54
|
def rails_root
|
39
55
|
@root ||= "#{Rails.root}/"
|
40
56
|
end
|
57
|
+
|
58
|
+
def render_count(payload)
|
59
|
+
if payload[:cache_hits]
|
60
|
+
"[#{payload[:cache_hits]} / #{payload[:count]} cache hits]"
|
61
|
+
else
|
62
|
+
"[#{payload[:count]} times]"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def log_rendering_start(payload)
|
69
|
+
info do
|
70
|
+
message = " Rendering #{from_rails_root(payload[:identifier])}"
|
71
|
+
message << " within #{from_rails_root(payload[:layout])}" if payload[:layout]
|
72
|
+
message
|
73
|
+
end
|
74
|
+
end
|
41
75
|
end
|
42
76
|
end
|
43
77
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'concurrent/map'
|
2
2
|
require 'active_support/core_ext/module/remove_method'
|
3
3
|
require 'active_support/core_ext/module/attribute_accessors'
|
4
4
|
require 'action_view/template/resolver'
|
@@ -6,10 +6,11 @@ require 'action_view/template/resolver'
|
|
6
6
|
module ActionView
|
7
7
|
# = Action View Lookup Context
|
8
8
|
#
|
9
|
-
# LookupContext is the object responsible
|
10
|
-
# templates, i.e. view paths and details.
|
11
|
-
#
|
12
|
-
#
|
9
|
+
# <tt>LookupContext</tt> is the object responsible for holding all information
|
10
|
+
# required for looking up templates, i.e. view paths and details.
|
11
|
+
# <tt>LookupContext</tt> is also responsible for generating a key, given to
|
12
|
+
# view paths, used in the resolver cache lookup. Since this key is generated
|
13
|
+
# only once during the request, it speeds up all cache accesses.
|
13
14
|
class LookupContext #:nodoc:
|
14
15
|
attr_accessor :prefixes, :rendered_format
|
15
16
|
|
@@ -19,9 +20,9 @@ module ActionView
|
|
19
20
|
mattr_accessor :registered_details
|
20
21
|
self.registered_details = []
|
21
22
|
|
22
|
-
def self.register_detail(name,
|
23
|
+
def self.register_detail(name, &block)
|
23
24
|
self.registered_details << name
|
24
|
-
|
25
|
+
Accessors::DEFAULT_PROCS[name] = block
|
25
26
|
|
26
27
|
Accessors.send :define_method, :"default_#{name}", &block
|
27
28
|
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
@@ -33,16 +34,12 @@ module ActionView
|
|
33
34
|
value = value.present? ? Array(value) : default_#{name}
|
34
35
|
_set_detail(:#{name}, value) if value != @details[:#{name}]
|
35
36
|
end
|
36
|
-
|
37
|
-
remove_possible_method :initialize_details
|
38
|
-
def initialize_details(details)
|
39
|
-
#{initialize.join("\n")}
|
40
|
-
end
|
41
37
|
METHOD
|
42
38
|
end
|
43
39
|
|
44
40
|
# Holds accessors for the registered details.
|
45
41
|
module Accessors #:nodoc:
|
42
|
+
DEFAULT_PROCS = {}
|
46
43
|
end
|
47
44
|
|
48
45
|
register_detail(:locale) do
|
@@ -54,19 +51,17 @@ module ActionView
|
|
54
51
|
end
|
55
52
|
register_detail(:formats) { ActionView::Base.default_formats || [:html, :text, :js, :css, :xml, :json] }
|
56
53
|
register_detail(:variants) { [] }
|
57
|
-
register_detail(:handlers){ Template::Handlers.extensions }
|
54
|
+
register_detail(:handlers) { Template::Handlers.extensions }
|
58
55
|
|
59
56
|
class DetailsKey #:nodoc:
|
60
57
|
alias :eql? :equal?
|
61
|
-
alias :object_hash :hash
|
62
58
|
|
63
|
-
|
64
|
-
@details_keys = ThreadSafe::Cache.new
|
59
|
+
@details_keys = Concurrent::Map.new
|
65
60
|
|
66
61
|
def self.get(details)
|
67
62
|
if details[:formats]
|
68
63
|
details = details.dup
|
69
|
-
details[:formats] &=
|
64
|
+
details[:formats] &= Template::Types.symbols
|
70
65
|
end
|
71
66
|
@details_keys[details] ||= new
|
72
67
|
end
|
@@ -75,8 +70,14 @@ module ActionView
|
|
75
70
|
@details_keys.clear
|
76
71
|
end
|
77
72
|
|
73
|
+
def self.digest_caches
|
74
|
+
@details_keys.values.map(&:digest_cache)
|
75
|
+
end
|
76
|
+
|
77
|
+
attr_reader :digest_cache
|
78
|
+
|
78
79
|
def initialize
|
79
|
-
@
|
80
|
+
@digest_cache = Concurrent::Map.new
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
@@ -130,11 +131,16 @@ module ActionView
|
|
130
131
|
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys, options))
|
131
132
|
end
|
132
133
|
|
133
|
-
def exists?(name, prefixes = [], partial = false, keys = [], options
|
134
|
+
def exists?(name, prefixes = [], partial = false, keys = [], **options)
|
134
135
|
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys, options))
|
135
136
|
end
|
136
137
|
alias :template_exists? :exists?
|
137
138
|
|
139
|
+
def any?(name, prefixes = [], partial = false)
|
140
|
+
@view_paths.exists?(*args_for_any(name, prefixes, partial))
|
141
|
+
end
|
142
|
+
alias :any_templates? :any?
|
143
|
+
|
138
144
|
# Adds fallbacks to the view paths. Useful in cases when you are rendering
|
139
145
|
# a :file.
|
140
146
|
def with_fallbacks
|
@@ -171,18 +177,44 @@ module ActionView
|
|
171
177
|
[user_details, details_key]
|
172
178
|
end
|
173
179
|
|
180
|
+
def args_for_any(name, prefixes, partial) # :nodoc:
|
181
|
+
name, prefixes = normalize_name(name, prefixes)
|
182
|
+
details, details_key = detail_args_for_any
|
183
|
+
[name, prefixes, partial || false, details, details_key]
|
184
|
+
end
|
185
|
+
|
186
|
+
def detail_args_for_any # :nodoc:
|
187
|
+
@detail_args_for_any ||= begin
|
188
|
+
details = {}
|
189
|
+
|
190
|
+
registered_details.each do |k|
|
191
|
+
if k == :variants
|
192
|
+
details[k] = :any
|
193
|
+
else
|
194
|
+
details[k] = Accessors::DEFAULT_PROCS[k].call
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
if @cache
|
199
|
+
[details, DetailsKey.get(details)]
|
200
|
+
else
|
201
|
+
[details, nil]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
174
206
|
# Support legacy foo.erb names even though we now ignore .erb
|
175
207
|
# as well as incorrectly putting part of the path in the template
|
176
208
|
# name instead of the prefix.
|
177
209
|
def normalize_name(name, prefixes) #:nodoc:
|
178
210
|
prefixes = prefixes.presence
|
179
|
-
parts = name.to_s.split('/')
|
211
|
+
parts = name.to_s.split('/'.freeze)
|
180
212
|
parts.shift if parts.first.empty?
|
181
213
|
name = parts.pop
|
182
214
|
|
183
215
|
return name, prefixes || [""] if parts.empty?
|
184
216
|
|
185
|
-
parts = parts.join('/')
|
217
|
+
parts = parts.join('/'.freeze)
|
186
218
|
prefixes = prefixes ? prefixes.map { |p| "#{p}/#{parts}" } : [parts]
|
187
219
|
|
188
220
|
return name, prefixes
|
@@ -194,21 +226,32 @@ module ActionView
|
|
194
226
|
include ViewPaths
|
195
227
|
|
196
228
|
def initialize(view_paths, details = {}, prefixes = [])
|
197
|
-
@
|
198
|
-
@skip_default_locale = false
|
229
|
+
@details_key = nil
|
199
230
|
@cache = true
|
200
231
|
@prefixes = prefixes
|
201
232
|
@rendered_format = nil
|
202
233
|
|
234
|
+
@details = initialize_details({}, details)
|
203
235
|
self.view_paths = view_paths
|
204
|
-
initialize_details(details)
|
205
236
|
end
|
206
237
|
|
238
|
+
def digest_cache
|
239
|
+
details_key.digest_cache
|
240
|
+
end
|
241
|
+
|
242
|
+
def initialize_details(target, details)
|
243
|
+
registered_details.each do |k|
|
244
|
+
target[k] = details[k] || Accessors::DEFAULT_PROCS[k].call
|
245
|
+
end
|
246
|
+
target
|
247
|
+
end
|
248
|
+
private :initialize_details
|
249
|
+
|
207
250
|
# Override formats= to expand ["*/*"] values and automatically
|
208
251
|
# add :html as fallback to :js.
|
209
252
|
def formats=(values)
|
210
253
|
if values
|
211
|
-
values.concat(default_formats) if values.delete "*/*"
|
254
|
+
values.concat(default_formats) if values.delete "*/*".freeze
|
212
255
|
if values == [:js]
|
213
256
|
values << :html
|
214
257
|
@html_fallback_for_js = true
|
@@ -217,12 +260,6 @@ module ActionView
|
|
217
260
|
super(values)
|
218
261
|
end
|
219
262
|
|
220
|
-
# Do not use the default locale on template lookup.
|
221
|
-
def skip_default_locale!
|
222
|
-
@skip_default_locale = true
|
223
|
-
self.locale = nil
|
224
|
-
end
|
225
|
-
|
226
263
|
# Override locale to return a symbol instead of array.
|
227
264
|
def locale
|
228
265
|
@details[:locale].first
|
@@ -237,23 +274,7 @@ module ActionView
|
|
237
274
|
config.locale = value
|
238
275
|
end
|
239
276
|
|
240
|
-
super(
|
241
|
-
end
|
242
|
-
|
243
|
-
# Uses the first format in the formats array for layout lookup.
|
244
|
-
def with_layout_format
|
245
|
-
if formats.size == 1
|
246
|
-
yield
|
247
|
-
else
|
248
|
-
old_formats = formats
|
249
|
-
_set_detail(:formats, formats[0,1])
|
250
|
-
|
251
|
-
begin
|
252
|
-
yield
|
253
|
-
ensure
|
254
|
-
_set_detail(:formats, old_formats)
|
255
|
-
end
|
256
|
-
end
|
277
|
+
super(default_locale)
|
257
278
|
end
|
258
279
|
end
|
259
280
|
end
|
data/lib/action_view/path_set.rb
CHANGED
@@ -58,6 +58,15 @@ module ActionView #:nodoc:
|
|
58
58
|
find_all(path, prefixes, *args).any?
|
59
59
|
end
|
60
60
|
|
61
|
+
def find_all_with_query(query) # :nodoc:
|
62
|
+
paths.each do |resolver|
|
63
|
+
templates = resolver.find_all_with_query(query)
|
64
|
+
return templates unless templates.empty?
|
65
|
+
end
|
66
|
+
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
|
61
70
|
private
|
62
71
|
|
63
72
|
def _find_all(path, prefixes, args, outside_app)
|
data/lib/action_view/railtie.rb
CHANGED
@@ -6,6 +6,7 @@ module ActionView
|
|
6
6
|
class Railtie < Rails::Railtie # :nodoc:
|
7
7
|
config.action_view = ActiveSupport::OrderedOptions.new
|
8
8
|
config.action_view.embed_authenticity_token_in_remote_forms = false
|
9
|
+
config.action_view.debug_missing_translation = true
|
9
10
|
|
10
11
|
config.eager_load_namespaces << ActionView
|
11
12
|
|
@@ -36,14 +37,28 @@ module ActionView
|
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
40
|
+
initializer "action_view.per_request_digest_cache" do |app|
|
41
|
+
ActiveSupport.on_load(:action_view) do
|
42
|
+
if app.config.consider_all_requests_local
|
43
|
+
app.executor.to_run ActionView::Digestor::PerExecutionDigestCacheExpiry
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
39
48
|
initializer "action_view.setup_action_pack" do |app|
|
40
49
|
ActiveSupport.on_load(:action_controller) do
|
41
|
-
ActionView::RoutingUrlFor.
|
50
|
+
ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor)
|
42
51
|
end
|
43
52
|
end
|
44
53
|
|
45
|
-
|
46
|
-
|
54
|
+
initializer "action_view.collection_caching", after: "action_controller.set_configs" do |app|
|
55
|
+
PartialRenderer.collection_cache = app.config.action_controller.cache_store
|
56
|
+
end
|
57
|
+
|
58
|
+
rake_tasks do |app|
|
59
|
+
unless app.config.api_only
|
60
|
+
load "action_view/tasks/cache_digests.rake"
|
61
|
+
end
|
47
62
|
end
|
48
63
|
end
|
49
64
|
end
|
@@ -2,29 +2,55 @@ require 'active_support/core_ext/module'
|
|
2
2
|
require 'action_view/model_naming'
|
3
3
|
|
4
4
|
module ActionView
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# a higher logical level.
|
5
|
+
# RecordIdentifier encapsulates methods used by various ActionView helpers
|
6
|
+
# to associate records with DOM elements.
|
8
7
|
#
|
9
|
-
#
|
10
|
-
# resources :posts
|
8
|
+
# Consider for example the following code that form of post:
|
11
9
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# <% end %> </div>
|
10
|
+
# <%= form_for(post) do |f| %>
|
11
|
+
# <%= f.text_field :body %>
|
12
|
+
# <% end %>
|
16
13
|
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
# post = Post.find(params[:id])
|
20
|
-
# post.update(params[:post])
|
14
|
+
# When +post+ is a new, unsaved ActiveRecord::Base instance, the resulting HTML
|
15
|
+
# is:
|
21
16
|
#
|
22
|
-
#
|
23
|
-
#
|
17
|
+
# <form class="new_post" id="new_post" action="/posts" accept-charset="UTF-8" method="post">
|
18
|
+
# <input type="text" name="post[body]" id="post_body" />
|
19
|
+
# </form>
|
20
|
+
#
|
21
|
+
# When +post+ is a persisted ActiveRecord::Base instance, the resulting HTML
|
22
|
+
# is:
|
23
|
+
#
|
24
|
+
# <form class="edit_post" id="edit_post_42" action="/posts/42" accept-charset="UTF-8" method="post">
|
25
|
+
# <input type="text" value="What a wonderful world!" name="post[body]" id="post_body" />
|
26
|
+
# </form>
|
27
|
+
#
|
28
|
+
# In both cases, the +id+ and +class+ of the wrapping DOM element are
|
29
|
+
# automatically generated, following naming conventions encapsulated by the
|
30
|
+
# RecordIdentifier methods #dom_id and #dom_class:
|
31
|
+
#
|
32
|
+
# dom_id(Post.new) # => "new_post"
|
33
|
+
# dom_class(Post.new) # => "post"
|
34
|
+
# dom_id(Post.find 42) # => "post_42"
|
35
|
+
# dom_class(Post.find 42) # => "post"
|
24
36
|
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
37
|
+
# Note that these methods do not strictly require +Post+ to be a subclass of
|
38
|
+
# ActiveRecord::Base.
|
39
|
+
# Any +Post+ class will work as long as its instances respond to +to_key+
|
40
|
+
# and +model_name+, given that +model_name+ responds to +param_key+.
|
41
|
+
# For instance:
|
42
|
+
#
|
43
|
+
# class Post
|
44
|
+
# attr_accessor :to_key
|
45
|
+
#
|
46
|
+
# def model_name
|
47
|
+
# OpenStruct.new param_key: 'post'
|
48
|
+
# end
|
49
|
+
#
|
50
|
+
# def self.find(id)
|
51
|
+
# new.tap { |post| post.to_key = [id] }
|
52
|
+
# end
|
53
|
+
# end
|
28
54
|
module RecordIdentifier
|
29
55
|
extend self
|
30
56
|
extend ModelNaming
|
@@ -78,7 +104,7 @@ module ActionView
|
|
78
104
|
# make sure yourself that your dom ids are valid, in case you overwrite this method.
|
79
105
|
def record_key_for_dom_id(record)
|
80
106
|
key = convert_to_model(record).to_key
|
81
|
-
key ? key.join(
|
107
|
+
key ? key.join(JOIN) : key
|
82
108
|
end
|
83
109
|
end
|
84
110
|
end
|