Replace dependency tracker with ripper based tracker#42458
Replace dependency tracker with ripper based tracker#42458jhawthorn merged 1 commit intorails:mainfrom
Conversation
There was a problem hiding this comment.
Was there a reason these changed? 🤔
There was a problem hiding this comment.
Yes! we correctly skip commented out render calls now! 🎉 so to make this test pass it has to be a real render call.
There was a problem hiding this comment.
Does the old form still work? Or was this showing a new feature with object kwarg?
There was a problem hiding this comment.
render @pokémon, partial: 'ピカチュウ' is actually invalid render syntax. I tested it and it actually renders the pokémon template, not the ピカチュウ partial, so I updated the test to hopefully have the same intent.
|
Nice work here, I just have a couple simple questions to help me gain more context on this. Thanks for putting it together!! |
|
Thanks @zzak! helpful comments. I also saw a little stray whitespace in the test file, so I am going to remove that quickly. |
e053119 to
60b707b
Compare
5c7ccb6 to
ede2795
Compare
rafaelfranca
left a comment
There was a problem hiding this comment.
Just a few comments on the code organization but looks good to me otherwise.
There was a problem hiding this comment.
Move this to before the initialize and move the initialize back to after all the class methods.
There was a problem hiding this comment.
| require "action_view/ripper_ast_parser" |
There was a problem hiding this comment.
Just put the attr_reader after the private block definition above.
There was a problem hiding this comment.
| class Node < ::Array | |
| class Node < ::Array # :nodoc: |
There was a problem hiding this comment.
| class NodeParser < ::Ripper | |
| class NodeParser < ::Ripper # :nodoc: |
There was a problem hiding this comment.
| class RenderCallExtractor < NodeParser | |
| class RenderCallExtractor < NodeParser # :nodoc: |
a647829 to
6f6c8f2
Compare
|
Ah, one thing before this merges. It looks like jbuilder uses ERBTracker, so I think I need to keep ERBTracker as an option to prevent breaking new apps. I'll also see how hard it would be to have jbuilder use the new tracker. |
👍🏽. Yeah, let's keep both while we change jbuilder. |
c0d0618 to
c5e9db9
Compare
There was a problem hiding this comment.
I feel weird requiring this here since it isn't used, but I have to have ERBTracker act like it did before this change. Let me know if that assumption is wrong.
There was a problem hiding this comment.
We can register an autoload instead in action_view.rb
There was a problem hiding this comment.
That is way better! thanks!
c5e9db9 to
fcbca92
Compare
actionview/lib/action_view.rb
Outdated
There was a problem hiding this comment.
Should it be inside eager_autoload given it is not used?
There was a problem hiding this comment.
🤦 It should not. Thanks!
fcbca92 to
0c5ed38
Compare
0c5ed38 to
40827d9
Compare
|
I think this branch is ready! Thanks for all the amazing feedback! I opened a PR to JBuilder to avoid their dependency on ERBTracker. I might take a look at haml and slim to make sure they don't have any issues. Ideally the ripper tracker is flexible enough that it can handle ERB, haml and slim since it looks at the compiled source rather than the source code, but if they customize the dependency tracker like JBuilder they might need an update in the meantime. |
|
Hi @HParker 👋 the I'm looking at resolving compatibility problems with Fragment Caching and ViewComponent, so I'm really interested in updates to Do you have any thoughts on potentially adding some explicit support for tracking render dependencies that involve passing classes as arguments to render, eg: I'll take a deeper look at the Ripper soon and maybe try to propose something more concrete, but I'm thinking along the lines of the ActionView::Template::Renderable where the identifier can be a class name instead of the usual virtual path format. Basically corresponding to this line in |
There was a problem hiding this comment.
Are there performance implications in compiling the template here? Or to put it another way; what are the benefits in compiling the output? Is it just so we can skip parsing render calls in commented-out lines?
There was a problem hiding this comment.
There are performance implications, but it should be worth it. Most of this work is already done at boot time. One advantage to structuring the tracker this way is that it should work for all render handlers/types since Ripper can treat them all the same after they are compiled. This should mean slim, haml and any other format you might want will work accurately without modification. The most important benefit is increased accuracy. There are commented out renders and there are other ways ERBTracker could be mistakes about what the dependencies of a template are. This should avoid those problems.
There was a problem hiding this comment.
Most of this work is already done at boot time.
That's true in https://github.com/jhawthorn/actionview_precompiler but is it true here? Won't the files be lazy-loaded when a cache block is encountered (and a digest is needed) during rendering, as opposed to everything being precompiled at boot time? 🤔
There was a problem hiding this comment.
There are performance implications, but it should be worth it.
Is it worth doing a bit of profiling and benchmarking?
There was a problem hiding this comment.
@Matt-Yorkley I think you are right about that case for the first time that that template is read or when the details change. After that, Rails should already know the digest. I am going to work on some benchmarks anyway since I should have posted those before regardless.
We should also be ready to move more template digesting to boot time now which should be better regardless since that should be faster no matter how much slower ripper is compared to ERB tracker.
There was a problem hiding this comment.
Is this superfluous after the previous check on line 99, given that RENDER_TYPE_KEYS is a subset of ALL_KNOWN_KEYS? Or am I reading it wrong?
There was a problem hiding this comment.
Ah, this logic is confusing. The previous check if (keys & RENDER_TYPE_KEYS).size < 1 checks that you have at least one render key. This check unless (keys - ALL_KNOWN_KEYS).empty? checks that you don't have any keys not listed in ALL_KNOWN_KEYS. I am going to try if (keys - ALL_KNOWN_KEYS).any? since unless _.empty? is super backwards sounding. Thanks for catching this!
There was a problem hiding this comment.
Aaaaahhh I see! I had to read it a couple more times 😅
Maybe extracting some comment-methods would be useful in this case? Like:
return nil if no_render_keys?(keys)
return nil if unknown_keys?(keys)f516e5b to
cc74240
Compare
Instead of using the ERBTracker, we can use RipperTracker which is extracted from https://github.com/jhawthorn/actionview_precompiler. Using a parser finds dependencies that would otherwise be difficult to find with the regular expressions. It should also theoretically work with other template systems since it operates on the compiled template instead of the contents of the file. Co-authored-by: John Hawthorn <[email protected]>
cc74240 to
897b9bf
Compare
|
Thanks for the comments @Matt-Yorkley,
I think it would probably be a lot of work to get something like that to work well with dependency resolution, but I haven't thought a lot about it. This code is already kinda slow and complicated, so my default answer is probably adding new features for a gem that isn't a part of rails is probably not a good idea. That being said I am open to being convinced I am wrong! If you want to link a thread about it on the rails forums I would love to see the discussion. We probably shouldn't discuss a new feature request/idea here. |
Instead of using the ERBTracker, we can use RipperTracker which is extracted from https://github.com/jhawthorn/actionview_precompiler.
Using a parser finds dependencies that would otherwise be difficult to find with the regular expressions. It should also theoretically work with other template systems since it operates on the compiled template instead of the contents of the file.
Co-authored-by: John Hawthorn