aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack
diff options
context:
space:
mode:
authorSam Stephenson <sam@37signals.com>2006-01-20 22:04:07 +0000
committerSam Stephenson <sam@37signals.com>2006-01-20 22:04:07 +0000
commit06dd1f2ca3398b978bb286688aa68acacd7dd712 (patch)
tree7b924286338cb81f252b448ec3851238fab9573e /actionpack
parentf9c13e6134bbc32dd826eec39fedba5de2514f88 (diff)
downloadrails-06dd1f2ca3398b978bb286688aa68acacd7dd712.tar.gz
rails-06dd1f2ca3398b978bb286688aa68acacd7dd712.tar.bz2
rails-06dd1f2ca3398b978bb286688aa68acacd7dd712.zip
Add render :update for inline RJS
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3441 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
Diffstat (limited to 'actionpack')
-rw-r--r--actionpack/CHANGELOG10
-rwxr-xr-xactionpack/lib/action_controller/base.rb37
-rw-r--r--actionpack/lib/action_controller/benchmarking.rb6
-rw-r--r--actionpack/lib/action_controller/layout.rb8
-rw-r--r--actionpack/test/controller/new_render_test.rb13
5 files changed, 60 insertions, 14 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index ec0216f565..a5150cee7f 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,15 @@
*SVN*
+* Add render :update for inline RJS. [Sam Stephenson] Example:
+ class UserController < ApplicationController
+ def refresh
+ render :update do |page|
+ page.replace_html 'user_list', :partial => 'user', :collection => @users
+ page.visual_effect :highlight, 'user_list'
+ end
+ end
+ end
+
* allow nil objects for error_messages_for [Michael Koziarski]
* Refactor human_size to exclude decimal place if it is zero. [Marcel Molina Jr.]
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index a5b74d6a19..40fa24a696 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -368,9 +368,9 @@ module ActionController #:nodoc:
# Returns a URL that has been rewritten according to the options hash and the defined Routes.
# (For doing a complete redirect, use redirect_to).
- #  
+ #  
# <tt>url_for</tt> is used to:
- #  
+ #  
# All keys given to url_for are forwarded to the Route module, save for the following:
# * <tt>:anchor</tt> -- specifies the anchor name to be appended to the path. For example,
# <tt>url_for :controller => 'posts', :action => 'show', :id => 10, :anchor => 'comments'</tt>
@@ -386,7 +386,7 @@ module ActionController #:nodoc:
#
# The default Routes setup supports a typical Rails path of "controller/action/id" where action and id are optional, with
# action defaulting to 'index' when not given. Here are some typical url_for statements and their corresponding URLs:
- #  
+ #  
# url_for :controller => 'posts', :action => 'recent' # => 'proto://host.com/posts/recent'
# url_for :controller => 'posts', :action => 'index' # => 'proto://host.com/posts'
# url_for :controller => 'posts', :action => 'show', :id => 10 # => 'proto://host.com/posts/show/10'
@@ -395,7 +395,7 @@ module ActionController #:nodoc:
# <tt>url_for :action => 'some_action'</tt> will retain the current controller, as expected. This behavior extends to
# other parameters, including <tt>:controller</tt>, <tt>:id</tt>, and any other parameters that are placed into a Route's
# path.
- #  
+ #  
# The URL helpers such as <tt>url_for</tt> have a limited form of memory: when generating a new URL, they can look for
# missing values in the current request's parameters. Routes attempts to guess when a value should and should not be
# taken from the defaults. There are a few simple rules on how this is performed:
@@ -418,7 +418,7 @@ module ActionController #:nodoc:
# answer has to do with the order in which the parameters appear in the generated path. In a nutshell, since the
# value that appears in the slot for <tt>:first</tt> is not equal to default value for <tt>:first</tt> we stop using
# defaults. On it's own, this rule can account for much of the typical Rails URL behavior.
- #  
+ #  
# Although a convienence, defaults can occasionaly get in your way. In some cases a default persists longer than desired.
# The default may be cleared by adding <tt>:name => nil</tt> to <tt>url_for</tt>'s options.
# This is often required when writing form helpers, since the defaults in play may vary greatly depending upon where the
@@ -571,6 +571,16 @@ module ActionController #:nodoc:
#
# _Deprecation_ _notice_: This used to have the signature <tt>render_template(template, status = 200, type = :rhtml)</tt>
#
+ # === Rendering inline JavaScriptGenerator page updates
+ #
+ # In addition to rendering JavaScriptGenerator page updates with Ajax in RJS templates (see ActionView::Base for details),
+ # you can also pass the <tt>:update</tt> parameter to +render+, along with a block, to render page updates inline.
+ #
+ # render :update do |page|
+ # page.replace_html 'user_list', :partial => 'user', :collection => @users
+ # page.visual_effect :highlight, 'user_list'
+ # end
+ #
# === Rendering nothing
#
# Rendering nothing is often convenient in combination with Ajax calls that perform their effect client-side or
@@ -581,12 +591,16 @@ module ActionController #:nodoc:
#
# # Renders an empty response with status code 401 (access denied)
# render :nothing => true, :status => 401
- def render(options = nil, deprecated_status = nil) #:doc:
+ def render(options = nil, deprecated_status = nil, &block) #:doc:
raise DoubleRenderError, "Can only render or redirect once per action" if performed?
# Backwards compatibility
unless options.is_a?(Hash)
- return render_file(options || default_template_name, deprecated_status, true)
+ if options == :update
+ options = {:update => true}
+ else
+ return render_file(options || default_template_name, deprecated_status, true)
+ end
end
if text = options[:text]
@@ -613,6 +627,10 @@ module ActionController #:nodoc:
render_partial(partial, ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals], options[:status])
end
+ elsif options[:update]
+ generator = ActionView::Helpers::PrototypeHelper::JavaScriptGenerator.new(@template, &block)
+ render_javascript(generator.to_s)
+
elsif options[:nothing]
# Safari doesn't pass the headers of the return if the response is zero length
render_text(" ", options[:status])
@@ -661,6 +679,11 @@ module ActionController #:nodoc:
@response.body = text
end
+ def render_javascript(javascript, status = nil)
+ @response.headers['Content-type'] = 'text/javascript'
+ render_text(javascript, status)
+ end
+
def render_nothing(status = nil)
render_text(' ', status)
end
diff --git a/actionpack/lib/action_controller/benchmarking.rb b/actionpack/lib/action_controller/benchmarking.rb
index ceed88f2bf..eff4d97fae 100644
--- a/actionpack/lib/action_controller/benchmarking.rb
+++ b/actionpack/lib/action_controller/benchmarking.rb
@@ -43,14 +43,14 @@ module ActionController #:nodoc:
end
end
- def render_with_benchmark(options = nil, deprecated_status = nil)
+ def render_with_benchmark(options = nil, deprecated_status = nil, &block)
unless logger
- render_without_benchmark(options, deprecated_status)
+ render_without_benchmark(options, deprecated_status, &block)
else
db_runtime = ActiveRecord::Base.connection.reset_runtime if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
render_output = nil
- @rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status) }.real
+ @rendering_runtime = Benchmark::measure{ render_output = render_without_benchmark(options, deprecated_status, &block) }.real
if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
@db_rt_before_render = db_runtime
diff --git a/actionpack/lib/action_controller/layout.rb b/actionpack/lib/action_controller/layout.rb
index baa035507d..94fa4cc4ba 100644
--- a/actionpack/lib/action_controller/layout.rb
+++ b/actionpack/lib/action_controller/layout.rb
@@ -211,7 +211,7 @@ module ActionController #:nodoc:
active_layout.include?('/') && !nested_controller ? active_layout : "layouts/#{active_layout}" if active_layout
end
- def render_with_a_layout(options = nil, deprecated_status = nil, deprecated_layout = nil) #:nodoc:
+ def render_with_a_layout(options = nil, deprecated_status = nil, deprecated_layout = nil, &block) #:nodoc:
template_with_options = options.is_a?(Hash)
if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options, deprecated_layout))
@@ -219,10 +219,10 @@ module ActionController #:nodoc:
logger.info("Rendering #{options} within #{layout}") if logger
if template_with_options
- content_for_layout = render_with_no_layout(options)
+ content_for_layout = render_with_no_layout(options, &block)
deprecated_status = options[:status] || deprecated_status
else
- content_for_layout = render_with_no_layout(options, deprecated_status)
+ content_for_layout = render_with_no_layout(options, deprecated_status, &block)
end
erase_render_results
@@ -230,7 +230,7 @@ module ActionController #:nodoc:
@template.instance_variable_set("@content_for_layout", content_for_layout)
render_text(@template.render_file(layout, true), deprecated_status)
else
- render_with_no_layout(options, deprecated_status)
+ render_with_no_layout(options, deprecated_status, &block)
end
end
diff --git a/actionpack/test/controller/new_render_test.rb b/actionpack/test/controller/new_render_test.rb
index 38d4cdb648..580717a655 100644
--- a/actionpack/test/controller/new_render_test.rb
+++ b/actionpack/test/controller/new_render_test.rb
@@ -188,6 +188,13 @@ class NewRenderTestController < ActionController::Base
render :action => 'delete_with_js'
end
+ def update_page
+ render :update do |page|
+ page.replace_html 'balance', '$37,000,000.00'
+ page.visual_effect :highlight, 'balance'
+ end
+ end
+
def action_talk_to_layout
# Action template sets variable that's picked up by layout
end
@@ -480,6 +487,12 @@ class NewRenderTest < Test::Unit::TestCase
assert_equal "world", assigns["hello"]
end
+ def test_update_page
+ get :update_page
+ assert_equal 'text/javascript', @response.headers['Content-type']
+ assert_equal 2, @response.body.split($/).length
+ end
+
def test_yield_content_for
get :yield_content_for
assert_equal "<title>Putting stuff in the title!</title>\n\nGreat stuff!\n", @response.body