A lot of funkiness going on with Hooks and dm-more
Reported by Carl Lerche | June 11th, 2008 @ 05:55 PM
Alright, I will try to explain this as best as I can. First, let me start by explaining how I came across this bug.
I created a simple model in Merb and I required dm-validations. All is good. I can save my model and specify the context ( User.new.save(:default) ).
Ok, now I decide that I would like to have the dm-timestamps extension. I require dm-timestamps BEFORE dm-validations.
All of a sudden, I have the OLD #save method (without validations). However, all the other methods from the Validation module are present. I can still do User.new.valid?
Funkiness!!!!
So, I decided to do some digging. I isolated the problem to line #33 in dm-timestamps.rb (model.before :save, :set_timestamp_properties).
It turns out that there is a bug with declaring instance hooks inside a def self.included(base) method. I believe that this method is run BEFORE the module is actually included (at least, before the class that is including the module has the methods defined in it). Now, I checked out the Hook code and hooks work by redefining the method that is being hooked (seems a bit fishy to me). In other words, the method that is being hooked is being redefined before it is actually defined by a module that is being included... or something.
I'm not exactly sure what it is, but it smells fishy.
Personally, I don't get why Hook is coded as is instead of something simpler where callbacks are explicitly invoked. It seems pretty complicated as is.
Comments and changes to this ticket
-
-
Carl Lerche June 11th, 2008 @ 09:51 PM
Check out this little bit of code. It demos why the bug happens.
#!/usr/bin/env ruby module FirstModule def self.included(base) base.class_eval %{ def test "world" end } base.class_eval { include SecondModule } end end module SecondModule def test "hello" end end class MyClass include FirstModule end # Will put "world". Hook assumes it will put "hello" puts MyClass.new.testBasically, dm-timestamp adds a before save Hook when included (using class_eval and rewriting the method being hooked) and dm-validations tries to include a new version of save so the dm-validations save method is completely lost.
-
Carl Lerche June 11th, 2008 @ 11:18 PM
Welp, I think I figured the problem out and I created a patch and spec.
-
Adam French June 12th, 2008 @ 10:48 AM
- → State changed from new to resolved
I just applied the patch and it works like a charm. Thanks a bunch carl!
Please Login or create a free account to add a new comment.
You can update this ticket by sending an email to from your email client. (help)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
