-
Notifications
You must be signed in to change notification settings - Fork 209
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Limit private callback lookup. #58
Conversation
Thanks for catching that! This is a good idea, but this code won't work in Ruby 1.8.7 because private_methods returns an array of strings. #1.9.3
"hello".private_methods(false)
=> [:initialize, :initialize_copy]
#1.8.7
"hello".private_methods(false)
=> ["initialize_copy", "initialize"] In a previous commit I ended up mapping the return value to an array of symbols. Would be good to see some tests included! =) |
Background: Commit 71937c0 introduced private callbacks, however, the use of "private_method_defined?" returns true all the way down the class hierarchy and thus causes trouble with a very common transition: Given an event "event :fail transitions_to :failed". If you don't explicitly define the "fail" event handler, "private_method_defined?" will still return true since Kernel#fail is defined for any object. Transitioning with "fail!" then causes a runtime error.
As you suggested, I've added |
@geekq, think we can get a bugfix 0.8.7 release soon? =) |
Sorry - was busy with my current project.
Going to do this this weekend/monday ETA: 2013-01-14 |
The change will brake class hierarchies with private callback methods. But it is less harm, than unintentionally calling some private methods, especially in kernel. So going to merge... Would like to test with ruby-1.9.3, ruby-1.8.7 and jruby. Unfortunately my current rbenv for 1.8.7 and 1.8.6 broken. Need to repair that first. |
Wouldn't defining the methods as |
After some testing I've determined the following about protected methods defined on a parent class: (this is consistent in 1.9.3 and 1.8.7):
Based on these results, I say we add |
I made a gist to help me understand and document all the craziness behind private methods, protected methods, and inheritance: |
Hi, I've prepared my continuous integration environment for testing with various ruby versions. Not yet on travis-ci.org, just on my notebook. Can now review/try out/merge. @sven Thanks for the test and for the improved 1.8.7 compatibility! @david Thanks for the 1.8.7 investigation and for the 'protected method' idea! I think, using protected methods as callbacks is the best way to go:
Best Regards, Vladimir (geekq) |
Thanks! My idea was actually to support both private and protected methods, by using both |
OK, adding support for private methods again ;-) - but only in the immediate class now. Big surprise: respond_to? returns true for inherited protected methods (for me). But it can change one more time in Ruby2. Meta programming is hard and it is even harder with a moving target like Ruby 1.9 ;-) So I'll keep all the 3 checks even if the second one currently seems to be unneeded on 1.8.7-p371 and 1.9.3-rc1 |
Great! I like how to checks are documented now with some comments! =D Otherwise it would be quite confusing to understand why all those checks are necessary. |
Support for private callbacks introduced in commit 71937c0 is a good thing, however, the way private callbacks are looked up caused a nasty issue in one of my models dealing with credit cards:
Now try to transition with
fail!
and - kaboom - runtime error. The problem is the lookup in the workflow gem:Eventhough no private event handler
fail
is defined in the model,private_method_defined?
still returnstrue
as it does for any object due toKernel#fail
.The problem is quite nasty and since "fail" appears to be a rather common transition in workflows, using another event name is not the best solution. But there's an easy way to limit the method lookup:
Which is exactly what this pull request contains :-)