class Tapioca::Compilers::Dsl::UrlHelpers
`Tapioca::Compilers::Dsl::UrlHelpers` generates RBI
files for classes that include or extend [`Rails.application.routes.url_helpers`](api.rubyonrails.org/v5.1.7/classes/ActionDispatch/Routing/UrlFor.html#module-ActionDispatch::Routing::UrlFor-label-URL+generation+for+named+routes).
For example, with the following setup:
~~~rb # config/application.rb class Application < Rails::Application
routes.draw do resource :index end
end ~~~
~~~rb app/models/post.rb class Post
# Use `T.unsafe` so that Sorbet does not complain about a dynamic # module being included. This allows the `include` to happen properly # at runtime but Sorbet won't see the include. However, since this # generator will generate the proper RBI files for the include, # static type checking will work as expected. T.unsafe(self).include Rails.application.routes.url_helpers
end ~~~
this generator will produce the following RBI
files:
~~~rbi # generated_path_helpers_module.rbi # typed: true module GeneratedPathHelpersModule
include ActionDispatch::Routing::PolymorphicRoutes include ActionDispatch::Routing::UrlFor sig { params(args: T.untyped).returns(String) } def edit_index_path(*args); end sig { params(args: T.untyped).returns(String) } def index_path(*args); end sig { params(args: T.untyped).returns(String) } def new_index_path(*args); end
end ~~~
~~~rbi # generated_url_helpers_module.rbi # typed: true module GeneratedUrlHelpersModule
include ActionDispatch::Routing::PolymorphicRoutes include ActionDispatch::Routing::UrlFor sig { params(args: T.untyped).returns(String) } def edit_index_url(*args); end sig { params(args: T.untyped).returns(String) } def index_url(*args); end sig { params(args: T.untyped).returns(String) } def new_index_url(*args); end
end ~~~
~~~rbi # post.rbi # typed: true class Post
include GeneratedPathHelpersModule include GeneratedUrlHelpersModule
end ~~~
Constants
- NON_DISCOVERABLE_INCLUDERS
Public Instance Methods
decorate(root, constant)
click to toggle source
# File lib/tapioca/compilers/dsl/url_helpers.rb, line 91 def decorate(root, constant) case constant when GeneratedPathHelpersModule.singleton_class, GeneratedUrlHelpersModule.singleton_class generate_module_for(root, constant) else root.create_path(constant) do |mod| create_mixins_for(mod, constant, GeneratedUrlHelpersModule) create_mixins_for(mod, constant, GeneratedPathHelpersModule) end end end
gather_constants()
click to toggle source
# File lib/tapioca/compilers/dsl/url_helpers.rb, line 109 def gather_constants Object.const_set(:GeneratedUrlHelpersModule, Rails.application.routes.named_routes.url_helpers_module) Object.const_set(:GeneratedPathHelpersModule, Rails.application.routes.named_routes.path_helpers_module) constants = all_modules.select do |mod| next unless name_of(mod) includes_helper?(mod, GeneratedUrlHelpersModule) || includes_helper?(mod, GeneratedPathHelpersModule) || includes_helper?(mod.singleton_class, GeneratedUrlHelpersModule) || includes_helper?(mod.singleton_class, GeneratedPathHelpersModule) end constants.concat(NON_DISCOVERABLE_INCLUDERS) end
Private Instance Methods
create_mixins_for(mod, constant, helper_module)
click to toggle source
# File lib/tapioca/compilers/dsl/url_helpers.rb, line 144 def create_mixins_for(mod, constant, helper_module) include_helper = constant.ancestors.include?(helper_module) || NON_DISCOVERABLE_INCLUDERS.include?(constant) extend_helper = constant.singleton_class.ancestors.include?(helper_module) mod.create_include(T.must(helper_module.name)) if include_helper mod.create_extend(T.must(helper_module.name)) if extend_helper end
generate_module_for(root, constant)
click to toggle source
# File lib/tapioca/compilers/dsl/url_helpers.rb, line 128 def generate_module_for(root, constant) root.create_module(T.must(constant.name)) do |mod| mod.create_include("::ActionDispatch::Routing::UrlFor") mod.create_include("::ActionDispatch::Routing::PolymorphicRoutes") constant.instance_methods(false).each do |method| mod.create_method( method.to_s, parameters: [create_rest_param("args", type: "T.untyped")], return_type: "String" ) end end end
includes_helper?(mod, helper)
click to toggle source
# File lib/tapioca/compilers/dsl/url_helpers.rb, line 153 def includes_helper?(mod, helper) superclass_ancestors = mod.superclass&.ancestors if Class === mod superclass_ancestors ||= [] (mod.ancestors - superclass_ancestors).include?(helper) end