actionpack 3.0.20 → 3.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 actionpack might be problematic. Click here for more details.
- data/CHANGELOG +88 -142
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +24 -19
- data/lib/abstract_controller/callbacks.rb +19 -19
- data/lib/abstract_controller/helpers.rb +11 -13
- data/lib/abstract_controller/layouts.rb +4 -5
- data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
- data/lib/abstract_controller/rendering.rb +34 -31
- data/lib/abstract_controller/url_for.rb +27 -0
- data/lib/abstract_controller/view_paths.rb +31 -6
- data/lib/action_controller.rb +5 -3
- data/lib/action_controller/base.rb +15 -16
- data/lib/action_controller/caching.rb +2 -2
- data/lib/action_controller/caching/actions.rb +11 -12
- data/lib/action_controller/caching/fragments.rb +41 -19
- data/lib/action_controller/caching/pages.rb +3 -9
- data/lib/action_controller/caching/sweeping.rb +0 -1
- data/lib/action_controller/deprecated.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +78 -20
- data/lib/action_controller/metal/compatibility.rb +0 -9
- data/lib/action_controller/metal/conditional_get.rb +9 -9
- data/lib/action_controller/metal/data_streaming.rb +145 -0
- data/lib/action_controller/metal/force_ssl.rb +35 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +37 -44
- data/lib/action_controller/metal/hide_actions.rb +2 -3
- data/lib/action_controller/metal/http_authentication.rb +41 -38
- data/lib/action_controller/metal/implicit_render.rb +13 -13
- data/lib/action_controller/metal/instrumentation.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +25 -19
- data/lib/action_controller/metal/params_wrapper.rb +224 -0
- data/lib/action_controller/metal/redirecting.rb +6 -2
- data/lib/action_controller/metal/renderers.rb +50 -36
- data/lib/action_controller/metal/rendering.rb +34 -25
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
- data/lib/action_controller/metal/responder.rb +47 -12
- data/lib/action_controller/metal/streaming.rb +244 -138
- data/lib/action_controller/metal/testing.rb +0 -9
- data/lib/action_controller/metal/url_for.rb +12 -14
- data/lib/action_controller/railtie.rb +19 -37
- data/lib/action_controller/railties/paths.rb +24 -0
- data/lib/action_controller/record_identifier.rb +4 -10
- data/lib/action_controller/test_case.rb +36 -19
- data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +5 -32
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
- data/lib/action_dispatch/http/mime_type.rb +45 -5
- data/lib/action_dispatch/http/rack_cache.rb +58 -0
- data/lib/action_dispatch/http/request.rb +27 -41
- data/lib/action_dispatch/http/response.rb +56 -54
- data/lib/action_dispatch/http/upload.rb +1 -11
- data/lib/action_dispatch/http/url.rb +102 -42
- data/lib/action_dispatch/middleware/callbacks.rb +8 -25
- data/lib/action_dispatch/middleware/closed_error.rb +7 -0
- data/lib/action_dispatch/middleware/cookies.rb +37 -15
- data/lib/action_dispatch/middleware/flash.rb +80 -11
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
- data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
- data/lib/action_dispatch/middleware/stack.rb +50 -17
- data/lib/action_dispatch/middleware/static.rb +41 -29
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/routing.rb +13 -1
- data/lib/action_dispatch/routing/mapper.rb +345 -227
- data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
- data/lib/action_dispatch/routing/redirection.rb +110 -0
- data/lib/action_dispatch/routing/route.rb +15 -13
- data/lib/action_dispatch/routing/route_set.rb +116 -90
- data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
- data/lib/action_dispatch/routing/url_for.rb +25 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -10
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
- data/lib/action_dispatch/testing/integration.rb +37 -28
- data/lib/action_dispatch/testing/performance_test.rb +1 -3
- data/lib/action_dispatch/testing/test_process.rb +1 -1
- data/lib/action_dispatch/testing/test_request.rb +9 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -111
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +39 -24
- data/lib/action_view/base.rb +61 -86
- data/lib/action_view/buffers.rb +43 -0
- data/lib/action_view/context.rb +21 -24
- data/lib/action_view/flows.rb +79 -0
- data/lib/action_view/helpers.rb +8 -6
- data/lib/action_view/helpers/active_model_helper.rb +0 -23
- data/lib/action_view/helpers/asset_paths.rb +79 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +11 -19
- data/lib/action_view/helpers/capture_helper.rb +19 -8
- data/lib/action_view/helpers/controller_helper.rb +21 -0
- data/lib/action_view/helpers/csrf_helper.rb +22 -4
- data/lib/action_view/helpers/date_helper.rb +36 -22
- data/lib/action_view/helpers/form_helper.rb +199 -113
- data/lib/action_view/helpers/form_options_helper.rb +10 -11
- data/lib/action_view/helpers/form_tag_helper.rb +94 -22
- data/lib/action_view/helpers/javascript_helper.rb +24 -107
- data/lib/action_view/helpers/number_helper.rb +36 -33
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/sprockets_helper.rb +69 -0
- data/lib/action_view/helpers/tag_helper.rb +34 -12
- data/lib/action_view/helpers/text_helper.rb +30 -145
- data/lib/action_view/helpers/translation_helper.rb +10 -17
- data/lib/action_view/helpers/url_helper.rb +70 -67
- data/lib/action_view/locale/en.yml +1 -1
- data/lib/action_view/lookup_context.rb +36 -14
- data/lib/action_view/{paths.rb → path_set.rb} +9 -8
- data/lib/action_view/railtie.rb +12 -4
- data/lib/action_view/renderer/abstract_renderer.rb +36 -0
- data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
- data/lib/action_view/renderer/renderer.rb +54 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
- data/lib/action_view/renderer/template_renderer.rb +74 -0
- data/lib/action_view/template.rb +91 -54
- data/lib/action_view/template/error.rb +11 -8
- data/lib/action_view/template/handler.rb +9 -1
- data/lib/action_view/template/handlers.rb +9 -9
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb.rb +21 -41
- data/lib/action_view/template/resolver.rb +171 -57
- data/lib/action_view/template/text.rb +0 -4
- data/lib/action_view/test_case.rb +32 -16
- data/lib/action_view/testing/resolvers.rb +16 -10
- data/lib/sprockets/railtie.rb +100 -0
- metadata +162 -140
- checksums.yaml +0 -7
- data/lib/action_controller/deprecated/base.rb +0 -143
- data/lib/action_controller/deprecated/dispatcher.rb +0 -28
- data/lib/action_controller/deprecated/url_writer.rb +0 -14
- data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
- data/lib/action_view/helpers/prototype_helper.rb +0 -851
- data/lib/action_view/helpers/raw_output_helper.rb +0 -18
- data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
- data/lib/action_view/render/layouts.rb +0 -83
- data/lib/action_view/render/rendering.rb +0 -67
- data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -5,7 +5,7 @@
|
|
5
5
|
format:
|
6
6
|
# Sets the separator between the units, for more precision (e.g. 1.0 / 2.0 == 0.5)
|
7
7
|
separator: "."
|
8
|
-
#
|
8
|
+
# Delimits thousands (e.g. 1,000,000 is a million) (always in groups of three)
|
9
9
|
delimiter: ","
|
10
10
|
# Number of decimals, behind the separator (the number 1 with a precision of 2 gives: 1.00)
|
11
11
|
precision: 3
|
@@ -9,8 +9,10 @@ module ActionView
|
|
9
9
|
# generate a key, given to view paths, used in the resolver cache lookup. Since
|
10
10
|
# this key is generated just once during the request, it speeds up all cache accesses.
|
11
11
|
class LookupContext #:nodoc:
|
12
|
+
attr_accessor :prefixes
|
13
|
+
|
12
14
|
mattr_accessor :fallbacks
|
13
|
-
@@fallbacks =
|
15
|
+
@@fallbacks = FallbackFileSystemResolver.instances
|
14
16
|
|
15
17
|
mattr_accessor :registered_details
|
16
18
|
self.registered_details = []
|
@@ -58,9 +60,11 @@ module ActionView
|
|
58
60
|
end
|
59
61
|
end
|
60
62
|
|
61
|
-
def initialize(view_paths, details = {})
|
63
|
+
def initialize(view_paths, details = {}, prefixes = [])
|
62
64
|
@details, @details_key = { :handlers => default_handlers }, nil
|
63
65
|
@frozen_formats, @skip_default_locale = false, false
|
66
|
+
@cache = true
|
67
|
+
@prefixes = prefixes
|
64
68
|
|
65
69
|
self.view_paths = view_paths
|
66
70
|
self.registered_detail_setters.each do |key, setter|
|
@@ -77,17 +81,17 @@ module ActionView
|
|
77
81
|
@view_paths = ActionView::Base.process_view_paths(paths)
|
78
82
|
end
|
79
83
|
|
80
|
-
def find(name,
|
81
|
-
@view_paths.find(*args_for_lookup(name,
|
84
|
+
def find(name, prefixes = [], partial = false, keys = [])
|
85
|
+
@view_paths.find(*args_for_lookup(name, prefixes, partial, keys))
|
82
86
|
end
|
83
87
|
alias :find_template :find
|
84
88
|
|
85
|
-
def find_all(name,
|
86
|
-
@view_paths.find_all(*args_for_lookup(name,
|
89
|
+
def find_all(name, prefixes = [], partial = false, keys = [])
|
90
|
+
@view_paths.find_all(*args_for_lookup(name, prefixes, partial, keys))
|
87
91
|
end
|
88
92
|
|
89
|
-
def exists?(name,
|
90
|
-
@view_paths.exists?(*args_for_lookup(name,
|
93
|
+
def exists?(name, prefixes = [], partial = false, keys = [])
|
94
|
+
@view_paths.exists?(*args_for_lookup(name, prefixes, partial, keys))
|
91
95
|
end
|
92
96
|
alias :template_exists? :exists?
|
93
97
|
|
@@ -106,18 +110,26 @@ module ActionView
|
|
106
110
|
|
107
111
|
protected
|
108
112
|
|
109
|
-
def args_for_lookup(name,
|
110
|
-
name,
|
111
|
-
[name,
|
113
|
+
def args_for_lookup(name, prefixes, partial, keys) #:nodoc:
|
114
|
+
name, prefixes = normalize_name(name, prefixes)
|
115
|
+
[name, prefixes, partial || false, @details, details_key, keys]
|
112
116
|
end
|
113
117
|
|
114
118
|
# Support legacy foo.erb names even though we now ignore .erb
|
115
119
|
# as well as incorrectly putting part of the path in the template
|
116
120
|
# name instead of the prefix.
|
117
|
-
def normalize_name(name,
|
121
|
+
def normalize_name(name, prefixes) #:nodoc:
|
118
122
|
name = name.to_s.gsub(handlers_regexp, '')
|
119
123
|
parts = name.split('/')
|
120
|
-
|
124
|
+
name = parts.pop
|
125
|
+
|
126
|
+
prefixes = if prefixes.blank?
|
127
|
+
[parts.join('/')]
|
128
|
+
else
|
129
|
+
prefixes.map { |prefix| [prefix, *parts].compact.join('/') }
|
130
|
+
end
|
131
|
+
|
132
|
+
return name, prefixes
|
121
133
|
end
|
122
134
|
|
123
135
|
def default_handlers #:nodoc:
|
@@ -130,10 +142,20 @@ module ActionView
|
|
130
142
|
end
|
131
143
|
|
132
144
|
module Details
|
145
|
+
attr_accessor :cache
|
146
|
+
|
133
147
|
# Calculate the details key. Remove the handlers from calculation to improve performance
|
134
148
|
# since the user cannot modify it explicitly.
|
135
149
|
def details_key #:nodoc:
|
136
|
-
@details_key ||= DetailsKey.get(@details)
|
150
|
+
@details_key ||= DetailsKey.get(@details) if @cache
|
151
|
+
end
|
152
|
+
|
153
|
+
# Temporary skip passing the details_key forward.
|
154
|
+
def disable_cache
|
155
|
+
old_value, @cache = @cache, false
|
156
|
+
yield
|
157
|
+
ensure
|
158
|
+
@cache = old_value
|
137
159
|
end
|
138
160
|
|
139
161
|
# Freeze the current formats in the lookup context. By freezing them, you are guaranteeing
|
@@ -10,16 +10,17 @@ module ActionView #:nodoc:
|
|
10
10
|
METHOD
|
11
11
|
end
|
12
12
|
|
13
|
-
def find(
|
14
|
-
|
15
|
-
raise MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) unless template
|
16
|
-
template
|
13
|
+
def find(*args)
|
14
|
+
find_all(*args).first || raise(MissingTemplate.new(self, *args))
|
17
15
|
end
|
18
16
|
|
19
|
-
def find_all(*args)
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
def find_all(path, prefixes = [], *args)
|
18
|
+
prefixes = [prefixes] if String === prefixes
|
19
|
+
prefixes.each do |prefix|
|
20
|
+
each do |resolver|
|
21
|
+
templates = resolver.find_all(path, prefix, *args)
|
22
|
+
return templates unless templates.empty?
|
23
|
+
end
|
23
24
|
end
|
24
25
|
[]
|
25
26
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -6,12 +6,12 @@ module ActionView
|
|
6
6
|
class Railtie < Rails::Railtie
|
7
7
|
config.action_view = ActiveSupport::OrderedOptions.new
|
8
8
|
config.action_view.stylesheet_expansions = {}
|
9
|
-
config.action_view.javascript_expansions = { :defaults =>
|
9
|
+
config.action_view.javascript_expansions = { :defaults => %w(jquery jquery_ujs) }
|
10
10
|
|
11
|
-
initializer "action_view.
|
11
|
+
initializer "action_view.cache_asset_ids" do |app|
|
12
12
|
unless app.config.cache_classes
|
13
13
|
ActiveSupport.on_load(:action_view) do
|
14
|
-
ActionView::Helpers::AssetTagHelper.
|
14
|
+
ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids = false
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -35,5 +35,13 @@ module ActionView
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
initializer "action_view.caching" do |app|
|
40
|
+
ActiveSupport.on_load(:action_view) do
|
41
|
+
if app.config.action_view.cache_template_loading.nil?
|
42
|
+
ActionView::Resolver.caching = app.config.cache_classes
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
38
46
|
end
|
39
|
-
end
|
47
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module ActionView
|
2
|
+
class AbstractRenderer #:nodoc:
|
3
|
+
delegate :find_template, :template_exists?, :with_fallbacks, :update_details,
|
4
|
+
:with_layout_format, :formats, :freeze_formats, :to => :@lookup_context
|
5
|
+
|
6
|
+
def initialize(lookup_context)
|
7
|
+
@lookup_context = lookup_context
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
# Checks if the given path contains a format and if so, change
|
15
|
+
# the lookup context to take this new format into account.
|
16
|
+
def wrap_formats(value)
|
17
|
+
return yield unless value.is_a?(String)
|
18
|
+
|
19
|
+
if value.sub!(formats_regexp, "")
|
20
|
+
update_details(:formats => [$1.to_sym]){ yield }
|
21
|
+
else
|
22
|
+
yield
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def formats_regexp
|
27
|
+
@@formats_regexp ||= /\.(#{Mime::SET.symbols.join('|')})$/
|
28
|
+
end
|
29
|
+
|
30
|
+
protected
|
31
|
+
|
32
|
+
def instrument(name, options={})
|
33
|
+
ActiveSupport::Notifications.instrument("render_#{name}.action_view", options){ yield }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -12,50 +12,49 @@ module ActionView
|
|
12
12
|
#
|
13
13
|
# <%= render :partial => "account" %>
|
14
14
|
#
|
15
|
-
# This would render "advertiser/_account.erb" and pass the instance variable @account in as a local variable
|
15
|
+
# This would render "advertiser/_account.html.erb" and pass the instance variable @account in as a local variable
|
16
16
|
# +account+ to the template for display.
|
17
17
|
#
|
18
18
|
# In another template for Advertiser#buy, we could have:
|
19
19
|
#
|
20
20
|
# <%= render :partial => "account", :locals => { :account => @buyer } %>
|
21
21
|
#
|
22
|
-
# <%
|
22
|
+
# <% @advertisements.each do |ad| %>
|
23
23
|
# <%= render :partial => "ad", :locals => { :ad => ad } %>
|
24
24
|
# <% end %>
|
25
25
|
#
|
26
|
-
# This would first render "advertiser/_account.erb" with @buyer passed in as the local variable +account+, then
|
27
|
-
# render "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display.
|
26
|
+
# This would first render "advertiser/_account.html.erb" with @buyer passed in as the local variable +account+, then
|
27
|
+
# render "advertiser/_ad.html.erb" and pass the local variable +ad+ to the template for display.
|
28
28
|
#
|
29
29
|
# == The :as and :object options
|
30
30
|
#
|
31
|
-
# By default PartialRenderer
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# <%= render :partial => "contract", :locals => { :contract => @contract } %>
|
31
|
+
# By default <tt>ActionView::Partials::PartialRenderer</tt> has its object in a local variable with the same
|
32
|
+
# name as the template. So, given
|
35
33
|
#
|
36
34
|
# <%= render :partial => "contract" %>
|
37
35
|
#
|
38
|
-
#
|
39
|
-
#
|
36
|
+
# within contract we'll get <tt>@contract</tt> in the local variable +contract+, as if we had written
|
37
|
+
#
|
38
|
+
# <%= render :partial => "contract", :locals => { :contract => @contract } %>
|
40
39
|
#
|
41
|
-
#
|
40
|
+
# With the <tt>:as</tt> option we can specify a different name for said local variable. For example, if we
|
41
|
+
# wanted it to be +agreement+ instead of +contract+ we'd do:
|
42
42
|
#
|
43
|
-
# <%= render :partial => "contract", :
|
43
|
+
# <%= render :partial => "contract", :as => 'agreement' %>
|
44
44
|
#
|
45
|
-
# The
|
45
|
+
# The <tt>:object</tt> option can be used to directly specify which object is rendered into the partial;
|
46
|
+
# useful when the template's object is elsewhere, in a different ivar or in a local variable for instance.
|
46
47
|
#
|
47
|
-
# Revisiting a previous example we could have written this code
|
48
|
+
# Revisiting a previous example we could have written this code:
|
48
49
|
#
|
49
50
|
# <%= render :partial => "account", :object => @buyer %>
|
50
51
|
#
|
51
|
-
# <%
|
52
|
+
# <% @advertisements.each do |ad| %>
|
52
53
|
# <%= render :partial => "ad", :object => ad %>
|
53
54
|
# <% end %>
|
54
55
|
#
|
55
|
-
# The
|
56
|
-
# such as 'form'. Using :object and :as together helps us.
|
56
|
+
# The <tt>:object</tt> and <tt>:as</tt> options can be used together.
|
57
57
|
#
|
58
|
-
# <%= render :partial => "form", :object => @contract, :as => :contract %>
|
59
58
|
# == Rendering a collection of partials
|
60
59
|
#
|
61
60
|
# The example of partial use describes a familiar pattern where a template needs to iterate over an array and
|
@@ -65,17 +64,22 @@ module ActionView
|
|
65
64
|
#
|
66
65
|
# <%= render :partial => "ad", :collection => @advertisements %>
|
67
66
|
#
|
68
|
-
# This will render "advertiser/_ad.erb" and pass the local variable +ad+ to the template for display. An
|
67
|
+
# This will render "advertiser/_ad.html.erb" and pass the local variable +ad+ to the template for display. An
|
69
68
|
# iteration counter will automatically be made available to the template with a name of the form
|
70
69
|
# +partial_name_counter+. In the case of the example above, the template would be fed +ad_counter+.
|
71
70
|
#
|
72
|
-
# The
|
71
|
+
# The <tt>:as</tt> option may be used when rendering partials.
|
73
72
|
#
|
74
|
-
#
|
75
|
-
#
|
73
|
+
# You can specify a partial to be rendered between elements via the <tt>:spacer_template</tt> option.
|
74
|
+
# The following example will render <tt>advertiser/_ad_divider.html.erb</tt> between each ad partial:
|
76
75
|
#
|
77
76
|
# <%= render :partial => "ad", :collection => @advertisements, :spacer_template => "ad_divider" %>
|
78
77
|
#
|
78
|
+
# If the given <tt>:collection</tt> is nil or empty, <tt>render</tt> will return nil. This will allow you
|
79
|
+
# to specify a text which will displayed instead by using this form:
|
80
|
+
#
|
81
|
+
# <%= render(:partial => "ad", :collection => @advertisements) || "There's no ad to be displayed" %>
|
82
|
+
#
|
79
83
|
# NOTE: Due to backwards compatibility concerns, the collection can't be one of hashes. Normally you'd also
|
80
84
|
# just keep domain objects, like Active Records, in there.
|
81
85
|
#
|
@@ -85,7 +89,7 @@ module ActionView
|
|
85
89
|
#
|
86
90
|
# <%= render :partial => "advertisement/ad", :locals => { :ad => @advertisement } %>
|
87
91
|
#
|
88
|
-
# This will render the partial "advertisement/_ad.erb" regardless of which controller this is being called from.
|
92
|
+
# This will render the partial "advertisement/_ad.html.erb" regardless of which controller this is being called from.
|
89
93
|
#
|
90
94
|
# == Rendering objects with the RecordIdentifier
|
91
95
|
#
|
@@ -210,173 +214,170 @@ module ActionView
|
|
210
214
|
# Deadline: <%= user.deadline %>
|
211
215
|
# <%- end -%>
|
212
216
|
# <% end %>
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
class PartialRenderer
|
217
|
-
PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} }
|
218
|
-
|
219
|
-
def initialize(view_context, options, block)
|
220
|
-
@view = view_context
|
221
|
-
@partial_names = PARTIAL_NAMES[@view.controller.class.name]
|
217
|
+
class PartialRenderer < AbstractRenderer #:nodoc:
|
218
|
+
PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} }
|
222
219
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
partial = options[:partial]
|
228
|
-
|
229
|
-
@options = options
|
230
|
-
@locals = options[:locals] || {}
|
231
|
-
@block = block
|
220
|
+
def initialize(*)
|
221
|
+
super
|
222
|
+
@partial_names = PARTIAL_NAMES[@lookup_context.prefixes.first]
|
223
|
+
end
|
232
224
|
|
233
|
-
|
234
|
-
|
235
|
-
@path = partial
|
236
|
-
@collection = collection
|
237
|
-
else
|
238
|
-
@object = partial
|
225
|
+
def render(context, options, block)
|
226
|
+
setup(context, options, block)
|
239
227
|
|
240
|
-
|
241
|
-
|
242
|
-
@path = paths.uniq.size == 1 ? paths.first : nil
|
243
|
-
else
|
244
|
-
@path = partial_path
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def render
|
250
|
-
identifier = ((@template = find_template) ? @template.identifier : @path)
|
228
|
+
wrap_formats(@path) do
|
229
|
+
identifier = ((@template = find_partial) ? @template.identifier : @path)
|
251
230
|
|
252
231
|
if @collection
|
253
|
-
|
254
|
-
:identifier => identifier || "collection", :count => @collection.size) do
|
232
|
+
instrument(:collection, :identifier => identifier || "collection", :count => @collection.size) do
|
255
233
|
render_collection
|
256
234
|
end
|
257
235
|
else
|
258
|
-
|
259
|
-
|
260
|
-
content = ActiveSupport::Notifications.instrument("render_partial.action_view",
|
261
|
-
:identifier => identifier) do
|
236
|
+
instrument(:partial, :identifier => identifier) do
|
262
237
|
render_partial
|
263
238
|
end
|
264
|
-
|
265
|
-
if !block && (layout = options[:layout])
|
266
|
-
content = @view._render_layout(find_template(layout), locals){ content }
|
267
|
-
end
|
268
|
-
|
269
|
-
content
|
270
239
|
end
|
271
240
|
end
|
241
|
+
end
|
272
242
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
if @options.key?(:spacer_template)
|
277
|
-
spacer = find_template(@options[:spacer_template]).render(@view, @locals)
|
278
|
-
end
|
243
|
+
def render_collection
|
244
|
+
return nil if @collection.blank?
|
279
245
|
|
280
|
-
|
281
|
-
|
246
|
+
if @options.key?(:spacer_template)
|
247
|
+
spacer = find_template(@options[:spacer_template]).render(@view, @locals)
|
282
248
|
end
|
283
249
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
if @options[:as]
|
288
|
-
as = @options[:as]
|
289
|
-
counter = "#{as}_counter".to_sym
|
290
|
-
else
|
291
|
-
as = template.variable_name
|
292
|
-
counter = template.counter_name
|
293
|
-
end
|
294
|
-
|
295
|
-
locals[counter] = -1
|
250
|
+
result = @template ? collection_with_template : collection_without_template
|
251
|
+
result.join(spacer).html_safe
|
252
|
+
end
|
296
253
|
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
segments << template.render(@view, locals)
|
301
|
-
end
|
254
|
+
def render_partial
|
255
|
+
locals, view, block = @locals, @view, @block
|
256
|
+
object, as = @object, @variable
|
302
257
|
|
303
|
-
|
258
|
+
if !block && (layout = @options[:layout])
|
259
|
+
layout = find_template(layout)
|
304
260
|
end
|
305
261
|
|
306
|
-
|
307
|
-
|
308
|
-
index, template = -1, nil
|
262
|
+
object ||= locals[as]
|
263
|
+
locals[as] = object
|
309
264
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
end
|
265
|
+
content = @template.render(view, locals) do |*name|
|
266
|
+
view._layout_for(*name, &block)
|
267
|
+
end
|
314
268
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
locals[counter || template.counter_name] = (index += 1)
|
269
|
+
content = layout.render(view, locals){ content } if layout
|
270
|
+
content
|
271
|
+
end
|
319
272
|
|
320
|
-
|
321
|
-
end
|
273
|
+
private
|
322
274
|
|
323
|
-
|
324
|
-
|
325
|
-
|
275
|
+
def setup(context, options, block)
|
276
|
+
@view = context
|
277
|
+
partial = options[:partial]
|
326
278
|
|
327
|
-
|
328
|
-
|
279
|
+
@options = options
|
280
|
+
@locals = options[:locals] || {}
|
281
|
+
@block = block
|
329
282
|
|
330
|
-
|
331
|
-
|
283
|
+
if String === partial
|
284
|
+
@object = options[:object]
|
285
|
+
@path = partial
|
286
|
+
@collection = collection
|
287
|
+
else
|
288
|
+
@object = partial
|
332
289
|
|
333
|
-
|
334
|
-
|
290
|
+
if @collection = collection_from_object || collection
|
291
|
+
paths = @collection_data = @collection.map { |o| partial_path(o) }
|
292
|
+
@path = paths.uniq.size == 1 ? paths.first : nil
|
293
|
+
else
|
294
|
+
@path = partial_path
|
335
295
|
end
|
336
296
|
end
|
337
297
|
|
338
|
-
|
298
|
+
if @path
|
299
|
+
@variable, @variable_counter = retrieve_variable(@path)
|
300
|
+
else
|
301
|
+
paths.map! { |path| retrieve_variable(path).unshift(path) }
|
302
|
+
end
|
339
303
|
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
304
|
+
self
|
305
|
+
end
|
306
|
+
|
307
|
+
def collection
|
308
|
+
if @options.key?(:collection)
|
309
|
+
collection = @options[:collection]
|
310
|
+
collection.respond_to?(:to_ary) ? collection.to_ary : []
|
345
311
|
end
|
312
|
+
end
|
346
313
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
end
|
314
|
+
def collection_from_object
|
315
|
+
if @object.respond_to?(:to_ary)
|
316
|
+
@object.to_ary
|
351
317
|
end
|
318
|
+
end
|
352
319
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
320
|
+
def find_partial
|
321
|
+
if path = @path
|
322
|
+
locals = @locals.keys
|
323
|
+
locals << @variable
|
324
|
+
locals << @variable_counter if @collection
|
325
|
+
find_template(path, locals)
|
357
326
|
end
|
327
|
+
end
|
358
328
|
|
359
|
-
|
360
|
-
|
361
|
-
|
329
|
+
def find_template(path=@path, locals=@locals.keys)
|
330
|
+
prefixes = path.include?(?/) ? [] : @lookup_context.prefixes
|
331
|
+
@lookup_context.find_template(path, prefixes, true, locals)
|
332
|
+
end
|
362
333
|
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
334
|
+
def collection_with_template
|
335
|
+
segments, locals, template = [], @locals, @template
|
336
|
+
as, counter = @variable, @variable_counter
|
337
|
+
|
338
|
+
locals[counter] = -1
|
339
|
+
|
340
|
+
@collection.each do |object|
|
341
|
+
locals[counter] += 1
|
342
|
+
locals[as] = object
|
343
|
+
segments << template.render(@view, locals)
|
368
344
|
end
|
345
|
+
|
346
|
+
segments
|
369
347
|
end
|
370
348
|
|
371
|
-
def
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
349
|
+
def collection_without_template
|
350
|
+
segments, locals, collection_data = [], @locals, @collection_data
|
351
|
+
index, template, cache = -1, nil, {}
|
352
|
+
keys = @locals.keys
|
353
|
+
|
354
|
+
@collection.each_with_index do |object, i|
|
355
|
+
path, *data = collection_data[i]
|
356
|
+
template = (cache[path] ||= find_template(path, keys + data))
|
357
|
+
locals[data[0]] = object
|
358
|
+
locals[data[1]] = (index += 1)
|
359
|
+
segments << template.render(@view, locals)
|
376
360
|
end
|
377
361
|
|
378
|
-
@
|
362
|
+
@template = template
|
363
|
+
segments
|
379
364
|
end
|
380
365
|
|
366
|
+
def partial_path(object = @object)
|
367
|
+
@partial_names[object.class.name] ||= begin
|
368
|
+
object = object.to_model if object.respond_to?(:to_model)
|
369
|
+
|
370
|
+
object.class.model_name.partial_path.dup.tap do |partial|
|
371
|
+
path = @lookup_context.prefixes.first
|
372
|
+
partial.insert(0, "#{File.dirname(path)}/") if partial.include?(?/) && path.include?(?/)
|
373
|
+
end
|
374
|
+
end
|
375
|
+
end
|
376
|
+
|
377
|
+
def retrieve_variable(path)
|
378
|
+
variable = @options[:as].try(:to_sym) || path[%r'_?(\w+)(\.\w+)*$', 1].to_sym
|
379
|
+
variable_counter = :"#{variable}_counter" if @collection
|
380
|
+
[variable, variable_counter]
|
381
|
+
end
|
381
382
|
end
|
382
383
|
end
|