aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view
diff options
context:
space:
mode:
authorSven Fuchs <svenfuchs@artweb-design.de>2008-08-21 19:04:39 +0200
committerSven Fuchs <svenfuchs@artweb-design.de>2008-08-21 19:04:39 +0200
commitaad429a46e3017fa7ca73f58428693e821be42b6 (patch)
treef749e0cdeab20c7f4be37ff49e064705f17cdfa5 /actionpack/lib/action_view
parentcf6840773b4f5046151f4d28c286069aabaafa10 (diff)
parent8622787f8748434b4ceb2b925a35b17a38e1f2d6 (diff)
downloadrails-aad429a46e3017fa7ca73f58428693e821be42b6.tar.gz
rails-aad429a46e3017fa7ca73f58428693e821be42b6.tar.bz2
rails-aad429a46e3017fa7ca73f58428693e821be42b6.zip
Merge branch 'master' into i18n
Diffstat (limited to 'actionpack/lib/action_view')
-rw-r--r--actionpack/lib/action_view/base.rb28
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helper.rb11
-rw-r--r--actionpack/lib/action_view/helpers/atom_feed_helper.rb24
-rw-r--r--actionpack/lib/action_view/partials.rb42
-rw-r--r--actionpack/lib/action_view/paths.rb28
-rw-r--r--actionpack/lib/action_view/renderable.rb15
6 files changed, 109 insertions, 39 deletions
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index ad59d92086..46bacbcbc1 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -169,6 +169,7 @@ module ActionView #:nodoc:
class << self
delegate :erb_trim_mode=, :to => 'ActionView::TemplateHandlers::ERB'
+ delegate :logger, :to => 'ActionController::Base'
end
def self.cache_template_loading=(*args)
@@ -246,17 +247,23 @@ module ActionView #:nodoc:
if partial_layout = options.delete(:layout)
if block_given?
- wrap_content_for_layout capture(&block) do
+ begin
+ @_proc_for_layout = block
concat(render(options.merge(:partial => partial_layout)))
+ ensure
+ @_proc_for_layout = nil
end
else
- wrap_content_for_layout render(options) do
+ begin
+ original_content_for_layout, @content_for_layout = @content_for_layout, render(options)
render(options.merge(:partial => partial_layout))
+ ensure
+ @content_for_layout = original_content_for_layout
end
end
elsif options[:file]
render_file(options[:file], nil, options[:locals])
- elsif options[:partial] && options[:collection]
+ elsif options[:partial] && options.has_key?(:collection)
render_partial_collection(options[:partial], options[:collection], options[:spacer_template], options[:locals], options[:as])
elsif options[:partial]
render_partial(options[:partial], options[:object], options[:locals])
@@ -322,7 +329,7 @@ module ActionView #:nodoc:
else
template = Template.new(template_path, view_paths)
- if self.class.warn_cache_misses && logger = ActionController::Base.logger
+ if self.class.warn_cache_misses && logger
logger.debug "[PERFORMANCE] Rendering a template that was " +
"not found in view path. Templates outside the view path are " +
"not cached and result in expensive disk operations. Move this " +
@@ -367,13 +374,6 @@ module ActionView #:nodoc:
InlineTemplate.new(text, type).render(self, local_assigns)
end
- def wrap_content_for_layout(content)
- original_content_for_layout, @content_for_layout = @content_for_layout, content
- yield
- ensure
- @content_for_layout = original_content_for_layout
- end
-
# Evaluate the local assigns and pushes them to the view.
def evaluate_assigns
unless @assigns_added
@@ -392,11 +392,5 @@ module ActionView #:nodoc:
controller.response.content_type ||= content_type
end
end
-
- def execute(method, local_assigns = {})
- send(method, local_assigns) do |*names|
- instance_variable_get "@content_for_#{names.first || 'layout'}"
- end
- end
end
end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 1e44b166d9..623ed1e8df 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -612,12 +612,21 @@ module ActionView
end
def join_asset_file_contents(paths)
- paths.collect { |path| File.read(File.join(ASSETS_DIR, path.split("?").first)) }.join("\n\n")
+ paths.collect { |path| File.read(asset_file_path(path)) }.join("\n\n")
end
def write_asset_file_contents(joined_asset_path, asset_paths)
FileUtils.mkdir_p(File.dirname(joined_asset_path))
File.open(joined_asset_path, "w+") { |cache| cache.write(join_asset_file_contents(asset_paths)) }
+
+ # Set mtime to the latest of the combined files to allow for
+ # consistent ETag without a shared filesystem.
+ mt = asset_paths.map { |p| File.mtime(asset_file_path(p)) }.max
+ File.utime(mt, mt, joined_asset_path)
+ end
+
+ def asset_file_path(path)
+ File.join(ASSETS_DIR, path.split('?').first)
end
def collect_asset_files(*path)
diff --git a/actionpack/lib/action_view/helpers/atom_feed_helper.rb b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
index ebb1cb34bc..e65d5d1f60 100644
--- a/actionpack/lib/action_view/helpers/atom_feed_helper.rb
+++ b/actionpack/lib/action_view/helpers/atom_feed_helper.rb
@@ -17,7 +17,7 @@ module ActionView
# # GET /posts.atom
# def index
# @posts = Post.find(:all)
- #
+ #
# respond_to do |format|
# format.html
# format.atom
@@ -29,12 +29,12 @@ module ActionView
# atom_feed do |feed|
# feed.title("My great blog!")
# feed.updated((@posts.first.created_at))
- #
+ #
# for post in @posts
# feed.entry(post) do |entry|
# entry.title(post.title)
# entry.content(post.body, :type => 'html')
- #
+ #
# entry.author do |author|
# author.name("DHH")
# end
@@ -47,8 +47,9 @@ module ActionView
# * <tt>:language</tt>: Defaults to "en-US".
# * <tt>:root_url</tt>: The HTML alternative that this feed is doubling for. Defaults to / on the current host.
# * <tt>:url</tt>: The URL for this feed. Defaults to the current URL.
- # * <tt>:schema_date</tt>: The date at which the tag scheme for the feed was first used. A good default is the year you
- # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified,
+ # * <tt>:id</tt>: The id for this feed. Defaults to "tag:#{request.host},#{options[:schema_date]}:#{request.request_uri.split(".")[0]}"
+ # * <tt>:schema_date</tt>: The date at which the tag scheme for the feed was first used. A good default is the year you
+ # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified,
# 2005 is used (as an "I don't care" value).
#
# Other namespaces can be added to the root element:
@@ -81,7 +82,7 @@ module ActionView
else
options[:schema_date] = "2005" # The Atom spec copyright date
end
-
+
xml = options[:xml] || eval("xml", block.binding)
xml.instruct!
@@ -89,10 +90,10 @@ module ActionView
feed_opts.merge!(options).reject!{|k,v| !k.to_s.match(/^xml/)}
xml.feed(feed_opts) do
- xml.id("tag:#{request.host},#{options[:schema_date]}:#{request.request_uri.split(".")[0]}")
+ xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.request_uri.split(".")[0]}")
xml.link(:rel => 'alternate', :type => 'text/html', :href => options[:root_url] || (request.protocol + request.host_with_port))
xml.link(:rel => 'self', :type => 'application/atom+xml', :href => options[:url] || request.url)
-
+
yield AtomFeedBuilder.new(xml, self, options)
end
end
@@ -102,7 +103,7 @@ module ActionView
def initialize(xml, view, feed_options = {})
@xml, @view, @feed_options = xml, view, feed_options
end
-
+
# Accepts a Date or Time object and inserts it in the proper format. If nil is passed, current time in UTC is used.
def updated(date_or_time = nil)
@xml.updated((date_or_time || Time.now.utc).xmlschema)
@@ -115,9 +116,10 @@ module ActionView
# * <tt>:published</tt>: Time first published. Defaults to the created_at attribute on the record if one such exists.
# * <tt>:updated</tt>: Time of update. Defaults to the updated_at attribute on the record if one such exists.
# * <tt>:url</tt>: The URL for this entry. Defaults to the polymorphic_url for the record.
+ # * <tt>:id</tt>: The ID for this entry. Defaults to "tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}"
def entry(record, options = {})
- @xml.entry do
- @xml.id("tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}")
+ @xml.entry do
+ @xml.id(options[:id] || "tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}")
if options[:published] || (record.respond_to?(:created_at) && record.created_at)
@xml.published((options[:published] || record.created_at).xmlschema)
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index eb74d4a4c7..074ba5a2b5 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -68,7 +68,7 @@ module ActionView
#
# <%# app/views/users/_editor.html.erb &>
# <div id="editor">
- # Deadline: $<%= user.deadline %>
+ # Deadline: <%= user.deadline %>
# <%= yield %>
# </div>
#
@@ -82,7 +82,7 @@ module ActionView
#
# Here's the editor:
# <div id="editor">
- # Deadline: $<%= user.deadline %>
+ # Deadline: <%= user.deadline %>
# Name: <%= user.name %>
# </div>
#
@@ -101,6 +101,40 @@ module ActionView
# </div>
#
# As you can see, the <tt>:locals</tt> hash is shared between both the partial and its layout.
+ #
+ # If you pass arguments to "yield" then this will be passed to the block. One way to use this is to pass
+ # an array to layout and treat it as an enumerable.
+ #
+ # <%# app/views/users/_user.html.erb &>
+ # <div class="user">
+ # Budget: $<%= user.budget %>
+ # <%= yield user %>
+ # </div>
+ #
+ # <%# app/views/users/index.html.erb &>
+ # <% render :layout => @users do |user| %>
+ # Title: <%= user.title %>
+ # <% end %>
+ #
+ # This will render the layout for each user and yield to the block, passing the user, each time.
+ #
+ # You can also yield multiple times in one layout and use block arguments to differentiate the sections.
+ #
+ # <%# app/views/users/_user.html.erb &>
+ # <div class="user">
+ # <%= yield user, :header %>
+ # Budget: $<%= user.budget %>
+ # <%= yield user, :footer %>
+ # </div>
+ #
+ # <%# app/views/users/index.html.erb &>
+ # <% render :layout => @users do |user, section| %>
+ # <%- case section when :header -%>
+ # Title: <%= user.title %>
+ # <%- when :footer -%>
+ # Deadline: <%= user.deadline %>
+ # <%- end -%>
+ # <% end %>
module Partials
extend ActiveSupport::Memoizable
@@ -127,7 +161,7 @@ module ActionView
end
def render_partial_collection(partial_path, collection, partial_spacer_template = nil, local_assigns = {}, as = nil) #:nodoc:
- return " " if collection.empty?
+ return nil if collection.blank?
local_assigns = local_assigns ? local_assigns.clone : {}
spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
@@ -146,7 +180,7 @@ module ActionView
def find_partial_path(partial_path)
if partial_path.include?('/')
- "#{File.dirname(partial_path)}/_#{File.basename(partial_path)}"
+ File.join(File.dirname(partial_path), "_#{File.basename(partial_path)}")
elsif respond_to?(:controller)
"#{controller.class.controller_path}/_#{partial_path}"
else
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index d97f963540..d6bf2137af 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -1,9 +1,9 @@
module ActionView #:nodoc:
- class PathSet < ActiveSupport::TypedArray #:nodoc:
+ class PathSet < Array #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
if Base.warn_cache_misses && defined?(Rails) && Rails.initialized?
- Rails.logger.debug "[PERFORMANCE] Processing view path during a " +
+ Base.logger.debug "[PERFORMANCE] Processing view path during a " +
"request. This an expense disk operation that should be done at " +
"boot. You can manually process this view path with " +
"ActionView::Base.process_view_paths(#{obj.inspect}) and set it " +
@@ -15,6 +15,30 @@ module ActionView #:nodoc:
end
end
+ def initialize(*args)
+ super(*args).map! { |obj| self.class.type_cast(obj) }
+ end
+
+ def <<(obj)
+ super(self.class.type_cast(obj))
+ end
+
+ def concat(array)
+ super(array.map! { |obj| self.class.type_cast(obj) })
+ end
+
+ def insert(index, obj)
+ super(index, self.class.type_cast(obj))
+ end
+
+ def push(*objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+
+ def unshift(*objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+
class Path #:nodoc:
def self.eager_load_templates!
@eager_load_templates = true
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 5fe1ca86f3..c011f21550 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -31,10 +31,17 @@ module ActionView
view.send(:evaluate_assigns)
view.send(:set_controller_content_type, mime_type) if respond_to?(:mime_type)
- view.send(:execute, method(local_assigns), local_assigns)
+
+ view.send(method_name(local_assigns), local_assigns) do |*names|
+ if proc = view.instance_variable_get("@_proc_for_layout")
+ view.capture(*names, &proc)
+ else
+ view.instance_variable_get("@content_for_#{names.first || 'layout'}")
+ end
+ end
end
- def method(local_assigns)
+ def method_name(local_assigns)
if local_assigns && local_assigns.any?
local_assigns_keys = "locals_#{local_assigns.keys.map { |k| k.to_s }.sort.join('_')}"
end
@@ -44,7 +51,7 @@ module ActionView
private
# Compile and evaluate the template's code (if necessary)
def compile(local_assigns)
- render_symbol = method(local_assigns)
+ render_symbol = method_name(local_assigns)
@@mutex.synchronize do
if recompile?(render_symbol)
@@ -65,7 +72,7 @@ module ActionView
end_src
begin
- logger = ActionController::Base.logger
+ logger = Base.logger
logger.debug "Compiling template #{render_symbol}" if logger
ActionView::Base::CompiledTemplates.module_eval(source, filename, 0)