actionview 4.1.0.beta1
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 +274 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +34 -0
- data/lib/action_view.rb +97 -0
- data/lib/action_view/base.rb +205 -0
- data/lib/action_view/buffers.rb +49 -0
- data/lib/action_view/context.rb +36 -0
- data/lib/action_view/dependency_tracker.rb +93 -0
- data/lib/action_view/digestor.rb +116 -0
- data/lib/action_view/flows.rb +76 -0
- data/lib/action_view/helpers.rb +64 -0
- data/lib/action_view/helpers/active_model_helper.rb +49 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +322 -0
- data/lib/action_view/helpers/asset_url_helper.rb +355 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +203 -0
- data/lib/action_view/helpers/cache_helper.rb +200 -0
- data/lib/action_view/helpers/capture_helper.rb +216 -0
- data/lib/action_view/helpers/controller_helper.rb +25 -0
- data/lib/action_view/helpers/csrf_helper.rb +30 -0
- data/lib/action_view/helpers/date_helper.rb +1075 -0
- data/lib/action_view/helpers/debug_helper.rb +39 -0
- data/lib/action_view/helpers/form_helper.rb +1876 -0
- data/lib/action_view/helpers/form_options_helper.rb +843 -0
- data/lib/action_view/helpers/form_tag_helper.rb +746 -0
- data/lib/action_view/helpers/javascript_helper.rb +75 -0
- data/lib/action_view/helpers/number_helper.rb +425 -0
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +108 -0
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +256 -0
- data/lib/action_view/helpers/tag_helper.rb +176 -0
- data/lib/action_view/helpers/tags.rb +41 -0
- data/lib/action_view/helpers/tags/base.rb +148 -0
- data/lib/action_view/helpers/tags/check_box.rb +64 -0
- data/lib/action_view/helpers/tags/checkable.rb +16 -0
- data/lib/action_view/helpers/tags/collection_check_boxes.rb +44 -0
- data/lib/action_view/helpers/tags/collection_helpers.rb +85 -0
- data/lib/action_view/helpers/tags/collection_radio_buttons.rb +36 -0
- data/lib/action_view/helpers/tags/collection_select.rb +28 -0
- data/lib/action_view/helpers/tags/color_field.rb +25 -0
- data/lib/action_view/helpers/tags/date_field.rb +13 -0
- data/lib/action_view/helpers/tags/date_select.rb +72 -0
- data/lib/action_view/helpers/tags/datetime_field.rb +22 -0
- data/lib/action_view/helpers/tags/datetime_local_field.rb +19 -0
- data/lib/action_view/helpers/tags/datetime_select.rb +8 -0
- data/lib/action_view/helpers/tags/email_field.rb +8 -0
- data/lib/action_view/helpers/tags/file_field.rb +8 -0
- data/lib/action_view/helpers/tags/grouped_collection_select.rb +29 -0
- data/lib/action_view/helpers/tags/hidden_field.rb +8 -0
- data/lib/action_view/helpers/tags/label.rb +65 -0
- data/lib/action_view/helpers/tags/month_field.rb +13 -0
- data/lib/action_view/helpers/tags/number_field.rb +18 -0
- data/lib/action_view/helpers/tags/password_field.rb +12 -0
- data/lib/action_view/helpers/tags/radio_button.rb +31 -0
- data/lib/action_view/helpers/tags/range_field.rb +8 -0
- data/lib/action_view/helpers/tags/search_field.rb +24 -0
- data/lib/action_view/helpers/tags/select.rb +41 -0
- data/lib/action_view/helpers/tags/tel_field.rb +8 -0
- data/lib/action_view/helpers/tags/text_area.rb +18 -0
- data/lib/action_view/helpers/tags/text_field.rb +29 -0
- data/lib/action_view/helpers/tags/time_field.rb +13 -0
- data/lib/action_view/helpers/tags/time_select.rb +8 -0
- data/lib/action_view/helpers/tags/time_zone_select.rb +20 -0
- data/lib/action_view/helpers/tags/url_field.rb +8 -0
- data/lib/action_view/helpers/tags/week_field.rb +13 -0
- data/lib/action_view/helpers/text_helper.rb +447 -0
- data/lib/action_view/helpers/translation_helper.rb +111 -0
- data/lib/action_view/helpers/url_helper.rb +625 -0
- data/lib/action_view/layouts.rb +426 -0
- data/lib/action_view/locale/en.yml +56 -0
- data/lib/action_view/log_subscriber.rb +44 -0
- data/lib/action_view/lookup_context.rb +249 -0
- data/lib/action_view/model_naming.rb +12 -0
- data/lib/action_view/path_set.rb +77 -0
- data/lib/action_view/railtie.rb +49 -0
- data/lib/action_view/record_identifier.rb +84 -0
- data/lib/action_view/renderer/abstract_renderer.rb +47 -0
- data/lib/action_view/renderer/partial_renderer.rb +492 -0
- data/lib/action_view/renderer/renderer.rb +50 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +103 -0
- data/lib/action_view/renderer/template_renderer.rb +96 -0
- data/lib/action_view/rendering.rb +145 -0
- data/lib/action_view/routing_url_for.rb +109 -0
- data/lib/action_view/tasks/dependencies.rake +17 -0
- data/lib/action_view/template.rb +340 -0
- data/lib/action_view/template/error.rb +141 -0
- data/lib/action_view/template/handlers.rb +53 -0
- data/lib/action_view/template/handlers/builder.rb +26 -0
- data/lib/action_view/template/handlers/erb.rb +145 -0
- data/lib/action_view/template/handlers/raw.rb +11 -0
- data/lib/action_view/template/resolver.rb +329 -0
- data/lib/action_view/template/text.rb +34 -0
- data/lib/action_view/template/types.rb +57 -0
- data/lib/action_view/test_case.rb +272 -0
- data/lib/action_view/testing/resolvers.rb +50 -0
- data/lib/action_view/vendor/html-scanner.rb +20 -0
- data/lib/action_view/vendor/html-scanner/html/document.rb +68 -0
- data/lib/action_view/vendor/html-scanner/html/node.rb +532 -0
- data/lib/action_view/vendor/html-scanner/html/sanitizer.rb +188 -0
- data/lib/action_view/vendor/html-scanner/html/selector.rb +830 -0
- data/lib/action_view/vendor/html-scanner/html/tokenizer.rb +107 -0
- data/lib/action_view/vendor/html-scanner/html/version.rb +11 -0
- data/lib/action_view/version.rb +11 -0
- data/lib/action_view/view_paths.rb +96 -0
- metadata +218 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_support/core_ext/string/output_safety'
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class OutputBuffer < ActiveSupport::SafeBuffer #:nodoc:
|
5
|
+
def initialize(*)
|
6
|
+
super
|
7
|
+
encode!
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(value)
|
11
|
+
return self if value.nil?
|
12
|
+
super(value.to_s)
|
13
|
+
end
|
14
|
+
alias :append= :<<
|
15
|
+
|
16
|
+
def safe_concat(value)
|
17
|
+
return self if value.nil?
|
18
|
+
super(value.to_s)
|
19
|
+
end
|
20
|
+
alias :safe_append= :safe_concat
|
21
|
+
end
|
22
|
+
|
23
|
+
class StreamingBuffer #:nodoc:
|
24
|
+
def initialize(block)
|
25
|
+
@block = block
|
26
|
+
end
|
27
|
+
|
28
|
+
def <<(value)
|
29
|
+
value = value.to_s
|
30
|
+
value = ERB::Util.h(value) unless value.html_safe?
|
31
|
+
@block.call(value)
|
32
|
+
end
|
33
|
+
alias :concat :<<
|
34
|
+
alias :append= :<<
|
35
|
+
|
36
|
+
def safe_concat(value)
|
37
|
+
@block.call(value.to_s)
|
38
|
+
end
|
39
|
+
alias :safe_append= :safe_concat
|
40
|
+
|
41
|
+
def html_safe?
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def html_safe
|
46
|
+
self
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActionView
|
2
|
+
module CompiledTemplates #:nodoc:
|
3
|
+
# holds compiled template code
|
4
|
+
end
|
5
|
+
|
6
|
+
# = Action View Context
|
7
|
+
#
|
8
|
+
# Action View contexts are supplied to Action Controller to render a template.
|
9
|
+
# The default Action View context is ActionView::Base.
|
10
|
+
#
|
11
|
+
# In order to work with ActionController, a Context must just include this module.
|
12
|
+
# The initialization of the variables used by the context (@output_buffer, @view_flow,
|
13
|
+
# and @virtual_path) is responsibility of the object that includes this module
|
14
|
+
# (although you can call _prepare_context defined below).
|
15
|
+
module Context
|
16
|
+
include CompiledTemplates
|
17
|
+
attr_accessor :output_buffer, :view_flow
|
18
|
+
|
19
|
+
# Prepares the context by setting the appropriate instance variables.
|
20
|
+
# :api: plugin
|
21
|
+
def _prepare_context
|
22
|
+
@view_flow = OutputFlow.new
|
23
|
+
@output_buffer = nil
|
24
|
+
@virtual_path = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# Encapsulates the interaction with the view flow so it
|
28
|
+
# returns the correct buffer on +yield+. This is usually
|
29
|
+
# overwritten by helpers to add more behavior.
|
30
|
+
# :api: plugin
|
31
|
+
def _layout_for(name=nil)
|
32
|
+
name ||= :layout
|
33
|
+
view_flow.get(name).html_safe
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'thread_safe'
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class DependencyTracker
|
5
|
+
@trackers = ThreadSafe::Cache.new
|
6
|
+
|
7
|
+
def self.find_dependencies(name, template)
|
8
|
+
tracker = @trackers[template.handler]
|
9
|
+
|
10
|
+
if tracker.present?
|
11
|
+
tracker.call(name, template)
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.register_tracker(extension, tracker)
|
18
|
+
handler = Template.handler_for_extension(extension)
|
19
|
+
@trackers[handler] = tracker
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.remove_tracker(handler)
|
23
|
+
@trackers.delete(handler)
|
24
|
+
end
|
25
|
+
|
26
|
+
class ERBTracker
|
27
|
+
EXPLICIT_DEPENDENCY = /# Template Dependency: (\S+)/
|
28
|
+
|
29
|
+
# Matches:
|
30
|
+
# render partial: "comments/comment", collection: commentable.comments
|
31
|
+
# render "comments/comments"
|
32
|
+
# render 'comments/comments'
|
33
|
+
# render('comments/comments')
|
34
|
+
#
|
35
|
+
# render(@topic) => render("topics/topic")
|
36
|
+
# render(topics) => render("topics/topic")
|
37
|
+
# render(message.topics) => render("topics/topic")
|
38
|
+
RENDER_DEPENDENCY = /
|
39
|
+
render\s* # render, followed by optional whitespace
|
40
|
+
\(? # start an optional parenthesis for the render call
|
41
|
+
(partial:|:partial\s+=>)?\s* # naming the partial, used with collection -- 1st capture
|
42
|
+
([@a-z"'][@\w\/\."']+) # the template name itself -- 2nd capture
|
43
|
+
/x
|
44
|
+
|
45
|
+
def self.call(name, template)
|
46
|
+
new(name, template).dependencies
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(name, template)
|
50
|
+
@name, @template = name, template
|
51
|
+
end
|
52
|
+
|
53
|
+
def dependencies
|
54
|
+
render_dependencies + explicit_dependencies
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_reader :name, :template
|
58
|
+
private :name, :template
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def source
|
63
|
+
template.source
|
64
|
+
end
|
65
|
+
|
66
|
+
def directory
|
67
|
+
name.split("/")[0..-2].join("/")
|
68
|
+
end
|
69
|
+
|
70
|
+
def render_dependencies
|
71
|
+
source.scan(RENDER_DEPENDENCY).
|
72
|
+
collect(&:second).uniq.
|
73
|
+
|
74
|
+
# render(@topic) => render("topics/topic")
|
75
|
+
# render(topics) => render("topics/topic")
|
76
|
+
# render(message.topics) => render("topics/topic")
|
77
|
+
collect { |name| name.sub(/\A@?([a-z_]+\.)*([a-z_]+)\z/) { "#{$2.pluralize}/#{$2.singularize}" } }.
|
78
|
+
|
79
|
+
# render("headline") => render("message/headline")
|
80
|
+
collect { |name| name.include?("/") ? name : "#{directory}/#{name}" }.
|
81
|
+
|
82
|
+
# replace quotes from string renders
|
83
|
+
collect { |name| name.gsub(/["']/, "") }
|
84
|
+
end
|
85
|
+
|
86
|
+
def explicit_dependencies
|
87
|
+
source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
register_tracker :erb, ERBTracker
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'thread_safe'
|
2
|
+
require 'action_view/dependency_tracker'
|
3
|
+
require 'monitor'
|
4
|
+
|
5
|
+
module ActionView
|
6
|
+
class Digestor
|
7
|
+
cattr_reader(:cache)
|
8
|
+
@@cache = ThreadSafe::Cache.new
|
9
|
+
@@digest_monitor = Monitor.new
|
10
|
+
|
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('.')
|
16
|
+
|
17
|
+
# this is a correctly done double-checked locking idiom
|
18
|
+
# (ThreadSafe::Cache's lookups have volatile semantics)
|
19
|
+
@@cache[cache_key] || @@digest_monitor.synchronize do
|
20
|
+
@@cache.fetch(cache_key) do # re-check under lock
|
21
|
+
compute_and_store_digest(cache_key, name, format, finder, options)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
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
|
37
|
+
|
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
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_reader :name, :format, :finder, :options
|
49
|
+
|
50
|
+
def initialize(name, format, finder, options={})
|
51
|
+
@name, @format, @finder, @options = name, format, finder, options
|
52
|
+
end
|
53
|
+
|
54
|
+
def digest
|
55
|
+
Digest::MD5.hexdigest("#{source}-#{dependency_digest}").tap do |digest|
|
56
|
+
logger.try :info, "Cache digest for #{name}.#{format}: #{digest}"
|
57
|
+
end
|
58
|
+
rescue ActionView::MissingTemplate
|
59
|
+
logger.try :error, "Couldn't find template for digesting: #{name}.#{format}"
|
60
|
+
''
|
61
|
+
end
|
62
|
+
|
63
|
+
def dependencies
|
64
|
+
DependencyTracker.find_dependencies(name, template)
|
65
|
+
rescue ActionView::MissingTemplate
|
66
|
+
[] # File doesn't exist, so no dependencies
|
67
|
+
end
|
68
|
+
|
69
|
+
def nested_dependencies
|
70
|
+
dependencies.collect do |dependency|
|
71
|
+
dependencies = PartialDigestor.new(dependency, format, finder).nested_dependencies
|
72
|
+
dependencies.any? ? { dependency => dependencies } : dependency
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def logger
|
79
|
+
ActionView::Base.logger
|
80
|
+
end
|
81
|
+
|
82
|
+
def logical_name
|
83
|
+
name.gsub(%r|/_|, "/")
|
84
|
+
end
|
85
|
+
|
86
|
+
def partial?
|
87
|
+
false
|
88
|
+
end
|
89
|
+
|
90
|
+
def template
|
91
|
+
@template ||= finder.find(logical_name, [], partial?, formats: [ format ])
|
92
|
+
end
|
93
|
+
|
94
|
+
def source
|
95
|
+
template.source
|
96
|
+
end
|
97
|
+
|
98
|
+
def dependency_digest
|
99
|
+
template_digests = dependencies.collect do |template_name|
|
100
|
+
Digestor.digest(template_name, format, finder, partial: true)
|
101
|
+
end
|
102
|
+
|
103
|
+
(template_digests + injected_dependencies).join("-")
|
104
|
+
end
|
105
|
+
|
106
|
+
def injected_dependencies
|
107
|
+
Array.wrap(options[:dependencies])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class PartialDigestor < Digestor # :nodoc:
|
112
|
+
def partial?
|
113
|
+
true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'active_support/core_ext/string/output_safety'
|
2
|
+
|
3
|
+
module ActionView
|
4
|
+
class OutputFlow #:nodoc:
|
5
|
+
attr_reader :content
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@content = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
|
9
|
+
end
|
10
|
+
|
11
|
+
# Called by _layout_for to read stored values.
|
12
|
+
def get(key)
|
13
|
+
@content[key]
|
14
|
+
end
|
15
|
+
|
16
|
+
# Called by each renderer object to set the layout contents.
|
17
|
+
def set(key, value)
|
18
|
+
@content[key] = value
|
19
|
+
end
|
20
|
+
|
21
|
+
# Called by content_for
|
22
|
+
def append(key, value)
|
23
|
+
@content[key] << value
|
24
|
+
end
|
25
|
+
alias_method :append!, :append
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class StreamingFlow < OutputFlow #:nodoc:
|
30
|
+
def initialize(view, fiber)
|
31
|
+
@view = view
|
32
|
+
@parent = nil
|
33
|
+
@child = view.output_buffer
|
34
|
+
@content = view.view_flow.content
|
35
|
+
@fiber = fiber
|
36
|
+
@root = Fiber.current.object_id
|
37
|
+
end
|
38
|
+
|
39
|
+
# Try to get stored content. If the content
|
40
|
+
# is not available and we are inside the layout
|
41
|
+
# fiber, we set that we are waiting for the given
|
42
|
+
# key and yield.
|
43
|
+
def get(key)
|
44
|
+
return super if @content.key?(key)
|
45
|
+
|
46
|
+
if inside_fiber?
|
47
|
+
view = @view
|
48
|
+
|
49
|
+
begin
|
50
|
+
@waiting_for = key
|
51
|
+
view.output_buffer, @parent = @child, view.output_buffer
|
52
|
+
Fiber.yield
|
53
|
+
ensure
|
54
|
+
@waiting_for = nil
|
55
|
+
view.output_buffer, @child = @parent, view.output_buffer
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
super
|
60
|
+
end
|
61
|
+
|
62
|
+
# Appends the contents for the given key. This is called
|
63
|
+
# by provides and resumes back to the fiber if it is
|
64
|
+
# the key it is waiting for.
|
65
|
+
def append!(key, value)
|
66
|
+
super
|
67
|
+
@fiber.resume if @waiting_for == key
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def inside_fiber?
|
73
|
+
Fiber.current.object_id != @root
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'active_support/benchmarkable'
|
2
|
+
|
3
|
+
module ActionView #:nodoc:
|
4
|
+
module Helpers #:nodoc:
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :ActiveModelHelper
|
8
|
+
autoload :AssetTagHelper
|
9
|
+
autoload :AssetUrlHelper
|
10
|
+
autoload :AtomFeedHelper
|
11
|
+
autoload :CacheHelper
|
12
|
+
autoload :CaptureHelper
|
13
|
+
autoload :ControllerHelper
|
14
|
+
autoload :CsrfHelper
|
15
|
+
autoload :DateHelper
|
16
|
+
autoload :DebugHelper
|
17
|
+
autoload :FormHelper
|
18
|
+
autoload :FormOptionsHelper
|
19
|
+
autoload :FormTagHelper
|
20
|
+
autoload :JavaScriptHelper, "action_view/helpers/javascript_helper"
|
21
|
+
autoload :NumberHelper
|
22
|
+
autoload :OutputSafetyHelper
|
23
|
+
autoload :RecordTagHelper
|
24
|
+
autoload :RenderingHelper
|
25
|
+
autoload :SanitizeHelper
|
26
|
+
autoload :TagHelper
|
27
|
+
autoload :TextHelper
|
28
|
+
autoload :TranslationHelper
|
29
|
+
autoload :UrlHelper
|
30
|
+
autoload :Tags
|
31
|
+
|
32
|
+
def self.eager_load!
|
33
|
+
super
|
34
|
+
Tags.eager_load!
|
35
|
+
end
|
36
|
+
|
37
|
+
extend ActiveSupport::Concern
|
38
|
+
|
39
|
+
include ActiveSupport::Benchmarkable
|
40
|
+
include ActiveModelHelper
|
41
|
+
include AssetTagHelper
|
42
|
+
include AssetUrlHelper
|
43
|
+
include AtomFeedHelper
|
44
|
+
include CacheHelper
|
45
|
+
include CaptureHelper
|
46
|
+
include ControllerHelper
|
47
|
+
include CsrfHelper
|
48
|
+
include DateHelper
|
49
|
+
include DebugHelper
|
50
|
+
include FormHelper
|
51
|
+
include FormOptionsHelper
|
52
|
+
include FormTagHelper
|
53
|
+
include JavaScriptHelper
|
54
|
+
include NumberHelper
|
55
|
+
include OutputSafetyHelper
|
56
|
+
include RecordTagHelper
|
57
|
+
include RenderingHelper
|
58
|
+
include SanitizeHelper
|
59
|
+
include TagHelper
|
60
|
+
include TextHelper
|
61
|
+
include TranslationHelper
|
62
|
+
include UrlHelper
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
require 'active_support/core_ext/enumerable'
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
# = Active Model Helpers
|
6
|
+
module Helpers
|
7
|
+
module ActiveModelHelper
|
8
|
+
end
|
9
|
+
|
10
|
+
module ActiveModelInstanceTag
|
11
|
+
def object
|
12
|
+
@active_model_object ||= begin
|
13
|
+
object = super
|
14
|
+
object.respond_to?(:to_model) ? object.to_model : object
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def content_tag(*)
|
19
|
+
error_wrapping(super)
|
20
|
+
end
|
21
|
+
|
22
|
+
def tag(type, options, *)
|
23
|
+
tag_generate_errors?(options) ? error_wrapping(super) : super
|
24
|
+
end
|
25
|
+
|
26
|
+
def error_wrapping(html_tag)
|
27
|
+
if object_has_errors?
|
28
|
+
Base.field_error_proc.call(html_tag, self)
|
29
|
+
else
|
30
|
+
html_tag
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def error_message
|
35
|
+
object.errors[@method_name]
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def object_has_errors?
|
41
|
+
object.respond_to?(:errors) && object.errors.respond_to?(:[]) && error_message.present?
|
42
|
+
end
|
43
|
+
|
44
|
+
def tag_generate_errors?(options)
|
45
|
+
options['type'] != 'hidden'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|