From 84f0a0bc30df58e1edfd09fdde2de891e4577321 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 4 Aug 2010 18:58:18 +0200 Subject: Reload action_methods in AbstractController after defining new method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: José Valim --- actionmailer/test/base_test.rb | 12 ++++++++++++ actionpack/lib/abstract_controller/base.rb | 12 ++++++++++++ actionpack/test/abstract/abstract_controller_test.rb | 14 ++++++++++++++ activesupport/lib/active_support/callbacks.rb | 5 ++++- 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb index e2b9df5d02..fec0ecf477 100644 --- a/actionmailer/test/base_test.rb +++ b/actionmailer/test/base_test.rb @@ -507,6 +507,18 @@ class BaseTest < ActiveSupport::TestCase assert_equal("Thanks for signing up this afternoon", mail.subject) end + test "action methods should be refreshed after defining new method" do + class FooMailer < ActionMailer::Base + # this triggers action_methods + self.respond_to?(:foo) + + def notify + end + end + + assert_equal ["notify"], FooMailer.action_methods + end + protected # Execute the block setting the given values and restoring old values after diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb index 8a8337858b..db0a6736e0 100644 --- a/actionpack/lib/abstract_controller/base.rb +++ b/actionpack/lib/abstract_controller/base.rb @@ -72,6 +72,13 @@ module AbstractController end end + # action_methods are cached and there is sometimes need to refresh + # them. clear_action_methods! allows you to do that, so next time + # you run action_methods, they will be recalculated + def clear_action_methods! + @action_methods = nil + end + # Returns the full controller name, underscored, without the ending Controller. # For instance, MyApp::MyPostsController would return "my_app/my_posts" for # controller_name. @@ -81,6 +88,11 @@ module AbstractController def controller_path @controller_path ||= name.sub(/Controller$/, '').underscore unless anonymous? end + + def method_added(name) + super + clear_action_methods! + end end abstract! diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb index 3b5013a47a..19855490b4 100644 --- a/actionpack/test/abstract/abstract_controller_test.rb +++ b/actionpack/test/abstract/abstract_controller_test.rb @@ -250,5 +250,19 @@ module AbstractController end end + class Me6 < AbstractController::Base + self.action_methods + + def index + end + end + + class TestActionMethodsReloading < ActiveSupport::TestCase + + test "action_methods should be reloaded after defining a new method" do + assert_equal ["index"], Me6.action_methods + end + end + end end diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb index 1c7802f7de..0fafd56f33 100644 --- a/activesupport/lib/active_support/callbacks.rb +++ b/activesupport/lib/active_support/callbacks.rb @@ -419,7 +419,10 @@ module ActiveSupport @_keyed_callbacks ||= {} @_keyed_callbacks[name] ||= begin str = send("_#{kind}_callbacks").compile(name, object) - class_eval "def #{name}() #{str} end", __FILE__, __LINE__ + class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1 + def #{name}() #{str} end + protected :#{name} + RUBY_EVAL true end end -- cgit v1.2.3