Skip to content

Conversation

@janko
Copy link

@janko janko commented Oct 28, 2025

It's common to want to traverse through several partials while updating HTML that a controller action renders. Rails.vim has a neat gf shortcut for this, though it probably doesn't have the precision that Prism would provide. This brings the same functionality to Ruby LSP Rails, by implementing "go to definition" support for render calls inside ERB templates.

Screen.Recording.2025-10-28.at.21.08.51.mov

It supports partial name passed as positional argument, or via :partial, :layout, and :spacer_template keyword arguments. It even handles :variants, :formats, and :handlers options, as well as :template for rendering non-partial templates. Relative lookup will also check in view directories of controller ancestors.

For the latter, I considered doing a call to the Rails process that will return ActionController::Base._prefixes. However, I couldn't think of a good enough interface, and that method ableit public is undocumented, so it seems like we shouldn't rely on it. Given that this ancestry lookup is non-configurable anyway, I chose to implement it in Ruby LSP land based on indexed controller files.

To avoid the overhead of booting the Rails process too many times in tests, I updated the test helpers to allow sending multiple textDocument/definition requests to the same server.

It's common to want to traverse through several partials while updating
HTML that a controller action renders. Rails.vim has a neat `gf`
shortcut for this, though it probably doesn't have the precision that
Prism would provide.

This brings the same functionality to Ruby LSP Rails, by implementing
"go to definition" support for render calls inside ERB templates. It
supports partial name passed as positional argument, or via `:partial`,
`:layout`, and `:spacer_template` keyword arguments. It even handles
`:variants`, `:formats`, and `:handlers` options, as well as `:template`
for rendering non-partial templates. Relative lookup will also check
in view directories of controller ancestors.

For the latter, I considered doing a call to the Rails process that will
return `ActionController::Base._prefixes`. However, I couldn't think of
a good enough interface, and that method ableit public is undocumented,
so it seems like we shouldn't rely on it. Given that this ancestry
lookup is non-configurable anyway, I chose to implement it in Ruby LSP
land based on indexed controller files.

To avoid the overhead of booting the Rails process too many times in
tests, I updated the test helpers to allow sending multiple
`textDocument/definition` requests to the same server.
@janko janko requested a review from a team as a code owner October 28, 2025 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant