actionpack 3.0.0.beta → 3.0.0.beta2
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 +291 -260
- data/lib/abstract_controller.rb +5 -2
- data/lib/abstract_controller/assigns.rb +21 -0
- data/lib/abstract_controller/base.rb +13 -5
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -14
- data/lib/abstract_controller/layouts.rb +50 -99
- data/lib/abstract_controller/logger.rb +2 -2
- data/lib/abstract_controller/rendering.rb +105 -173
- data/lib/abstract_controller/view_paths.rb +69 -0
- data/lib/action_controller.rb +1 -2
- data/lib/action_controller/base.rb +10 -32
- data/lib/action_controller/caching.rb +19 -18
- data/lib/action_controller/caching/actions.rb +17 -11
- data/lib/action_controller/caching/fragments.rb +5 -17
- data/lib/action_controller/caching/pages.rb +24 -24
- data/lib/action_controller/caching/sweeping.rb +1 -3
- data/lib/action_controller/deprecated.rb +0 -2
- data/lib/action_controller/deprecated/base.rb +143 -0
- data/lib/action_controller/metal.rb +29 -26
- data/lib/action_controller/metal/compatibility.rb +18 -87
- data/lib/action_controller/metal/cookies.rb +0 -1
- data/lib/action_controller/metal/head.rb +1 -0
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/hide_actions.rb +4 -6
- data/lib/action_controller/metal/http_authentication.rb +18 -33
- data/lib/action_controller/metal/implicit_render.rb +21 -0
- data/lib/action_controller/metal/instrumentation.rb +1 -1
- data/lib/action_controller/metal/mime_responds.rb +2 -1
- data/lib/action_controller/metal/rack_delegation.rb +3 -8
- data/lib/action_controller/metal/redirecting.rb +2 -1
- data/lib/action_controller/metal/renderers.rb +4 -2
- data/lib/action_controller/metal/rendering.rb +31 -44
- data/lib/action_controller/metal/request_forgery_protection.rb +41 -4
- data/lib/action_controller/metal/responder.rb +2 -0
- data/lib/action_controller/metal/session_management.rb +0 -36
- data/lib/action_controller/metal/streaming.rb +20 -47
- data/lib/action_controller/metal/testing.rb +0 -1
- data/lib/action_controller/metal/url_for.rb +11 -148
- data/lib/action_controller/middleware.rb +2 -1
- data/lib/action_controller/polymorphic_routes.rb +1 -2
- data/lib/action_controller/railtie.rb +63 -10
- data/lib/action_controller/railties/{subscriber.rb → log_subscriber.rb} +5 -12
- data/lib/action_controller/railties/url_helpers.rb +14 -0
- data/lib/action_controller/record_identifier.rb +20 -1
- data/lib/action_controller/test_case.rb +123 -12
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/cache.rb +20 -3
- data/lib/action_dispatch/http/filter_parameters.rb +40 -25
- data/lib/action_dispatch/http/mime_negotiation.rb +6 -17
- data/lib/action_dispatch/http/mime_type.rb +2 -7
- data/lib/action_dispatch/http/request.rb +12 -33
- data/lib/action_dispatch/http/response.rb +35 -15
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +5 -32
- data/lib/action_dispatch/middleware/callbacks.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +4 -3
- data/lib/action_dispatch/middleware/params_parser.rb +4 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +51 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +6 -8
- data/lib/action_dispatch/middleware/show_exceptions.rb +0 -14
- data/lib/action_dispatch/middleware/stack.rb +6 -2
- data/lib/action_dispatch/railtie.rb +3 -1
- data/lib/action_dispatch/routing.rb +2 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +35 -7
- data/lib/action_dispatch/routing/mapper.rb +134 -48
- data/lib/action_dispatch/routing/route.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +217 -158
- data/lib/action_dispatch/routing/url_for.rb +139 -0
- data/lib/action_dispatch/testing/assertions/response.rb +14 -61
- data/lib/action_dispatch/testing/assertions/routing.rb +25 -14
- data/lib/action_dispatch/testing/integration.rb +32 -50
- data/lib/action_dispatch/testing/performance_test.rb +3 -1
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +2 -0
- data/lib/action_pack/version.rb +4 -3
- data/lib/action_view.rb +11 -6
- data/lib/action_view/base.rb +33 -121
- data/lib/action_view/context.rb +0 -2
- data/lib/action_view/helpers.rb +26 -23
- data/lib/action_view/helpers/active_model_helper.rb +28 -18
- data/lib/action_view/helpers/asset_tag_helper.rb +109 -54
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +22 -1
- data/lib/action_view/helpers/capture_helper.rb +22 -22
- data/lib/action_view/helpers/date_helper.rb +6 -5
- data/lib/action_view/helpers/form_helper.rb +78 -63
- data/lib/action_view/helpers/form_options_helper.rb +6 -4
- data/lib/action_view/helpers/form_tag_helper.rb +26 -15
- data/lib/action_view/helpers/javascript_helper.rb +90 -10
- data/lib/action_view/helpers/number_helper.rb +315 -118
- data/lib/action_view/helpers/prototype_helper.rb +19 -46
- data/lib/action_view/helpers/record_tag_helper.rb +4 -4
- data/lib/action_view/helpers/tag_helper.rb +7 -24
- data/lib/action_view/helpers/text_helper.rb +8 -7
- data/lib/action_view/helpers/translation_helper.rb +7 -5
- data/lib/action_view/helpers/url_helper.rb +19 -16
- data/lib/action_view/locale/en.yml +45 -6
- data/lib/action_view/lookup_context.rb +190 -0
- data/lib/action_view/paths.rb +22 -63
- data/lib/action_view/railtie.rb +14 -4
- data/lib/action_view/railties/{subscriber.rb → log_subscriber.rb} +1 -1
- data/lib/action_view/render/layouts.rb +73 -0
- data/lib/action_view/render/partials.rb +15 -41
- data/lib/action_view/render/rendering.rb +27 -78
- data/lib/action_view/template.rb +20 -24
- data/lib/action_view/template/error.rb +22 -2
- data/lib/action_view/template/handlers/erb.rb +33 -9
- data/lib/action_view/template/handlers/rjs.rb +1 -2
- data/lib/action_view/template/resolver.rb +46 -104
- data/lib/action_view/template/text.rb +5 -12
- data/lib/action_view/test_case.rb +14 -23
- metadata +83 -40
- data/lib/abstract_controller/compatibility.rb +0 -18
- data/lib/abstract_controller/localized_cache.rb +0 -49
- data/lib/action_controller/metal/configuration.rb +0 -28
- data/lib/action_controller/url_rewriter.rb +0 -76
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'active_support/core_ext/array/wrap'
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
|
+
|
4
|
+
module ActionView
|
5
|
+
# LookupContext is the object responsible to hold all information required to lookup
|
6
|
+
# templates, i.e. view paths and details. The LookupContext is also responsible to
|
7
|
+
# generate a key, given to view paths, used in the resolver cache lookup. Since
|
8
|
+
# this key is generated just once during the request, it speeds up all cache accesses.
|
9
|
+
class LookupContext #:nodoc:
|
10
|
+
mattr_accessor :fallbacks
|
11
|
+
@@fallbacks = [FileSystemResolver.new(""), FileSystemResolver.new("/")]
|
12
|
+
|
13
|
+
mattr_accessor :registered_details
|
14
|
+
self.registered_details = []
|
15
|
+
|
16
|
+
def self.register_detail(name, options = {}, &block)
|
17
|
+
self.registered_details << name
|
18
|
+
Accessors.send :define_method, :"_#{name}_defaults", &block
|
19
|
+
Accessors.module_eval <<-METHOD, __FILE__, __LINE__ + 1
|
20
|
+
def #{name}
|
21
|
+
@details[:#{name}]
|
22
|
+
end
|
23
|
+
|
24
|
+
def #{name}=(value)
|
25
|
+
value = Array.wrap(value.presence || _#{name}_defaults)
|
26
|
+
|
27
|
+
if value != @details[:#{name}]
|
28
|
+
@details_key = nil
|
29
|
+
@details = @details.dup if @details.frozen?
|
30
|
+
@details[:#{name}] = value.freeze
|
31
|
+
end
|
32
|
+
end
|
33
|
+
METHOD
|
34
|
+
end
|
35
|
+
|
36
|
+
# Holds accessors for the registered details.
|
37
|
+
module Accessors #:nodoc:
|
38
|
+
end
|
39
|
+
|
40
|
+
register_detail(:formats) { Mime::SET.symbols }
|
41
|
+
register_detail(:locale) { [I18n.locale] }
|
42
|
+
|
43
|
+
class DetailsKey #:nodoc:
|
44
|
+
alias :eql? :equal?
|
45
|
+
alias :object_hash :hash
|
46
|
+
|
47
|
+
attr_reader :hash
|
48
|
+
@details_keys = Hash.new
|
49
|
+
|
50
|
+
def self.get(details)
|
51
|
+
@details_keys[details.freeze] ||= new
|
52
|
+
end
|
53
|
+
|
54
|
+
def initialize
|
55
|
+
@hash = object_hash
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(view_paths, details = {})
|
60
|
+
@details, @details_key = { :handlers => default_handlers }, nil
|
61
|
+
@frozen_formats = false
|
62
|
+
self.view_paths = view_paths
|
63
|
+
self.update_details(details, true)
|
64
|
+
end
|
65
|
+
|
66
|
+
module ViewPaths
|
67
|
+
attr_reader :view_paths
|
68
|
+
|
69
|
+
# Whenever setting view paths, makes a copy so we can manipulate then in
|
70
|
+
# instance objects as we wish.
|
71
|
+
def view_paths=(paths)
|
72
|
+
@view_paths = ActionView::Base.process_view_paths(paths)
|
73
|
+
end
|
74
|
+
|
75
|
+
def find(name, prefix = nil, partial = false)
|
76
|
+
@view_paths.find(*args_for_lookup(name, prefix, partial))
|
77
|
+
end
|
78
|
+
alias :find_template :find
|
79
|
+
|
80
|
+
def find_all(name, prefix = nil, partial = false)
|
81
|
+
@view_paths.find_all(*args_for_lookup(name, prefix, partial))
|
82
|
+
end
|
83
|
+
|
84
|
+
def exists?(name, prefix = nil, partial = false)
|
85
|
+
@view_paths.exists?(*args_for_lookup(name, prefix, partial))
|
86
|
+
end
|
87
|
+
alias :template_exists? :exists?
|
88
|
+
|
89
|
+
# Add fallbacks to the view paths. Useful in cases you are rendering a :file.
|
90
|
+
def with_fallbacks
|
91
|
+
added_resolvers = 0
|
92
|
+
self.class.fallbacks.each do |resolver|
|
93
|
+
next if view_paths.include?(resolver)
|
94
|
+
view_paths.push(resolver)
|
95
|
+
added_resolvers += 1
|
96
|
+
end
|
97
|
+
yield
|
98
|
+
ensure
|
99
|
+
added_resolvers.times { view_paths.pop }
|
100
|
+
end
|
101
|
+
|
102
|
+
protected
|
103
|
+
|
104
|
+
def args_for_lookup(name, prefix, partial) #:nodoc:
|
105
|
+
name, prefix = normalize_name(name, prefix)
|
106
|
+
[name, prefix, partial || false, @details, details_key]
|
107
|
+
end
|
108
|
+
|
109
|
+
# Support legacy foo.erb names even though we now ignore .erb
|
110
|
+
# as well as incorrectly putting part of the path in the template
|
111
|
+
# name instead of the prefix.
|
112
|
+
def normalize_name(name, prefix) #:nodoc:
|
113
|
+
name = name.to_s.gsub(handlers_regexp, '')
|
114
|
+
parts = name.split('/')
|
115
|
+
return parts.pop, [prefix, *parts].compact.join("/")
|
116
|
+
end
|
117
|
+
|
118
|
+
def default_handlers #:nodoc:
|
119
|
+
@default_handlers ||= Template::Handlers.extensions
|
120
|
+
end
|
121
|
+
|
122
|
+
def handlers_regexp #:nodoc:
|
123
|
+
@handlers_regexp ||= /\.(?:#{default_handlers.join('|')})$/
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module Details
|
128
|
+
# Calculate the details key. Remove the handlers from calculation to improve performance
|
129
|
+
# since the user cannot modify it explicitly.
|
130
|
+
def details_key #:nodoc:
|
131
|
+
@details_key ||= DetailsKey.get(@details)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Freeze the current formats in the lookup context. By freezing them, you are guaranteeing
|
135
|
+
# that next template lookups are not going to modify the formats. The controller can also
|
136
|
+
# use this, to ensure that formats won't be further modified (as it does in respond_to blocks).
|
137
|
+
def freeze_formats(formats, unless_frozen=false) #:nodoc:
|
138
|
+
return if unless_frozen && @frozen_formats
|
139
|
+
self.formats = formats
|
140
|
+
@frozen_formats = true
|
141
|
+
end
|
142
|
+
|
143
|
+
# Overload formats= to reject [:"*/*"] values.
|
144
|
+
def formats=(value)
|
145
|
+
value = nil if value == [:"*/*"]
|
146
|
+
value << :html if value == [:js]
|
147
|
+
super(value)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Overload locale to return a symbol instead of array
|
151
|
+
def locale
|
152
|
+
@details[:locale].first
|
153
|
+
end
|
154
|
+
|
155
|
+
# Overload locale= to also set the I18n.locale. If the current I18n.config object responds
|
156
|
+
# to i18n_config, it means that it's has a copy of the original I18n configuration and it's
|
157
|
+
# acting as proxy, which we need to skip.
|
158
|
+
def locale=(value)
|
159
|
+
if value
|
160
|
+
config = I18n.config.respond_to?(:i18n_config) ? I18n.config.i18n_config : I18n.config
|
161
|
+
config.locale = value
|
162
|
+
end
|
163
|
+
super(I18n.locale)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Update the details keys by merging the given hash into the current
|
167
|
+
# details hash. If a block is given, the details are modified just during
|
168
|
+
# the execution of the block and reverted to the previous value after.
|
169
|
+
def update_details(new_details, force=false)
|
170
|
+
old_details = @details.dup
|
171
|
+
|
172
|
+
registered_details.each do |key|
|
173
|
+
send(:"#{key}=", new_details[key]) if force || new_details.key?(key)
|
174
|
+
end
|
175
|
+
|
176
|
+
if block_given?
|
177
|
+
begin
|
178
|
+
yield
|
179
|
+
ensure
|
180
|
+
@details = old_details
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
include Accessors
|
187
|
+
include Details
|
188
|
+
include ViewPaths
|
189
|
+
end
|
190
|
+
end
|
data/lib/action_view/paths.rb
CHANGED
@@ -1,80 +1,39 @@
|
|
1
1
|
module ActionView #:nodoc:
|
2
2
|
class PathSet < Array #:nodoc:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
%w(initialize << concat insert push unshift).each do |method|
|
4
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
5
|
+
def #{method}(*args)
|
6
|
+
super
|
7
|
+
typecast!
|
8
8
|
end
|
9
|
-
|
10
|
-
else
|
11
|
-
obj
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(*args)
|
16
|
-
super(*args).map! { |obj| self.class.type_cast(obj) }
|
17
|
-
end
|
18
|
-
|
19
|
-
def <<(obj)
|
20
|
-
super(self.class.type_cast(obj))
|
21
|
-
end
|
22
|
-
|
23
|
-
def concat(array)
|
24
|
-
super(array.map! { |obj| self.class.type_cast(obj) })
|
25
|
-
end
|
26
|
-
|
27
|
-
def insert(index, obj)
|
28
|
-
super(index, self.class.type_cast(obj))
|
29
|
-
end
|
30
|
-
|
31
|
-
def push(*objs)
|
32
|
-
super(*objs.map { |obj| self.class.type_cast(obj) })
|
9
|
+
METHOD
|
33
10
|
end
|
34
11
|
|
35
|
-
def
|
36
|
-
|
12
|
+
def find(path, prefix = nil, partial = false, details = {}, key = nil)
|
13
|
+
template = find_all(path, prefix, partial, details, key).first
|
14
|
+
raise MissingTemplate.new(self, "#{prefix}/#{path}", details, partial) unless template
|
15
|
+
template
|
37
16
|
end
|
38
17
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
if template = load_path.find(template_path, details, prefix, partial)
|
44
|
-
return template
|
45
|
-
end
|
18
|
+
def find_all(*args)
|
19
|
+
each do |resolver|
|
20
|
+
templates = resolver.find_all(*args)
|
21
|
+
return templates unless templates.empty?
|
46
22
|
end
|
47
|
-
|
48
|
-
raise ActionView::MissingTemplate.new(self, "#{prefix}/#{path}", details, partial)
|
23
|
+
[]
|
49
24
|
end
|
50
|
-
|
51
|
-
def exists?(path, extension = nil, prefix = nil, partial = false)
|
52
|
-
template_path = path.sub(/^\//, '')
|
53
25
|
|
54
|
-
|
55
|
-
|
56
|
-
end
|
57
|
-
false
|
26
|
+
def exists?(*args)
|
27
|
+
find_all(*args).any?
|
58
28
|
end
|
59
29
|
|
60
|
-
|
61
|
-
return original_template_path if original_template_path.respond_to?(:render)
|
62
|
-
template_path = original_template_path.sub(/^\//, '')
|
30
|
+
protected
|
63
31
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
elsif format == :js && html_fallback && template = load_path["#{template_path}.#{I18n.locale}.html"]
|
69
|
-
return template
|
70
|
-
elsif format == :js && html_fallback && template = load_path["#{template_path}.html"]
|
71
|
-
return template
|
72
|
-
end
|
32
|
+
def typecast!
|
33
|
+
each_with_index do |path, i|
|
34
|
+
next unless path.is_a?(String)
|
35
|
+
self[i] = FileSystemResolver.new(path)
|
73
36
|
end
|
74
|
-
|
75
|
-
return Template.new(original_template_path, original_template_path.to_s =~ /\A\// ? "" : ".") if File.file?(original_template_path)
|
76
|
-
|
77
|
-
raise MissingTemplate.new(self, original_template_path, format)
|
78
37
|
end
|
79
38
|
end
|
80
39
|
end
|
data/lib/action_view/railtie.rb
CHANGED
@@ -3,14 +3,24 @@ require "rails"
|
|
3
3
|
|
4
4
|
module ActionView
|
5
5
|
class Railtie < Rails::Railtie
|
6
|
-
|
6
|
+
config.action_view = ActiveSupport::OrderedOptions.new
|
7
7
|
|
8
|
-
require "action_view/railties/
|
9
|
-
|
8
|
+
require "action_view/railties/log_subscriber"
|
9
|
+
log_subscriber :action_view, ActionView::Railties::LogSubscriber.new
|
10
10
|
|
11
11
|
initializer "action_view.cache_asset_timestamps" do |app|
|
12
12
|
unless app.config.cache_classes
|
13
|
-
|
13
|
+
ActiveSupport.on_load(:action_view) do
|
14
|
+
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
initializer "action_view.set_configs" do |app|
|
20
|
+
ActiveSupport.on_load(:action_view) do
|
21
|
+
app.config.action_view.each do |k,v|
|
22
|
+
send "#{k}=", v
|
23
|
+
end
|
14
24
|
end
|
15
25
|
end
|
16
26
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ActionView
|
2
2
|
module Railties
|
3
|
-
class
|
3
|
+
class LogSubscriber < Rails::LogSubscriber
|
4
4
|
def render_template(event)
|
5
5
|
message = "Rendered #{from_rails_root(event.payload[:identifier])}"
|
6
6
|
message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Layouts
|
3
|
+
# You can think of a layout as a method that is called with a block. _layout_for
|
4
|
+
# returns the contents that are yielded to the layout. If the user calls yield
|
5
|
+
# :some_name, the block, by default, returns content_for(:some_name). If the user
|
6
|
+
# calls yield, the default block returns content_for(:layout).
|
7
|
+
#
|
8
|
+
# The user can override this default by passing a block to the layout.
|
9
|
+
#
|
10
|
+
# ==== Example
|
11
|
+
#
|
12
|
+
# # The template
|
13
|
+
# <%= render :layout => "my_layout" do %>Content<% end %>
|
14
|
+
#
|
15
|
+
# # The layout
|
16
|
+
# <html><% yield %></html>
|
17
|
+
#
|
18
|
+
# In this case, instead of the default block, which would return content_for(:layout),
|
19
|
+
# this method returns the block that was passed in to render layout, and the response
|
20
|
+
# would be <html>Content</html>.
|
21
|
+
#
|
22
|
+
# Finally, the block can take block arguments, which can be passed in by yield.
|
23
|
+
#
|
24
|
+
# ==== Example
|
25
|
+
#
|
26
|
+
# # The template
|
27
|
+
# <%= render :layout => "my_layout" do |customer| %>Hello <%= customer.name %><% end %>
|
28
|
+
#
|
29
|
+
# # The layout
|
30
|
+
# <html><% yield Struct.new(:name).new("David") %></html>
|
31
|
+
#
|
32
|
+
# In this case, the layout would receive the block passed into <tt>render :layout</tt>,
|
33
|
+
# and the Struct specified in the layout would be passed into the block. The result
|
34
|
+
# would be <html>Hello David</html>.
|
35
|
+
def _layout_for(name = nil, &block) #:nodoc:
|
36
|
+
if !block || name
|
37
|
+
@_content_for[name || :layout]
|
38
|
+
else
|
39
|
+
capture(&block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# This is the method which actually finds the layout using details in the lookup
|
44
|
+
# context object. If no layout is found, it checkes if at least a layout with
|
45
|
+
# the given name exists across all details before raising the error.
|
46
|
+
#
|
47
|
+
# If self.formats contains several formats, just the first one is considered in
|
48
|
+
# the layout lookup.
|
49
|
+
def find_layout(layout)
|
50
|
+
begin
|
51
|
+
if formats.size == 1
|
52
|
+
_find_layout(layout)
|
53
|
+
else
|
54
|
+
update_details(:formats => self.formats.first){ _find_layout(layout) }
|
55
|
+
end
|
56
|
+
rescue ActionView::MissingTemplate => e
|
57
|
+
update_details(:formats => nil) do
|
58
|
+
raise unless template_exists?(layout)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def _find_layout(layout) #:nodoc:
|
64
|
+
layout =~ /^\// ?
|
65
|
+
with_fallbacks { find_template(layout) } : find_template(layout)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Contains the logic that actually renders the layout.
|
69
|
+
def _render_layout(layout, locals, &block) #:nodoc:
|
70
|
+
layout.render(self, locals){ |*name| _layout_for(*name, &block) }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_support/core_ext/object/blank'
|
2
|
+
|
1
3
|
module ActionView
|
2
4
|
# There's also a convenience method for rendering sub templates within the current controller that depends on a
|
3
5
|
# single object (we call this kind of sub templates for partials). It relies on the fact that partials should
|
@@ -123,7 +125,7 @@ module ActionView
|
|
123
125
|
# You can also apply a layout to a block within any template:
|
124
126
|
#
|
125
127
|
# <%# app/views/users/_chief.html.erb &>
|
126
|
-
#
|
128
|
+
# <%= render(:layout => "administrator", :locals => { :user => chief }) do %>
|
127
129
|
# Title: <%= chief.title %>
|
128
130
|
# <% end %>
|
129
131
|
#
|
@@ -146,7 +148,7 @@ module ActionView
|
|
146
148
|
# </div>
|
147
149
|
#
|
148
150
|
# <%# app/views/users/index.html.erb &>
|
149
|
-
#
|
151
|
+
# <%= render :layout => @users do |user| %>
|
150
152
|
# Title: <%= user.title %>
|
151
153
|
# <% end %>
|
152
154
|
#
|
@@ -162,7 +164,7 @@ module ActionView
|
|
162
164
|
# </div>
|
163
165
|
#
|
164
166
|
# <%# app/views/users/index.html.erb &>
|
165
|
-
#
|
167
|
+
# <%= render :layout => @users do |user, section| %>
|
166
168
|
# <%- case section when :header -%>
|
167
169
|
# Title: <%= user.title %>
|
168
170
|
# <%- when :footer -%>
|
@@ -174,17 +176,11 @@ module ActionView
|
|
174
176
|
|
175
177
|
class PartialRenderer
|
176
178
|
PARTIAL_NAMES = Hash.new {|h,k| h[k] = {} }
|
177
|
-
TEMPLATES = Hash.new {|h,k| h[k] = {} }
|
178
|
-
|
179
|
-
attr_reader :template
|
180
179
|
|
181
180
|
def initialize(view_context, options, block)
|
182
181
|
@view = view_context
|
183
182
|
@partial_names = PARTIAL_NAMES[@view.controller.class]
|
184
183
|
|
185
|
-
key = Thread.current[:format_locale_key]
|
186
|
-
@templates = TEMPLATES[key] if key
|
187
|
-
|
188
184
|
setup(options, block)
|
189
185
|
end
|
190
186
|
|
@@ -228,6 +224,7 @@ module ActionView
|
|
228
224
|
if !@block && (layout = @options[:layout])
|
229
225
|
content = @view._render_layout(find_template(layout), @locals){ content }
|
230
226
|
end
|
227
|
+
|
231
228
|
content
|
232
229
|
end
|
233
230
|
end
|
@@ -244,9 +241,9 @@ module ActionView
|
|
244
241
|
end
|
245
242
|
|
246
243
|
def collection_with_template(template = @template)
|
247
|
-
segments, locals, as = [], @locals, @options[:as] || template.variable_name
|
244
|
+
segments, locals, as, template = [], @locals, @options[:as] || @template.variable_name, @template
|
248
245
|
|
249
|
-
counter_name
|
246
|
+
counter_name = template.counter_name
|
250
247
|
locals[counter_name] = -1
|
251
248
|
|
252
249
|
@collection.each do |object|
|
@@ -256,7 +253,6 @@ module ActionView
|
|
256
253
|
segments << template.render(@view, locals)
|
257
254
|
end
|
258
255
|
|
259
|
-
@template = template
|
260
256
|
segments
|
261
257
|
end
|
262
258
|
|
@@ -277,7 +273,7 @@ module ActionView
|
|
277
273
|
end
|
278
274
|
|
279
275
|
def render_partial(object = @object)
|
280
|
-
locals, view = @locals, @view
|
276
|
+
locals, view, template = @locals, @view, @template
|
281
277
|
|
282
278
|
object ||= locals[template.variable_name]
|
283
279
|
locals[@options[:as] || template.variable_name] = object
|
@@ -288,6 +284,7 @@ module ActionView
|
|
288
284
|
end
|
289
285
|
|
290
286
|
private
|
287
|
+
|
291
288
|
def collection
|
292
289
|
if @object.respond_to?(:to_ary)
|
293
290
|
@object
|
@@ -296,20 +293,10 @@ module ActionView
|
|
296
293
|
end
|
297
294
|
end
|
298
295
|
|
299
|
-
def find_template(path
|
300
|
-
unless
|
301
|
-
|
302
|
-
|
303
|
-
path && @templates[path] ||= _find_template(path)
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
def _find_template(path)
|
308
|
-
if controller = @view.controller
|
309
|
-
prefix = controller.controller_path unless path.include?(?/)
|
310
|
-
end
|
311
|
-
|
312
|
-
@view.find(path, {:formats => @view.formats}, prefix, true)
|
296
|
+
def find_template(path=@path)
|
297
|
+
return path unless path.is_a?(String)
|
298
|
+
prefix = @view.controller_path unless path.include?(?/)
|
299
|
+
@view.find_template(path, prefix, true)
|
313
300
|
end
|
314
301
|
|
315
302
|
def partial_path(object = @object)
|
@@ -324,21 +311,8 @@ module ActionView
|
|
324
311
|
end
|
325
312
|
end
|
326
313
|
|
327
|
-
def render_partial(options)
|
328
|
-
_evaluate_assigns_and_ivars
|
329
|
-
|
330
|
-
details = options[:_details]
|
331
|
-
|
332
|
-
# Is this needed
|
333
|
-
self.formats = details[:formats] if details
|
334
|
-
renderer = PartialRenderer.new(self, options, nil)
|
335
|
-
text = renderer.render
|
336
|
-
options[:_template] = renderer.template
|
337
|
-
text
|
338
|
-
end
|
339
|
-
|
340
314
|
def _render_partial(options, &block) #:nodoc:
|
341
|
-
if defined?
|
315
|
+
if defined?(@renderer)
|
342
316
|
@renderer.setup(options, block)
|
343
317
|
else
|
344
318
|
@renderer = PartialRenderer.new(self, options, block)
|