aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiotr Sarnacki <drogus@gmail.com>2010-08-04 18:58:18 +0200
committerJosé Valim <jose.valim@gmail.com>2010-08-04 14:44:34 -0300
commit84f0a0bc30df58e1edfd09fdde2de891e4577321 (patch)
tree9ae43e050fa94d61378927d277c9c8d61bc53d00
parent462666b73717333d460684339c6f6ce07475f713 (diff)
downloadrails-84f0a0bc30df58e1edfd09fdde2de891e4577321.tar.gz
rails-84f0a0bc30df58e1edfd09fdde2de891e4577321.tar.bz2
rails-84f0a0bc30df58e1edfd09fdde2de891e4577321.zip
Reload action_methods in AbstractController after defining new method.
Signed-off-by: José Valim <jose.valim@gmail.com>
-rw-r--r--actionmailer/test/base_test.rb12
-rw-r--r--actionpack/lib/abstract_controller/base.rb12
-rw-r--r--actionpack/test/abstract/abstract_controller_test.rb14
-rw-r--r--activesupport/lib/active_support/callbacks.rb5
4 files changed, 42 insertions, 1 deletions
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