Revision 75dd7e8f
Added by Ohad Levy almost 13 years ago
- ID 75dd7e8f2dece952a92d6bd2d4e896816bf55d8f
extras/puppet | ||
---|---|---|
Subproject commit 1fec77660a1d32337fc053a5789bf6116ccd7b31
|
||
Subproject commit cb859514db796521f0c61adf1dd6ad9ab4860800
|
vendor/plugins/render_component/README | ||
---|---|---|
Components allow you to call other actions for their rendered response while executing another action. You can either delegate
|
||
the entire response rendering or you can mix a partial response in with your other content.
|
||
|
||
class WeblogController < ActionController::Base
|
||
# Performs a method and then lets hello_world output its render
|
||
def delegate_action
|
||
do_other_stuff_before_hello_world
|
||
render_component :controller => "greeter", :action => "hello_world", :params => { :person => "david" }
|
||
end
|
||
end
|
||
|
||
class GreeterController < ActionController::Base
|
||
def hello_world
|
||
render :text => "#{params[:person]} says, Hello World!"
|
||
end
|
||
end
|
||
|
||
The same can be done in a view to do a partial rendering:
|
||
|
||
Let's see a greeting:
|
||
<%= render_component :controller => "greeter", :action => "hello_world" %>
|
||
|
||
It is also possible to specify the controller as a class constant, bypassing the inflector
|
||
code to compute the controller class at runtime:
|
||
|
||
<%= render_component :controller => GreeterController, :action => "hello_world" %>
|
||
|
||
== When to use components
|
||
|
||
Components should be used with care. They're significantly slower than simply splitting reusable parts into partials and
|
||
conceptually more complicated. Don't use components as a way of separating concerns inside a single application. Instead,
|
||
reserve components to those rare cases where you truly have reusable view and controller elements that can be employed
|
||
across many applications at once.
|
||
|
||
So to repeat: Components are a special-purpose approach that can often be replaced with better use of partials and filters.
|
||
|
||
Copyright (c) 2007 David Heinemeier Hansson, released under the MIT license
|
vendor/plugins/render_component/Rakefile | ||
---|---|---|
require 'rake'
|
||
require 'rake/testtask'
|
||
require 'rake/rdoctask'
|
||
|
||
desc 'Default: run unit tests.'
|
||
task :default => :test
|
||
|
||
desc 'Test the components plugin.'
|
||
Rake::TestTask.new(:test) do |t|
|
||
t.libs << 'lib'
|
||
t.pattern = 'test/**/*_test.rb'
|
||
t.verbose = true
|
||
end
|
||
|
||
desc 'Generate documentation for the components plugin.'
|
||
Rake::RDocTask.new(:rdoc) do |rdoc|
|
||
rdoc.rdoc_dir = 'rdoc'
|
||
rdoc.title = 'Components'
|
||
rdoc.options << '--line-numbers' << '--inline-source'
|
||
rdoc.rdoc_files.include('README')
|
||
rdoc.rdoc_files.include('lib/**/*.rb')
|
||
end
|
vendor/plugins/render_component/init.rb | ||
---|---|---|
require 'components'
|
||
ActionController::Base.send :include, Components
|
vendor/plugins/render_component/lib/components.rb | ||
---|---|---|
module Components
|
||
def self.included(base) #:nodoc:
|
||
base.class_eval do
|
||
include InstanceMethods
|
||
extend ClassMethods
|
||
helper HelperMethods
|
||
|
||
# If this controller was instantiated to process a component request,
|
||
# +parent_controller+ points to the instantiator of this controller.
|
||
attr_accessor :parent_controller
|
||
|
||
alias_method_chain :process_cleanup, :render_component
|
||
alias_method_chain :session=, :render_component
|
||
alias_method_chain :flash, :render_component
|
||
#alias_method_chain :assign_shortcuts, :render_component
|
||
alias_method_chain :send_response, :render_component
|
||
|
||
alias_method :component_request?, :parent_controller
|
||
end
|
||
end
|
||
|
||
module ClassMethods
|
||
# Track parent controller to identify component requests
|
||
def process_with_components(request, response, parent_controller = nil) #:nodoc:
|
||
controller = new
|
||
controller.parent_controller = parent_controller
|
||
controller.process(request, response)
|
||
end
|
||
end
|
||
|
||
module HelperMethods
|
||
def render_component(options)
|
||
@controller.__send__(:render_component_as_string, options)
|
||
end
|
||
end
|
||
|
||
module InstanceMethods
|
||
# Extracts the action_name from the request parameters and performs that action.
|
||
def process_with_components(request, response, method = :perform_action, *arguments) #:nodoc:
|
||
flash.discard if component_request?
|
||
process_without_components(request, response, method, *arguments)
|
||
end
|
||
|
||
def send_response_with_render_component
|
||
response.prepare! unless component_request?
|
||
response
|
||
end
|
||
|
||
protected
|
||
# Renders the component specified as the response for the current method
|
||
def render_component(options) #:doc:
|
||
component_logging(options) do
|
||
render_for_text(component_response(options, true).body, response.headers["Status"])
|
||
end
|
||
end
|
||
|
||
# Returns the component response as a string
|
||
def render_component_as_string(options) #:doc:
|
||
component_logging(options) do
|
||
response = component_response(options, false)
|
||
|
||
if redirected = response.redirected_to
|
||
render_component_as_string(redirected)
|
||
else
|
||
response.body
|
||
end
|
||
end
|
||
end
|
||
|
||
def flash_with_render_component(refresh = false) #:nodoc:
|
||
if !defined?(@_flash) || refresh
|
||
@_flash =
|
||
if defined?(@parent_controller)
|
||
@parent_controller.flash
|
||
else
|
||
flash_without_render_component
|
||
end
|
||
end
|
||
@_flash
|
||
end
|
||
|
||
private
|
||
def component_response(options, reuse_response)
|
||
klass = component_class(options)
|
||
request = request_for_component(klass.controller_path, options)
|
||
new_response = reuse_response ? response : response.dup
|
||
|
||
klass.process_with_components(request, new_response, self)
|
||
end
|
||
|
||
# determine the controller class for the component request
|
||
def component_class(options)
|
||
if controller = options[:controller]
|
||
controller.is_a?(Class) ? controller : "#{controller.camelize}Controller".constantize
|
||
else
|
||
self.class
|
||
end
|
||
end
|
||
|
||
# Create a new request object based on the current request.
|
||
# The new request inherits the session from the current request,
|
||
# bypassing any session options set for the component controller's class
|
||
def request_for_component(controller_path, options)
|
||
new_request = request.dup
|
||
new_request.session = request.session
|
||
|
||
new_request.instance_variable_set(
|
||
:@parameters,
|
||
(options[:params] || {}).with_indifferent_access.update(
|
||
"controller" => controller_path, "action" => options[:action], "id" => options[:id]
|
||
)
|
||
)
|
||
|
||
new_request
|
||
end
|
||
|
||
def component_logging(options)
|
||
if logger
|
||
logger.info "Start rendering component (#{options.inspect}): "
|
||
result = yield
|
||
logger.info "\n\nEnd of component rendering"
|
||
result
|
||
else
|
||
yield
|
||
end
|
||
end
|
||
|
||
def session_with_render_component=(options = {})
|
||
session_without_render_component=(options) unless component_request?
|
||
end
|
||
|
||
def process_cleanup_with_render_component
|
||
process_cleanup_without_render_component unless component_request?
|
||
end
|
||
|
||
def assign_shortcuts_with_render_component(request, response)
|
||
assign_shortcuts_without_render_component(request, response)
|
||
flash(:refresh)
|
||
flash.sweep if @_session && !component_request?
|
||
end
|
||
end
|
||
end
|
vendor/plugins/render_component/test/abstract_unit.rb | ||
---|---|---|
require 'rubygems'
|
||
require 'test/unit'
|
||
require 'action_controller'
|
||
require 'action_controller/test_process'
|
||
ActionController::Routing::Routes.reload rescue nil
|
||
|
||
$: << File.dirname(__FILE__) + "/../lib"
|
||
require File.dirname(__FILE__) + "/../init"
|
vendor/plugins/render_component/test/components_test.rb | ||
---|---|---|
require File.dirname(__FILE__) + '/abstract_unit'
|
||
|
||
class CallerController < ActionController::Base
|
||
def calling_from_controller
|
||
render_component(:controller => "callee", :action => "being_called")
|
||
end
|
||
|
||
def calling_from_controller_with_params
|
||
render_component(:controller => "callee", :action => "being_called", :params => { "name" => "David" })
|
||
end
|
||
|
||
def calling_from_controller_with_different_status_code
|
||
render_component(:controller => "callee", :action => "blowing_up")
|
||
end
|
||
|
||
def calling_from_template
|
||
render :inline => "Ring, ring: <%= render_component(:controller => 'callee', :action => 'being_called') %>"
|
||
end
|
||
|
||
def internal_caller
|
||
render :inline => "Are you there? <%= render_component(:action => 'internal_callee') %>"
|
||
end
|
||
|
||
def internal_callee
|
||
render :text => "Yes, ma'am"
|
||
end
|
||
|
||
def set_flash
|
||
render_component(:controller => "callee", :action => "set_flash")
|
||
end
|
||
|
||
def use_flash
|
||
render_component(:controller => "callee", :action => "use_flash")
|
||
end
|
||
|
||
def calling_redirected
|
||
render_component(:controller => "callee", :action => "redirected")
|
||
end
|
||
|
||
def calling_redirected_as_string
|
||
render :inline => "<%= render_component(:controller => 'callee', :action => 'redirected') %>"
|
||
end
|
||
|
||
def rescue_action(e) raise end
|
||
end
|
||
|
||
class CalleeController < ActionController::Base
|
||
def being_called
|
||
render :text => "#{params[:name] || "Lady"} of the House, speaking"
|
||
end
|
||
|
||
def blowing_up
|
||
render :text => "It's game over, man, just game over, man!", :status => 500
|
||
end
|
||
|
||
def set_flash
|
||
flash[:notice] = 'My stoney baby'
|
||
render :text => 'flash is set'
|
||
end
|
||
|
||
def use_flash
|
||
render :text => flash[:notice] || 'no flash'
|
||
end
|
||
|
||
def redirected
|
||
redirect_to :controller => "callee", :action => "being_called"
|
||
end
|
||
|
||
def rescue_action(e) raise end
|
||
end
|
||
|
||
class ComponentsTest < Test::Unit::TestCase
|
||
def setup
|
||
@controller = CallerController.new
|
||
@request = ActionController::TestRequest.new
|
||
@response = ActionController::TestResponse.new
|
||
end
|
||
|
||
def test_calling_from_controller
|
||
get :calling_from_controller
|
||
assert_equal "Lady of the House, speaking", @response.body
|
||
end
|
||
|
||
def test_calling_from_controller_with_params
|
||
get :calling_from_controller_with_params
|
||
assert_equal "David of the House, speaking", @response.body
|
||
end
|
||
|
||
def test_calling_from_controller_with_different_status_code
|
||
get :calling_from_controller_with_different_status_code
|
||
assert_equal 500, @response.response_code
|
||
end
|
||
|
||
def test_calling_from_template
|
||
get :calling_from_template
|
||
assert_equal "Ring, ring: Lady of the House, speaking", @response.body
|
||
end
|
||
|
||
def test_etag_is_set_for_parent_template_when_calling_from_template
|
||
get :calling_from_template
|
||
expected_etag = etag_for("Ring, ring: Lady of the House, speaking")
|
||
assert_equal expected_etag, @response.headers['ETag']
|
||
end
|
||
|
||
def test_internal_calling
|
||
get :internal_caller
|
||
assert_equal "Are you there? Yes, ma'am", @response.body
|
||
end
|
||
|
||
def test_flash
|
||
get :set_flash
|
||
assert_equal 'My stoney baby', flash[:notice]
|
||
get :use_flash
|
||
assert_equal 'My stoney baby', @response.body
|
||
get :use_flash
|
||
assert_equal 'no flash', @response.body
|
||
end
|
||
|
||
def test_component_redirect_redirects
|
||
get :calling_redirected
|
||
|
||
assert_redirected_to :controller=>"callee", :action => "being_called"
|
||
end
|
||
|
||
def test_component_multiple_redirect_redirects
|
||
test_component_redirect_redirects
|
||
test_internal_calling
|
||
end
|
||
|
||
def test_component_as_string_redirect_renders_redirected_action
|
||
get :calling_redirected_as_string
|
||
|
||
assert_equal "Lady of the House, speaking", @response.body
|
||
end
|
||
|
||
protected
|
||
def etag_for(text)
|
||
%("#{Digest::MD5.hexdigest(text)}")
|
||
end
|
||
end
|
Also available in: Unified diff
removed non required plugin, and updated reference puppet modules