diff --git a/gems/actionpack/7.2/_test/test.rb b/gems/actionpack/7.2/_test/test.rb
index edda1d0d..377cc99f 100644
--- a/gems/actionpack/7.2/_test/test.rb
+++ b/gems/actionpack/7.2/_test/test.rb
@@ -31,3 +31,54 @@ def show
request_http_digest_authentication("Admin", "Denied").length
end
end
+
+# Routing DSL forms from the Rails routing guide
+class AdminConstraint
+ def matches?(request)
+ request.path.start_with?("/admin")
+ end
+end
+
+ActionDispatch::Routing::RouteSet.new.draw do
+ root "pages#home"
+ root(to: "pages#home", as: :home).has_named_route?(:home)
+
+ get "profile", to: "users#show", as: :profile
+ get "photos/search" => "photos#search"
+ get "health", to: ->(_env) { [200, { "content-type" => "text/plain" }, ["OK"]] }
+ get "old", to: redirect("/new")
+ post "uploads", controller: :uploads, action: :create, defaults: { format: "json" }, format: false
+ match("photos", "pictures", to: "photos#show", via: [:get, :post]).has_named_route?(:photos)
+ match "exports/:id", to: "exports#show", via: :all, constraints: { id: /\d+/ }, anchor: true
+
+ resources :photos, only: [:index, :show], param: :slug, path: "pictures", as: :images do
+ member { get :preview }.has_named_route?(:preview_image)
+ collection { get :search }.has_named_route?(:search_images)
+ new { get :draft }.has_named_route?(:draft_new_image)
+ get :recent, on: :collection
+ nested { resources :comments, except: :destroy }.has_named_route?(:image_comments)
+ end.has_named_route?(:images)
+ resource :geocoder, controller: "geocoders", module: "maps"
+ resources :articles, concerns: [:commentable], path_names: { new: "make" }, shallow: true
+ shallow { resources(:posts) { resources :drafts } }.has_named_route?(:posts)
+
+ namespace(:admin, path: "control", as: :ctl) { resources :articles }.has_named_route?(:ctl_articles)
+ scope(module: "admin", path: "manage", as: :manage) { resources :users }.has_named_route?(:manage_users)
+ scope("(:locale)", locale: /en|nl/) { resources :books }
+ scope(only: :index) { resources :tags }
+
+ controller(:pages) { get "about", action: :about }.has_named_route?(:about)
+ defaults(format: :json) { get "status", to: "status#show" }.has_named_route?(:status)
+
+ constraints(subdomain: "api") { resources :keys }
+ constraints(id: /\d+/) { get "items/:id", to: "items#show" }
+ constraints(->(request) { request.xhr? }) { get "async", to: "async#show" }
+ constraints(AdminConstraint.new) { get "admin", to: "admin#index" }
+ get "secure", to: "secure#show", constraints: ->(request) { request.ssl? }
+
+ concern(:commentable) { |options| resources :comments, **options }
+ concerns(:commentable, only: :index).first&.to_proc
+
+ mount Rack::Head.new(->(_env) { [200, { "content-type" => "text/plain" }, ["OK"]] }), at: "/head", as: :head
+ with_default_scope(module: "v1") { get "ping", to: "ping#show" }.has_named_route?(:ping)
+end
diff --git a/gems/actionpack/7.2/_test/test.rbs b/gems/actionpack/7.2/_test/test.rbs
index 18bcbc7c..b1a08e95 100644
--- a/gems/actionpack/7.2/_test/test.rbs
+++ b/gems/actionpack/7.2/_test/test.rbs
@@ -10,3 +10,7 @@ end
class AuthController < ActionController::Base
def show: () -> void
end
+
+class AdminConstraint
+ def matches?: (ActionDispatch::Request request) -> bool
+end
diff --git a/gems/actionpack/7.2/actiondispatch.rbs b/gems/actionpack/7.2/actiondispatch.rbs
index f0c6a05e..1786cb68 100644
--- a/gems/actionpack/7.2/actiondispatch.rbs
+++ b/gems/actionpack/7.2/actiondispatch.rbs
@@ -81,42 +81,332 @@ module ActionDispatch
end
class Mapper
+ # A route path, resource name, controller, or action.
+ type path = String | Symbol
+
+ # HTTP verbs the route recognizes, such as `:get`, `[:get, :post]`, or `:all`.
+ type via = Symbol | Array[Symbol]
+
+ # `true` requires a format segment, `false` drops it, and a String or Regexp constrains it.
+ type format = bool | String | Regexp | nil
+
+ # Values accepted by the `:only` and `:except` resource options.
+ type actions = path | Array[path]
+
+ # Values accepted by the `:to` option: `"controller#action"`, an action name, a Rack application, or a controller class.
+ type endpoint = String | ^(Rack::env env) -> Rack::response | Rack::_Application | singleton(ActionController::Metal)
+
+ # Request constraints are objects responding to `matches?`, or callables taking the request.
+ interface _RequestMatcher
+ def matches?: (ActionDispatch::Request request) -> boolish
+ end
+
+ type request_constraint = ^(ActionDispatch::Request request) -> boolish | _RequestMatcher
+
+ # Segment constraints (`{ id: /\d+/ }`) and request conditions (`{ subdomain: "api" }`), or a request constraint.
+ type constraints = Hash[Symbol, untyped] | request_constraint
+
+ # The scope a member, collection, or new route is added to.
+ type on = :member | :collection | :new
+
+ # A concern defined with a callable receives the mapper and the options given to `concerns`.
+ interface _Concern
+ def call: (ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+ end
+
+ module Base
+ # Mount a Rack-based application to be used within the application.
+ #
+ # mount SomeRackApp, at: "some_route"
+ #
+ # Alternatively:
+ #
+ # mount(SomeRackApp => "some_route")
+ #
+ # For options, see +match+, as +mount+ uses it internally.
+ #
+ # All mounted applications come with routing helpers to access them.
+ # These are named after the class specified, so for the above example
+ # the helper is either +some_rack_app_path+ or +some_rack_app_url+.
+ # To customize this helper's name, use the +:as+ option:
+ #
+ # mount(SomeRackApp => "some_route", as: "exciting")
+ #
+ # This will generate the +exciting_path+ and +exciting_url+ helpers
+ # which can be used to navigate to this mounted app.
+ def mount: (untyped app, at: String, ?as: path?, ?via: via, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[untyped, untyped] app_to_path_and_options) -> self
+
+ def with_default_scope: (Hash[Symbol, untyped] scope) { () [self: ActionDispatch::Routing::Mapper] -> void } -> self
+
+ # Query if the following named route was already defined.
+ def has_named_route?: (path name) -> bool
+ end
+
module HttpHelpers
# Define a route that only recognizes HTTP GET.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# get 'bacon', to: 'food#bacon'
- def get: (*untyped args) ?{ () -> untyped } -> untyped
+ def get: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP POST.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# post 'bacon', to: 'food#bacon'
- def post: (*untyped args) ?{ () -> untyped } -> untyped
+ def post: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP PATCH.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# patch 'bacon', to: 'food#bacon'
- def patch: (*untyped args) ?{ () -> untyped } -> untyped
+ def patch: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP PUT.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# put 'bacon', to: 'food#bacon'
- def put: (*untyped args) ?{ () -> untyped } -> untyped
+ def put: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP DELETE.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# delete 'broccoli', to: 'food#broccoli'
- def delete: (*untyped args) ?{ () -> untyped } -> untyped
+ def delete: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
+
+ def options: (path path, *path paths, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
private
def map_method: (untyped method, untyped args) ?{ () -> untyped } -> untyped
end
+ module Scoping
+ # Scopes a set of routes to the given default options.
+ #
+ # Take the following route definition as an example:
+ #
+ # scope path: ":account_id", as: "account" do
+ # resources :projects
+ # end
+ #
+ # This generates helpers such as +account_projects_path+, just like +resources+ does.
+ # The difference here being that the routes generated are like /:account_id/projects,
+ # rather than /accounts/:account_id/projects.
+ #
+ # === Options
+ #
+ # Takes same options as Base#match and Resources#resources.
+ #
+ # # route /posts (without the prefix /admin) to Admin::PostsController
+ # scope module: "admin" do
+ # resources :posts
+ # end
+ #
+ # # prefix the posts resource's requests with '/admin'
+ # scope path: "/admin" do
+ # resources :posts
+ # end
+ #
+ # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
+ # scope as: "sekret" do
+ # resources :posts
+ # end
+ def scope: (*(path | Array[path]) paths, ?only: actions, ?except: actions, ?module: path, ?path: path, ?as: path, ?controller: path, ?action: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?shallow: bool, ?shallow_path: path, ?shallow_prefix: path, ?path_names: Hash[Symbol, String], ?format: format, ?via: via, ?to: endpoint, **untyped) { () -> void } -> self
+
+ # Scopes routes to a specific controller
+ #
+ # controller "food" do
+ # match "bacon", action: :bacon, via: :get
+ # end
+ def controller: [T] (path controller) { () -> T } -> T
+
+ # Scopes routes to a specific namespace. For example:
+ #
+ # namespace :admin do
+ # resources :posts
+ # end
+ #
+ # This generates the following routes:
+ #
+ # admin_posts GET /admin/posts(.:format) admin/posts#index
+ # admin_posts POST /admin/posts(.:format) admin/posts#create
+ # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
+ # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
+ # admin_post GET /admin/posts/:id(.:format) admin/posts#show
+ # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
+ # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
+ #
+ # === Options
+ #
+ # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+
+ # options all default to the name of the namespace.
+ #
+ # For options, see Base#match. For +:shallow_path+ option, see
+ # Resources#resources.
+ #
+ # # accessible through /sekret/posts rather than /admin/posts
+ # namespace :admin, path: "sekret" do
+ # resources :posts
+ # end
+ #
+ # # maps to Sekret::PostsController rather than Admin::PostsController
+ # namespace :admin, module: "sekret" do
+ # resources :posts
+ # end
+ #
+ # # generates +sekret_posts_path+ rather than +admin_posts_path+
+ # namespace :admin, as: "sekret" do
+ # resources :posts
+ # end
+ def namespace: (path name, ?as: path, ?path: path, ?shallow_path: path, ?shallow_prefix: path, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], **untyped) { () -> void } -> self
+
+ # === Parameter Restriction
+ # Allows you to constrain the nested routes based on a set of rules.
+ # For instance, in order to change the routes to allow for a dot character in the +id+ parameter:
+ #
+ # constraints(id: /\d+\.\d+/) do
+ # resources :posts
+ # end
+ #
+ # Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be.
+ # The +id+ parameter must match the constraint passed in for this example.
+ #
+ # You may use this to also restrict other parameters:
+ #
+ # resources :posts do
+ # constraints(post_id: /\d+\.\d+/) do
+ # resources :comments
+ # end
+ # end
+ #
+ # === Restricting based on IP
+ #
+ # Routes can also be constrained to an IP or a certain range of IP addresses:
+ #
+ # constraints(ip: /192\.168\.\d+\.\d+/) do
+ # resources :posts
+ # end
+ #
+ # Any user connecting from the 192.168.* range will be able to see this resource,
+ # where as any user connecting outside of this range will be told there is no such route.
+ #
+ # === Dynamic request matching
+ #
+ # Requests to routes can be constrained based on specific criteria:
+ #
+ # constraints(-> (req) { req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
+ # resources :iphones
+ # end
+ #
+ # You are able to move this logic out into a class if it is too complex for routes.
+ # This class must have a +matches?+ method defined on it which either returns +true+
+ # if the user should be given access to that route, or +false+ if the user should not.
+ #
+ # class Iphone
+ # def self.matches?(request)
+ # request.env["HTTP_USER_AGENT"] =~ /iPhone/
+ # end
+ # end
+ #
+ # An expected place for this code would be +lib/constraints+.
+ #
+ # This class is then used like this:
+ #
+ # constraints(Iphone) do
+ # resources :iphones
+ # end
+ def constraints: (?constraints constraints) { () -> void } -> self
+
+ # Allows you to set default parameters for a route, such as this:
+ # defaults id: 'home' do
+ # match 'scoped_pages/(:id)', to: 'pages#show'
+ # end
+ # Using this, the +:id+ parameter here will default to 'home'.
+ def defaults: [T] (?Hash[Symbol, untyped] defaults) { () -> T } -> T
+ end
+
+ module Concerns
+ # Define a routing concern using a name.
+ #
+ # Concerns may be defined inline, using a block, or handled by
+ # another object, by passing that object as the second parameter.
+ #
+ # The concern object, if supplied, should respond to call,
+ # which will receive two parameters:
+ #
+ # * The current mapper
+ # * A hash of options which the concern object may use
+ #
+ # Options may also be used by concerns defined in a block by accepting
+ # a block parameter. So, using a block, you might do something as
+ # simple as limit the actions available on certain resources, passing
+ # standard resource options through the concern:
+ #
+ # concern :commentable do |options|
+ # resources :comments, options
+ # end
+ #
+ # resources :posts, concerns: :commentable
+ # resources :archived_posts do
+ # # Don't allow comments on archived posts
+ # concerns :commentable, only: [:index, :show]
+ # end
+ #
+ # Or, using a callable object, you might implement something more
+ # specific to your application, which would be out of place in your
+ # routes file.
+ #
+ # # purchasable.rb
+ # class Purchasable
+ # def initialize(defaults = {})
+ # @defaults = defaults
+ # end
+ #
+ # def call(mapper, options = {})
+ # options = @defaults.merge(options)
+ # mapper.resources :purchases
+ # mapper.resources :receipts
+ # mapper.resources :returns if options[:returnable]
+ # end
+ # end
+ #
+ # # routes.rb
+ # concern :purchasable, Purchasable.new(returnable: true)
+ #
+ # resources :toys, concerns: :purchasable
+ # resources :electronics, concerns: :purchasable
+ # resources :pets do
+ # concerns :purchasable, returnable: false
+ # end
+ #
+ # Any routing helpers can be used inside a concern. If using a
+ # callable, they're accessible from the Mapper that's passed to
+ # call.
+ def concern: (Symbol name, (^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void) callable) -> ^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+ | (Symbol name, _Concern callable) -> _Concern
+ | (Symbol name) { (Hash[Symbol, untyped] options) [self: ActionDispatch::Routing::Mapper] -> void } -> ^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+
+ # Use the named concerns
+ #
+ # resources :posts do
+ # concerns :commentable
+ # end
+ #
+ # Concerns also work in any routes helper that you want to use:
+ #
+ # namespace :posts do
+ # concerns :commentable
+ # end
+ def concerns: (*(Symbol | Array[Symbol]) names, **untyped options) -> Array[Symbol]
+ end
+
module Resources
# Sometimes, you have a resource that clients always look up without
# referencing an ID. A common example, /profile always shows the
@@ -139,7 +429,7 @@ module ActionDispatch
#
# === Options
# Takes same options as resources[rdoc-ref:#resources]
- def resource: (*untyped resources) ?{ () -> untyped } -> untyped
+ def resource: (*path resources, ?as: path, ?controller: path, ?path: path, ?only: actions, ?except: actions, ?param: path, ?concerns: Symbol | Array[Symbol], ?shallow: bool, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?path_names: Hash[Symbol, String], ?shallow_path: path, ?shallow_prefix: path, ?format: format, **untyped) ?{ () -> void } -> self
# In Rails, a resourceful route provides a mapping between HTTP verbs
# and URLs and controller actions. By convention, each action also maps
@@ -278,7 +568,67 @@ module ActionDispatch
#
# # resource actions are at /admin/posts.
# resources :posts, path: "admin/posts"
- def resources: (*untyped resources) ?{ () -> untyped } -> untyped
+ def resources: (*path resources, ?as: path, ?controller: path, ?path: path, ?only: actions, ?except: actions, ?param: path, ?concerns: Symbol | Array[Symbol], ?shallow: bool, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?path_names: Hash[Symbol, String], ?shallow_path: path, ?shallow_prefix: path, ?format: format, **untyped) ?{ () -> void } -> self
+
+ # To add a route to the collection:
+ #
+ # resources :photos do
+ # collection do
+ # get 'search'
+ # end
+ # end
+ #
+ # This will enable Rails to recognize paths such as /photos/search
+ # with GET, and route to the search action of +PhotosController+. It will also
+ # create the search_photos_url and search_photos_path
+ # route helpers.
+ def collection: [T] () { () -> T } -> T
+
+ # To add a member route, add a member block into the resource block:
+ #
+ # resources :photos do
+ # member do
+ # get 'preview'
+ # end
+ # end
+ #
+ # This will recognize /photos/1/preview with GET, and route to the
+ # preview action of +PhotosController+. It will also create the
+ # preview_photo_url and preview_photo_path helpers.
+ def member: [T] () { () -> T } -> T
+
+ def new: [T] () { () -> T } -> T
+
+ def nested: () { () -> void } -> self
+
+ def namespace: (path name, ?as: path, ?path: path, ?shallow_path: path, ?shallow_prefix: path, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], **untyped) { () -> void } -> self
+
+ def shallow: [T] () { () -> T } -> T
+
+ # Matches a URL pattern to one or more routes.
+ # For more information, see match[rdoc-ref:Base#match].
+ #
+ # match 'path' => 'controller#action', via: :patch
+ # match 'path', to: 'controller#action', via: :post
+ # match 'path', 'otherpath', on: :member, via: :get
+ def match: (path path, *path paths, ?as: path?, ?via: via, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
+
+ # You can specify what Rails should route "/" to with the root method:
+ #
+ # root to: 'pages#main'
+ #
+ # For options, see +match+, as +root+ uses it internally.
+ #
+ # You can also pass a string which will expand
+ #
+ # root 'pages#main'
+ #
+ # You should put the root route at the top of config/routes.rb,
+ # because this means it will be matched first. As this is the most popular route
+ # of most Rails applications, this is beneficial.
+ def root: (String to, ?as: path?, ?via: via, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?format: format, **untyped) -> self
+ | (to: endpoint, ?as: path?, ?via: via, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?format: format, **untyped) -> self
end
end
end
diff --git a/gems/actionpack/7.2/actionpack-generated.rbs b/gems/actionpack/7.2/actionpack-generated.rbs
index 7136f58c..7bb05ee0 100644
--- a/gems/actionpack/7.2/actionpack-generated.rbs
+++ b/gems/actionpack/7.2/actionpack-generated.rbs
@@ -8857,36 +8857,10 @@ module ActionDispatch
# segment or disable it by supplying +false+.
def match: (untyped path, ?untyped? options) -> nil
- # Mount a Rack-based application to be used within the application.
- #
- # mount SomeRackApp, at: "some_route"
- #
- # Alternatively:
- #
- # mount(SomeRackApp => "some_route")
- #
- # For options, see +match+, as +mount+ uses it internally.
- #
- # All mounted applications come with routing helpers to access them.
- # These are named after the class specified, so for the above example
- # the helper is either +some_rack_app_path+ or +some_rack_app_url+.
- # To customize this helper's name, use the +:as+ option:
- #
- # mount(SomeRackApp => "some_route", as: "exciting")
- #
- # This will generate the +exciting_path+ and +exciting_url+ helpers
- # which can be used to navigate to this mounted app.
- def mount: (untyped app, ?untyped? options) -> untyped
-
def default_url_options=: (untyped options) -> untyped
alias default_url_options default_url_options=
- def with_default_scope: (untyped scope) { () -> untyped } -> untyped
-
- # Query if the following named route was already defined.
- def has_named_route?: (untyped name) -> untyped
-
private
def rails_app?: (untyped app) -> untyped
@@ -8951,151 +8925,8 @@ module ActionDispatch
# PATCH/PUT /admin/posts/1
# DELETE /admin/posts/1
module Scoping
- # Scopes a set of routes to the given default options.
- #
- # Take the following route definition as an example:
- #
- # scope path: ":account_id", as: "account" do
- # resources :projects
- # end
- #
- # This generates helpers such as +account_projects_path+, just like +resources+ does.
- # The difference here being that the routes generated are like /:account_id/projects,
- # rather than /accounts/:account_id/projects.
- #
- # === Options
- #
- # Takes same options as Base#match and Resources#resources.
- #
- # # route /posts (without the prefix /admin) to Admin::PostsController
- # scope module: "admin" do
- # resources :posts
- # end
- #
- # # prefix the posts resource's requests with '/admin'
- # scope path: "/admin" do
- # resources :posts
- # end
- #
- # # prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
- # scope as: "sekret" do
- # resources :posts
- # end
- def scope: (*untyped args) { () -> untyped } -> untyped
-
POISON: untyped
- # Scopes routes to a specific controller
- #
- # controller "food" do
- # match "bacon", action: :bacon, via: :get
- # end
- def controller: (untyped controller) { () -> untyped } -> untyped
-
- # Scopes routes to a specific namespace. For example:
- #
- # namespace :admin do
- # resources :posts
- # end
- #
- # This generates the following routes:
- #
- # admin_posts GET /admin/posts(.:format) admin/posts#index
- # admin_posts POST /admin/posts(.:format) admin/posts#create
- # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
- # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
- # admin_post GET /admin/posts/:id(.:format) admin/posts#show
- # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
- # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
- #
- # === Options
- #
- # The +:path+, +:as+, +:module+, +:shallow_path+ and +:shallow_prefix+
- # options all default to the name of the namespace.
- #
- # For options, see Base#match. For +:shallow_path+ option, see
- # Resources#resources.
- #
- # # accessible through /sekret/posts rather than /admin/posts
- # namespace :admin, path: "sekret" do
- # resources :posts
- # end
- #
- # # maps to Sekret::PostsController rather than Admin::PostsController
- # namespace :admin, module: "sekret" do
- # resources :posts
- # end
- #
- # # generates +sekret_posts_path+ rather than +admin_posts_path+
- # namespace :admin, as: "sekret" do
- # resources :posts
- # end
- def namespace: (untyped path, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped
-
- # === Parameter Restriction
- # Allows you to constrain the nested routes based on a set of rules.
- # For instance, in order to change the routes to allow for a dot character in the +id+ parameter:
- #
- # constraints(id: /\d+\.\d+/) do
- # resources :posts
- # end
- #
- # Now routes such as +/posts/1+ will no longer be valid, but +/posts/1.1+ will be.
- # The +id+ parameter must match the constraint passed in for this example.
- #
- # You may use this to also restrict other parameters:
- #
- # resources :posts do
- # constraints(post_id: /\d+\.\d+/) do
- # resources :comments
- # end
- # end
- #
- # === Restricting based on IP
- #
- # Routes can also be constrained to an IP or a certain range of IP addresses:
- #
- # constraints(ip: /192\.168\.\d+\.\d+/) do
- # resources :posts
- # end
- #
- # Any user connecting from the 192.168.* range will be able to see this resource,
- # where as any user connecting outside of this range will be told there is no such route.
- #
- # === Dynamic request matching
- #
- # Requests to routes can be constrained based on specific criteria:
- #
- # constraints(-> (req) { req.env["HTTP_USER_AGENT"] =~ /iPhone/ }) do
- # resources :iphones
- # end
- #
- # You are able to move this logic out into a class if it is too complex for routes.
- # This class must have a +matches?+ method defined on it which either returns +true+
- # if the user should be given access to that route, or +false+ if the user should not.
- #
- # class Iphone
- # def self.matches?(request)
- # request.env["HTTP_USER_AGENT"] =~ /iPhone/
- # end
- # end
- #
- # An expected place for this code would be +lib/constraints+.
- #
- # This class is then used like this:
- #
- # constraints(Iphone) do
- # resources :iphones
- # end
- def constraints: (?::Hash[untyped, untyped] constraints) { () -> untyped } -> untyped
-
- # Allows you to set default parameters for a route, such as this:
- # defaults id: 'home' do
- # match 'scoped_pages/(:id)', to: 'pages#show'
- # end
- # Using this, the +:id+ parameter here will default to 'home'.
- def defaults: (?::Hash[untyped, untyped] defaults) { () -> untyped } -> untyped
-
private
def merge_path_scope: (untyped parent, untyped child) -> untyped
@@ -9251,64 +9082,8 @@ module ActionDispatch
def resources_path_names: (untyped options) -> untyped
- # To add a route to the collection:
- #
- # resources :photos do
- # collection do
- # get 'search'
- # end
- # end
- #
- # This will enable Rails to recognize paths such as /photos/search
- # with GET, and route to the search action of +PhotosController+. It will also
- # create the search_photos_url and search_photos_path
- # route helpers.
- def collection: () { () -> untyped } -> untyped
-
- # To add a member route, add a member block into the resource block:
- #
- # resources :photos do
- # member do
- # get 'preview'
- # end
- # end
- #
- # This will recognize /photos/1/preview with GET, and route to the
- # preview action of +PhotosController+. It will also create the
- # preview_photo_url and preview_photo_path helpers.
- def member: () { () -> untyped } -> untyped
-
- def new: () { () -> untyped } -> untyped
-
- def nested: () { () -> untyped } -> untyped
-
- def shallow: () { () -> untyped } -> untyped
-
def shallow?: () -> untyped
- # Matches a URL pattern to one or more routes.
- # For more information, see match[rdoc-ref:Base#match].
- #
- # match 'path' => 'controller#action', via: :patch
- # match 'path', to: 'controller#action', via: :post
- # match 'path', 'otherpath', on: :member, via: :get
- def match: (untyped path, *untyped rest) { () -> untyped } -> untyped
-
- # You can specify what Rails should route "/" to with the root method:
- #
- # root to: 'pages#main'
- #
- # For options, see +match+, as +root+ uses it internally.
- #
- # You can also pass a string which will expand
- #
- # root 'pages#main'
- #
- # You should put the root route at the top of config/routes.rb,
- # because this means it will be matched first. As this is the most popular route
- # of most Rails applications, this is beneficial.
- def root: (untyped path, ?::Hash[untyped, untyped] options) -> untyped
-
private
def parent_resource: () -> untyped
@@ -9391,76 +9166,6 @@ module ActionDispatch
# concerns :commentable
# end
module Concerns
- # Define a routing concern using a name.
- #
- # Concerns may be defined inline, using a block, or handled by
- # another object, by passing that object as the second parameter.
- #
- # The concern object, if supplied, should respond to call,
- # which will receive two parameters:
- #
- # * The current mapper
- # * A hash of options which the concern object may use
- #
- # Options may also be used by concerns defined in a block by accepting
- # a block parameter. So, using a block, you might do something as
- # simple as limit the actions available on certain resources, passing
- # standard resource options through the concern:
- #
- # concern :commentable do |options|
- # resources :comments, options
- # end
- #
- # resources :posts, concerns: :commentable
- # resources :archived_posts do
- # # Don't allow comments on archived posts
- # concerns :commentable, only: [:index, :show]
- # end
- #
- # Or, using a callable object, you might implement something more
- # specific to your application, which would be out of place in your
- # routes file.
- #
- # # purchasable.rb
- # class Purchasable
- # def initialize(defaults = {})
- # @defaults = defaults
- # end
- #
- # def call(mapper, options = {})
- # options = @defaults.merge(options)
- # mapper.resources :purchases
- # mapper.resources :receipts
- # mapper.resources :returns if options[:returnable]
- # end
- # end
- #
- # # routes.rb
- # concern :purchasable, Purchasable.new(returnable: true)
- #
- # resources :toys, concerns: :purchasable
- # resources :electronics, concerns: :purchasable
- # resources :pets do
- # concerns :purchasable, returnable: false
- # end
- #
- # Any routing helpers can be used inside a concern. If using a
- # callable, they're accessible from the Mapper that's passed to
- # call.
- def concern: (untyped name, ?untyped? callable) { () -> untyped } -> untyped
-
- # Use the named concerns
- #
- # resources :posts do
- # concerns :commentable
- # end
- #
- # Concerns also work in any routes helper that you want to use:
- #
- # namespace :posts do
- # concerns :commentable
- # end
- def concerns: (*untyped args) -> untyped
end
module CustomUrls
diff --git a/gems/actionpack/8.1/_test/test.rb b/gems/actionpack/8.1/_test/test.rb
index db5a44c6..eb1b683c 100644
--- a/gems/actionpack/8.1/_test/test.rb
+++ b/gems/actionpack/8.1/_test/test.rb
@@ -117,3 +117,54 @@ def show
request_http_digest_authentication("Admin", "Denied").length
end
end
+
+# Routing DSL forms from the Rails routing guide
+class AdminConstraint
+ def matches?(request)
+ request.path.start_with?("/admin")
+ end
+end
+
+ActionDispatch::Routing::RouteSet.new.draw do
+ root "pages#home"
+ root(to: "pages#home", as: :home).first&.length
+
+ get "profile", to: "users#show", as: :profile
+ get "photos/search" => "photos#search"
+ get "health", to: ->(_env) { [200, { "content-type" => "text/plain" }, ["OK"]] }
+ get "old", to: redirect("/new")
+ post "uploads", controller: :uploads, action: :create, defaults: { format: "json" }, format: false
+ match("photos", to: "photos#show", via: [:get, :post]).size
+ match "exports/:id", to: "exports#show", via: :all, constraints: { id: /\d+/ }, anchor: true
+
+ resources :photos, only: [:index, :show], param: :slug, path: "pictures", as: :images do
+ member { get :preview }.has_named_route?(:preview_image)
+ collection { get :search }.has_named_route?(:search_images)
+ new { get :draft }.has_named_route?(:draft_new_image)
+ get :recent, on: :collection
+ nested { resources :comments, except: :destroy }.has_named_route?(:image_comments)
+ end.has_named_route?(:images)
+ resource :geocoder, controller: "geocoders", module: "maps"
+ resources :articles, concerns: [:commentable], path_names: { new: "make" }, shallow: true
+ shallow { resources(:posts) { resources :drafts } }.has_named_route?(:posts)
+
+ namespace(:admin, path: "control", as: :ctl) { resources :articles }.has_named_route?(:ctl_articles)
+ scope(module: "admin", path: "manage", as: :manage) { resources :users }.has_named_route?(:manage_users)
+ scope("(:locale)", locale: /en|nl/) { resources :books }
+ scope(only: :index) { resources :tags }
+
+ controller(:pages) { get "about", action: :about }.has_named_route?(:about)
+ defaults(format: :json) { get "status", to: "status#show" }.has_named_route?(:status)
+
+ constraints(subdomain: "api") { resources :keys }
+ constraints(id: /\d+/) { get "items/:id", to: "items#show" }
+ constraints(->(request) { request.xhr? }) { get "async", to: "async#show" }
+ constraints(AdminConstraint.new) { get "admin", to: "admin#index" }
+ get "secure", to: "secure#show", constraints: ->(request) { request.ssl? }
+
+ concern(:commentable) { |options| resources :comments, **options }
+ concerns(:commentable, only: :index).first&.to_proc
+
+ mount Rack::Head.new(->(_env) { [200, { "content-type" => "text/plain" }, ["OK"]] }), at: "/head", as: :head
+ with_default_scope(module: "v1") { get "ping", to: "ping#show" }.has_named_route?(:ping)
+end
diff --git a/gems/actionpack/8.1/_test/test.rbs b/gems/actionpack/8.1/_test/test.rbs
index d568eb0a..1b4162bb 100644
--- a/gems/actionpack/8.1/_test/test.rbs
+++ b/gems/actionpack/8.1/_test/test.rbs
@@ -24,3 +24,7 @@ end
class AuthController < ActionController::Base
def show: () -> void
end
+
+class AdminConstraint
+ def matches?: (ActionDispatch::Request request) -> bool
+end
diff --git a/gems/actionpack/8.1/actiondispatch.rbs b/gems/actionpack/8.1/actiondispatch.rbs
index 5edd8f20..aa2beb84 100644
--- a/gems/actionpack/8.1/actiondispatch.rbs
+++ b/gems/actionpack/8.1/actiondispatch.rbs
@@ -81,36 +81,338 @@ module ActionDispatch
end
class Mapper
+ # A route path, resource name, controller, or action.
+ type path = String | Symbol
+
+ # HTTP verbs the route recognizes, such as `:get`, `[:get, :post]`, or `:all`.
+ type via = Symbol | Array[Symbol]
+
+ # `true` requires a format segment, `false` drops it, and a String or Regexp constrains it.
+ type format = bool | String | Regexp | nil
+
+ # Values accepted by the `:only` and `:except` resource options.
+ type actions = path | Array[path]
+
+ # Values accepted by the `:to` option: `"controller#action"`, an action name, a Rack application, or a controller class.
+ type endpoint = String | ^(Rack::env env) -> Rack::response | Rack::_Application | singleton(ActionController::Metal)
+
+ # Request constraints are objects responding to `matches?`, or callables taking the request.
+ interface _RequestMatcher
+ def matches?: (ActionDispatch::Request request) -> boolish
+ end
+
+ type request_constraint = ^(ActionDispatch::Request request) -> boolish | _RequestMatcher
+
+ # Segment constraints (`{ id: /\d+/ }`) and request conditions (`{ subdomain: "api" }`), or a request constraint.
+ type constraints = Hash[Symbol, untyped] | request_constraint
+
+ # The scope a member, collection, or new route is added to.
+ type on = :member | :collection | :new
+
+ # A concern defined with a callable receives the mapper and the options given to `concerns`.
+ interface _Concern
+ def call: (ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+ end
+
+ module Base
+ # Mount a Rack-based application to be used within the application.
+ #
+ # mount SomeRackApp, at: "some_route"
+ #
+ # For options, see `match`, as `mount` uses it internally.
+ #
+ # All mounted applications come with routing helpers to access them. These are
+ # named after the class specified, so for the above example the helper is either
+ # `some_rack_app_path` or `some_rack_app_url`. To customize this helper's name,
+ # use the `:as` option:
+ #
+ # mount(SomeRackApp, at: "some_route", as: "exciting")
+ #
+ # This will generate the `exciting_path` and `exciting_url` helpers which can be
+ # used to navigate to this mounted app.
+ def mount: (untyped app, at: String, ?as: path?, ?via: via, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[untyped, untyped] app_to_path_and_options) -> self
+
+ def with_default_scope: (Hash[Symbol, untyped] scope) { () [self: ActionDispatch::Routing::Mapper] -> void } -> self
+
+ # Query if the following named route was already defined.
+ def has_named_route?: (path name) -> bool
+ end
+
module HttpHelpers
# Define a route that only recognizes HTTP GET.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# get 'bacon', to: 'food#bacon'
- def get: (*untyped args) ?{ () -> untyped } -> untyped
+ def get: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP POST.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# post 'bacon', to: 'food#bacon'
- def post: (*untyped args) ?{ () -> untyped } -> untyped
+ def post: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP PATCH.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# patch 'bacon', to: 'food#bacon'
- def patch: (*untyped args) ?{ () -> untyped } -> untyped
+ def patch: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP PUT.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# put 'bacon', to: 'food#bacon'
- def put: (*untyped args) ?{ () -> untyped } -> untyped
+ def put: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
# Define a route that only recognizes HTTP DELETE.
# For supported arguments, see match[rdoc-ref:Base#match]
#
# delete 'broccoli', to: 'food#broccoli'
- def delete: (*untyped args) ?{ () -> untyped } -> untyped
+ def delete: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
+
+ # Define a route that only recognizes HTTP OPTIONS. For supported arguments, see
+ # [match](rdoc-ref:Base#match)
+ #
+ # options 'carrots', to: 'food#carrots'
+ def options: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
+
+ # Define a route that recognizes HTTP CONNECT (and GET) requests. More
+ # specifically this recognizes HTTP/1 protocol upgrade requests and HTTP/2
+ # CONNECT requests with the protocol pseudo header. For supported arguments,
+ # see [match](rdoc-ref:Base#match)
+ #
+ # connect 'live', to: 'live#index'
+ def connect: (path path, ?as: path?, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> self
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> self
+ end
+
+ module Scoping
+ # Scopes a set of routes to the given default options.
+ #
+ # Take the following route definition as an example:
+ #
+ # scope path: ":account_id", as: "account" do
+ # resources :projects
+ # end
+ #
+ # This generates helpers such as `account_projects_path`, just like `resources`
+ # does. The difference here being that the routes generated are like
+ # /:account_id/projects, rather than /accounts/:account_id/projects.
+ #
+ # ### Options
+ #
+ # Takes same options as `Base#match` and `Resources#resources`.
+ #
+ # # route /posts (without the prefix /admin) to Admin::PostsController
+ # scope module: "admin" do
+ # resources :posts
+ # end
+ #
+ # # prefix the posts resource's requests with '/admin'
+ # scope path: "/admin" do
+ # resources :posts
+ # end
+ #
+ # # prefix the routing helper name: sekret_posts_path instead of posts_path
+ # scope as: "sekret" do
+ # resources :posts
+ # end
+ def scope: (*(path | Array[path]) paths, ?only: actions, ?except: actions, ?module: path, ?path: path, ?as: path, ?controller: path, ?action: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?shallow: bool, ?shallow_path: path, ?shallow_prefix: path, ?path_names: Hash[Symbol, String], ?format: format, ?via: via, ?to: endpoint, **untyped) { () -> void } -> self
+
+ # Scopes routes to a specific controller
+ #
+ # controller "food" do
+ # match "bacon", action: :bacon, via: :get
+ # end
+ def controller: [T] (path controller) { () -> T } -> T
+
+ # Scopes routes to a specific namespace. For example:
+ #
+ # namespace :admin do
+ # resources :posts
+ # end
+ #
+ # This generates the following routes:
+ #
+ # admin_posts GET /admin/posts(.:format) admin/posts#index
+ # admin_posts POST /admin/posts(.:format) admin/posts#create
+ # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
+ # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
+ # admin_post GET /admin/posts/:id(.:format) admin/posts#show
+ # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
+ # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
+ #
+ # ### Options
+ #
+ # The `:path`, `:as`, `:module`, `:shallow_path`, and `:shallow_prefix` options
+ # all default to the name of the namespace.
+ #
+ # For options, see `Base#match`. For `:shallow_path` option, see
+ # `Resources#resources`.
+ #
+ # # accessible through /sekret/posts rather than /admin/posts
+ # namespace :admin, path: "sekret" do
+ # resources :posts
+ # end
+ #
+ # # maps to Sekret::PostsController rather than Admin::PostsController
+ # namespace :admin, module: "sekret" do
+ # resources :posts
+ # end
+ #
+ # # generates sekret_posts_path rather than admin_posts_path
+ # namespace :admin, as: "sekret" do
+ # resources :posts
+ # end
+ def namespace: (path name, ?as: path, ?path: path, ?shallow_path: path, ?shallow_prefix: path, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], **untyped) { () -> void } -> self
+
+ # ### Parameter Restriction
+ # Allows you to constrain the nested routes based on a set of rules. For
+ # instance, in order to change the routes to allow for a dot character in the
+ # `id` parameter:
+ #
+ # constraints(id: /\d+\.\d+/) do
+ # resources :posts
+ # end
+ #
+ # Now routes such as `/posts/1` will no longer be valid, but `/posts/1.1` will
+ # be. The `id` parameter must match the constraint passed in for this example.
+ #
+ # You may use this to also restrict other parameters:
+ #
+ # resources :posts do
+ # constraints(post_id: /\d+\.\d+/) do
+ # resources :comments
+ # end
+ # end
+ #
+ # ### Restricting based on IP
+ #
+ # Routes can also be constrained to an IP or a certain range of IP addresses:
+ #
+ # constraints(ip: /192\.168\.\d+\.\d+/) do
+ # resources :posts
+ # end
+ #
+ # Any user connecting from the 192.168.* range will be able to see this
+ # resource, where as any user connecting outside of this range will be told
+ # there is no such route.
+ #
+ # ### Dynamic request matching
+ #
+ # Requests to routes can be constrained based on specific criteria:
+ #
+ # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
+ # resources :iphones
+ # end
+ #
+ # You are able to move this logic out into a class if it is too complex for
+ # routes. This class must have a `matches?` method defined on it which either
+ # returns `true` if the user should be given access to that route, or `false` if
+ # the user should not.
+ #
+ # class Iphone
+ # def self.matches?(request)
+ # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
+ # end
+ # end
+ #
+ # An expected place for this code would be `lib/constraints`.
+ #
+ # This class is then used like this:
+ #
+ # constraints(Iphone) do
+ # resources :iphones
+ # end
+ def constraints: (?constraints constraints) { () -> void } -> self
+
+ # Allows you to set default parameters for a route, such as this:
+ #
+ # defaults id: 'home' do
+ # match 'scoped_pages/(:id)', to: 'pages#show'
+ # end
+ #
+ # Using this, the `:id` parameter here will default to 'home'.
+ def defaults: [T] (?Hash[Symbol, untyped] defaults) { () -> T } -> T
+ end
+
+ module Concerns
+ # Define a routing concern using a name.
+ #
+ # Concerns may be defined inline, using a block, or handled by another object,
+ # by passing that object as the second parameter.
+ #
+ # The concern object, if supplied, should respond to `call`, which will receive
+ # two parameters:
+ #
+ # * The current mapper
+ # * A hash of options which the concern object may use
+ #
+ # Options may also be used by concerns defined in a block by accepting a block
+ # parameter. So, using a block, you might do something as simple as limit the
+ # actions available on certain resources, passing standard resource options
+ # through the concern:
+ #
+ # concern :commentable do |options|
+ # resources :comments, options
+ # end
+ #
+ # resources :posts, concerns: :commentable
+ # resources :archived_posts do
+ # # Don't allow comments on archived posts
+ # concerns :commentable, only: [:index, :show]
+ # end
+ #
+ # Or, using a callable object, you might implement something more specific to
+ # your application, which would be out of place in your routes file.
+ #
+ # # purchasable.rb
+ # class Purchasable
+ # def initialize(defaults = {})
+ # @defaults = defaults
+ # end
+ #
+ # def call(mapper, options = {})
+ # options = @defaults.merge(options)
+ # mapper.resources :purchases
+ # mapper.resources :receipts
+ # mapper.resources :returns if options[:returnable]
+ # end
+ # end
+ #
+ # # routes.rb
+ # concern :purchasable, Purchasable.new(returnable: true)
+ #
+ # resources :toys, concerns: :purchasable
+ # resources :electronics, concerns: :purchasable
+ # resources :pets do
+ # concerns :purchasable, returnable: false
+ # end
+ #
+ # Any routing helpers can be used inside a concern. If using a callable, they're
+ # accessible from the Mapper that's passed to `call`.
+ def concern: (Symbol name, (^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void) callable) -> ^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+ | (Symbol name, _Concern callable) -> _Concern
+ | (Symbol name) { (Hash[Symbol, untyped] options) [self: ActionDispatch::Routing::Mapper] -> void } -> ^(ActionDispatch::Routing::Mapper mapper, Hash[Symbol, untyped] options) -> void
+
+ # Use the named concerns
+ #
+ # resources :posts do
+ # concerns :commentable
+ # end
+ #
+ # Concerns also work in any routes helper that you want to use:
+ #
+ # namespace :posts do
+ # concerns :commentable
+ # end
+ def concerns: (*(Symbol | Array[Symbol]) names, **untyped options) -> Array[Symbol]
end
module Resources
@@ -135,7 +437,7 @@ module ActionDispatch
#
# === Options
# Takes same options as resources[rdoc-ref:#resources]
- def resource: (*untyped resources) ?{ () -> untyped } -> untyped
+ def resource: (*path resources, ?as: path, ?controller: path, ?path: path, ?only: actions, ?except: actions, ?param: path, ?concerns: Symbol | Array[Symbol], ?shallow: bool, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?path_names: Hash[Symbol, String], ?shallow_path: path, ?shallow_prefix: path, ?format: format, **untyped) ?{ () -> void } -> self
# In Rails, a resourceful route provides a mapping between HTTP verbs
# and URLs and controller actions. By convention, each action also maps
@@ -274,7 +576,66 @@ module ActionDispatch
#
# # resource actions are at /admin/posts.
# resources :posts, path: "admin/posts"
- def resources: (*untyped resources) ?{ () -> untyped } -> untyped
+ def resources: (*path resources, ?as: path, ?controller: path, ?path: path, ?only: actions, ?except: actions, ?param: path, ?concerns: Symbol | Array[Symbol], ?shallow: bool, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?path_names: Hash[Symbol, String], ?shallow_path: path, ?shallow_prefix: path, ?format: format, **untyped) ?{ () -> void } -> self
+
+ # To add a route to the collection:
+ #
+ # resources :photos do
+ # collection do
+ # get 'search'
+ # end
+ # end
+ #
+ # This will enable Rails to recognize paths such as `/photos/search` with GET,
+ # and route to the search action of `PhotosController`. It will also create the
+ # `search_photos_url` and `search_photos_path` route helpers.
+ def collection: [T] () { () -> T } -> T
+
+ # To add a member route, add a member block into the resource block:
+ #
+ # resources :photos do
+ # member do
+ # get 'preview'
+ # end
+ # end
+ #
+ # This will recognize `/photos/1/preview` with GET, and route to the preview
+ # action of `PhotosController`. It will also create the `preview_photo_url` and
+ # `preview_photo_path` helpers.
+ def member: [T] () { () -> T } -> T
+
+ def new: [T] () { () -> T } -> T
+
+ def nested: () { () -> void } -> self
+
+ # See ActionDispatch::Routing::Mapper::Scoping#namespace.
+ def namespace: (path name, ?as: path, ?path: path, ?shallow_path: path, ?shallow_prefix: path, ?module: path, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], **untyped) { () -> void } -> self
+
+ def shallow: [T] () { () -> T } -> T
+
+ # Matches a URL pattern to one or more routes. For more information, see
+ # [match](rdoc-ref:Base#match).
+ #
+ # match 'path', to: 'controller#action', via: :post
+ # match 'otherpath', on: :member, via: :get
+ def match: (path path, ?as: path?, ?via: via, ?to: endpoint, ?controller: path, ?action: path, ?on: on, ?defaults: Hash[Symbol, untyped], ?constraints: constraints, ?anchor: bool, ?format: format, ?path: path, ?internal: bool, **untyped) -> Array[path]
+ | (Hash[path, untyped] path_to_endpoint_and_options) -> Array[path]
+
+ # You can specify what Rails should route "/" to with the root method:
+ #
+ # root to: 'pages#main'
+ #
+ # For options, see `match`, as `root` uses it internally.
+ #
+ # You can also pass a string which will expand
+ #
+ # root 'pages#main'
+ #
+ # You should put the root route at the top of `config/routes.rb`, because this
+ # means it will be matched first. As this is the most popular route of most
+ # Rails applications, this is beneficial.
+ def root: (String to, ?as: path?, ?via: via, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?format: format, **untyped) -> Array[String]
+ | (to: endpoint, ?as: path?, ?via: via, ?constraints: constraints, ?defaults: Hash[Symbol, untyped], ?format: format, **untyped) -> Array[String]
end
end
end
diff --git a/gems/actionpack/8.1/actionpack-generated.rbs b/gems/actionpack/8.1/actionpack-generated.rbs
index c1aa5d0e..b4434d68 100644
--- a/gems/actionpack/8.1/actionpack-generated.rbs
+++ b/gems/actionpack/8.1/actionpack-generated.rbs
@@ -10663,32 +10663,10 @@ module ActionDispatch
#
def match: (untyped path, ?untyped? options) -> nil
- # Mount a Rack-based application to be used within the application.
- #
- # mount SomeRackApp, at: "some_route"
- #
- # For options, see `match`, as `mount` uses it internally.
- #
- # All mounted applications come with routing helpers to access them. These are
- # named after the class specified, so for the above example the helper is either
- # `some_rack_app_path` or `some_rack_app_url`. To customize this helper's name,
- # use the `:as` option:
- #
- # mount(SomeRackApp, at: "some_route", as: "exciting")
- #
- # This will generate the `exciting_path` and `exciting_url` helpers which can be
- # used to navigate to this mounted app.
- def mount: (?untyped? app, ?untyped? deprecated_options, ?as: untyped, ?via: untyped?, ?at: untyped?, ?defaults: untyped?, ?constraints: untyped?, ?anchor: bool, ?format: bool, ?path: untyped?, ?internal: untyped?, **untyped mapping) ?{ (?) -> untyped } -> self
-
def default_url_options=: (untyped options) -> untyped
alias default_url_options default_url_options=
- def with_default_scope: (untyped scope) { (?) -> untyped } -> untyped
-
- # Query if the following named route was already defined.
- def has_named_route?: (untyped name) -> untyped
-
private
def assign_deprecated_option: (untyped deprecated_options, untyped key, untyped method_name) -> (untyped | nil)
@@ -10703,19 +10681,6 @@ module ActionDispatch
end
module HttpHelpers
- # Define a route that only recognizes HTTP OPTIONS. For supported arguments, see
- # [match](rdoc-ref:Base#match)
- #
- # options 'carrots', to: 'food#carrots'
- def options: (*untyped path_or_actions, ?as: untyped, ?to: untyped?, ?controller: untyped?, ?action: untyped?, ?on: untyped?, ?defaults: untyped?, ?constraints: untyped?, ?anchor: bool, ?format: bool, ?path: untyped?, ?internal: untyped?, **untyped mapping) ?{ (?) -> untyped } -> self
-
- # Define a route that recognizes HTTP CONNECT (and GET) requests. More
- # specifically this recognizes HTTP/1 protocol upgrade requests and HTTP/2
- # CONNECT requests with the protocol pseudo header. For supported arguments,
- # see [match](rdoc-ref:Base#match)
- #
- # connect 'live', to: 'live#index'
- def connect: (*untyped path_or_actions, ?as: untyped, ?to: untyped?, ?controller: untyped?, ?action: untyped?, ?on: untyped?, ?defaults: untyped?, ?constraints: untyped?, ?anchor: bool, ?format: bool, ?path: untyped?, ?internal: untyped?, **untyped mapping) ?{ (?) -> untyped } -> self
end
# You may wish to organize groups of controllers under a namespace. Most
@@ -10772,156 +10737,8 @@ module ActionDispatch
# PATCH/PUT /admin/posts/1
# DELETE /admin/posts/1
module Scoping
- # Scopes a set of routes to the given default options.
- #
- # Take the following route definition as an example:
- #
- # scope path: ":account_id", as: "account" do
- # resources :projects
- # end
- #
- # This generates helpers such as `account_projects_path`, just like `resources`
- # does. The difference here being that the routes generated are like
- # /:account_id/projects, rather than /accounts/:account_id/projects.
- #
- # ### Options
- #
- # Takes same options as `Base#match` and `Resources#resources`.
- #
- # # route /posts (without the prefix /admin) to Admin::PostsController
- # scope module: "admin" do
- # resources :posts
- # end
- #
- # # prefix the posts resource's requests with '/admin'
- # scope path: "/admin" do
- # resources :posts
- # end
- #
- # # prefix the routing helper name: sekret_posts_path instead of posts_path
- # scope as: "sekret" do
- # resources :posts
- # end
- def scope: (*untyped args, ?only: untyped?, ?except: untyped?, **untyped options) { () -> untyped } -> untyped
-
POISON: untyped
- # Scopes routes to a specific controller
- #
- # controller "food" do
- # match "bacon", action: :bacon, via: :get
- # end
- def controller: (untyped controller) { () -> untyped } -> untyped
-
- # Scopes routes to a specific namespace. For example:
- #
- # namespace :admin do
- # resources :posts
- # end
- #
- # This generates the following routes:
- #
- # admin_posts GET /admin/posts(.:format) admin/posts#index
- # admin_posts POST /admin/posts(.:format) admin/posts#create
- # new_admin_post GET /admin/posts/new(.:format) admin/posts#new
- # edit_admin_post GET /admin/posts/:id/edit(.:format) admin/posts#edit
- # admin_post GET /admin/posts/:id(.:format) admin/posts#show
- # admin_post PATCH/PUT /admin/posts/:id(.:format) admin/posts#update
- # admin_post DELETE /admin/posts/:id(.:format) admin/posts#destroy
- #
- # ### Options
- #
- # The `:path`, `:as`, `:module`, `:shallow_path`, and `:shallow_prefix` options
- # all default to the name of the namespace.
- #
- # For options, see `Base#match`. For `:shallow_path` option, see
- # `Resources#resources`.
- #
- # # accessible through /sekret/posts rather than /admin/posts
- # namespace :admin, path: "sekret" do
- # resources :posts
- # end
- #
- # # maps to Sekret::PostsController rather than Admin::PostsController
- # namespace :admin, module: "sekret" do
- # resources :posts
- # end
- #
- # # generates sekret_posts_path rather than admin_posts_path
- # namespace :admin, as: "sekret" do
- # resources :posts
- # end
- def namespace: (untyped name, ?untyped? deprecated_options, ?as: untyped, ?path: untyped, ?shallow_path: untyped, ?shallow_prefix: untyped, **untyped options) { (?) -> untyped } -> untyped
-
- # ### Parameter Restriction
- # Allows you to constrain the nested routes based on a set of rules. For
- # instance, in order to change the routes to allow for a dot character in the
- # `id` parameter:
- #
- # constraints(id: /\d+\.\d+/) do
- # resources :posts
- # end
- #
- # Now routes such as `/posts/1` will no longer be valid, but `/posts/1.1` will
- # be. The `id` parameter must match the constraint passed in for this example.
- #
- # You may use this to also restrict other parameters:
- #
- # resources :posts do
- # constraints(post_id: /\d+\.\d+/) do
- # resources :comments
- # end
- # end
- #
- # ### Restricting based on IP
- #
- # Routes can also be constrained to an IP or a certain range of IP addresses:
- #
- # constraints(ip: /192\.168\.\d+\.\d+/) do
- # resources :posts
- # end
- #
- # Any user connecting from the 192.168.* range will be able to see this
- # resource, where as any user connecting outside of this range will be told
- # there is no such route.
- #
- # ### Dynamic request matching
- #
- # Requests to routes can be constrained based on specific criteria:
- #
- # constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
- # resources :iphones
- # end
- #
- # You are able to move this logic out into a class if it is too complex for
- # routes. This class must have a `matches?` method defined on it which either
- # returns `true` if the user should be given access to that route, or `false` if
- # the user should not.
- #
- # class Iphone
- # def self.matches?(request)
- # /iPhone/.match?(request.env["HTTP_USER_AGENT"])
- # end
- # end
- #
- # An expected place for this code would be `lib/constraints`.
- #
- # This class is then used like this:
- #
- # constraints(Iphone) do
- # resources :iphones
- # end
- def constraints: (?::Hash[untyped, untyped] constraints) { (?) -> untyped } -> untyped
-
- # Allows you to set default parameters for a route, such as this:
- #
- # defaults id: 'home' do
- # match 'scoped_pages/(:id)', to: 'pages#show'
- # end
- #
- # Using this, the `:id` parameter here will default to 'home'.
- def defaults: (?::Hash[untyped, untyped] defaults) { () -> untyped } -> untyped
-
private
def merge_path_scope: (untyped parent, untyped child) -> untyped
@@ -11079,41 +10896,6 @@ module ActionDispatch
def resources_path_names: (untyped options) -> untyped
- # To add a route to the collection:
- #
- # resources :photos do
- # collection do
- # get 'search'
- # end
- # end
- #
- # This will enable Rails to recognize paths such as `/photos/search` with GET,
- # and route to the search action of `PhotosController`. It will also create the
- # `search_photos_url` and `search_photos_path` route helpers.
- def collection: () { (?) -> untyped } -> untyped
-
- # To add a member route, add a member block into the resource block:
- #
- # resources :photos do
- # member do
- # get 'preview'
- # end
- # end
- #
- # This will recognize `/photos/1/preview` with GET, and route to the preview
- # action of `PhotosController`. It will also create the `preview_photo_url` and
- # `preview_photo_path` helpers.
- def member: () { (?) -> untyped } -> untyped
-
- def new: () { (?) -> untyped } -> untyped
-
- def nested: () { (?) -> untyped } -> untyped
-
- # See ActionDispatch::Routing::Mapper::Scoping#namespace.
- def namespace: (untyped name, ?untyped? deprecated_options, ?as: untyped, ?path: untyped, ?shallow_path: untyped, ?shallow_prefix: untyped, **untyped options) { (?) -> untyped } -> untyped
-
- def shallow: () { () -> untyped } -> untyped
-
def shallow?: () -> untyped
# Loads another routes file with the given `name` located inside the
@@ -11140,28 +10922,6 @@ module ActionDispatch
# single routes file.
def draw: (untyped name) -> untyped
- # Matches a URL pattern to one or more routes. For more information, see
- # [match](rdoc-ref:Base#match).
- #
- # match 'path', to: 'controller#action', via: :post
- # match 'otherpath', on: :member, via: :get
- def match: (*untyped path_or_actions, ?as: untyped, ?via: untyped?, ?to: untyped?, ?controller: untyped?, ?action: untyped?, ?on: untyped?, ?defaults: untyped?, ?constraints: untyped?, ?anchor: untyped?, ?format: untyped?, ?path: untyped?, ?internal: untyped?, **untyped mapping) ?{ (?) -> untyped } -> untyped
-
- # You can specify what Rails should route "/" to with the root method:
- #
- # root to: 'pages#main'
- #
- # For options, see `match`, as `root` uses it internally.
- #
- # You can also pass a string which will expand
- #
- # root 'pages#main'
- #
- # You should put the root route at the top of `config/routes.rb`, because this
- # means it will be matched first. As this is the most popular route of most
- # Rails applications, this is beneficial.
- def root: (untyped path, ?::Hash[untyped, untyped] options) -> untyped
-
private
def parent_resource: () -> untyped
@@ -11246,74 +11006,6 @@ module ActionDispatch
# concerns :commentable
# end
module Concerns
- # Define a routing concern using a name.
- #
- # Concerns may be defined inline, using a block, or handled by another object,
- # by passing that object as the second parameter.
- #
- # The concern object, if supplied, should respond to `call`, which will receive
- # two parameters:
- #
- # * The current mapper
- # * A hash of options which the concern object may use
- #
- # Options may also be used by concerns defined in a block by accepting a block
- # parameter. So, using a block, you might do something as simple as limit the
- # actions available on certain resources, passing standard resource options
- # through the concern:
- #
- # concern :commentable do |options|
- # resources :comments, options
- # end
- #
- # resources :posts, concerns: :commentable
- # resources :archived_posts do
- # # Don't allow comments on archived posts
- # concerns :commentable, only: [:index, :show]
- # end
- #
- # Or, using a callable object, you might implement something more specific to
- # your application, which would be out of place in your routes file.
- #
- # # purchasable.rb
- # class Purchasable
- # def initialize(defaults = {})
- # @defaults = defaults
- # end
- #
- # def call(mapper, options = {})
- # options = @defaults.merge(options)
- # mapper.resources :purchases
- # mapper.resources :receipts
- # mapper.resources :returns if options[:returnable]
- # end
- # end
- #
- # # routes.rb
- # concern :purchasable, Purchasable.new(returnable: true)
- #
- # resources :toys, concerns: :purchasable
- # resources :electronics, concerns: :purchasable
- # resources :pets do
- # concerns :purchasable, returnable: false
- # end
- #
- # Any routing helpers can be used inside a concern. If using a callable, they're
- # accessible from the Mapper that's passed to `call`.
- def concern: (untyped name, ?untyped? callable) ?{ (?) -> untyped } -> untyped
-
- # Use the named concerns
- #
- # resources :posts do
- # concerns :commentable
- # end
- #
- # Concerns also work in any routes helper that you want to use:
- #
- # namespace :posts do
- # concerns :commentable
- # end
- def concerns: (*untyped args, **untyped options) -> untyped
end
module CustomUrls