From 4ee3e5b094463383891789f484e927b19fccc744 Mon Sep 17 00:00:00 2001 From: Yehuda Katz + Carl Lerche Date: Thu, 30 Apr 2009 15:13:40 -0700 Subject: Ported over the concept of public instance methods on controller child classes as callable action methods --- actionpack/lib/action_controller/abstract/base.rb | 48 +++++++++++++++++++---- actionpack/lib/action_controller/new_base/base.rb | 14 +++---- actionpack/test/controller/render_test.rb | 7 ++++ actionpack/test/new_base/render_test.rb | 10 +++++ actionpack/test/new_base/test_helper.rb | 10 ++--- 5 files changed, 69 insertions(+), 20 deletions(-) (limited to 'actionpack') diff --git a/actionpack/lib/action_controller/abstract/base.rb b/actionpack/lib/action_controller/abstract/base.rb index a87a490a2d..3b85ba5565 100644 --- a/actionpack/lib/action_controller/abstract/base.rb +++ b/actionpack/lib/action_controller/abstract/base.rb @@ -4,13 +4,44 @@ module AbstractController attr_internal :response_body attr_internal :response_obj attr_internal :action_name - - def self.process(action) - new.process(action) + + class << self + attr_reader :abstract + + def abstract! + @abstract = true + end + + alias_method :abstract?, :abstract + + def internal_methods + controller = self + controller = controller.superclass until controller.abstract? + controller.public_instance_methods(true) + end + + def process(action) + new.process(action) + end + + def hidden_actions + [] + end + + def action_methods + @action_methods ||= + # All public instance methods of this class, including ancestors + public_instance_methods(true).map { |m| m.to_sym }.to_set - + # Except for public instance methods of Base and its ancestors + internal_methods.map { |m| m.to_sym } + + # Be sure to include shadowed public instance methods of this class + public_instance_methods(false).map { |m| m.to_sym } - + # And always exclude explicitly hidden actions + hidden_actions + end end - def self.inherited(klass) - end + abstract! def initialize self.response_obj = {} @@ -29,6 +60,10 @@ module AbstractController private + def action_methods + self.class.action_methods + end + # It is possible for respond_to?(action_name) to be false and # respond_to?(:action_missing) to be false if respond_to_action? # is overridden in a subclass. For instance, ActionController::Base @@ -45,8 +80,7 @@ module AbstractController # you must handle it by also overriding process_action and # handling the case. def respond_to_action?(action_name) - respond_to?(action_name) || respond_to?(:action_missing, true) + action_methods.include?(action_name) || respond_to?(:action_missing, true) end - end end \ No newline at end of file diff --git a/actionpack/lib/action_controller/new_base/base.rb b/actionpack/lib/action_controller/new_base/base.rb index 9f7a148b3c..00d161289e 100644 --- a/actionpack/lib/action_controller/new_base/base.rb +++ b/actionpack/lib/action_controller/new_base/base.rb @@ -1,5 +1,6 @@ module ActionController class Http < AbstractController::Base + abstract! # :api: public attr_internal :request, :response, :params @@ -19,18 +20,15 @@ module ActionController # :api: public def controller_path() self.class.controller_path end - - # :api: private - def self.action_methods - @action_names ||= Set.new(self.public_instance_methods - self::CORE_METHODS) + + # :api: private + def self.internal_methods + ActionController::Http.public_instance_methods(true) end # :api: private def self.action_names() action_methods end - # :api: private - def action_methods() self.class.action_names end - # :api: private def action_names() action_methods end @@ -44,7 +42,7 @@ module ActionController def call(env) @_request = ActionDispatch::Request.new(env) @_response = ActionDispatch::Response.new - process(@_request.parameters[:action]) + process(@_request.parameters[:action].to_sym) @_response.body = response_body @_response.prepare! self diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index d4a18a673c..e6b2ee7e9f 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -4,6 +4,7 @@ require 'pathname' module Fun class GamesController < ActionController::Base + # :ported: def hello_world end end @@ -116,6 +117,7 @@ class TestController < ActionController::Base render :text => "hello #{@person}" end + # :ported: def render_action_hello_world render :action => "hello_world" end @@ -839,17 +841,20 @@ class RenderTest < ActionController::TestCase assert_equal "hello david", @response.body end + # :ported: def test_render_action get :render_action_hello_world assert_template "test/hello_world" end + # :ported: def test_render_action_hello_world_as_string get :render_action_hello_world_as_string assert_equal "Hello world!", @response.body assert_template "test/hello_world" end + # :ported: def test_render_action_with_symbol get :render_action_hello_world_with_symbol assert_template "test/hello_world" @@ -949,6 +954,7 @@ class RenderTest < ActionController::TestCase assert_equal 'application/json', @response.content_type end + # :ported: def test_render_custom_code get :render_custom_code assert_response 404 @@ -1082,6 +1088,7 @@ class RenderTest < ActionController::TestCase assert_template "test/hello_world" end + # :ported: def test_nested_rendering @controller = Fun::GamesController.new get :hello_world diff --git a/actionpack/test/new_base/render_test.rb b/actionpack/test/new_base/render_test.rb index 93bc8d854c..bc7203f294 100644 --- a/actionpack/test/new_base/render_test.rb +++ b/actionpack/test/new_base/render_test.rb @@ -35,4 +35,14 @@ module Render end end end + + class TestRenderObjectMethod < SimpleRouteCase + describe "Methods on Object are not actions" + + test "raises an exception" do + assert_raises(AbstractController::ActionNotFound) do + get "/render/blank_render/clone" + end + end + end end \ No newline at end of file diff --git a/actionpack/test/new_base/test_helper.rb b/actionpack/test/new_base/test_helper.rb index 03af5a66a6..d58b83cf7b 100644 --- a/actionpack/test/new_base/test_helper.rb +++ b/actionpack/test/new_base/test_helper.rb @@ -34,6 +34,8 @@ end module ActionController class Base2 < Http + abstract! + use AbstractController::Callbacks use AbstractController::Helpers use AbstractController::Logger @@ -80,15 +82,13 @@ module ActionController end def respond_to_action?(action_name) - super || view_paths.find_by_parts(action_name, {:formats => formats, :locales => [I18n.locale]}, controller_path) + super || view_paths.find_by_parts?(action_name.to_s, {:formats => formats, :locales => [I18n.locale]}, controller_path) end - - # append_view_path File.join(File.dirname(__FILE__), '..', 'fixtures') - - CORE_METHODS = self.public_instance_methods end class CompatibleBase2 < Base2 + abstract! + use ActionController::Rails2Compatibility end end -- cgit v1.2.3