Solargraph and Rails
Ruby on Rails uses a lot of “magic” that makes it difficult, but not impossible, to gather code intelligence through static analysis. This page explains the current progress and provides some tips for improving Solargraph’s intellisense features in Rails projects.
There are two simple steps that should partially improve intellisense with Rails:
solargraph bundlefrom your Rails project’s root directory.
- Add the most recent version of this file to the project: https://gist.github.com/castwide/28b349566a223dfb439a337aea29713e
Documenting Gems with
The gems at the core of Rails (actionpack, activerecord, etc.) contain little to no YARD documentation. They generally use RDoc syntax instead. In order to make the most use of the existing documentation,
solargraph bundle creates a special documentation cache that gets generated from RDoc and converted to YARD. Solargraph has a whitelist of Rails-related gems that require this alternative. Any other gems receive the usual YARD documentation.
The Comment File
The code in the gist should be added as a Ruby file somewhere that makes it visible to Solargraph, e.g., a file named
definitions.rb in the
config directory. Since the file only contains comments, Solargraph will process it but it has no impact on the runtime. The comments contain YARD directives that fill some of the gaps in Solargraph’s understanding of the Rails app.
This section, for example, exposes some of the ActiveRecord methods that are defined at runtime but are not discoverable through static analysis:
# @!parse # class ActiveRecord::Base # extend ActiveRecord::QueryMethods # extend ActiveRecord::FinderMethods # extend ActiveRecord::Associations::ClassMethods # include ActiveRecord::Persistence # end
@!override directive allows you to inject your own YARD tags into external methods. This example applies overloads to
ActiveRecord::FinderMethods#find so your models can infer the correct types from your models’
# @!override ActiveRecord::FinderMethods#find # @overload find(id) # @param id [Integer] # @return [self] # @overload find(list) # @param list [Array] # @return [Array<self>] # @overload find(*args) # @return [Array<self>] # @return [self, Array<self>]