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
Child controller's before action is overridden by parent #43332
Comments
I think this is regular behavior of Ruby. You used This article might be helpful https://medium.com/@leo_hetsch/ruby-modules-include-vs-prepend-vs-extend-f09837a5b073 |
@RolandStuder |
To get this to pass remove or in BaseControllerDecorator, set |
@Austio Thanks. I'm reporting a potential bug, modifying the test doesn't make sense here. Actually the code I posted is a simplified version I met in real life. I found the wired behavior and dig into the source code a little bit, and it seems there are something not quite right. |
@samzhao2008 reporting investigation so others can pick up and don't have to take those steps This also works using Classes for callbacks instead of methods, i think i see where this bug could be. Hopefully adjusting to classes will unblock your more complex case.
|
On using classesI think your best bet here is to use Classes to define your callbacks, then the load order will not matter here at all. The reason that this works with classes is due to the callbacks only deduping when we have a symbol On load orderIf you switch the order of prepending (do Base first, then Child) there is not an issue here. I'm not sure if this is a bug in callbacks because the load order is different than what i would normally expect (normally meaning a plain rails project with no manual includes like the example) from what would be loaded in a rails/ruby application. There very well could be a "cache key" issue that i'd like to dig deeper into. I'd like to see if i can reproduce any other error scenarios here before writing this off. This is happening because internally when we define callbacks on the Base after they are defined on the Child, we update the callbacks on the Child with the method. # Current behavior, this fails
ChildController.prepend(ChildControllerDecorator)
BaseController.prepend(BaseControllerDecorator)
# "normal" loading order, this will work
BaseController.prepend(BaseControllerDecorator)
ChildController.prepend(ChildControllerDecorator) |
@Austio Thanks for introducing to use class for before_action. I never know that before. I think the method/symbol way is a more common use case. So, the behavior should be consistent in all cases. If it's not, it's a bug which should be fixed. Yes, switch the 2 lines works. But, it's just the way to make the test pass. In a real life project these lines of code may in many different files, we can not and should not care about the load order. |
@samzhao2008 I see what you mean here. The logic for removing duplicates was added to prevent duplicates within the same controller. I'll see if i can patch this in a reasonable way. In meantime, encourage you to define these callbacks with Classes to sidestep the load order issue. |
@Austio nice! I'm also trying to fix it. |
Steps to reproduce
Expected behavior
ChildController's before action should not be overridden by parent. In the test case, @instance_var should be set to
:index
, and only be set whenindex
action is executed.Actual behavior
ChildController's before action is overridden by parent. wrong execution condition and value.
System configuration
Rails version:
main
branchRuby version: 2.7.2
In order to figure it out, I read the source code. It seems every time the
before_action
orprepend_before_action
is executed, there is a operation calledremove_duplicates
which remove the filters with the same name from itself and its descendants. It should not remove filters with the same name from its descendants, right?The text was updated successfully, but these errors were encountered: