# The generated code is based on Ruby on Rails source code # You can find the license of Ruby on Rails from following. #Copyright (c) 2005-2019 David Heinemeier Hansson # #Permission is hereby granted, free of charge, to any person obtaining #a copy of this software and associated documentation files (the #"Software"), to deal in the Software without restriction, including #without limitation the rights to use, copy, modify, merge, publish, #distribute, sublicense, and/or sell copies of the Software, and to #permit persons to whom the Software is furnished to do so, subject to #the following conditions: # #The above copyright notice and this permission notice shall be #included in all copies or substantial portions of the Software. # #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, #EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF #MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND #NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE #LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION #OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION #WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. module AbstractController module AssetPaths # nodoc: extend ActiveSupport::Concern end end module AbstractController # Raised when a non-existing controller action is triggered. class ActionNotFound < StandardError end # AbstractController::Base is a low-level API. Nobody should be # using it directly, and subclasses (like ActionController::Base) are # expected to provide their own +render+ method, since rendering means # different things depending on the context. class Base # # Returns the body of the HTTP response sent by the controller. attr_accessor response_body(@_response_body): untyped # # Returns the name of the action this controller is processing. attr_accessor action_name(@_action_name): untyped # # Returns the formats that can be processed by the controller. attr_accessor formats(@_formats): untyped include ActiveSupport::Configurable extend ActiveSupport::DescendantsTracker attr_reader self.abstract: untyped alias self.abstract? self.abstract # Define a controller as abstract. See internal_methods for more # details. def self.abstract!: () -> untyped def self.inherited: (untyped klass) -> untyped # A list of all internal methods for a controller. This finds the first # abstract superclass of a controller, and gets a list of all public # instance methods on that abstract class. Public instance methods of # a controller would normally be considered action methods, so methods # declared on abstract classes are being removed. # (ActionController::Metal and ActionController::Base are defined as abstract) def self.internal_methods: () -> untyped # A list of method names that should be considered actions. This # includes all public instance methods on a controller, less # any internal methods (see internal_methods), adding back in # any methods that are internal, but still exist on the class # itself. # # ==== Returns # * Set - A set of all methods that should be considered actions. def self.action_methods: () -> untyped # action_methods are cached and there is sometimes a need to refresh # them. ::clear_action_methods! allows you to do that, so next time # you run action_methods, they will be recalculated. def self.clear_action_methods!: () -> untyped # Returns the full controller name, underscored, without the ending Controller. # # class MyApp::MyPostsController < AbstractController::Base # # end # # MyApp::MyPostsController.controller_path # => "my_app/my_posts" # # ==== Returns # * String def self.controller_path: () -> untyped # Refresh the cached action_methods when a new action_method is added. def self.method_added: (untyped name) -> untyped # Calls the action going through the entire action dispatch stack. # # The actual method that is called is determined by calling # #method_for_action. If no method can handle the action, then an # AbstractController::ActionNotFound error is raised. # # ==== Returns # * self def process: (untyped action, *untyped args) -> untyped # Delegates to the class' ::controller_path def controller_path: () -> untyped # Delegates to the class' ::action_methods def action_methods: () -> untyped # Returns true if a method for the action is available and # can be dispatched, false otherwise. # # Notice that action_methods.include?("foo") may return # false and available_action?("foo") returns true because # this method considers actions that are also available # through other means, for example, implicit render ones. # # ==== Parameters # * action_name - The name of an action to be tested def available_action?: (untyped action_name) -> untyped # Tests if a response body is set. Used to determine if the # +process_action+ callback needs to be terminated in # +AbstractController::Callbacks+. def performed?: () -> untyped # Returns true if the given controller is capable of rendering # a path. A subclass of +AbstractController::Base+ # may return false. An Email controller for example does not # support paths, only full URLs. def self.supports_path?: () -> ::TrueClass private # Returns true if the name can be considered an action because # it has a method defined in the controller. # # ==== Parameters # * name - The name of an action to be tested def action_method?: (untyped name) -> untyped # Call the action. Override this in a subclass to modify the # behavior around processing an action. This, and not #process, # is the intended way to override action dispatching. # # Notice that the first argument is the method to be dispatched # which is *not* necessarily the same as the action name. def process_action: (untyped method_name, *untyped args) -> untyped # Actually call the method associated with the action. Override # this method if you wish to change how action methods are called, # not to add additional behavior around it. For example, you would # override #send_action if you want to inject arguments into the # method. alias send_action send # If the action name was not found, but a method called "action_missing" # was found, #method_for_action will return "_handle_action_missing". # This method calls #action_missing with the current action name. def _handle_action_missing: (*untyped args) -> untyped # Takes an action name and returns the name of the method that will # handle the action. # # It checks if the action name is valid and returns false otherwise. # # See method_for_action for more information. # # ==== Parameters # * action_name - An action name to find a method name for # # ==== Returns # * string - The name of the method that handles the action # * false - No valid method name could be found. # Raise +AbstractController::ActionNotFound+. def _find_action_name: (untyped action_name) -> untyped # Takes an action name and returns the name of the method that will # handle the action. In normal cases, this method returns the same # name as it receives. By default, if #method_for_action receives # a name that is not an action, it will look for an #action_missing # method and return "_handle_action_missing" if one is found. # # Subclasses may override this method to add additional conditions # that should be considered an action. For instance, an HTTP controller # with a template matching the action name is considered to exist. # # If you override this method to handle additional cases, you may # also provide a method (like +_handle_method_missing+) to handle # the case. # # If none of these conditions are true, and +method_for_action+ # returns +nil+, an +AbstractController::ActionNotFound+ exception will be raised. # # ==== Parameters # * action_name - An action name to find a method name for # # ==== Returns # * string - The name of the method that handles the action # * nil - No method name could be found. def method_for_action: (untyped action_name) -> untyped # Checks if the action name is valid and returns false otherwise. def _valid_action_name?: (untyped action_name) -> untyped end end module AbstractController module Caching # Fragment caching is used for caching various blocks within # views without caching the entire action as a whole. This is # useful when certain elements of an action change frequently or # depend on complicated state while other parts rarely change or # can be shared amongst multiple parties. The caching is done using # the +cache+ helper available in the Action View. See # ActionView::Helpers::CacheHelper for more information. # # While it's strongly recommended that you use key-based cache # expiration (see links in CacheHelper for more information), # it is also possible to manually expire caches. For example: # # expire_fragment('name_of_cache') module Fragments extend ActiveSupport::Concern module ClassMethods # Allows you to specify controller-wide key prefixes for # cache fragments. Pass either a constant +value+, or a block # which computes a value each time a cache key is generated. # # For example, you may want to prefix all fragment cache keys # with a global version identifier, so you can easily # invalidate all caches. # # class ApplicationController # fragment_cache_key "v1" # end # # When it's time to invalidate all fragments, simply change # the string constant. Or, progressively roll out the cache # invalidation using a computed value: # # class ApplicationController # fragment_cache_key do # @account.id.odd? ? "v1" : "v2" # end # end def fragment_cache_key: (?untyped? value) { () -> untyped } -> untyped end # Given a key (as described in +expire_fragment+), returns # a key array suitable for use in reading, writing, or expiring a # cached fragment. All keys begin with :views, # followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set, # followed by any controller-wide key prefix values, ending # with the specified +key+ value. def combined_fragment_cache_key: (untyped key) -> untyped # Writes +content+ to the location signified by # +key+ (see +expire_fragment+ for acceptable formats). def write_fragment: (untyped key, untyped content, ?untyped? options) -> untyped # Reads a cached fragment from the location signified by +key+ # (see +expire_fragment+ for acceptable formats). def read_fragment: (untyped key, ?untyped? options) -> (nil | untyped) # Check if a cached fragment from the location signified by # +key+ exists (see +expire_fragment+ for acceptable formats). def fragment_exist?: (untyped key, ?untyped? options) -> (nil | untyped) # Removes fragments from the cache. # # +key+ can take one of three forms: # # * String - This would normally take the form of a path, like # pages/45/notes. # * Hash - Treated as an implicit call to +url_for+, like # { controller: 'pages', action: 'notes', id: 45} # * Regexp - Will remove any fragment that matches, so # %r{pages/\d*/notes} might remove all notes. Make sure you # don't use anchors in the regex (^ or $) because # the actual filename matched looks like # ./cache/filename/path.cache. Note: Regexp expiration is # only supported on caches that can iterate over all keys (unlike # memcached). # # +options+ is passed through to the cache store's +delete+ # method (or delete_matched, for Regexp keys). def expire_fragment: (untyped key, ?untyped? options) -> (nil | untyped) def instrument_fragment_cache: (untyped name, untyped key) { () -> untyped } -> untyped end end end module AbstractController module Caching extend ActiveSupport::Concern extend ActiveSupport::Autoload module ConfigMethods def cache_store: () -> untyped def cache_store=: (untyped store) -> untyped private def cache_configured?: () -> untyped end include ConfigMethods include AbstractController::Caching::Fragments extend ConfigMethods module ClassMethods def view_cache_dependency: () { () -> untyped } -> untyped end def view_cache_dependencies: () -> untyped private def cache: (untyped key, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped end end module AbstractController # = Abstract Controller Callbacks # # Abstract Controller provides hooks during the life cycle of a controller action. # Callbacks allow you to trigger logic during this cycle. Available callbacks are: # # * after_action # * append_after_action # * append_around_action # * append_before_action # * around_action # * before_action # * prepend_after_action # * prepend_around_action # * prepend_before_action # * skip_after_action # * skip_around_action # * skip_before_action # # NOTE: Calling the same callback multiple times will overwrite previous callback definitions. # module Callbacks extend ActiveSupport::Concern # Uses ActiveSupport::Callbacks as the base functionality. For # more details on the whole callback system, read the documentation # for ActiveSupport::Callbacks. include ActiveSupport::Callbacks # Override AbstractController::Base#process_action to run the # process_action callbacks around the normal behavior. def process_action: (*untyped args) -> untyped module ClassMethods # If +:only+ or +:except+ are used, convert the options into the # +:if+ and +:unless+ options of ActiveSupport::Callbacks. # # The basic idea is that :only => :index gets converted to # :if => proc {|c| c.action_name == "index" }. # # Note that :only has priority over :if in case they # are used together. # # only: :index, if: -> { true } # the :if option will be ignored. # # Note that :if has priority over :except in case they # are used together. # # except: :index, if: -> { true } # the :except option will be ignored. # # ==== Options # * only - The callback should be run only for this action. # * except - The callback should be run for all actions except this action. def _normalize_callback_options: (untyped options) -> untyped def _normalize_callback_option: (untyped options, untyped from, untyped to) -> untyped # Take callback names and an optional callback proc, normalize them, # then call the block with each callback. This allows us to abstract # the normalization across several methods that use it. # # ==== Parameters # * callbacks - An array of callbacks, with an optional # options hash as the last parameter. # * block - A proc that should be added to the callbacks. # # ==== Block Parameters # * name - The callback to be added. # * options - A hash of options to be used when adding the callback. def _insert_callbacks: (untyped callbacks, ?untyped? block) { (untyped, untyped) -> untyped } -> untyped end end end module AbstractController module Collector def self.generate_method_for_mime: (untyped mime) -> untyped private def method_missing: (untyped symbol) { () -> untyped } -> untyped end end module AbstractController class Error < StandardError end end module AbstractController module Helpers extend ActiveSupport::Concern class MissingHelperError < LoadError def initialize: (untyped error, untyped path) -> untyped end module ClassMethods # When a class is inherited, wrap its helper module in a new module. # This ensures that the parent class's module can be changed # independently of the child class's. def inherited: (untyped klass) -> untyped # Declare a controller method as a helper. For example, the following # makes the +current_user+ and +logged_in?+ controller methods available # to the view: # class ApplicationController < ActionController::Base # helper_method :current_user, :logged_in? # # def current_user # @current_user ||= User.find_by(id: session[:user]) # end # # def logged_in? # current_user != nil # end # end # # In a view: # <% if logged_in? -%>Welcome, <%= current_user.name %><% end -%> # # ==== Parameters # * method[, method] - A name or names of a method on the controller # to be made available on the view. def helper_method: (*untyped meths) -> untyped # The +helper+ class method can take a series of helper module names, a block, or both. # # ==== Options # * *args - Module, Symbol, String # * block - A block defining helper methods # # When the argument is a module it will be included directly in the template class. # helper FooHelper # => includes FooHelper # # When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file # and include the module in the template class. The second form illustrates how to include custom helpers # when working with namespaced controllers, or other cases where the file containing the helper definition is not # in one of Rails' standard load paths: # helper :foo # => requires 'foo_helper' and includes FooHelper # helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper # # Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available # to the template. # # # One line # helper { def hello() "Hello, world!" end } # # # Multi-line # helper do # def foo(bar) # "#{bar} is the very best" # end # end # # Finally, all the above styles can be mixed together, and the +helper+ method can be invoked with a mix of # +symbols+, +strings+, +modules+ and blocks. # # helper(:three, BlindHelper) { def mice() 'mice' end } # def helper: (*untyped args) { () -> untyped } -> untyped # Clears up all existing helpers in this class, only keeping the helper # with the same name as this class. def clear_helpers: () -> untyped # Returns a list of modules, normalized from the acceptable kinds of # helpers with the following behavior: # # String or Symbol:: :FooBar or "FooBar" becomes "foo_bar_helper", # and "foo_bar_helper.rb" is loaded using require_dependency. # # Module:: No further processing # # After loading the appropriate files, the corresponding modules # are returned. # # ==== Parameters # * args - An array of helpers # # ==== Returns # * Array - A normalized list of modules for the list of # helpers provided. def modules_for_helpers: (untyped args) -> untyped private # Makes all the (instance) methods in the helper module available to templates # rendered through this controller. # # ==== Parameters # * module - The module to include into the current helper module # for the class def add_template_helper: (untyped mod) -> untyped def default_helper_module!: () -> untyped end end end module AbstractController module Logger # nodoc: extend ActiveSupport::Concern include ActiveSupport::Benchmarkable end end module AbstractController module Railties module RoutesHelpers def self.with: (untyped routes, ?bool include_path_helpers) -> untyped end end end module AbstractController class DoubleRenderError < Error DEFAULT_MESSAGE: ::String def initialize: (?untyped? message) -> untyped end module Rendering extend ActiveSupport::Concern include ActionView::ViewPaths # Normalizes arguments, options and then delegates render_to_body and # sticks the result in self.response_body. def render: (*untyped args) { () -> untyped } -> untyped # Raw rendering of a template to a string. # # It is similar to render, except that it does not # set the +response_body+ and it should be guaranteed # to always return a string. # # If a component extends the semantics of +response_body+ # (as ActionController extends it to be anything that # responds to the method each), this method needs to be # overridden in order to still return a string. def render_to_string: (*untyped args) { () -> untyped } -> untyped # Performs the actual template rendering. def render_to_body: (?::Hash[untyped, untyped] options) -> nil # Returns Content-Type of rendered content. def rendered_format: () -> untyped DEFAULT_PROTECTED_INSTANCE_VARIABLES: untyped # This method should return a hash with assigns. # You can overwrite this configuration per controller. def view_assigns: () -> untyped private def _normalize_args: (?untyped? action, ?::Hash[untyped, untyped] options) -> untyped def _normalize_options: (untyped options) -> untyped def _process_options: (untyped options) -> untyped def _process_format: (untyped format) -> nil def _process_variant: (untyped options) -> nil def _set_html_content_type: () -> nil def _set_rendered_content_type: (untyped format) -> nil def _normalize_render: (*untyped args) { () -> untyped } -> untyped def _protected_ivars: () -> untyped end end module AbstractController module Translation # Delegates to I18n.translate. Also aliased as t. # # When the given key starts with a period, it will be scoped by the current # controller and action. So if you call translate(".foo") from # PeopleController#index, it will convert the call to # I18n.translate("people.index.foo"). This makes it less repetitive # to translate many keys within the same controller / action and gives you a # simple framework for scoping them consistently. def translate: (untyped key, **untyped options) -> untyped alias t translate # Delegates to I18n.localize. Also aliased as l. def localize: (untyped object, **untyped options) -> untyped alias l localize end end module AbstractController # Includes +url_for+ into the host class (e.g. an abstract controller or mailer). The class # has to provide a +RouteSet+ by implementing the _routes methods. Otherwise, an # exception will be raised. # # Note that this module is completely decoupled from HTTP - the only requirement is a valid # _routes implementation. module UrlFor extend ActiveSupport::Concern include ActionDispatch::Routing::UrlFor def _routes: () -> untyped module ClassMethods def _routes: () -> nil def action_methods: () -> untyped end end end module AbstractController extend ActiveSupport::Autoload def self.eager_load!: () -> untyped end module ActionController module ApiRendering extend ActiveSupport::Concern include Rendering def render_to_body: (?::Hash[untyped, untyped] options) -> untyped end end module ActionController # API Controller is a lightweight version of ActionController::Base, # created for applications that don't require all functionalities that a complete # \Rails controller provides, allowing you to create controllers with just the # features that you need for API only applications. # # An API Controller is different from a normal controller in the sense that # by default it doesn't include a number of features that are usually required # by browser access only: layouts and templates rendering, # flash, assets, and so on. This makes the entire controller stack thinner, # suitable for API applications. It doesn't mean you won't have such # features if you need them: they're all available for you to include in # your application, they're just not part of the default API controller stack. # # Normally, +ApplicationController+ is the only controller that inherits from # ActionController::API. All other controllers in turn inherit from # +ApplicationController+. # # A sample controller could look like this: # # class PostsController < ApplicationController # def index # posts = Post.all # render json: posts # end # end # # Request, response, and parameters objects all work the exact same way as # ActionController::Base. # # == Renders # # The default API Controller stack includes all renderers, which means you # can use render :json and brothers freely in your controllers. Keep # in mind that templates are not going to be rendered, so you need to ensure # your controller is calling either render or redirect_to in # all actions, otherwise it will return 204 No Content. # # def show # post = Post.find(params[:id]) # render json: post # end # # == Redirects # # Redirects are used to move from one action to another. You can use the # redirect_to method in your controllers in the same way as in # ActionController::Base. For example: # # def create # redirect_to root_url and return if not_authorized? # # do stuff here # end # # == Adding New Behavior # # In some scenarios you may want to add back some functionality provided by # ActionController::Base that is not present by default in # ActionController::API, for instance MimeResponds. This # module gives you the respond_to method. Adding it is quite simple, # you just need to include the module in a specific controller or in # +ApplicationController+ in case you want it available in your entire # application: # # class ApplicationController < ActionController::API # include ActionController::MimeResponds # end # # class PostsController < ApplicationController # def index # posts = Post.all # # respond_to do |format| # format.json { render json: posts } # format.xml { render xml: posts } # end # end # end # # Make sure to check the modules included in ActionController::Base # if you want to use any other functionality that is not provided # by ActionController::API out of the box. class API < Metal # Shortcut helper that returns all the ActionController::API modules except # the ones passed as arguments: # # class MyAPIBaseController < ActionController::Metal # ActionController::API.without_modules(:ForceSSL, :UrlFor).each do |left| # include left # end # end # # This gives better control over what you want to exclude and makes it easier # to create an API controller class, instead of listing the modules required # manually. def self.without_modules: (*untyped modules) -> untyped MODULES: ::Array[untyped] end end module ActionController # Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed # on request and then either it renders a template or redirects to another action. An action is defined as a public method # on the controller, which will automatically be made accessible to the web-server through \Rails Routes. # # By default, only the ApplicationController in a \Rails application inherits from ActionController::Base. All other # controllers inherit from ApplicationController. This gives you one class to configure things such as # request forgery protection and filtering of sensitive request parameters. # # A sample controller could look like this: # # class PostsController < ApplicationController # def index # @posts = Post.all # end # # def create # @post = Post.create params[:post] # redirect_to posts_path # end # end # # Actions, by default, render a template in the app/views directory corresponding to the name of the controller and action # after executing code in the action. For example, the +index+ action of the PostsController would render the # template app/views/posts/index.html.erb by default after populating the @posts instance variable. # # Unlike index, the create action will not render a template. After performing its main purpose (creating a # new post), it initiates a redirect instead. This redirect works by returning an external # 302 Moved HTTP response that takes the user to the index action. # # These two methods represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect. # Most actions are variations on these themes. # # == Requests # # For every request, the router determines the value of the +controller+ and +action+ keys. These determine which controller # and action are called. The remaining request parameters, the session (if one is available), and the full request with # all the HTTP headers are made available to the action through accessor methods. Then the action is performed. # # The full request object is available via the request accessor and is primarily used to query for HTTP headers: # # def server_ip # location = request.env["REMOTE_ADDR"] # render plain: "This server hosted at #{location}" # end # # == Parameters # # All request parameters, whether they come from a query string in the URL or form data submitted through a POST request are # available through the params method which returns a hash. For example, an action that was performed through # /posts?category=All&limit=5 will include { "category" => "All", "limit" => "5" } in params. # # It's also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as: # # # # # A request coming from a form holding these inputs will include { "post" => { "name" => "david", "address" => "hyacintvej" } }. # If the address input had been named post[address][street], the params would have included # { "post" => { "address" => { "street" => "hyacintvej" } } }. There's no limit to the depth of the nesting. # # == Sessions # # Sessions allow you to store objects in between requests. This is useful for objects that are not yet ready to be persisted, # such as a Signup object constructed in a multi-paged process, or objects that don't change much and are needed all the time, such # as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it's likely # they could be changed unknowingly. It's usually too much work to keep it all synchronized -- something databases already excel at. # # You can place objects in the session by using the session method, which accesses a hash: # # session[:person] = Person.authenticate(user_name, password) # # You can retrieve it again through the same hash: # # "Hello #{session[:person]}" # # For removing objects from the session, you can either assign a single key to +nil+: # # # removes :person from session # session[:person] = nil # # or you can remove the entire session with +reset_session+. # # Sessions are stored by default in a browser cookie that's cryptographically signed, but unencrypted. # This prevents the user from tampering with the session but also allows them to see its contents. # # Do not put secret information in cookie-based sessions! # # == Responses # # Each action results in a response, which holds the headers and document to be sent to the user's browser. The actual response # object is generated automatically through the use of renders and redirects and requires no user intervention. # # == Renders # # Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering # of a template. Included in the Action Pack is the Action View, which enables rendering of ERB templates. It's automatically configured. # The controller passes objects to the view by assigning instance variables: # # def show # @post = Post.find(params[:id]) # end # # Which are then automatically available to the view: # # Title: <%= @post.title %> # # You don't have to rely on the automated rendering. For example, actions that could result in the rendering of different templates # will use the manual rendering methods: # # def search # @results = Search.find(params[:query]) # case @results.count # when 0 then render action: "no_results" # when 1 then render action: "show" # when 2..10 then render action: "show_many" # end # end # # Read more about writing ERB and Builder templates in ActionView::Base. # # == Redirects # # Redirects are used to move from one action to another. For example, after a create action, which stores a blog entry to the # database, we might like to show the user the new entry. Because we're following good DRY principles (Don't Repeat Yourself), we're # going to reuse (and redirect to) a show action that we'll assume has already been created. The code might look like this: # # def create # @entry = Entry.new(params[:entry]) # if @entry.save # # The entry was saved correctly, redirect to show # redirect_to action: 'show', id: @entry.id # else # # things didn't go so well, do something else # end # end # # In this case, after saving our new entry to the database, the user is redirected to the show method, which is then executed. # Note that this is an external HTTP-level redirection which will cause the browser to make a second request (a GET to the show action), # and not some internal re-routing which calls both "create" and then "show" within one request. # # Learn more about redirect_to and what options you have in ActionController::Redirecting. # # == Calling multiple redirects or renders # # An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError: # # def do_something # redirect_to action: "elsewhere" # render action: "overthere" # raises DoubleRenderError # end # # If you need to redirect on the condition of something, then be sure to add "and return" to halt execution. # # def do_something # redirect_to(action: "elsewhere") and return if monkeys.nil? # render action: "overthere" # won't be called if monkeys is nil # end # class Base < Metal # Shortcut helper that returns all the modules included in # ActionController::Base except the ones passed as arguments: # # class MyBaseController < ActionController::Metal # ActionController::Base.without_modules(:ParamsWrapper, :Streaming).each do |left| # include left # end # end # # This gives better control over what you want to exclude and makes it # easier to create a bare controller class, instead of listing the modules # required manually. def self.without_modules: (*untyped modules) -> untyped MODULES: ::Array[untyped] # Define some internal variables that should not be propagated to the view. PROTECTED_IVARS: untyped def _protected_ivars: () -> untyped end end module ActionController # \Caching is a cheap way of speeding up slow applications by keeping the result of # calculations, renderings, and database calls around for subsequent requests. # # You can read more about each approach by clicking the modules below. # # Note: To turn off all caching provided by Action Controller, set # config.action_controller.perform_caching = false # # == \Caching stores # # All the caching stores from ActiveSupport::Cache are available to be used as backends # for Action Controller caching. # # Configuration examples (FileStore is the default): # # config.action_controller.cache_store = :memory_store # config.action_controller.cache_store = :file_store, '/path/to/cache/directory' # config.action_controller.cache_store = :mem_cache_store, 'localhost' # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211') # config.action_controller.cache_store = MyOwnStore.new('parameter') module Caching extend ActiveSupport::Autoload extend ActiveSupport::Concern include AbstractController::Caching private def instrument_payload: (untyped key) -> { controller: untyped, action: untyped, key: untyped } def instrument_name: () -> "action_controller" end end module ActionController # Override the default form builder for all views rendered by this # controller and any of its descendants. Accepts a subclass of # +ActionView::Helpers::FormBuilder+. # # For example, given a form builder: # # class AdminFormBuilder < ActionView::Helpers::FormBuilder # def special_field(name) # end # end # # The controller specifies a form builder as its default: # # class AdminAreaController < ApplicationController # default_form_builder AdminFormBuilder # end # # Then in the view any form using +form_for+ will be an instance of the # specified form builder: # # <%= form_for(@instance) do |builder| %> # <%= builder.special_field(:name) %> # <% end %> module FormBuilder extend ActiveSupport::Concern module ClassMethods # Set the form builder to be used as the default for all forms # in the views rendered by this controller and its subclasses. # # ==== Parameters # * builder - Default form builder, an instance of +ActionView::Helpers::FormBuilder+ def default_form_builder: (untyped builder) -> untyped end # Default form builder for the controller def default_form_builder: () -> untyped end end module ActionController class LogSubscriber < ActiveSupport::LogSubscriber INTERNAL_PARAMS: ::Array[untyped] def start_processing: (untyped event) -> (nil | untyped) def process_action: (untyped event) -> untyped def halted_callback: (untyped event) -> untyped def send_file: (untyped event) -> untyped def redirect_to: (untyped event) -> untyped def send_data: (untyped event) -> untyped def unpermitted_parameters: (untyped event) -> untyped def logger: () -> untyped end end module ActionController module BasicImplicitRender # :nodoc: def send_action: (untyped method, *untyped args) -> untyped def default_render: () -> untyped end end module ActionController module ConditionalGet extend ActiveSupport::Concern include Head module ClassMethods # Allows you to consider additional controller-wide information when generating an ETag. # For example, if you serve pages tailored depending on who's logged in at the moment, you # may want to add the current user id to be part of the ETag to prevent unauthorized displaying # of cached pages. # # class InvoicesController < ApplicationController # etag { current_user.try :id } # # def show # # Etag will differ even for the same invoice when it's viewed by a different current_user # @invoice = Invoice.find(params[:id]) # fresh_when(@invoice) # end # end def etag: () { () -> untyped } -> untyped end # Sets the +etag+, +last_modified+, or both on the response and renders a # 304 Not Modified response if the request is already fresh. # # === Parameters: # # * :etag Sets a "weak" ETag validator on the response. See the # +:weak_etag+ option. # * :weak_etag Sets a "weak" ETag validator on the response. # Requests that set If-None-Match header may return a 304 Not Modified # response if it matches the ETag exactly. A weak ETag indicates semantic # equivalence, not byte-for-byte equality, so they're good for caching # HTML pages in browser caches. They can't be used for responses that # must be byte-identical, like serving Range requests within a PDF file. # * :strong_etag Sets a "strong" ETag validator on the response. # Requests that set If-None-Match header may return a 304 Not Modified # response if it matches the ETag exactly. A strong ETag implies exact # equality: the response must match byte for byte. This is necessary for # doing Range requests within a large video or PDF file, for example, or # for compatibility with some CDNs that don't support weak ETags. # * :last_modified Sets a "weak" last-update validator on the # response. Subsequent requests that set If-Modified-Since may return a # 304 Not Modified response if last_modified <= If-Modified-Since. # * :public By default the Cache-Control header is private, set this to # +true+ if you want your application to be cacheable by other devices (proxy caches). # * :template By default, the template digest for the current # controller/action is included in ETags. If the action renders a # different template, you can include its digest instead. If the action # doesn't render a template at all, you can pass template: false # to skip any attempt to check for a template digest. # # === Example: # # def show # @article = Article.find(params[:id]) # fresh_when(etag: @article, last_modified: @article.updated_at, public: true) # end # # This will render the show template if the request isn't sending a matching ETag or # If-Modified-Since header and just a 304 Not Modified response if there's a match. # # You can also just pass a record. In this case +last_modified+ will be set # by calling +updated_at+ and +etag+ by passing the object itself. # # def show # @article = Article.find(params[:id]) # fresh_when(@article) # end # # You can also pass an object that responds to +maximum+, such as a # collection of active records. In this case +last_modified+ will be set by # calling maximum(:updated_at) on the collection (the timestamp of the # most recently updated record) and the +etag+ by passing the object itself. # # def index # @articles = Article.all # fresh_when(@articles) # end # # When passing a record or a collection, you can still set the public header: # # def show # @article = Article.find(params[:id]) # fresh_when(@article, public: true) # end # # When rendering a different template than the default controller/action # style, you can indicate which digest to include in the ETag: # # before_action { fresh_when @article, template: 'widgets/show' } # def fresh_when: (?untyped? object, ?template: untyped? template, ?public: bool `public`, ?last_modified: untyped? last_modified, ?strong_etag: untyped? strong_etag, ?weak_etag: untyped? weak_etag, ?etag: untyped? etag) -> untyped # Sets the +etag+ and/or +last_modified+ on the response and checks it against # the client request. If the request doesn't match the options provided, the # request is considered stale and should be generated from scratch. Otherwise, # it's fresh and we don't need to generate anything and a reply of 304 Not Modified is sent. # # === Parameters: # # * :etag Sets a "weak" ETag validator on the response. See the # +:weak_etag+ option. # * :weak_etag Sets a "weak" ETag validator on the response. # Requests that set If-None-Match header may return a 304 Not Modified # response if it matches the ETag exactly. A weak ETag indicates semantic # equivalence, not byte-for-byte equality, so they're good for caching # HTML pages in browser caches. They can't be used for responses that # must be byte-identical, like serving Range requests within a PDF file. # * :strong_etag Sets a "strong" ETag validator on the response. # Requests that set If-None-Match header may return a 304 Not Modified # response if it matches the ETag exactly. A strong ETag implies exact # equality: the response must match byte for byte. This is necessary for # doing Range requests within a large video or PDF file, for example, or # for compatibility with some CDNs that don't support weak ETags. # * :last_modified Sets a "weak" last-update validator on the # response. Subsequent requests that set If-Modified-Since may return a # 304 Not Modified response if last_modified <= If-Modified-Since. # * :public By default the Cache-Control header is private, set this to # +true+ if you want your application to be cacheable by other devices (proxy caches). # * :template By default, the template digest for the current # controller/action is included in ETags. If the action renders a # different template, you can include its digest instead. If the action # doesn't render a template at all, you can pass template: false # to skip any attempt to check for a template digest. # # === Example: # # def show # @article = Article.find(params[:id]) # # if stale?(etag: @article, last_modified: @article.updated_at) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats # end # end # end # # You can also just pass a record. In this case +last_modified+ will be set # by calling +updated_at+ and +etag+ by passing the object itself. # # def show # @article = Article.find(params[:id]) # # if stale?(@article) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats # end # end # end # # You can also pass an object that responds to +maximum+, such as a # collection of active records. In this case +last_modified+ will be set by # calling +maximum(:updated_at)+ on the collection (the timestamp of the # most recently updated record) and the +etag+ by passing the object itself. # # def index # @articles = Article.all # # if stale?(@articles) # @statistics = @articles.really_expensive_call # respond_to do |format| # # all the supported formats # end # end # end # # When passing a record or a collection, you can still set the public header: # # def show # @article = Article.find(params[:id]) # # if stale?(@article, public: true) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats # end # end # end # # When rendering a different template than the default controller/action # style, you can indicate which digest to include in the ETag: # # def show # super if stale? @article, template: 'widgets/show' # end # def stale?: (?untyped? object, **untyped freshness_kwargs) -> untyped # Sets an HTTP 1.1 Cache-Control header. Defaults to issuing a +private+ # instruction, so that intermediate caches must not cache the response. # # expires_in 20.minutes # expires_in 3.hours, public: true # expires_in 3.hours, public: true, must_revalidate: true # # This method will overwrite an existing Cache-Control header. # See https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html for more possibilities. # # HTTP Cache-Control Extensions for Stale Content. See https://tools.ietf.org/html/rfc5861 # It helps to cache an asset and serve it while is being revalidated and/or returning with an error. # # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds # expires_in 3.hours, public: true, stale_while_revalidate: 60.seconds, stale_if_error: 5.minutes # # The method will also ensure an HTTP Date header for client compatibility. def expires_in: (untyped seconds, ?::Hash[untyped, untyped] options) -> untyped # Sets an HTTP 1.1 Cache-Control header of no-cache. This means the # resource will be marked as stale, so clients must always revalidate. # Intermediate/browser caches may still store the asset. def expires_now: () -> untyped # Cache or yield the block. The cache is supposed to never expire. # # You can use this method when you have an HTTP response that never changes, # and the browser and proxies should cache it indefinitely. # # * +public+: By default, HTTP responses are private, cached only on the # user's web browser. To allow proxies to cache the response, set +true+ to # indicate that they can serve the cached response to all users. def http_cache_forever: (?public: bool `public`) { () -> untyped } -> untyped private def combine_etags: (untyped validator, untyped options) -> untyped end end module ActionController # nodoc: module ContentSecurityPolicy # TODO: Documentation extend ActiveSupport::Concern include AbstractController::Helpers include AbstractController::Callbacks module ClassMethods def content_security_policy: (?bool enabled, **untyped options) { (untyped) -> untyped } -> untyped def content_security_policy_report_only: (?bool report_only, **untyped options) -> untyped end private def content_security_policy?: () -> untyped def content_security_policy_nonce: () -> untyped def current_content_security_policy: () -> untyped end end module ActionController # nodoc: module Cookies extend ActiveSupport::Concern private def cookies: () -> untyped end end module ActionController # nodoc: # Methods for sending arbitrary data and for streaming files to the browser, # instead of rendering. module DataStreaming extend ActiveSupport::Concern include ActionController::Rendering DEFAULT_SEND_FILE_TYPE: ::String DEFAULT_SEND_FILE_DISPOSITION: ::String private def send_file: (untyped path, ?::Hash[untyped, untyped] options) -> untyped def send_data: (untyped data, ?::Hash[untyped, untyped] options) -> untyped def send_file_headers!: (untyped options) -> untyped end end module ActionController # Allows configuring default headers that will be automatically merged into # each response. module DefaultHeaders extend ActiveSupport::Concern module ClassMethods def make_response!: (untyped request) -> untyped end end end module ActionController # When you're using the flash, it's generally used as a conditional on the view. # This means the content of the view depends on the flash. Which in turn means # that the ETag for a response should be computed with the content of the flash # in mind. This does that by including the content of the flash as a component # in the ETag that's generated for a response. module EtagWithFlash extend ActiveSupport::Concern include ActionController::ConditionalGet end end module ActionController # When our views change, they should bubble up into HTTP cache freshness # and bust browser caches. So the template digest for the current action # is automatically included in the ETag. # # Enabled by default for apps that use Action View. Disable by setting # # config.action_controller.etag_with_template_digest = false # # Override the template to digest by passing +:template+ to +fresh_when+ # and +stale?+ calls. For example: # # # We're going to render widgets/show, not posts/show # fresh_when @post, template: 'widgets/show' # # # We're not going to render a template, so omit it from the ETag. # fresh_when @post, template: false # module EtagWithTemplateDigest extend ActiveSupport::Concern include ActionController::ConditionalGet private def determine_template_etag: (untyped options) -> untyped # Pick the template digest to include in the ETag. If the +:template+ option # is present, use the named template. If +:template+ is +nil+ or absent, use # the default controller/action template. If +:template+ is false, omit the # template digest from the ETag. def pick_template_for_etag: (untyped options) -> untyped def lookup_and_digest_template: (untyped template) -> untyped end end module ActionController class ActionControllerError < StandardError end class BadRequest < ActionControllerError # nodoc: def initialize: (?untyped? msg) -> untyped end class RenderError < ActionControllerError end class RoutingError < ActionControllerError # nodoc: attr_reader failures: untyped def initialize: (untyped message, ?untyped failures) -> untyped end class UrlGenerationError < ActionControllerError end class MethodNotAllowed < ActionControllerError # nodoc: def initialize: (*untyped allowed_methods) -> untyped end class NotImplemented < MethodNotAllowed end class MissingFile < ActionControllerError end class SessionOverflowError < ActionControllerError # nodoc: DEFAULT_MESSAGE: ::String def initialize: (?untyped? message) -> untyped end class UnknownHttpMethod < ActionControllerError end class UnknownFormat < ActionControllerError end # Raised when a nested respond_to is triggered and the content types of each # are incompatible. For example: # # respond_to do |outer_type| # outer_type.js do # respond_to do |inner_type| # inner_type.html { render body: "HTML" } # end # end # end class RespondToMismatchError < ActionControllerError DEFAULT_MESSAGE: ::String def initialize: (?untyped? message) -> untyped end class MissingExactTemplate < UnknownFormat end end module ActionController # nodoc: module Flash extend ActiveSupport::Concern module ClassMethods # Creates new flash types. You can pass as many types as you want to create # flash types other than the default alert and notice in # your controllers and views. For instance: # # # in application_controller.rb # class ApplicationController < ActionController::Base # add_flash_types :warning # end # # # in your controller # redirect_to user_path(@user), warning: "Incomplete profile" # # # in your view # <%= warning %> # # This method will automatically define a new method for each of the given # names, and it will be available in your views. def add_flash_types: (*untyped types) -> untyped end private def redirect_to: (?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] response_options_and_flash) -> untyped end end module ActionController module ForceSSL # This module is deprecated in favor of +config.force_ssl+ in your environment # config file. This will ensure all endpoints not explicitly marked otherwise # will have all communication served over HTTPS. # :nodoc: extend ActiveSupport::Concern include AbstractController::Callbacks ACTION_OPTIONS: ::Array[untyped] URL_OPTIONS: ::Array[untyped] REDIRECT_OPTIONS: ::Array[untyped] module ClassMethods # :nodoc: def force_ssl: (?::Hash[untyped, untyped] options) -> untyped end def force_ssl_redirect: (?untyped? host_or_options) -> untyped end end module ActionController module Head # Returns a response that has no content (merely headers). The options # argument is interpreted to be a hash of header names and values. # This allows you to easily return a response that consists only of # significant headers: # # head :created, location: person_path(@person) # # head :created, location: @person # # It can also be used to return exceptional conditions: # # return head(:method_not_allowed) unless request.post? # return head(:bad_request) unless valid_request? # render # # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list of valid +status+ symbols. def head: (untyped status, ?::Hash[untyped, untyped] options) -> ::TrueClass private def include_content?: (untyped status) -> untyped end end module ActionController # The \Rails framework provides a large number of helpers for working with assets, dates, forms, # numbers and model objects, to name a few. These helpers are available to all templates # by default. # # In addition to using the standard template helpers provided, creating custom helpers to # extract complicated logic or reusable functionality is strongly encouraged. By default, each controller # will include all helpers. These helpers are only accessible on the controller through #helpers # # In previous versions of \Rails the controller will include a helper which # matches the name of the controller, e.g., MyController will automatically # include MyHelper. To return old behavior set +config.action_controller.include_all_helpers+ to +false+. # # Additional helpers can be specified using the +helper+ class method in ActionController::Base or any # controller which inherits from it. # # The +to_s+ method from the \Time class can be wrapped in a helper method to display a custom message if # a \Time object is blank: # # module FormattedTimeHelper # def format_time(time, format=:long, blank_message=" ") # time.blank? ? blank_message : time.to_s(format) # end # end # # FormattedTimeHelper can now be included in a controller, using the +helper+ class method: # # class EventsController < ActionController::Base # helper FormattedTimeHelper # def index # @events = Event.all # end # end # # Then, in any view rendered by EventsController, the format_time method can be called: # # <% @events.each do |event| -%> #

# <%= format_time(event.time, :short, "N/A") %> | <%= event.name %> #

# <% end -%> # # Finally, assuming we have two event instances, one which has a time and one which does not, # the output might look like this: # # 23 Aug 11:30 | Carolina Railhawks Soccer Match # N/A | Carolina Railhawks Training Workshop # module Helpers extend ActiveSupport::Concern attr_accessor self.helpers_path: untyped include AbstractController::Helpers module ClassMethods # Declares helper accessors for controller attributes. For example, the # following adds new +name+ and name= instance methods to a # controller and makes them available to the view: # attr_accessor :name # helper_attr :name # # ==== Parameters # * attrs - Names of attributes to be converted into helpers. def helper_attr: (*untyped attrs) -> untyped # Provides a proxy to access helper methods from outside the view. def helpers: () -> untyped # Overwrite modules_for_helpers to accept :all as argument, which loads # all helpers in helpers_path. # # ==== Parameters # * args - A list of helpers # # ==== Returns # * array - A normalized list of modules for the list of helpers provided. def modules_for_helpers: (untyped args) -> untyped # Returns a list of helper names in a given path. # # ActionController::Base.all_helpers_from_path 'app/helpers' # # => ["application", "chart", "rubygems"] def all_helpers_from_path: (untyped path) -> untyped private # Extract helper names from files in app/helpers/**/*_helper.rb def all_application_helpers: () -> untyped end # Provides a proxy to access helper methods from outside the view. def helpers: () -> untyped end end module ActionController # Makes it dead easy to do HTTP Basic, Digest and Token authentication. module HttpAuthentication # Makes it dead easy to do HTTP \Basic authentication. # # === Simple \Basic example # # class PostsController < ApplicationController # http_basic_authenticate_with name: "dhh", password: "secret", except: :index # # def index # render plain: "Everyone can see me!" # end # # def edit # render plain: "I'm only accessible if you know the password" # end # end # # === Advanced \Basic example # # Here is a more advanced \Basic example where only Atom feeds and the XML API is protected by HTTP authentication, # the regular HTML interface is protected by a session approach: # # class ApplicationController < ActionController::Base # before_action :set_account, :authenticate # # private # def set_account # @account = Account.find_by(url_name: request.subdomains.first) # end # # def authenticate # case request.format # when Mime[:xml], Mime[:atom] # if user = authenticate_with_http_basic { |u, p| @account.users.authenticate(u, p) } # @current_user = user # else # request_http_basic_authentication # end # else # if session_authenticated? # @current_user = @account.users.find(session[:authenticated][:user_id]) # else # redirect_to(login_url) and return false # end # end # end # end # # In your integration tests, you can do something like this: # # def test_access_granted_from_xml # authorization = ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password) # # get "/notes/1.xml", headers: { 'HTTP_AUTHORIZATION' => authorization } # # assert_equal 200, status # end module Basic extend ::ActionController::HttpAuthentication::Basic module ControllerMethods extend ActiveSupport::Concern module ClassMethods def http_basic_authenticate_with: (password: untyped password, name: untyped name, ?realm: untyped? realm, **untyped options) -> untyped end def http_basic_authenticate_or_request_with: (password: untyped password, name: untyped name, ?message: untyped? message, ?realm: untyped? realm) -> untyped def authenticate_or_request_with_http_basic: (?untyped? realm, ?untyped? message) { () -> untyped } -> untyped def authenticate_with_http_basic: () { () -> untyped } -> untyped def request_http_basic_authentication: (?::String realm, ?untyped? message) -> untyped end def authenticate: (untyped request) { () -> untyped } -> untyped def has_basic_credentials?: (untyped request) -> untyped def user_name_and_password: (untyped request) -> untyped def decode_credentials: (untyped request) -> untyped def auth_scheme: (untyped request) -> untyped def auth_param: (untyped request) -> untyped def encode_credentials: (untyped user_name, untyped password) -> ::String def authentication_request: (untyped controller, untyped realm, untyped message) -> untyped end # Makes it dead easy to do HTTP \Digest authentication. # # === Simple \Digest example # # require 'digest/md5' # class PostsController < ApplicationController # REALM = "SuperSecret" # USERS = {"dhh" => "secret", #plain text password # "dap" => Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))} #ha1 digest password # # before_action :authenticate, except: [:index] # # def index # render plain: "Everyone can see me!" # end # # def edit # render plain: "I'm only accessible if you know the password" # end # # private # def authenticate # authenticate_or_request_with_http_digest(REALM) do |username| # USERS[username] # end # end # end # # === Notes # # The +authenticate_or_request_with_http_digest+ block must return the user's password # or the ha1 digest hash so the framework can appropriately hash to check the user's # credentials. Returning +nil+ will cause authentication to fail. # # Storing the ha1 hash: MD5(username:realm:password), is better than storing a plain password. If # the password file or database is compromised, the attacker would be able to use the ha1 hash to # authenticate as the user at this +realm+, but would not have the user's password to try using at # other sites. # # In rare instances, web servers or front proxies strip authorization headers before # they reach your application. You can debug this situation by logging all environment # variables, and check for HTTP_AUTHORIZATION, amongst others. module Digest extend ::ActionController::HttpAuthentication::Digest module ControllerMethods def authenticate_or_request_with_http_digest: (?::String realm, ?untyped? message) { () -> untyped } -> untyped # Authenticate with HTTP Digest, returns true or false def authenticate_with_http_digest: (?::String realm) { () -> untyped } -> untyped # Render output including the HTTP Digest authentication header def request_http_digest_authentication: (?::String realm, ?untyped? message) -> untyped end # Returns false on a valid response, true otherwise def authenticate: (untyped request, untyped realm) { () -> untyped } -> untyped # Returns false unless the request credentials response value matches the expected value. # First try the password as a ha1 digest password. If this fails, then try it as a plain # text password. def validate_digest_response: (untyped request, untyped realm) { () -> untyped } -> (::FalseClass | untyped) # Returns the expected response for a request of +http_method+ to +uri+ with the decoded +credentials+ and the expected +password+ # Optional parameter +password_is_ha1+ is set to +true+ by default, since best practice is to store ha1 digest instead # of a plain-text password. def expected_response: (untyped http_method, untyped uri, untyped credentials, untyped password, ?bool password_is_ha1) -> untyped def ha1: (untyped credentials, untyped password) -> untyped def encode_credentials: (untyped http_method, untyped credentials, untyped password, untyped password_is_ha1) -> untyped def decode_credentials_header: (untyped request) -> untyped def decode_credentials: (untyped header) -> untyped def authentication_header: (untyped controller, untyped realm) -> untyped def authentication_request: (untyped controller, untyped realm, ?untyped? message) -> untyped def secret_token: (untyped request) -> untyped # Uses an MD5 digest based on time to generate a value to be used only once. # # A server-specified data string which should be uniquely generated each time a 401 response is made. # It is recommended that this string be base64 or hexadecimal data. # Specifically, since the string is passed in the header lines as a quoted string, the double-quote character is not allowed. # # The contents of the nonce are implementation dependent. # The quality of the implementation depends on a good choice. # A nonce might, for example, be constructed as the base 64 encoding of # # time-stamp H(time-stamp ":" ETag ":" private-key) # # where time-stamp is a server-generated time or other non-repeating value, # ETag is the value of the HTTP ETag header associated with the requested entity, # and private-key is data known only to the server. # With a nonce of this form a server would recalculate the hash portion after receiving the client authentication header and # reject the request if it did not match the nonce from that header or # if the time-stamp value is not recent enough. In this way the server can limit the time of the nonce's validity. # The inclusion of the ETag prevents a replay request for an updated version of the resource. # (Note: including the IP address of the client in the nonce would appear to offer the server the ability # to limit the reuse of the nonce to the same client that originally got it. # However, that would break proxy farms, where requests from a single user often go through different proxies in the farm. # Also, IP address spoofing is not that hard.) # # An implementation might choose not to accept a previously used nonce or a previously used digest, in order to # protect against a replay attack. Or, an implementation might choose to use one-time nonces or digests for # POST, PUT, or PATCH requests and a time-stamp for GET requests. For more details on the issues involved see Section 4 # of this document. # # The nonce is opaque to the client. Composed of Time, and hash of Time with secret # key from the Rails session secret generated upon creation of project. Ensures # the time cannot be modified by client. def nonce: (untyped secret_key, ?untyped time) -> untyped # Might want a shorter timeout depending on whether the request # is a PATCH, PUT, or POST, and if the client is a browser or web service. # Can be much shorter if the Stale directive is implemented. This would # allow a user to use new nonce without prompting the user again for their # username and password. def validate_nonce: (untyped secret_key, untyped request, untyped value, ?untyped seconds_to_timeout) -> (::FalseClass | untyped) # Opaque based on digest of secret key def opaque: (untyped secret_key) -> untyped end # Makes it dead easy to do HTTP Token authentication. # # Simple Token example: # # class PostsController < ApplicationController # TOKEN = "secret" # # before_action :authenticate, except: [ :index ] # # def index # render plain: "Everyone can see me!" # end # # def edit # render plain: "I'm only accessible if you know the password" # end # # private # def authenticate # authenticate_or_request_with_http_token do |token, options| # # Compare the tokens in a time-constant manner, to mitigate # # timing attacks. # ActiveSupport::SecurityUtils.secure_compare(token, TOKEN) # end # end # end # # # Here is a more advanced Token example where only Atom feeds and the XML API is protected by HTTP token authentication, # the regular HTML interface is protected by a session approach: # # class ApplicationController < ActionController::Base # before_action :set_account, :authenticate # # private # def set_account # @account = Account.find_by(url_name: request.subdomains.first) # end # # def authenticate # case request.format # when Mime[:xml], Mime[:atom] # if user = authenticate_with_http_token { |t, o| @account.users.authenticate(t, o) } # @current_user = user # else # request_http_token_authentication # end # else # if session_authenticated? # @current_user = @account.users.find(session[:authenticated][:user_id]) # else # redirect_to(login_url) and return false # end # end # end # end # # # In your integration tests, you can do something like this: # # def test_access_granted_from_xml # authorization = ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token) # # get "/notes/1.xml", headers: { 'HTTP_AUTHORIZATION' => authorization } # # assert_equal 200, status # end # # # On shared hosts, Apache sometimes doesn't pass authentication headers to # FCGI instances. If your environment matches this description and you cannot # authenticate, try this rule in your Apache setup: # # RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L] module Token TOKEN_KEY: ::String TOKEN_REGEX: untyped AUTHN_PAIR_DELIMITERS: untyped extend ::ActionController::HttpAuthentication::Token module ControllerMethods def authenticate_or_request_with_http_token: (?::String realm, ?untyped? message) { () -> untyped } -> untyped def authenticate_with_http_token: () { () -> untyped } -> untyped def request_http_token_authentication: (?::String realm, ?untyped? message) -> untyped end def authenticate: (untyped controller) { () -> untyped } -> untyped # Parses the token and options out of the token Authorization header. # The value for the Authorization header is expected to have the prefix # "Token" or "Bearer". If the header looks like this: # Authorization: Token token="abc", nonce="def" # Then the returned token is "abc", and the options are # {nonce: "def"} # # request - ActionDispatch::Request instance with the current headers. # # Returns an +Array+ of [String, Hash] if a token is present. # Returns +nil+ if no token is found. def token_and_options: (untyped request) -> untyped def token_params_from: (untyped auth) -> untyped # Takes raw_params and turns it into an array of parameters def params_array_from: (untyped raw_params) -> untyped # This removes the " characters wrapping the value. def rewrite_param_values: (untyped array_params) -> untyped # This method takes an authorization body and splits up the key-value # pairs by the standardized :, ;, or \t # delimiters defined in +AUTHN_PAIR_DELIMITERS+. def raw_params: (untyped auth) -> untyped # Encodes the given token and options into an Authorization header value. # # token - String token. # options - optional Hash of the options. # # Returns String. def encode_credentials: (untyped token, ?::Hash[untyped, untyped] options) -> ::String # Sets a WWW-Authenticate header to let the client know a token is desired. # # controller - ActionController::Base instance for the outgoing response. # realm - String realm to use in the header. # # Returns nothing. def authentication_request: (untyped controller, untyped realm, ?untyped? message) -> untyped end end end module ActionController # Handles implicit rendering for a controller action that does not # explicitly respond with +render+, +respond_to+, +redirect+, or +head+. # # For API controllers, the implicit response is always 204 No Content. # # For all other controllers, we use these heuristics to decide whether to # render a template, raise an error for a missing template, or respond with # 204 No Content: # # First, if we DO find a template, it's rendered. Template lookup accounts # for the action name, locales, format, variant, template handlers, and more # (see +render+ for details). # # Second, if we DON'T find a template but the controller action does have # templates for other formats, variants, etc., then we trust that you meant # to provide a template for this response, too, and we raise # ActionController::UnknownFormat with an explanation. # # Third, if we DON'T find a template AND the request is a page load in a web # browser (technically, a non-XHR GET request for an HTML response) where # you reasonably expect to have rendered a template, then we raise # ActionView::UnknownFormat with an explanation. # # Finally, if we DON'T find a template AND the request isn't a browser page # load, then we implicitly respond with 204 No Content. module ImplicitRender # :stopdoc: include BasicImplicitRender def default_render: () -> untyped def method_for_action: (untyped action_name) -> untyped private def interactive_browser_request?: () -> untyped end end module ActionController # Adds instrumentation to several ends in ActionController::Base. It also provides # some hooks related with process_action. This allows an ORM like Active Record # and/or DataMapper to plug in ActionController and show related information. # # Check ActiveRecord::Railties::ControllerRuntime for an example. module Instrumentation extend ActiveSupport::Concern include AbstractController::Logger attr_accessor view_runtime(@_view_runtime): untyped def process_action: (*untyped args) -> untyped def render: (*untyped args) -> untyped def send_file: (untyped path, ?::Hash[untyped, untyped] options) -> untyped def send_data: (untyped data, ?::Hash[untyped, untyped] options) -> untyped def redirect_to: (*untyped args) -> untyped private # A hook invoked every time a before callback is halted. def halted_callback_hook: (untyped filter) -> untyped def cleanup_view_runtime: () { () -> untyped } -> untyped def append_info_to_payload: (untyped payload) -> untyped module ClassMethods def log_process_action: (untyped payload) -> untyped end end end module ActionController # Mix this module into your controller, and all actions in that controller # will be able to stream data to the client as it's written. # # class MyController < ActionController::Base # include ActionController::Live # # def stream # response.headers['Content-Type'] = 'text/event-stream' # 100.times { # response.stream.write "hello world\n" # sleep 1 # } # ensure # response.stream.close # end # end # # There are a few caveats with this module. You *cannot* write headers after the # response has been committed (Response#committed? will return truthy). # Calling +write+ or +close+ on the response stream will cause the response # object to be committed. Make sure all headers are set before calling write # or close on your stream. # # You *must* call close on your stream when you're finished, otherwise the # socket may be left open forever. # # The final caveat is that your actions are executed in a separate thread than # the main thread. Make sure your actions are thread safe, and this shouldn't # be a problem (don't share state across threads, etc). module Live extend ActiveSupport::Concern module ClassMethods def make_response!: (untyped request) -> untyped end # This class provides the ability to write an SSE (Server Sent Event) # to an IO stream. The class is initialized with a stream and can be used # to either write a JSON string or an object which can be converted to JSON. # # Writing an object will convert it into standard SSE format with whatever # options you have configured. You may choose to set the following options: # # 1) Event. If specified, an event with this name will be dispatched on # the browser. # 2) Retry. The reconnection time in milliseconds used when attempting # to send the event. # 3) Id. If the connection dies while sending an SSE to the browser, then # the server will receive a +Last-Event-ID+ header with value equal to +id+. # # After setting an option in the constructor of the SSE object, all future # SSEs sent across the stream will use those options unless overridden. # # Example Usage: # # class MyController < ActionController::Base # include ActionController::Live # # def index # response.headers['Content-Type'] = 'text/event-stream' # sse = SSE.new(response.stream, retry: 300, event: "event-name") # sse.write({ name: 'John'}) # sse.write({ name: 'John'}, id: 10) # sse.write({ name: 'John'}, id: 10, event: "other-event") # sse.write({ name: 'John'}, id: 10, event: "other-event", retry: 500) # ensure # sse.close # end # end # # Note: SSEs are not currently supported by IE. However, they are supported # by Chrome, Firefox, Opera, and Safari. class SSE PERMITTED_OPTIONS: ::Array[untyped] def initialize: (untyped stream, ?::Hash[untyped, untyped] options) -> untyped def close: () -> untyped def write: (untyped object, ?::Hash[untyped, untyped] options) -> untyped private def perform_write: (untyped json, untyped options) -> untyped end class ClientDisconnected < RuntimeError end class Buffer < ActionDispatch::Response::Buffer # nodoc: include MonitorMixin # Ignore that the client has disconnected. # # If this value is `true`, calling `write` after the client # disconnects will result in the written content being silently # discarded. If this value is `false` (the default), a # ClientDisconnected exception will be raised. attr_accessor ignore_disconnect: untyped def initialize: (untyped response) -> untyped def write: (untyped string) -> untyped # Write a 'close' event to the buffer; the producer/writing thread # uses this to notify us that it's finished supplying content. # # See also #abort. def close: () -> untyped # Inform the producer/writing thread that the client has # disconnected; the reading thread is no longer interested in # anything that's being written. # # See also #close. def abort: () -> untyped # Is the client still connected and waiting for content? # # The result of calling `write` when this is `false` is determined # by `ignore_disconnect`. def connected?: () -> untyped def on_error: () { () -> untyped } -> untyped def call_on_error: () -> untyped private def each_chunk: () { (untyped) -> untyped } -> untyped end class Response < ActionDispatch::Response private def before_committed: () -> untyped def build_buffer: (untyped response, untyped body) -> untyped end def process: (untyped name) -> untyped def response_body=: (untyped body) -> untyped private def new_controller_thread: () { () -> untyped } -> untyped def log_error: (untyped exception) -> (nil | untyped) end end module ActionController # nodoc: module MimeResponds # Without web-service support, an action which collects the data for displaying a list of people # might look something like this: # # def index # @people = Person.all # end # # That action implicitly responds to all formats, but formats can also be explicitly enumerated: # # def index # @people = Person.all # respond_to :html, :js # end # # Here's the same action, with web-service support baked in: # # def index # @people = Person.all # # respond_to do |format| # format.html # format.js # format.xml { render xml: @people } # end # end # # What that says is, "if the client wants HTML or JS in response to this action, just respond as we # would have before, but if the client wants XML, return them the list of people in XML format." # (Rails determines the desired response format from the HTTP Accept header submitted by the client.) # # Supposing you have an action that adds a new person, optionally creating their company # (by name) if it does not already exist, without web-services, it might look like this: # # def create # @company = Company.find_or_create_by(name: params[:company][:name]) # @person = @company.people.create(params[:person]) # # redirect_to(person_list_url) # end # # Here's the same action, with web-service support baked in: # # def create # company = params[:person].delete(:company) # @company = Company.find_or_create_by(name: company[:name]) # @person = @company.people.create(params[:person]) # # respond_to do |format| # format.html { redirect_to(person_list_url) } # format.js # format.xml { render xml: @person.to_xml(include: @company) } # end # end # # If the client wants HTML, we just redirect them back to the person list. If they want JavaScript, # then it is an Ajax request and we render the JavaScript template associated with this action. # Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also # include the person's company in the rendered XML, so you get something like this: # # # ... # ... # # ... # ... # ... # # # # Note, however, the extra bit at the top of that action: # # company = params[:person].delete(:company) # @company = Company.find_or_create_by(name: company[:name]) # # This is because the incoming XML document (if a web-service request is in process) can only contain a # single root-node. So, we have to rearrange things so that the request looks like this (url-encoded): # # person[name]=...&person[company][name]=...&... # # And, like this (xml-encoded): # # # ... # # ... # # # # In other words, we make the request so that it operates on a single entity's person. Then, in the action, # we extract the company data from the request, find or create the company, and then create the new person # with the remaining data. # # Note that you can define your own XML parameter parser which would allow you to describe multiple entities # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow # and accept Rails' defaults, life will be much easier. # # If you need to use a MIME type which isn't supported by default, you can register your own handlers in # +config/initializers/mime_types.rb+ as follows. # # Mime::Type.register "image/jpg", :jpg # # +respond_to+ also allows you to specify a common block for different formats by using +any+: # # def index # @people = Person.all # # respond_to do |format| # format.html # format.any(:xml, :json) { render request.format.to_sym => @people } # end # end # # In the example above, if the format is xml, it will render: # # render xml: @people # # Or if the format is json: # # render json: @people # # +any+ can also be used with no arguments, in which case it will be used for any format requested by # the user: # # respond_to do |format| # format.html # format.any { redirect_to support_path } # end # # Formats can have different variants. # # The request variant is a specialization of the request format, like :tablet, # :phone, or :desktop. # # We often want to render different html/json/xml templates for phones, # tablets, and desktop browsers. Variants make it easy. # # You can set the variant in a +before_action+: # # request.variant = :tablet if request.user_agent =~ /iPad/ # # Respond to variants in the action just like you respond to formats: # # respond_to do |format| # format.html do |variant| # variant.tablet # renders app/views/projects/show.html+tablet.erb # variant.phone { extra_setup; render ... } # variant.none { special_setup } # executed only if there is no variant set # end # end # # Provide separate templates for each format and variant: # # app/views/projects/show.html.erb # app/views/projects/show.html+tablet.erb # app/views/projects/show.html+phone.erb # # When you're not sharing any code within the format, you can simplify defining variants # using the inline syntax: # # respond_to do |format| # format.js { render "trash" } # format.html.phone { redirect_to progress_path } # format.html.none { render "trash" } # end # # Variants also support common +any+/+all+ block that formats have. # # It works for both inline: # # respond_to do |format| # format.html.any { render html: "any" } # format.html.phone { render html: "phone" } # end # # and block syntax: # # respond_to do |format| # format.html do |variant| # variant.any(:tablet, :phablet){ render html: "any" } # variant.phone { render html: "phone" } # end # end # # You can also set an array of variants: # # request.variant = [:tablet, :phone] # # This will work similarly to formats and MIME types negotiation. If there # is no +:tablet+ variant declared, the +:phone+ variant will be used: # # respond_to do |format| # format.html.none # format.html.phone # this gets rendered # end def respond_to: (*untyped mimes) { (untyped) -> untyped } -> untyped # A container for responses available from the current controller for # requests for different mime-types sent to a particular action. # # The public controller methods +respond_to+ may be called with a block # that is used to define responses to different mime-types, e.g. # for +respond_to+ : # # respond_to do |format| # format.html # format.xml { render xml: @people } # end # # In this usage, the argument passed to the block (+format+ above) is an # instance of the ActionController::MimeResponds::Collector class. This # object serves as a container in which available responses can be stored by # calling any of the dynamically generated, mime-type-specific methods such # as +html+, +xml+ etc on the Collector. Each response is represented by a # corresponding block if present. # # A subsequent call to #negotiate_format(request) will enable the Collector # to determine which specific mime-type it should respond with for the current # request, with this response then being accessible by calling #response. class Collector include AbstractController::Collector attr_accessor format: untyped def initialize: (untyped mimes, ?untyped? variant) -> untyped def any: (*untyped args) { () -> untyped } -> untyped alias all any def custom: (untyped mime_type) { () -> untyped } -> untyped def response: () -> untyped def negotiate_format: (untyped request) -> untyped class VariantCollector # nodoc: def initialize: (?untyped? variant) -> untyped def any: (*untyped args) { () -> untyped } -> untyped alias all any def method_missing: (untyped name, *untyped args) { () -> untyped } -> untyped def variant: () -> untyped private def variant_key: () -> untyped end end end end module ActionController # Specify binary encoding for parameters for a given action. module ParameterEncoding extend ActiveSupport::Concern module ClassMethods def inherited: (untyped klass) -> untyped def setup_param_encode: () -> untyped def binary_params_for?: (untyped action) -> untyped # Specify that a given action's parameters should all be encoded as # ASCII-8BIT (it "skips" the encoding default of UTF-8). # # For example, a controller would use it like this: # # class RepositoryController < ActionController::Base # skip_parameter_encoding :show # # def show # @repo = Repository.find_by_filesystem_path params[:file_path] # # # `repo_name` is guaranteed to be UTF-8, but was ASCII-8BIT, so # # tag it as such # @repo_name = params[:repo_name].force_encoding 'UTF-8' # end # # def index # @repositories = Repository.all # end # end # # The show action in the above controller would have all parameter values # encoded as ASCII-8BIT. This is useful in the case where an application # must handle data but encoding of the data is unknown, like file system data. def skip_parameter_encoding: (untyped action) -> untyped end end end module ActionController # Wraps the parameters hash into a nested hash. This will allow clients to # submit requests without having to specify any root elements. # # This functionality is enabled in +config/initializers/wrap_parameters.rb+ # and can be customized. # # You could also turn it on per controller by setting the format array to # a non-empty array: # # class UsersController < ApplicationController # wrap_parameters format: [:json, :xml, :url_encoded_form, :multipart_form] # end # # If you enable +ParamsWrapper+ for +:json+ format, instead of having to # send JSON parameters like this: # # {"user": {"name": "Konata"}} # # You can send parameters like this: # # {"name": "Konata"} # # And it will be wrapped into a nested hash with the key name matching the # controller's name. For example, if you're posting to +UsersController+, # your new +params+ hash will look like this: # # {"name" => "Konata", "user" => {"name" => "Konata"}} # # You can also specify the key in which the parameters should be wrapped to, # and also the list of attributes it should wrap by using either +:include+ or # +:exclude+ options like this: # # class UsersController < ApplicationController # wrap_parameters :person, include: [:username, :password] # end # # On Active Record models with no +:include+ or +:exclude+ option set, # it will only wrap the parameters returned by the class method # attribute_names. # # If you're going to pass the parameters to an +ActiveModel+ object (such as # User.new(params[:user])), you might consider passing the model class to # the method instead. The +ParamsWrapper+ will actually try to determine the # list of attribute names from the model and only wrap those attributes: # # class UsersController < ApplicationController # wrap_parameters Person # end # # You still could pass +:include+ and +:exclude+ to set the list of attributes # you want to wrap. # # By default, if you don't specify the key in which the parameters would be # wrapped to, +ParamsWrapper+ will actually try to determine if there's # a model related to it or not. This controller, for example: # # class Admin::UsersController < ApplicationController # end # # will try to check if Admin::User or +User+ model exists, and use it to # determine the wrapper key respectively. If both models don't exist, # it will then fallback to use +user+ as the key. module ParamsWrapper extend ActiveSupport::Concern EXCLUDE_PARAMETERS: ::Array[untyped] class Options # :nodoc: include Mutex_m def self.from_hash: (untyped hash) -> untyped def initialize: (untyped name, untyped format, untyped `include`, untyped exclude, untyped klass, untyped model) -> untyped def model: () -> untyped def include: () -> untyped def name: () -> untyped private # Determine the wrapper model from the controller's name. By convention, # this could be done by trying to find the defined model that has the # same singular name as the controller. For example, +UsersController+ # will try to find if the +User+ model exists. # # This method also does namespace lookup. Foo::Bar::UsersController will # try to find Foo::Bar::User, Foo::User and finally User. def _default_wrap_model: () -> (nil | untyped) end module ClassMethods def _set_wrapper_options: (untyped options) -> untyped # Sets the name of the wrapper key, or the model which +ParamsWrapper+ # would use to determine the attribute names from. # # ==== Examples # wrap_parameters format: :xml # # enables the parameter wrapper for XML format # # wrap_parameters :person # # wraps parameters into +params[:person]+ hash # # wrap_parameters Person # # wraps parameters by determining the wrapper key from Person class # (+person+, in this case) and the list of attribute names # # wrap_parameters include: [:username, :title] # # wraps only +:username+ and +:title+ attributes from parameters. # # wrap_parameters false # # disables parameters wrapping for this controller altogether. # # ==== Options # * :format - The list of formats in which the parameters wrapper # will be enabled. # * :include - The list of attribute names which parameters wrapper # will wrap into a nested hash. # * :exclude - The list of attribute names which parameters wrapper # will exclude from a nested hash. def wrap_parameters: (untyped name_or_model_or_options, ?::Hash[untyped, untyped] options) -> untyped # Sets the default wrapper key or model which will be used to determine # wrapper key and attribute names. Called automatically when the # module is inherited. def inherited: (untyped klass) -> untyped end # Performs parameters wrapping upon the request. Called automatically # by the metal call stack. def process_action: (*untyped args) -> untyped private # Returns the wrapper key which will be used to store wrapped parameters. def _wrapper_key: () -> untyped # Returns the list of enabled formats. def _wrapper_formats: () -> untyped # Returns the list of parameters which will be selected for wrapped. def _wrap_parameters: (untyped parameters) -> ::Hash[untyped, untyped] def _extract_parameters: (untyped parameters) -> untyped # Checks if we should perform parameters wrapping. def _wrapper_enabled?: () -> (::FalseClass | untyped) def _perform_parameter_wrapping: () -> untyped end end module ActionController module Redirecting extend ActiveSupport::Concern include AbstractController::Logger include ActionController::UrlFor # Redirects the browser to the target specified in +options+. This parameter can be any one of: # # * Hash - The URL will be generated by calling url_for with the +options+. # * Record - The URL will be generated by calling url_for with the +options+, which will reference a named URL for that record. # * String starting with protocol:// (like http://) or a protocol relative reference (like //) - Is passed straight through as the target for redirection. # * String not containing a protocol - The current protocol and host is prepended to the string. # * Proc - A block that will be executed in the controller's context. Should return any option accepted by +redirect_to+. # # === Examples: # # redirect_to action: "show", id: 5 # redirect_to @post # redirect_to "http://www.rubyonrails.org" # redirect_to "/images/screenshot.jpg" # redirect_to posts_url # redirect_to proc { edit_post_url(@post) } # # The redirection happens as a 302 Found header unless otherwise specified using the :status option: # # redirect_to post_url(@post), status: :found # redirect_to action: 'atom', status: :moved_permanently # redirect_to post_url(@post), status: 301 # redirect_to action: 'atom', status: 302 # # The status code can either be a standard {HTTP Status code}[https://www.iana.org/assignments/http-status-codes] as an # integer, or a symbol representing the downcased, underscored and symbolized description. # Note that the status code must be a 3xx HTTP code, or redirection will not occur. # # If you are using XHR requests other than GET or POST and redirecting after the # request then some browsers will follow the redirect using the original request # method. This may lead to undesirable behavior such as a double DELETE. To work # around this you can return a 303 See Other status code which will be # followed using a GET request. # # redirect_to posts_url, status: :see_other # redirect_to action: 'index', status: 303 # # It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names # +alert+ and +notice+ as well as a general purpose +flash+ bucket. # # redirect_to post_url(@post), alert: "Watch it, mister!" # redirect_to post_url(@post), status: :found, notice: "Pay attention to the road" # redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id } # redirect_to({ action: 'atom' }, alert: "Something serious happened") # # Statements after +redirect_to+ in our controller get executed, so +redirect_to+ doesn't stop the execution of the function. # To terminate the execution of the function immediately after the +redirect_to+, use return. # redirect_to post_url(@post) and return def redirect_to: (?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] response_options) -> untyped # Redirects the browser to the page that issued the request (the referrer) # if possible, otherwise redirects to the provided default fallback # location. # # The referrer information is pulled from the HTTP +Referer+ (sic) header on # the request. This is an optional header and its presence on the request is # subject to browser security settings and user preferences. If the request # is missing this header, the fallback_location will be used. # # redirect_back fallback_location: { action: "show", id: 5 } # redirect_back fallback_location: @post # redirect_back fallback_location: "http://www.rubyonrails.org" # redirect_back fallback_location: "/images/screenshot.jpg" # redirect_back fallback_location: posts_url # redirect_back fallback_location: proc { edit_post_url(@post) } # redirect_back fallback_location: '/', allow_other_host: false # # ==== Options # * :fallback_location - The default fallback location that will be used on missing +Referer+ header. # * :allow_other_host - Allow or disallow redirection to the host that is different to the current host, defaults to true. # # All other options that can be passed to redirect_to are accepted as # options and the behavior is identical. def redirect_back: (fallback_location: untyped fallback_location, ?allow_other_host: bool allow_other_host, **untyped args) -> untyped def self?._compute_redirect_to_location: (untyped request, untyped options) -> untyped private def _extract_redirect_to_status: (untyped options, untyped response_options) -> untyped def _url_host_allowed?: (untyped url) -> untyped end end module ActionController # See Renderers.add def self.add_renderer: (untyped key) { () -> untyped } -> untyped # See Renderers.remove def self.remove_renderer: (untyped key) -> untyped # See Responder#api_behavior class MissingRenderer < LoadError def initialize: (untyped format) -> untyped end module Renderers extend ActiveSupport::Concern # A Set containing renderer names that correspond to available renderer procs. # Default values are :json, :js, :xml. RENDERERS: untyped # Used in ActionController::Base # and ActionController::API to include all # renderers by default. module All extend ActiveSupport::Concern include Renderers end # Adds a new renderer to call within controller actions. # A renderer is invoked by passing its name as an option to # AbstractController::Rendering#render. To create a renderer # pass it a name and a block. The block takes two arguments, the first # is the value paired with its key and the second is the remaining # hash of options passed to +render+. # # Create a csv renderer: # # ActionController::Renderers.add :csv do |obj, options| # filename = options[:filename] || 'data' # str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s # send_data str, type: Mime[:csv], # disposition: "attachment; filename=#{filename}.csv" # end # # Note that we used Mime[:csv] for the csv mime type as it comes with Rails. # For a custom renderer, you'll need to register a mime type with # Mime::Type.register. # # To use the csv renderer in a controller action: # # def show # @csvable = Csvable.find(params[:id]) # respond_to do |format| # format.html # format.csv { render csv: @csvable, filename: @csvable.name } # end # end def self.add: (untyped key) { () -> untyped } -> untyped # This method is the opposite of add method. # # To remove a csv renderer: # # ActionController::Renderers.remove(:csv) def self.remove: (untyped key) -> untyped def self._render_with_renderer_method_name: (untyped key) -> ::String module ClassMethods # Adds, by name, a renderer or renderers to the +_renderers+ available # to call within controller actions. # # It is useful when rendering from an ActionController::Metal controller or # otherwise to add an available renderer proc to a specific controller. # # Both ActionController::Base and ActionController::API # include ActionController::Renderers::All, making all renderers # available in the controller. See Renderers::RENDERERS and Renderers.add. # # Since ActionController::Metal controllers cannot render, the controller # must include AbstractController::Rendering, ActionController::Rendering, # and ActionController::Renderers, and have at least one renderer. # # Rather than including ActionController::Renderers::All and including all renderers, # you may specify which renderers to include by passing the renderer name or names to # +use_renderers+. For example, a controller that includes only the :json renderer # (+_render_with_renderer_json+) might look like: # # class MetalRenderingController < ActionController::Metal # include AbstractController::Rendering # include ActionController::Rendering # include ActionController::Renderers # # use_renderers :json # # def show # render json: record # end # end # # You must specify a +use_renderer+, else the +controller.renderer+ and # +controller._renderers+ will be nil, and the action will fail. def use_renderers: (*untyped args) -> untyped alias use_renderer use_renderers end # Called by +render+ in AbstractController::Rendering # which sets the return value as the +response_body+. # # If no renderer is found, +super+ returns control to # ActionView::Rendering.render_to_body, if present. def render_to_body: (untyped options) -> untyped def _render_to_body_with_renderer: (untyped options) -> (untyped | nil) end end module ActionController module Rendering extend ActiveSupport::Concern RENDER_FORMATS_IN_PRIORITY: ::Array[untyped] module ClassMethods # Returns a renderer instance (inherited from ActionController::Renderer) # for the controller. attr_reader renderer: untyped def setup_renderer!: () -> untyped def inherited: (untyped klass) -> untyped end def process_action: () -> untyped def render: (*untyped args) -> untyped # Overwrite render_to_string because body can now be set to a Rack body. def render_to_string: () -> untyped def render_to_body: (?::Hash[untyped, untyped] options) -> untyped private def _process_variant: (untyped options) -> untyped def _render_in_priorities: (untyped options) -> (untyped | nil) def _set_html_content_type: () -> untyped def _set_rendered_content_type: (untyped format) -> untyped # Normalize arguments by catching blocks and setting them on :update. def _normalize_args: (?untyped? action, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped # Normalize both text and status options. def _normalize_options: (untyped options) -> untyped def _normalize_text: (untyped options) -> untyped # Process controller specific options, as status, content-type and location. def _process_options: (untyped options) -> untyped end end module ActionController class InvalidAuthenticityToken < ActionControllerError end class InvalidCrossOriginRequest < ActionControllerError end # Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks # by including a token in the rendered HTML for your application. This token is # stored as a random string in the session, to which an attacker does not have # access. When a request reaches your application, \Rails verifies the received # token with the token in the session. All requests are checked except GET requests # as these should be idempotent. Keep in mind that all session-oriented requests # are CSRF protected by default, including JavaScript and HTML requests. # # Since HTML and JavaScript requests are typically made from the browser, we # need to ensure to verify request authenticity for the web browser. We can # use session-oriented authentication for these types of requests, by using # the protect_from_forgery method in our controllers. # # GET requests are not protected since they don't have side effects like writing # to the database and don't leak sensitive information. JavaScript requests are # an exception: a third-party site can use a # # The first two characters (">) are required in case the exception happens # while rendering attributes for a given tag. You can check the real cause # for the exception in your logger. # # == Web server support # # Not all web servers support streaming out-of-the-box. You need to check # the instructions for each of them. # # ==== Unicorn # # Unicorn supports streaming but it needs to be configured. For this, you # need to create a config file as follow: # # # unicorn.config.rb # listen 3000, tcp_nopush: false # # And use it on initialization: # # unicorn_rails --config-file unicorn.config.rb # # You may also want to configure other parameters like :tcp_nodelay. # Please check its documentation for more information: https://bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen # # If you are using Unicorn with NGINX, you may need to tweak NGINX. # Streaming should work out of the box on Rainbows. # # ==== Passenger # # To be described. # module Streaming extend ActiveSupport::Concern private # Set proper cache control and transfer encoding when streaming def _process_options: (untyped options) -> untyped # Call render_body if we are streaming instead of usual +render+. def _render_template: (untyped options) -> untyped end end module ActionController # Raised when a required parameter is missing. # # params = ActionController::Parameters.new(a: {}) # params.fetch(:b) # # => ActionController::ParameterMissing: param is missing or the value is empty: b # params.require(:a) # # => ActionController::ParameterMissing: param is missing or the value is empty: a class ParameterMissing[T, U] < KeyError[T, U] attr_reader param: untyped def initialize: (untyped param) -> untyped end # Raised when a supplied parameter is not expected and # ActionController::Parameters.action_on_unpermitted_parameters # is set to :raise. # # params = ActionController::Parameters.new(a: "123", b: "456") # params.permit(:c) # # => ActionController::UnpermittedParameters: found unpermitted parameters: :a, :b class UnpermittedParameters < IndexError attr_reader params: untyped def initialize: (untyped params) -> untyped end # Raised when a Parameters instance is not marked as permitted and # an operation to transform it to hash is called. # # params = ActionController::Parameters.new(a: "123", b: "456") # params.to_h # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash class UnfilteredParameters < ArgumentError def initialize: () -> untyped end # == Action Controller \Parameters # # Allows you to choose which attributes should be permitted for mass updating # and thus prevent accidentally exposing that which shouldn't be exposed. # Provides two methods for this purpose: #require and #permit. The former is # used to mark parameters as required. The latter is used to set the parameter # as permitted and limit which attributes should be allowed for mass updating. # # params = ActionController::Parameters.new({ # person: { # name: "Francesco", # age: 22, # role: "admin" # } # }) # # permitted = params.require(:person).permit(:name, :age) # permitted # => "Francesco", "age"=>22} permitted: true> # permitted.permitted? # => true # # Person.first.update!(permitted) # # => # # # It provides two options that controls the top-level behavior of new instances: # # * +permit_all_parameters+ - If it's +true+, all the parameters will be # permitted by default. The default is +false+. # * +action_on_unpermitted_parameters+ - Allow to control the behavior when parameters # that are not explicitly permitted are found. The values can be +false+ to just filter them # out, :log to additionally write a message on the logger, or :raise to raise # ActionController::UnpermittedParameters exception. The default value is :log # in test and development environments, +false+ otherwise. # # Examples: # # params = ActionController::Parameters.new # params.permitted? # => false # # ActionController::Parameters.permit_all_parameters = true # # params = ActionController::Parameters.new # params.permitted? # => true # # params = ActionController::Parameters.new(a: "123", b: "456") # params.permit(:c) # # => # # ActionController::Parameters.action_on_unpermitted_parameters = :raise # # params = ActionController::Parameters.new(a: "123", b: "456") # params.permit(:c) # # => ActionController::UnpermittedParameters: found unpermitted keys: a, b # # Please note that these options *are not thread-safe*. In a multi-threaded # environment they should only be set once at boot-time and never mutated at # runtime. # # You can fetch values of ActionController::Parameters using either # :key or "key". # # params = ActionController::Parameters.new(key: "value") # params[:key] # => "value" # params["key"] # => "value" class Parameters # Returns a new instance of ActionController::Parameters. # Also, sets the +permitted+ attribute to the default value of # ActionController::Parameters.permit_all_parameters. # # class Person < ActiveRecord::Base # end # # params = ActionController::Parameters.new(name: "Francesco") # params.permitted? # => false # Person.new(params) # => ActiveModel::ForbiddenAttributesError # # ActionController::Parameters.permit_all_parameters = true # # params = ActionController::Parameters.new(name: "Francesco") # params.permitted? # => true # Person.new(params) # => # def initialize: (?::Hash[untyped, untyped] parameters) -> untyped # Returns true if another +Parameters+ object contains the same content and # permitted flag. def ==: (untyped other) -> untyped # Returns a safe ActiveSupport::HashWithIndifferentAccess # representation of the parameters with all unpermitted keys removed. # # params = ActionController::Parameters.new({ # name: "Senjougahara Hitagi", # oddity: "Heavy stone crab" # }) # params.to_h # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash # # safe_params = params.permit(:name) # safe_params.to_h # => {"name"=>"Senjougahara Hitagi"} def to_h: () -> untyped # Returns a safe Hash representation of the parameters # with all unpermitted keys removed. # # params = ActionController::Parameters.new({ # name: "Senjougahara Hitagi", # oddity: "Heavy stone crab" # }) # params.to_hash # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash # # safe_params = params.permit(:name) # safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"} def to_hash: () -> untyped # Returns a string representation of the receiver suitable for use as a URL # query string: # # params = ActionController::Parameters.new({ # name: "David", # nationality: "Danish" # }) # params.to_query # # => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash # # safe_params = params.permit(:name, :nationality) # safe_params.to_query # # => "name=David&nationality=Danish" # # An optional namespace can be passed to enclose key names: # # params = ActionController::Parameters.new({ # name: "David", # nationality: "Danish" # }) # safe_params = params.permit(:name, :nationality) # safe_params.to_query("user") # # => "user%5Bname%5D=David&user%5Bnationality%5D=Danish" # # The string pairs "key=value" that conform the query string # are sorted lexicographically in ascending order. # # This method is also aliased as +to_param+. def to_query: (*untyped args) -> untyped alias to_param to_query # Returns an unsafe, unfiltered # ActiveSupport::HashWithIndifferentAccess representation of the # parameters. # # params = ActionController::Parameters.new({ # name: "Senjougahara Hitagi", # oddity: "Heavy stone crab" # }) # params.to_unsafe_h # # => {"name"=>"Senjougahara Hitagi", "oddity" => "Heavy stone crab"} def to_unsafe_h: () -> untyped alias to_unsafe_hash to_unsafe_h # Convert all hashes in values into parameters, then yield each pair in # the same way as Hash#each_pair. def each_pair: () { (untyped) -> untyped } -> untyped alias each each_pair # Convert all hashes in values into parameters, then yield each value in # the same way as Hash#each_value. def each_value: () { (untyped) -> untyped } -> untyped # Attribute that keeps track of converted arrays, if any, to avoid double # looping in the common use case permit + mass-assignment. Defined in a # method to instantiate it only if needed. # # Testing membership still loops, but it's going to be faster than our own # loop that converts values. Also, we are not going to build a new array # object per fetch. def converted_arrays: () -> untyped # Returns +true+ if the parameter is permitted, +false+ otherwise. # # params = ActionController::Parameters.new # params.permitted? # => false # params.permit! # params.permitted? # => true def permitted?: () -> untyped # Sets the +permitted+ attribute to +true+. This can be used to pass # mass assignment. Returns +self+. # # class Person < ActiveRecord::Base # end # # params = ActionController::Parameters.new(name: "Francesco") # params.permitted? # => false # Person.new(params) # => ActiveModel::ForbiddenAttributesError # params.permit! # params.permitted? # => true # Person.new(params) # => # def permit!: () -> untyped # This method accepts both a single key and an array of keys. # # When passed a single key, if it exists and its associated value is # either present or the singleton +false+, returns said value: # # ActionController::Parameters.new(person: { name: "Francesco" }).require(:person) # # => "Francesco"} permitted: false> # # Otherwise raises ActionController::ParameterMissing: # # ActionController::Parameters.new.require(:person) # # ActionController::ParameterMissing: param is missing or the value is empty: person # # ActionController::Parameters.new(person: nil).require(:person) # # ActionController::ParameterMissing: param is missing or the value is empty: person # # ActionController::Parameters.new(person: "\t").require(:person) # # ActionController::ParameterMissing: param is missing or the value is empty: person # # ActionController::Parameters.new(person: {}).require(:person) # # ActionController::ParameterMissing: param is missing or the value is empty: person # # When given an array of keys, the method tries to require each one of them # in order. If it succeeds, an array with the respective return values is # returned: # # params = ActionController::Parameters.new(user: { ... }, profile: { ... }) # user_params, profile_params = params.require([:user, :profile]) # # Otherwise, the method re-raises the first exception found: # # params = ActionController::Parameters.new(user: {}, profile: {}) # user_params, profile_params = params.require([:user, :profile]) # # ActionController::ParameterMissing: param is missing or the value is empty: user # # Technically this method can be used to fetch terminal values: # # # CAREFUL # params = ActionController::Parameters.new(person: { name: "Finn" }) # name = params.require(:person).require(:name) # CAREFUL # # but take into account that at some point those ones have to be permitted: # # def person_params # params.require(:person).permit(:name).tap do |person_params| # person_params.require(:name) # SAFER # end # end # # for example. def require: (untyped key) -> untyped # Alias of #require. alias required require # Returns a new ActionController::Parameters instance that # includes only the given +filters+ and sets the +permitted+ attribute # for the object to +true+. This is useful for limiting which attributes # should be allowed for mass updating. # # params = ActionController::Parameters.new(user: { name: "Francesco", age: 22, role: "admin" }) # permitted = params.require(:user).permit(:name, :age) # permitted.permitted? # => true # permitted.has_key?(:name) # => true # permitted.has_key?(:age) # => true # permitted.has_key?(:role) # => false # # Only permitted scalars pass the filter. For example, given # # params.permit(:name) # # +:name+ passes if it is a key of +params+ whose associated value is of type # +String+, +Symbol+, +NilClass+, +Numeric+, +TrueClass+, +FalseClass+, # +Date+, +Time+, +DateTime+, +StringIO+, +IO+, # +ActionDispatch::Http::UploadedFile+ or +Rack::Test::UploadedFile+. # Otherwise, the key +:name+ is filtered out. # # You may declare that the parameter should be an array of permitted scalars # by mapping it to an empty array: # # params = ActionController::Parameters.new(tags: ["rails", "parameters"]) # params.permit(tags: []) # # Sometimes it is not possible or convenient to declare the valid keys of # a hash parameter or its internal structure. Just map to an empty hash: # # params.permit(preferences: {}) # # Be careful because this opens the door to arbitrary input. In this # case, +permit+ ensures values in the returned structure are permitted # scalars and filters out anything else. # # You can also use +permit+ on nested parameters, like: # # params = ActionController::Parameters.new({ # person: { # name: "Francesco", # age: 22, # pets: [{ # name: "Purplish", # category: "dogs" # }] # } # }) # # permitted = params.permit(person: [ :name, { pets: :name } ]) # permitted.permitted? # => true # permitted[:person][:name] # => "Francesco" # permitted[:person][:age] # => nil # permitted[:person][:pets][0][:name] # => "Purplish" # permitted[:person][:pets][0][:category] # => nil # # Note that if you use +permit+ in a key that points to a hash, # it won't allow all the hash. You also need to specify which # attributes inside the hash should be permitted. # # params = ActionController::Parameters.new({ # person: { # contact: { # email: "none@test.com", # phone: "555-1234" # } # } # }) # # params.require(:person).permit(:contact) # # => # # params.require(:person).permit(contact: :phone) # # => "555-1234"} permitted: true>} permitted: true> # # params.require(:person).permit(contact: [ :email, :phone ]) # # => "none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true> def permit: (*untyped filters) -> untyped # Returns a parameter for the given +key+. If not found, # returns +nil+. # # params = ActionController::Parameters.new(person: { name: "Francesco" }) # params[:person] # => "Francesco"} permitted: false> # params[:none] # => nil def []: (untyped key) -> untyped # Assigns a value to a given +key+. The given key may still get filtered out # when +permit+ is called. def []=: (untyped key, untyped value) -> untyped # Returns a parameter for the given +key+. If the +key+ # can't be found, there are several options: With no other arguments, # it will raise an ActionController::ParameterMissing error; # if a second argument is given, then that is returned (converted to an # instance of ActionController::Parameters if possible); if a block # is given, then that will be run and its result returned. # # params = ActionController::Parameters.new(person: { name: "Francesco" }) # params.fetch(:person) # => "Francesco"} permitted: false> # params.fetch(:none) # => ActionController::ParameterMissing: param is missing or the value is empty: none # params.fetch(:none, {}) # => # params.fetch(:none, "Francesco") # => "Francesco" # params.fetch(:none) { "Francesco" } # => "Francesco" def fetch: (untyped key, *untyped args) { () -> untyped } -> untyped # Extracts the nested parameter from the given +keys+ by calling +dig+ # at each step. Returns +nil+ if any intermediate step is +nil+. # # params = ActionController::Parameters.new(foo: { bar: { baz: 1 } }) # params.dig(:foo, :bar, :baz) # => 1 # params.dig(:foo, :zot, :xyz) # => nil # # params2 = ActionController::Parameters.new(foo: [10, 11, 12]) # params2.dig(:foo, 1) # => 11 def dig: (*untyped keys) -> untyped # Returns a new ActionController::Parameters instance that # includes only the given +keys+. If the given +keys+ # don't exist, returns an empty hash. # # params = ActionController::Parameters.new(a: 1, b: 2, c: 3) # params.slice(:a, :b) # => 1, "b"=>2} permitted: false> # params.slice(:d) # => def slice: (*untyped keys) -> untyped # Returns current ActionController::Parameters instance which # contains only the given +keys+. def slice!: (*untyped keys) -> untyped # Returns a new ActionController::Parameters instance that # filters out the given +keys+. # # params = ActionController::Parameters.new(a: 1, b: 2, c: 3) # params.except(:a, :b) # => 3} permitted: false> # params.except(:d) # => 1, "b"=>2, "c"=>3} permitted: false> def except: (*untyped keys) -> untyped # Removes and returns the key/value pairs matching the given keys. # # params = ActionController::Parameters.new(a: 1, b: 2, c: 3) # params.extract!(:a, :b) # => 1, "b"=>2} permitted: false> # params # => 3} permitted: false> def extract!: (*untyped keys) -> untyped # Returns a new ActionController::Parameters with the results of # running +block+ once for every value. The keys are unchanged. # # params = ActionController::Parameters.new(a: 1, b: 2, c: 3) # params.transform_values { |x| x * 2 } # # => 2, "b"=>4, "c"=>6} permitted: false> def transform_values: () { (untyped) -> untyped } -> untyped # Performs values transformation and returns the altered # ActionController::Parameters instance. def transform_values!: () { (untyped) -> untyped } -> untyped # Returns a new ActionController::Parameters instance with the # results of running +block+ once for every key. The values are unchanged. def transform_keys: () { () -> untyped } -> untyped # Performs keys transformation and returns the altered # ActionController::Parameters instance. def transform_keys!: () { () -> untyped } -> untyped # Deletes a key-value pair from +Parameters+ and returns the value. If # +key+ is not found, returns +nil+ (or, with optional code block, yields # +key+ and returns the result). Cf. +#extract!+, which returns the # corresponding +ActionController::Parameters+ object. def delete: (untyped key) { () -> untyped } -> untyped # Returns a new instance of ActionController::Parameters with only # items that the block evaluates to true. def select: () { () -> untyped } -> untyped # Equivalent to Hash#keep_if, but returns +nil+ if no changes were made. def select!: () { () -> untyped } -> untyped alias keep_if select! # Returns a new instance of ActionController::Parameters with items # that the block evaluates to true removed. def reject: () { () -> untyped } -> untyped # Removes items that the block evaluates to true and returns self. def reject!: () { () -> untyped } -> untyped alias delete_if reject! # Returns values that were assigned to the given +keys+. Note that all the # +Hash+ objects will be converted to ActionController::Parameters. def values_at: (*untyped keys) -> untyped # Returns a new ActionController::Parameters with all keys from # +other_hash+ merged into current hash. def merge: (untyped other_hash) -> untyped # Returns current ActionController::Parameters instance with # +other_hash+ merged into current hash. def merge!: (untyped other_hash) -> untyped # Returns a new ActionController::Parameters with all keys from # current hash merged into +other_hash+. def reverse_merge: (untyped other_hash) -> untyped alias with_defaults reverse_merge # Returns current ActionController::Parameters instance with # current hash merged into +other_hash+. def reverse_merge!: (untyped other_hash) -> untyped alias with_defaults! reverse_merge! def stringify_keys: () -> untyped def inspect: () -> ::String def self.hook_into_yaml_loading: () -> untyped def init_with: (untyped coder) -> untyped # Returns duplicate of object including all parameters. def deep_dup: () -> untyped attr_reader parameters: untyped attr_writer permitted: untyped def fields_for_style?: () -> untyped private def new_instance_with_inherited_permitted_status: (untyped hash) -> untyped def convert_parameters_to_hashes: (untyped value, untyped using) -> untyped def convert_hashes_to_parameters: (untyped key, untyped value) -> untyped def convert_value_to_parameters: (untyped value) -> untyped def each_element: (untyped object) { (untyped) -> untyped } -> untyped def unpermitted_parameters!: (untyped params) -> untyped def unpermitted_keys: (untyped params) -> untyped # This is a white list of permitted scalar types that includes the ones # supported in XML and JSON requests. # # This list is in particular used to filter ordinary requests, String goes # as first element to quickly short-circuit the common case. # # If you modify this collection please update the API of +permit+ above. PERMITTED_SCALAR_TYPES: ::Array[untyped] def permitted_scalar?: (untyped value) -> untyped # Adds existing keys to the params if their values are scalar. # # For example: # # puts self.keys #=> ["zipcode(90210i)"] # params = {} # # permitted_scalar_filter(params, "zipcode") # # puts params.keys # => ["zipcode"] def permitted_scalar_filter: (untyped params, untyped permitted_key) -> untyped def array_of_permitted_scalars?: (untyped value) { (untyped) -> untyped } -> untyped def non_scalar?: (untyped value) -> untyped EMPTY_ARRAY: untyped EMPTY_HASH: ::Hash[untyped, untyped] def hash_filter: (untyped params, untyped filter) -> untyped def permit_any_in_parameters: (untyped params) -> untyped def permit_any_in_array: (untyped array) -> untyped def initialize_copy: (untyped source) -> untyped end # == Strong \Parameters # # It provides an interface for protecting attributes from end-user # assignment. This makes Action Controller parameters forbidden # to be used in Active Model mass assignment until they have been explicitly # enumerated. # # In addition, parameters can be marked as required and flow through a # predefined raise/rescue flow to end up as a 400 Bad Request with no # effort. # # class PeopleController < ActionController::Base # # Using "Person.create(params[:person])" would raise an # # ActiveModel::ForbiddenAttributesError exception because it'd # # be using mass assignment without an explicit permit step. # # This is the recommended form: # def create # Person.create(person_params) # end # # # This will pass with flying colors as long as there's a person key in the # # parameters, otherwise it'll raise an ActionController::ParameterMissing # # exception, which will get caught by ActionController::Base and turned # # into a 400 Bad Request reply. # def update # redirect_to current_account.people.find(params[:id]).tap { |person| # person.update!(person_params) # } # end # # private # # Using a private method to encapsulate the permissible parameters is # # a good pattern since you'll be able to reuse the same permit # # list between create and update. Also, you can specialize this method # # with per-user checking of permissible attributes. # def person_params # params.require(:person).permit(:name, :age) # end # end # # In order to use accepts_nested_attributes_for with Strong \Parameters, you # will need to specify which nested attributes should be permitted. You might want # to allow +:id+ and +:_destroy+, see ActiveRecord::NestedAttributes for more information. # # class Person # has_many :pets # accepts_nested_attributes_for :pets # end # # class PeopleController < ActionController::Base # def create # Person.create(person_params) # end # # ... # # private # # def person_params # # It's mandatory to specify the nested attributes that should be permitted. # # If you use `permit` with just the key that points to the nested attributes hash, # # it will return an empty hash. # params.require(:person).permit(:name, :age, pets_attributes: [ :id, :name, :category ]) # end # end # # See ActionController::Parameters.require and ActionController::Parameters.permit # for more information. module StrongParameters # Returns a new ActionController::Parameters object that # has been instantiated with the request.parameters. def params: () -> untyped # Assigns the given +value+ to the +params+ hash. If +value+ # is a Hash, this will create an ActionController::Parameters # object that has been instantiated with the given +value+ hash. def params=: (untyped value) -> untyped end end module ActionController module Testing extend ActiveSupport::Concern module Functional # Behavior specific to functional tests # :nodoc: def recycle!: () -> untyped end end end module ActionController # Includes +url_for+ into the host class. The class has to provide a +RouteSet+ by implementing # the _routes method. Otherwise, an exception will be raised. # # In addition to AbstractController::UrlFor, this module accesses the HTTP layer to define # URL options like the +host+. In order to do so, this module requires the host class # to implement +env+ which needs to be Rack-compatible and +request+ # which is either an instance of +ActionDispatch::Request+ or an object # that responds to the +host+, +optional_port+, +protocol+ and # +symbolized_path_parameter+ methods. # # class RootUrl # include ActionController::UrlFor # include Rails.application.routes.url_helpers # # delegate :env, :request, to: :controller # # def initialize(controller) # @controller = controller # @url = root_path # named route from the application. # end # end module UrlFor extend ActiveSupport::Concern include AbstractController::UrlFor def url_options: () -> untyped end end module ActionController class MiddlewareStack < ActionDispatch::MiddlewareStack class Middleware < ActionDispatch::MiddlewareStack::Middleware # Extend ActionDispatch middleware stack to make it aware of options # allowing the following syntax in controllers: # # class PostsController < ApplicationController # use AuthenticationMiddleware, except: [:index, :show] # end # # nodoc: # nodoc: def initialize: (untyped klass, untyped args, untyped actions, untyped strategy, untyped block) -> untyped def valid?: (untyped action) -> untyped end def build: (untyped action, ?untyped? app) { () -> untyped } -> untyped private INCLUDE: untyped EXCLUDE: untyped NULL: untyped def build_middleware: (untyped klass, untyped args, untyped block) -> Middleware end # ActionController::Metal is the simplest possible controller, providing a # valid Rack interface without the additional niceties provided by # ActionController::Base. # # A sample metal controller might look like this: # # class HelloController < ActionController::Metal # def index # self.response_body = "Hello World!" # end # end # # And then to route requests to your metal controller, you would add # something like this to config/routes.rb: # # get 'hello', to: HelloController.action(:index) # # The +action+ method returns a valid Rack application for the \Rails # router to dispatch to. # # == Rendering Helpers # # ActionController::Metal by default provides no utilities for rendering # views, partials, or other responses aside from explicitly calling of # response_body=, content_type=, and status=. To # add the render helpers you're used to having in a normal controller, you # can do the following: # # class HelloController < ActionController::Metal # include AbstractController::Rendering # include ActionView::Layouts # append_view_path "#{Rails.root}/app/views" # # def index # render "hello/index" # end # end # # == Redirection Helpers # # To add redirection helpers to your metal controller, do the following: # # class HelloController < ActionController::Metal # include ActionController::Redirecting # include Rails.application.routes.url_helpers # # def index # redirect_to root_url # end # end # # == Other Helpers # # You can refer to the modules included in ActionController::Base to see # other features you can bring into your metal controller. # class Metal < AbstractController::Base # Returns the last part of the controller's name, underscored, without the ending # Controller. For instance, PostsController returns posts. # Namespaces are left out, so Admin::PostsController returns posts as well. # # ==== Returns # * string def self.controller_name: () -> untyped def self.make_response!: (untyped request) -> untyped def self.binary_params_for?: (untyped action) -> ::FalseClass # Delegates to the class' controller_name. def controller_name: () -> untyped attr_accessor response(@_response): untyped attr_accessor request(@_request): untyped def initialize: () -> untyped def params: () -> untyped def params=: (untyped val) -> untyped alias response_code status # Basic url_for that can be overridden for more robust functionality. def url_for: (untyped string) -> untyped def response_body=: (untyped body) -> (nil | untyped) # Tests if render or redirect has already happened. def performed?: () -> untyped def dispatch: (untyped name, untyped request, untyped response) -> untyped def set_response!: (untyped response) -> untyped def set_request!: (untyped request) -> untyped def to_a: () -> untyped def reset_session: () -> untyped def self.inherited: (untyped base) -> untyped # Pushes the given Rack middleware and its arguments to the bottom of the # middleware stack. def self.use: (*untyped args) { () -> untyped } -> untyped # Alias for +middleware_stack+. def self.middleware: () -> untyped # Returns a Rack endpoint for the given action name. def self.action: (untyped name) -> untyped # Direct dispatch to the controller. Instantiates the controller, then # executes the action named +name+. def self.dispatch: (untyped name, untyped req, untyped res) -> untyped end end module ActionController class Railtie < Rails::Railtie extend ::ActionController::Railties::Helpers end end module ActionController module Railties module Helpers def inherited: (untyped klass) -> (nil | untyped) end end end module ActionController # ActionController::Renderer allows you to render arbitrary templates # without requirement of being in controller actions. # # You get a concrete renderer class by invoking ActionController::Base#renderer. # For example: # # ApplicationController.renderer # # It allows you to call method #render directly. # # ApplicationController.renderer.render template: '...' # # You can use this shortcut in a controller, instead of the previous example: # # ApplicationController.render template: '...' # # #render allows you to use the same options that you can use when rendering in a controller. # For example: # # FooController.render :action, locals: { ... }, assigns: { ... } # # The template will be rendered in a Rack environment which is accessible through # ActionController::Renderer#env. You can set it up in two ways: # # * by changing renderer defaults, like # # ApplicationController.renderer.defaults # => hash with default Rack environment # # * by initializing an instance of renderer by passing it a custom environment. # # ApplicationController.renderer.new(method: 'post', https: true) # class Renderer attr_reader defaults: untyped attr_reader controller: untyped DEFAULTS: untyped # Create a new renderer instance for a specific controller class. def self.for: (untyped controller, ?::Hash[untyped, untyped] env, ?untyped defaults) -> untyped # Create a new renderer for the same controller but with a new env. def new: (?::Hash[untyped, untyped] env) -> untyped # Create a new renderer for the same controller but with new defaults. def with_defaults: (untyped defaults) -> untyped # Accepts a custom Rack environment to render templates in. # It will be merged with the default Rack environment defined by # +ActionController::Renderer::DEFAULTS+. def initialize: (untyped controller, untyped env, untyped defaults) -> untyped # Render templates with any options from ActionController::Base#render_to_string. # # The primary options are: # * :partial - See ActionView::PartialRenderer for details. # * :file - Renders an explicit template file. Add :locals to pass in, if so desired. # It shouldn(trim non-ascii characters)t be used directly with unsanitized user input due to lack of validation. # * :inline - Renders an ERB template string. # * :plain - Renders provided text and sets the content type as text/plain. # * :html - Renders the provided HTML safe string, otherwise # performs HTML escape on the string first. Sets the content type as text/html. # * :json - Renders the provided hash or object in JSON. You don't # need to call .to_json on the object you want to render. # * :body - Renders provided text and sets content type of text/plain. # # If no options hash is passed or if :update is specified, the default is # to render a partial and use the second parameter as the locals hash. def render: (*untyped args) -> untyped private def normalize_keys: (untyped env) -> untyped RACK_KEY_TRANSLATION: ::Hash[untyped, untyped] IDENTITY: untyped RACK_VALUE_TRANSLATION: ::Hash[untyped, untyped] def rack_key_for: (untyped key) -> untyped def rack_value_for: (untyped key, untyped value) -> untyped end end module ActionController module TemplateAssertions # :nodoc: def assert_template: (?::Hash[untyped, untyped] options, ?untyped? message) -> untyped end end module ActionController class Metal include Testing::Functional end class TestRequest < ActionDispatch::TestRequest # ActionController::TestCase will be deprecated and moved to a gem in the future. # Please use ActionDispatch::IntegrationTest going forward. # nodoc: DEFAULT_ENV: untyped def self.new_session: () -> TestSession attr_reader controller_class: untyped # Create a new test request with default `env` values. def self.create: (untyped controller_class) -> untyped def self.default_env: () -> untyped def initialize: (untyped env, untyped session, untyped controller_class) -> untyped def query_string=: (untyped string) -> untyped def content_type=: (untyped `type`) -> untyped def assign_parameters: (untyped routes, untyped controller_path, untyped action, untyped parameters, untyped generated_path, untyped query_string_keys) -> untyped ENCODER: untyped private def params_parsers: () -> untyped end class LiveTestResponse < Live::Response # Was the response successful? alias success? successful? # Was the URL not found? alias missing? not_found? # Was there a server-side error? alias error? server_error? end class TestSession < Rack::Session::Abstract::PersistedSecure::SecureSessionHash # Methods #destroy and #load! are overridden to avoid calling methods on the # @store object, which does not exist for the TestSession class. # nodoc: DEFAULT_OPTIONS: untyped def initialize: (?::Hash[untyped, untyped] session) -> untyped def exists?: () -> ::TrueClass def keys: () -> untyped def values: () -> untyped def destroy: () -> untyped def dig: (*untyped keys) -> untyped def fetch: (untyped key, *untyped args) { () -> untyped } -> untyped private def load!: () -> untyped end # Superclass for ActionController functional tests. Functional tests allow you to # test a single controller action per test method. # # == Use integration style controller tests over functional style controller tests. # # Rails discourages the use of functional tests in favor of integration tests # (use ActionDispatch::IntegrationTest). # # New Rails applications no longer generate functional style controller tests and they should # only be used for backward compatibility. Integration style controller tests perform actual # requests, whereas functional style controller tests merely simulate a request. Besides, # integration tests are as fast as functional tests and provide lot of helpers such as +as+, # +parsed_body+ for effective testing of controller actions including even API endpoints. # # == Basic example # # Functional tests are written as follows: # 1. First, one uses the +get+, +post+, +patch+, +put+, +delete+ or +head+ method to simulate # an HTTP request. # 2. Then, one asserts whether the current state is as expected. "State" can be anything: # the controller's HTTP response, the database contents, etc. # # For example: # # class BooksControllerTest < ActionController::TestCase # def test_create # # Simulate a POST response with the given HTTP parameters. # post(:create, params: { book: { title: "Love Hina" }}) # # # Asserts that the controller tried to redirect us to # # the created book's URI. # assert_response :found # # # Asserts that the controller really put the book in the database. # assert_not_nil Book.find_by(title: "Love Hina") # end # end # # You can also send a real document in the simulated HTTP request. # # def test_create # json = {book: { title: "Love Hina" }}.to_json # post :create, body: json # end # # == Special instance variables # # ActionController::TestCase will also automatically provide the following instance # variables for use in the tests: # # @controller:: # The controller instance that will be tested. # @request:: # An ActionController::TestRequest, representing the current HTTP # request. You can modify this object before sending the HTTP request. For example, # you might want to set some session properties before sending a GET request. # @response:: # An ActionDispatch::TestResponse object, representing the response # of the last HTTP response. In the above example, @response becomes valid # after calling +post+. If the various assert methods are not sufficient, then you # may use this object to inspect the HTTP response in detail. # # == Controller is automatically inferred # # ActionController::TestCase will automatically infer the controller under test # from the test class name. If the controller cannot be inferred from the test # class name, you can explicitly set it with +tests+. # # class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase # tests WidgetController # end # # == \Testing controller internals # # In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions # can be used against. These collections are: # # * session: Objects being saved in the session. # * flash: The flash objects currently in the session. # * cookies: \Cookies being sent to the user on this request. # # These collections can be used just like any other hash: # # assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave" # assert flash.empty? # makes sure that there's nothing in the flash # # On top of the collections, you have the complete URL that a given action redirected to available in redirect_to_url. # # For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another # action call which can then be asserted against. # # == Manipulating session and cookie variables # # Sometimes you need to set up the session and cookie variables for a test. # To do this just assign a value to the session or cookie collection: # # session[:key] = "value" # cookies[:key] = "value" # # To clear the cookies for a test just clear the cookie collection: # # cookies.clear # # == \Testing named routes # # If you're using named routes, they can be easily tested using the original named routes' methods straight in the test case. # # assert_redirected_to page_url(title: 'foo') class TestCase < ActiveSupport::TestCase module Behavior extend ActiveSupport::Concern include ActionDispatch::TestProcess include ActiveSupport::Testing::ConstantLookup include Rails::Dom::Testing::Assertions attr_reader response: untyped attr_reader request: untyped module ClassMethods # Sets the controller class name. Useful if the name can't be inferred from test class. # Normalizes +controller_class+ before using. # # tests WidgetController # tests :widget # tests 'widget' def tests: (untyped controller_class) -> untyped def controller_class=: (untyped new_class) -> untyped def controller_class: () -> untyped def determine_default_controller_class: (untyped name) -> untyped end # Simulate a GET request with the given parameters. # # - +action+: The controller action to call. # - +params+: The hash with HTTP parameters that you want to pass. This may be +nil+. # - +body+: The request body with a string that is appropriately encoded # (application/x-www-form-urlencoded or multipart/form-data). # - +session+: A hash of parameters to store in the session. This may be +nil+. # - +flash+: A hash of parameters to store in the flash. This may be +nil+. # # You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with # +post+, +patch+, +put+, +delete+, and +head+. # Example sending parameters, session and setting a flash message: # # get :show, # params: { id: 7 }, # session: { user_id: 1 }, # flash: { notice: 'This is flash message' } # # Note that the request method is not verified. The different methods are # available to make the tests more expressive. def get: (untyped action, **untyped args) -> untyped # Simulate a POST request with the given parameters and set/volley the response. # See +get+ for more details. def post: (untyped action, **untyped args) -> untyped # Simulate a PATCH request with the given parameters and set/volley the response. # See +get+ for more details. def patch: (untyped action, **untyped args) -> untyped # Simulate a PUT request with the given parameters and set/volley the response. # See +get+ for more details. def put: (untyped action, **untyped args) -> untyped # Simulate a DELETE request with the given parameters and set/volley the response. # See +get+ for more details. def delete: (untyped action, **untyped args) -> untyped # Simulate a HEAD request with the given parameters and set/volley the response. # See +get+ for more details. def head: (untyped action, **untyped args) -> untyped # Simulate an HTTP request to +action+ by specifying request method, # parameters and set/volley the response. # # - +action+: The controller action to call. # - +method+: Request method used to send the HTTP request. Possible values # are +GET+, +POST+, +PATCH+, +PUT+, +DELETE+, +HEAD+. Defaults to +GET+. Can be a symbol. # - +params+: The hash with HTTP parameters that you want to pass. This may be +nil+. # - +body+: The request body with a string that is appropriately encoded # (application/x-www-form-urlencoded or multipart/form-data). # - +session+: A hash of parameters to store in the session. This may be +nil+. # - +flash+: A hash of parameters to store in the flash. This may be +nil+. # - +format+: Request format. Defaults to +nil+. Can be string or symbol. # - +as+: Content type. Defaults to +nil+. Must be a symbol that corresponds # to a mime type. # # Example calling +create+ action and sending two params: # # process :create, # method: 'POST', # params: { # user: { name: 'Gaurish Sharma', email: 'user@example.com' } # }, # session: { user_id: 1 }, # flash: { notice: 'This is flash message' } # # To simulate +GET+, +POST+, +PATCH+, +PUT+, +DELETE+ and +HEAD+ requests # prefer using #get, #post, #patch, #put, #delete and #head methods # respectively which will make tests more expressive. # # Note that the request method is not verified. def process: (untyped action, ?as: untyped? as, ?xhr: bool xhr, ?format: untyped? format, ?flash: ::Hash[untyped, untyped] flash, ?body: untyped? body, ?session: untyped? session, ?params: untyped? params, ?method: ::String method) -> untyped def controller_class_name: () -> untyped def generated_path: (untyped generated_extras) -> untyped def query_parameter_names: (untyped generated_extras) -> untyped def setup_controller_request_and_response: () -> untyped def build_response: (untyped klass) -> untyped include ActionController::TemplateAssertions include ActionDispatch::Assertions private def scrub_env!: (untyped env) -> untyped def document_root_element: () -> untyped def check_required_ivars: () -> untyped end include Behavior end end module ActionController extend ActiveSupport::Autoload end module ActionDispatch module Http module Cache module Request HTTP_IF_MODIFIED_SINCE: ::String HTTP_IF_NONE_MATCH: ::String def if_modified_since: () -> untyped def if_none_match: () -> untyped def if_none_match_etags: () -> untyped def not_modified?: (untyped modified_at) -> untyped def etag_matches?: (untyped etag) -> untyped # Check response freshness (Last-Modified and ETag) against request # If-Modified-Since and If-None-Match conditions. If both headers are # supplied, both must match, or the request is not considered fresh. def fresh?: (untyped response) -> (::FalseClass | untyped) end module Response attr_reader cache_control: untyped def last_modified: () -> untyped def last_modified?: () -> untyped def last_modified=: (untyped utc_time) -> untyped def date: () -> untyped def date?: () -> untyped def date=: (untyped utc_time) -> untyped # This method sets a weak ETag validator on the response so browsers # and proxies may cache the response, keyed on the ETag. On subsequent # requests, the If-None-Match header is set to the cached ETag. If it # matches the current ETag, we can return a 304 Not Modified response # with no body, letting the browser or proxy know that their cache is # current. Big savings in request time and network bandwidth. # # Weak ETags are considered to be semantically equivalent but not # byte-for-byte identical. This is perfect for browser caching of HTML # pages where we don't care about exact equality, just what the user # is viewing. # # Strong ETags are considered byte-for-byte identical. They allow a # browser or proxy cache to support Range requests, useful for paging # through a PDF file or scrubbing through a video. Some CDNs only # support strong ETags and will ignore weak ETags entirely. # # Weak ETags are what we almost always need, so they're the default. # Check out #strong_etag= to provide a strong ETag validator. def etag=: (untyped weak_validators) -> untyped def weak_etag=: (untyped weak_validators) -> untyped def strong_etag=: (untyped strong_validators) -> untyped def etag?: () -> untyped # True if an ETag is set and it's a weak validator (preceded with W/) def weak_etag?: () -> untyped # True if an ETag is set and it isn't a weak validator (not preceded with W/) def strong_etag?: () -> untyped private DATE: ::String LAST_MODIFIED: ::String SPECIAL_KEYS: untyped def generate_weak_etag: (untyped validators) -> ::String def generate_strong_etag: (untyped validators) -> ::String def cache_control_segments: () -> untyped def cache_control_headers: () -> untyped def prepare_cache_control!: () -> untyped DEFAULT_CACHE_CONTROL: ::String NO_CACHE: ::String PUBLIC: ::String PRIVATE: ::String MUST_REVALIDATE: ::String def handle_conditional_get!: () -> untyped def merge_and_normalize_cache_control!: (untyped cache_control) -> untyped end end end end module ActionDispatch module Http class ContentDisposition # :nodoc: def self.format: (filename: untyped filename, disposition: untyped disposition) -> untyped attr_reader disposition: untyped attr_reader filename: untyped def initialize: (filename: untyped filename, disposition: untyped disposition) -> untyped TRADITIONAL_ESCAPED_CHAR: untyped def ascii_filename: () -> untyped RFC_5987_ESCAPED_CHAR: untyped def utf8_filename: () -> untyped def to_s: () -> untyped private def percent_escape: (untyped string, untyped pattern) -> untyped end end end module ActionDispatch # nodoc: class ContentSecurityPolicy class Middleware CONTENT_TYPE: ::String POLICY: ::String POLICY_REPORT_ONLY: ::String def initialize: (untyped app) -> untyped def call: (untyped env) -> untyped private def html_response?: (untyped headers) -> untyped def header_name: (untyped request) -> untyped def policy_present?: (untyped headers) -> untyped end module Request POLICY: ::String POLICY_REPORT_ONLY: ::String NONCE_GENERATOR: ::String NONCE: ::String NONCE_DIRECTIVES: ::String def content_security_policy: () -> untyped def content_security_policy=: (untyped policy) -> untyped def content_security_policy_report_only: () -> untyped def content_security_policy_report_only=: (untyped value) -> untyped def content_security_policy_nonce_generator: () -> untyped def content_security_policy_nonce_generator=: (untyped generator) -> untyped def content_security_policy_nonce_directives: () -> untyped def content_security_policy_nonce_directives=: (untyped generator) -> untyped def content_security_policy_nonce: () -> untyped private def generate_content_security_policy_nonce: () -> untyped end MAPPINGS: untyped DIRECTIVES: untyped DEFAULT_NONCE_DIRECTIVES: untyped attr_reader directives: untyped def initialize: () { (untyped) -> untyped } -> untyped def initialize_copy: (untyped other) -> untyped def block_all_mixed_content: (?bool enabled) -> untyped def plugin_types: (*untyped types) -> untyped def report_uri: (untyped uri) -> untyped def require_sri_for: (*untyped types) -> untyped def sandbox: (*untyped values) -> untyped def upgrade_insecure_requests: (?bool enabled) -> untyped def build: (?untyped? context, ?untyped? nonce, ?untyped? nonce_directives) -> untyped private def apply_mappings: (untyped sources) -> untyped def apply_mapping: (untyped source) -> untyped def build_directives: (untyped context, untyped nonce, untyped nonce_directives) -> untyped def build_directive: (untyped sources, untyped context) -> untyped def resolve_source: (untyped source, untyped context) -> untyped def nonce_directive?: (untyped directive, untyped nonce_directives) -> untyped end end module ActionDispatch module Http # Allows you to specify sensitive parameters which will be replaced from # the request log by looking in the query string of the request and all # sub-hashes of the params hash to filter. Filtering only certain sub-keys # from a hash is possible by using the dot notation: 'credit_card.number'. # If a block is given, each key and value of the params hash and all # sub-hashes are passed to it, where the value or the key can be replaced using # String#replace or similar methods. # # env["action_dispatch.parameter_filter"] = [:password] # => replaces the value to all keys matching /password/i with "[FILTERED]" # # env["action_dispatch.parameter_filter"] = [:foo, "bar"] # => replaces the value to all keys matching /foo|bar/i with "[FILTERED]" # # env["action_dispatch.parameter_filter"] = [ "credit_card.code" ] # => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not # change { file: { code: "xxxx"} } # # env["action_dispatch.parameter_filter"] = -> (k, v) do # v.reverse! if k =~ /secret/i # end # => reverses the value to all keys matching /secret/i module FilterParameters ENV_MATCH: ::Array[untyped] NULL_PARAM_FILTER: untyped NULL_ENV_FILTER: untyped def initialize: () -> untyped # Returns a hash of parameters with all sensitive data replaced. def filtered_parameters: () -> untyped # Returns a hash of request.env with all sensitive data replaced. def filtered_env: () -> untyped # Reconstructs a path with all sensitive GET parameters replaced. def filtered_path: () -> untyped private def parameter_filter: () -> untyped def env_filter: () -> untyped def parameter_filter_for: (untyped filters) -> ActiveSupport::ParameterFilter KV_RE: ::String PAIR_RE: untyped def filtered_query_string: () -> untyped end end end module ActionDispatch module Http module FilterRedirect FILTERED: ::String def filtered_location: () -> untyped private def location_filters: () -> untyped def location_filter_match?: () -> untyped end end end module ActionDispatch module Http # Provides access to the request's HTTP headers from the environment. # # env = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" } # headers = ActionDispatch::Http::Headers.from_hash(env) # headers["Content-Type"] # => "text/plain" # headers["User-Agent"] # => "curl/7.43.0" # # Also note that when headers are mapped to CGI-like variables by the Rack # server, both dashes and underscores are converted to underscores. This # ambiguity cannot be resolved at this stage anymore. Both underscores and # dashes have to be interpreted as if they were originally sent as dashes. # # # GET / HTTP/1.1 # # ... # # User-Agent: curl/7.43.0 # # X_Custom_Header: token # # headers["X_Custom_Header"] # => nil # headers["X-Custom-Header"] # => "token" class Headers CGI_VARIABLES: untyped HTTP_HEADER: untyped include Enumerable[untyped] def self.from_hash: (untyped hash) -> untyped def initialize: (untyped request) -> untyped # Returns the value for the given key mapped to @env. def []: (untyped key) -> untyped # Sets the given value for the key mapped to @env. def []=: (untyped key, untyped value) -> untyped # Add a value to a multivalued header like Vary or Accept-Encoding. def add: (untyped key, untyped value) -> untyped def key?: (untyped key) -> untyped alias include? key? DEFAULT: untyped # Returns the value for the given key mapped to @env. # # If the key is not found and an optional code block is not provided, # raises a KeyError exception. # # If the code block is provided, then it will be run and # its result returned. def fetch: (untyped key, ?untyped default) { () -> untyped } -> untyped def each: () { (untyped) -> untyped } -> untyped # Returns a new Http::Headers instance containing the contents of # headers_or_env and the original instance. def merge: (untyped headers_or_env) -> untyped # Adds the contents of headers_or_env to original instance # entries; duplicate keys are overwritten with the values from # headers_or_env. def merge!: (untyped headers_or_env) -> untyped def env: () -> untyped private # Converts an HTTP header name to an environment variable name if it is # not contained within the headers hash. def env_name: (untyped key) -> untyped end end end module ActionDispatch module Http module MimeNegotiation extend ActiveSupport::Concern RESCUABLE_MIME_FORMAT_ERRORS: ::Array[untyped] # The MIME type of the HTTP request, such as Mime[:xml]. def content_mime_type: () -> untyped def content_type: () -> untyped def has_content_type?: () -> untyped # Returns the accepted MIME type for the request. def accepts: () -> untyped # Returns the MIME type for the \format used in the request. # # GET /posts/5.xml | request.format => Mime[:xml] # GET /posts/5.xhtml | request.format => Mime[:html] # GET /posts/5 | request.format => Mime[:html] or Mime[:js], or request.accepts.first # def format: (?untyped view_path) -> untyped def formats: () -> untyped # Sets the \variant for template. def variant=: (untyped variant) -> untyped def variant: () -> untyped # Sets the \format by string extension, which can be used to force custom formats # that are not controlled by the extension. # # class ApplicationController < ActionController::Base # before_action :adjust_format_for_iphone # # private # def adjust_format_for_iphone # request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/] # end # end def format=: (untyped `extension`) -> untyped # Sets the \formats by string extensions. This differs from #format= by allowing you # to set multiple, ordered formats, which is useful when you want to have a fallback. # # In this example, the :iphone format will be used if it's available, otherwise it'll fallback # to the :html format. # # class ApplicationController < ActionController::Base # before_action :adjust_format_for_iphone_with_html_fallback # # private # def adjust_format_for_iphone_with_html_fallback # request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/] # end # end def formats=: (untyped extensions) -> untyped # Returns the first MIME type that matches the provided array of MIME types. def negotiate_mime: (untyped order) -> untyped private BROWSER_LIKE_ACCEPTS: untyped def valid_accept_header: () -> untyped def use_accept_header: () -> untyped def format_from_path_extension: () -> untyped end end end module Mime class Mimes include Enumerable[untyped] def initialize: () -> untyped def each: () { (untyped) -> untyped } -> untyped def <<: (untyped `type`) -> untyped def delete_if: () { (untyped) -> untyped } -> untyped def symbols: () -> untyped end SET: untyped EXTENSION_LOOKUP: ::Hash[untyped, untyped] LOOKUP: ::Hash[untyped, untyped] def self.[]: (untyped `type`) -> untyped def self.fetch: (untyped `type`) { (untyped) -> untyped } -> untyped # Encapsulates the notion of a MIME type. Can be used at render time, for example, with: # # class PostsController < ActionController::Base # def show # @post = Post.find(params[:id]) # # respond_to do |format| # format.html # format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar") } # format.xml { render xml: @post } # end # end # end class Type attr_reader symbol: untyped class AcceptItem # A simple helper class used in parsing the accept header. # nodoc: attr_accessor index: untyped # A simple helper class used in parsing the accept header. # nodoc: attr_accessor name: untyped # A simple helper class used in parsing the accept header. # nodoc: attr_accessor q: untyped alias to_s name def initialize: (untyped index, untyped name, ?untyped? q) -> untyped def <=>: (untyped item) -> untyped end class AcceptList # nodoc: def self.sort!: (untyped list) -> untyped def self.find_item_by_name: (untyped array, untyped name) -> untyped end TRAILING_STAR_REGEXP: untyped PARAMETER_SEPARATOR_REGEXP: untyped def self.register_callback: () { () -> untyped } -> untyped def self.lookup: (untyped string) -> untyped def self.lookup_by_extension: (untyped `extension`) -> untyped # Registers an alias that's not used on MIME type lookup, but can be referenced directly. Especially useful for # rendering different HTML versions depending on the user agent, like an iPhone. def self.register_alias: (untyped string, untyped symbol, ?untyped extension_synonyms) -> untyped def self.register: (untyped string, untyped symbol, ?untyped mime_type_synonyms, ?untyped extension_synonyms, ?bool skip_lookup) -> untyped def self.parse: (untyped accept_header) -> untyped def self.parse_trailing_star: (untyped accept_header) -> untyped # For an input of 'text', returns [Mime[:json], Mime[:xml], Mime[:ics], # Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text]. # # For an input of 'application', returns [Mime[:html], Mime[:js], # Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form]. def self.parse_data_with_trailing_star: (untyped `type`) -> untyped # This method is opposite of register method. # # To unregister a MIME type: # # Mime::Type.unregister(:mobile) def self.unregister: (untyped symbol) -> untyped attr_reader hash: untyped MIME_NAME: ::String MIME_PARAMETER_KEY: ::String MIME_PARAMETER_VALUE: ::String MIME_PARAMETER: ::String MIME_REGEXP: untyped class InvalidMimeType < StandardError end def initialize: (untyped string, ?untyped? symbol, ?untyped synonyms) -> untyped def to_s: () -> untyped def to_str: () -> untyped def to_sym: () -> untyped def ref: () -> untyped def ===: (untyped list) -> untyped def ==: (untyped mime_type) -> (::FalseClass | untyped) def eql?: (untyped other) -> untyped def =~: (untyped mime_type) -> (::FalseClass | untyped) def html?: () -> untyped def all?: () -> ::FalseClass attr_reader string: untyped attr_reader synonyms: untyped private def to_ary: () -> nil def to_a: () -> nil def method_missing: (untyped method, *untyped args) -> untyped def respond_to_missing?: (untyped method, ?bool include_private) -> untyped end class AllType < Type include Singleton def initialize: () -> untyped def all?: () -> ::TrueClass def html?: () -> ::TrueClass end # ALL isn't a real MIME type, so we don't register it for lookup with the # other concrete types. It's a wildcard match that we use for `respond_to` # negotiation internals. ALL: untyped class NullType include Singleton def nil?: () -> ::TrueClass def ref: () -> nil private def respond_to_missing?: (untyped method, untyped _) -> untyped def method_missing: (untyped method, *untyped args) -> untyped end end module ActionDispatch module Http include ActiveSupport::Deprecation::DeprecatedConstantAccessor end end module ActionDispatch module Http module Parameters extend ActiveSupport::Concern PARAMETERS_KEY: ::String DEFAULT_PARSERS: ::Hash[untyped, untyped] # Raised when raw data from the request cannot be parsed by the parser # defined for request's content MIME type. class ParseError < StandardError def initialize: () -> untyped end # Returns the parameter parsers. attr_reader self.parameter_parsers: untyped module ClassMethods # Configure the parameter parser for a given MIME type. # # It accepts a hash where the key is the symbol of the MIME type # and the value is a proc. # # original_parsers = ActionDispatch::Request.parameter_parsers # xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} } # new_parsers = original_parsers.merge(xml: xml_parser) # ActionDispatch::Request.parameter_parsers = new_parsers def parameter_parsers=: (untyped parsers) -> untyped end # Returns both GET and POST \parameters in a single hash. def parameters: () -> untyped alias params parameters def path_parameters=: (untyped parameters) -> untyped # Returns a hash with the \parameters used to form the \path of the request. # Returned hash keys are strings: # # {'action' => 'my_action', 'controller' => 'my_controller'} def path_parameters: () -> untyped private def set_binary_encoding: (untyped params, untyped controller, untyped action) -> untyped def binary_params_for?: (untyped controller, untyped action) -> untyped def parse_formatted_parameters: (untyped parsers) { () -> untyped } -> untyped def log_parse_error_once: () -> untyped def params_parsers: () -> untyped end end end module ActionDispatch class RailsMetaStore < Rack::Cache::MetaStore def self.resolve: (untyped uri) -> untyped def initialize: (?untyped store) -> untyped def read: (untyped key) -> untyped def write: (untyped key, untyped value) -> untyped ::Rack::Cache::MetaStore::RAILS: untyped end class RailsEntityStore < Rack::Cache::EntityStore def self.resolve: (untyped uri) -> untyped def initialize: (?untyped store) -> untyped def exist?: (untyped key) -> untyped def open: (untyped key) -> untyped def read: (untyped key) -> untyped def write: (untyped body) -> ::Array[untyped] ::Rack::Cache::EntityStore::RAILS: untyped end end module ActionDispatch class Request include Rack::Request::Helpers include ActionDispatch::Http::Cache::Request include ActionDispatch::Http::MimeNegotiation include ActionDispatch::Http::Parameters include ActionDispatch::Http::FilterParameters include ActionDispatch::Http::URL include ActionDispatch::ContentSecurityPolicy::Request include Rack::Request::Env LOCALHOST: untyped ENV_METHODS: untyped def self.empty: () -> untyped def initialize: (untyped env) -> untyped PASS_NOT_FOUND: untyped def controller_class: () -> untyped def controller_class_for: (untyped name) -> untyped # Returns true if the request has a header matching the given key parameter. # # request.key? :ip_spoofing_check # => true def key?: (untyped key) -> untyped # List of HTTP request methods from the following RFCs: # Hypertext Transfer Protocol -- HTTP/1.1 (https://www.ietf.org/rfc/rfc2616.txt) # HTTP Extensions for Distributed Authoring -- WEBDAV (https://www.ietf.org/rfc/rfc2518.txt) # Versioning Extensions to WebDAV (https://www.ietf.org/rfc/rfc3253.txt) # Ordered Collections Protocol (WebDAV) (https://www.ietf.org/rfc/rfc3648.txt) # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (https://www.ietf.org/rfc/rfc3744.txt) # Web Distributed Authoring and Versioning (WebDAV) SEARCH (https://www.ietf.org/rfc/rfc5323.txt) # Calendar Extensions to WebDAV (https://www.ietf.org/rfc/rfc4791.txt) # PATCH Method for HTTP (https://www.ietf.org/rfc/rfc5789.txt) RFC2616: ::Array[untyped] RFC2518: ::Array[untyped] RFC3253: ::Array[untyped] RFC3648: ::Array[untyped] RFC3744: ::Array[untyped] RFC5323: ::Array[untyped] RFC4791: ::Array[untyped] RFC5789: ::Array[untyped] HTTP_METHODS: untyped HTTP_METHOD_LOOKUP: ::Hash[untyped, untyped] # Returns the HTTP \method that the application should see. # In the case where the \method was overridden by a middleware # (for instance, if a HEAD request was converted to a GET, # or if a _method parameter was used to determine the \method # the application should use), this \method returns the overridden # value, not the original. def request_method: () -> untyped def routes: () -> untyped def routes=: (untyped routes) -> untyped def engine_script_name: (untyped _routes) -> untyped def engine_script_name=: (untyped name) -> untyped def request_method=: (untyped request_method) -> untyped def controller_instance: () -> untyped def controller_instance=: (untyped controller) -> untyped def http_auth_salt: () -> untyped def show_exceptions?: () -> untyped # Returns a symbol form of the #request_method. def request_method_symbol: () -> untyped # Returns the original value of the environment's REQUEST_METHOD, # even if it was overridden by middleware. See #request_method for # more information. def method: () -> untyped # Returns a symbol form of the #method. def method_symbol: () -> untyped # Provides access to the request's HTTP headers, for example: # # request.headers["Content-Type"] # => "text/plain" def headers: () -> untyped # Early Hints is an HTTP/2 status code that indicates hints to help a client start # making preparations for processing the final response. # # If the env contains +rack.early_hints+ then the server accepts HTTP2 push for Link headers. # # The +send_early_hints+ method accepts a hash of links as follows: # # send_early_hints("Link" => "; rel=preload; as=style\n; rel=preload") # # If you are using +javascript_include_tag+ or +stylesheet_link_tag+ the # Early Hints headers are included by default if supported. def send_early_hints: (untyped links) -> (nil | untyped) # Returns a +String+ with the last requested path including their params. # # # get '/foo' # request.original_fullpath # => '/foo' # # # get '/foo?bar' # request.original_fullpath # => '/foo?bar' def original_fullpath: () -> untyped # Returns the +String+ full path including params of the last URL requested. # # # get "/articles" # request.fullpath # => "/articles" # # # get "/articles?page=2" # request.fullpath # => "/articles?page=2" def fullpath: () -> untyped # Returns the original request URL as a +String+. # # # get "/articles?page=2" # request.original_url # => "http://www.example.com/articles?page=2" def original_url: () -> untyped # The +String+ MIME type of the request. # # # get "/articles" # request.media_type # => "application/x-www-form-urlencoded" def media_type: () -> untyped # Returns the content length of the request as an integer. def content_length: () -> untyped # Returns true if the "X-Requested-With" header contains "XMLHttpRequest" # (case-insensitive), which may need to be manually added depending on the # choice of JavaScript libraries and frameworks. def xml_http_request?: () -> untyped alias xhr? xml_http_request? # Returns the IP address of client as a +String+. def ip: () -> untyped # Returns the IP address of client as a +String+, # usually set by the RemoteIp middleware. def remote_ip: () -> untyped def remote_ip=: (untyped remote_ip) -> untyped ACTION_DISPATCH_REQUEST_ID: ::String # Returns the unique request id, which is based on either the X-Request-Id header that can # be generated by a firewall, load balancer, or web server or by the RequestId middleware # (which sets the action_dispatch.request_id environment variable). # # This unique ID is useful for tracing a request from end-to-end as part of logging or debugging. # This relies on the Rack variable set by the ActionDispatch::RequestId middleware. def request_id: () -> untyped def request_id=: (untyped id) -> untyped alias uuid request_id # Returns the lowercase name of the HTTP server software. def server_software: () -> untyped # Read the request \body. This is useful for web services that need to # work with raw requests directly. def raw_post: () -> untyped # The request body is an IO input stream. If the RAW_POST_DATA environment # variable is already set, wrap it in a StringIO. def body: () -> untyped # Determine whether the request body contains form-data by checking # the request Content-Type for one of the media-types: # "application/x-www-form-urlencoded" or "multipart/form-data". The # list of form-data media types can be modified through the # +FORM_DATA_MEDIA_TYPES+ array. # # A request body is not assumed to contain form-data when no # Content-Type header is provided and the request_method is POST. def form_data?: () -> untyped def body_stream: () -> untyped # TODO This should be broken apart into AD::Request::Session and probably # be included by the session middleware. def reset_session: () -> untyped def session=: (untyped session) -> untyped def session_options=: (untyped options) -> untyped # Override Rack's GET method to support indifferent access. def GET: () -> untyped alias query_parameters GET # Override Rack's POST method to support indifferent access. def POST: () -> untyped alias request_parameters POST # Returns the authorization header regardless of whether it was specified directly or through one of the # proxy alternatives. def authorization: () -> untyped # True if the request came from localhost, 127.0.0.1, or ::1. def local?: () -> untyped def request_parameters=: (untyped params) -> untyped def logger: () -> untyped def commit_flash: () -> nil def ssl?: () -> untyped private def check_method: (untyped name) -> untyped end end module ActionDispatch # :nodoc: # Represents an HTTP response generated by a controller action. Use it to # retrieve the current state of the response, or customize the response. It can # either represent a real HTTP response (i.e. one that is meant to be sent # back to the web browser) or a TestResponse (i.e. one that is generated # from integration tests). # # \Response is mostly a Ruby on \Rails framework implementation detail, and # should never be used directly in controllers. Controllers should use the # methods defined in ActionController::Base instead. For example, if you want # to set the HTTP response's content MIME type, then use # ActionControllerBase#headers instead of Response#headers. # # Nevertheless, integration tests may want to inspect controller responses in # more detail, and that's when \Response can be useful for application # developers. Integration test methods such as # ActionDispatch::Integration::Session#get and # ActionDispatch::Integration::Session#post return objects of type # TestResponse (which are of course also of type \Response). # # For example, the following demo integration test prints the body of the # controller response to the console: # # class DemoControllerTest < ActionDispatch::IntegrationTest # def test_print_root_path_to_console # get('/') # puts response.body # end # end class Response class Header # :nodoc: def initialize: (untyped response, untyped header) -> untyped def []=: (untyped k, untyped v) -> untyped def merge: (untyped other) -> untyped def to_hash: () -> untyped end # The request that the response is responding to. attr_accessor request: untyped # The HTTP status code. attr_reader status: untyped # Get headers for this response. attr_reader header: untyped alias headers header def each: () { () -> untyped } -> untyped CONTENT_TYPE: ::String SET_COOKIE: ::String LOCATION: ::String NO_CONTENT_CODES: ::Array[untyped] include Rack::Response::Helpers # Aliasing these off because AD::Http::Cache::Response defines them. alias _cache_control cache_control alias _cache_control= cache_control= include ActionDispatch::Http::FilterRedirect include ActionDispatch::Http::Cache::Response include MonitorMixin class Buffer # :nodoc: def initialize: (untyped response, untyped buf) -> untyped def body: () -> untyped def write: (untyped string) -> untyped def each: () { (untyped) -> untyped } -> untyped def abort: () -> nil def close: () -> untyped def closed?: () -> untyped private def each_chunk: () { () -> untyped } -> untyped end def self.create: (?::Integer status, ?::Hash[untyped, untyped] header, ?untyped body, ?default_headers: untyped default_headers) -> untyped def self.merge_default_headers: (untyped original, untyped default) -> untyped # The underlying body, as a streamable object. attr_reader stream: untyped def initialize: (?::Integer status, ?::Hash[untyped, untyped] header, ?untyped body) { (untyped) -> untyped } -> untyped def has_header?: (untyped key) -> untyped def get_header: (untyped key) -> untyped def set_header: (untyped key, untyped v) -> untyped def delete_header: (untyped key) -> untyped def await_commit: () -> untyped def await_sent: () -> untyped def commit!: () -> untyped def sending!: () -> untyped def sent!: () -> untyped def sending?: () -> untyped def committed?: () -> untyped def sent?: () -> untyped # Sets the HTTP status code. def status=: (untyped status) -> untyped # Sets the HTTP response's content MIME type. For example, in the controller # you could write this: # # response.content_type = "text/plain" # # If a character set has been defined for this response (see charset=) then # the character set information will also be included in the content type # information. def content_type=: (untyped content_type) -> (nil | untyped) # Content type of response. def content_type: () -> untyped # Media type of response. def media_type: () -> untyped def sending_file=: (untyped v) -> untyped # Sets the HTTP character set. In case of +nil+ parameter # it sets the charset to +default_charset+. # # response.charset = 'utf-16' # => 'utf-16' # response.charset = nil # => 'utf-8' def charset=: (untyped charset) -> untyped # The charset of the response. HTML wants to know the encoding of the # content you're giving them, so we need to send that along. def charset: () -> untyped # The response code of the request. def response_code: () -> untyped # Returns a string to ensure compatibility with Net::HTTPResponse. def code: () -> untyped # Returns the corresponding message for the current HTTP status code: # # response.status = 200 # response.message # => "OK" # # response.status = 404 # response.message # => "Not Found" # def message: () -> untyped alias status_message message # Returns the content of the response as a string. This contains the contents # of any calls to render. def body: () -> untyped def write: (untyped string) -> untyped # Allows you to manually set or override the response body. def body=: (untyped body) -> untyped class FileBody # Avoid having to pass an open file handle as the response body. # Rack::Sendfile will usually intercept the response and uses # the path directly, so there is no reason to open the file. # nodoc: attr_reader to_path: untyped def initialize: (untyped path) -> untyped def body: () -> untyped # Stream the file's contents if Rack::Sendfile isn't present. def each: () { (untyped) -> untyped } -> untyped end # Send the file stored at +path+ as the response body. def send_file: (untyped path) -> untyped def reset_body!: () -> untyped def body_parts: () -> untyped # The location header we'll be responding with. alias redirect_url location def close: () -> untyped def abort: () -> untyped # Turns the Response into a Rack-compatible array of the status, headers, # and body. Allows explicit splatting: # # status, headers, body = *response def to_a: () -> untyped alias prepare! to_a # Returns the response cookies, converted to a Hash of (name => value) pairs # # assert_equal 'AuthorOfNewPage', r.cookies['author'] def cookies: () -> untyped private class ContentTypeHeader[T] < ::Struct[T] attr_accessor mime_type(): untyped attr_accessor charset(): untyped end NullContentTypeHeader: untyped CONTENT_TYPE_PARSER: untyped def parse_content_type: (untyped content_type) -> untyped # Small internal convenience method to get the parsed version of the current # content type header. def parsed_content_type_header: () -> untyped def set_content_type: (untyped content_type, untyped charset) -> untyped def before_committed: () -> (nil | untyped) def before_sending: () -> untyped def build_buffer: (untyped response, untyped body) -> Buffer def munge_body_object: (untyped body) -> untyped def assign_default_content_type_and_charset!: () -> (nil | untyped) class RackBody def initialize: (untyped response) -> untyped def each: (*untyped args) { () -> untyped } -> untyped def close: () -> untyped def body: () -> untyped def respond_to?: (untyped method, ?bool include_private) -> untyped def to_path: () -> untyped def to_ary: () -> nil end def handle_no_content!: () -> untyped def rack_response: (untyped status, untyped header) -> untyped end end module ActionDispatch module Http # Models uploaded files. # # The actual file is accessible via the +tempfile+ accessor, though some # of its interface is available directly for convenience. # # Uploaded files are temporary files whose lifespan is one request. When # the object is finalized Ruby unlinks the file, so there is no need to # clean them with a separate maintenance task. class UploadedFile # The basename of the file in the client. attr_accessor original_filename: untyped # A string with the MIME type of the file. attr_accessor content_type: untyped # A +Tempfile+ object with the actual uploaded file. Note that some of # its interface is available directly. attr_accessor tempfile: untyped # A string with the headers of the multipart request. attr_accessor headers: untyped def initialize: (untyped hash) -> untyped # Shortcut for +tempfile.read+. def read: (?untyped? length, ?untyped? buffer) -> untyped # Shortcut for +tempfile.open+. def open: () -> untyped # Shortcut for +tempfile.close+. def close: (?bool unlink_now) -> untyped # Shortcut for +tempfile.path+. def path: () -> untyped # Shortcut for +tempfile.to_path+. def to_path: () -> untyped # Shortcut for +tempfile.rewind+. def rewind: () -> untyped # Shortcut for +tempfile.size+. def size: () -> untyped # Shortcut for +tempfile.eof?+. def eof?: () -> untyped def to_io: () -> untyped end end end module ActionDispatch module Http module URL IP_HOST_REGEXP: untyped HOST_REGEXP: untyped PROTOCOL_REGEXP: untyped # Returns the domain part of a host given the domain level. # # # Top-level domain example # extract_domain('www.example.com', 1) # => "example.com" # # Second-level domain example # extract_domain('dev.www.example.co.uk', 2) # => "example.co.uk" def self.extract_domain: (untyped host, untyped tld_length) -> untyped # Returns the subdomains of a host as an Array given the domain level. # # # Top-level domain example # extract_subdomains('www.example.com', 1) # => ["www"] # # Second-level domain example # extract_subdomains('dev.www.example.co.uk', 2) # => ["dev", "www"] def self.extract_subdomains: (untyped host, untyped tld_length) -> untyped # Returns the subdomains of a host as a String given the domain level. # # # Top-level domain example # extract_subdomain('www.example.com', 1) # => "www" # # Second-level domain example # extract_subdomain('dev.www.example.co.uk', 2) # => "dev.www" def self.extract_subdomain: (untyped host, untyped tld_length) -> untyped def self.url_for: (untyped options) -> untyped def self.full_url_for: (untyped options) -> untyped def self.path_for: (untyped options) -> untyped private def self.add_params: (untyped path, untyped params) -> untyped def self.add_anchor: (untyped path, untyped anchor) -> untyped def self.extract_domain_from: (untyped host, untyped tld_length) -> untyped def self.extract_subdomains_from: (untyped host, untyped tld_length) -> untyped def self.add_trailing_slash: (untyped path) -> untyped def self.build_host_url: (untyped host, untyped port, untyped protocol, untyped options, untyped path) -> untyped def self.named_host?: (untyped host) -> untyped def self.normalize_protocol: (untyped protocol) -> untyped def self.normalize_host: (untyped _host, untyped options) -> untyped def self.normalize_port: (untyped port, untyped protocol) { (untyped) -> untyped } -> (nil | untyped) public def initialize: () -> untyped # Returns the complete URL used for this request. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.url # => "http://example.com" def url: () -> untyped # Returns 'https://' if this is an SSL request and 'http://' otherwise. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.protocol # => "http://" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on' # req.protocol # => "https://" def protocol: () -> untyped # Returns the \host and port for this request, such as "example.com:8080". # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.raw_host_with_port # => "example.com" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.raw_host_with_port # => "example.com:80" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.raw_host_with_port # => "example.com:8080" def raw_host_with_port: () -> untyped # Returns the host for this request, such as "example.com". # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.host # => "example.com" def host: () -> untyped # Returns a \host:\port string for this request, such as "example.com" or # "example.com:8080". Port is only included if it is not a default port # (80 or 443) # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.host_with_port # => "example.com" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.host_with_port # => "example.com" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.host_with_port # => "example.com:8080" def host_with_port: () -> ::String # Returns the port number of this request as an integer. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.port # => 80 # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.port # => 8080 def port: () -> untyped # Returns the standard \port number for this request's protocol. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.standard_port # => 80 def standard_port: () -> untyped # Returns whether this request is using the standard port # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.standard_port? # => true # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.standard_port? # => false def standard_port?: () -> untyped # Returns a number \port suffix like 8080 if the \port number of this request # is not the default HTTP \port 80 or HTTPS \port 443. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.optional_port # => nil # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.optional_port # => 8080 def optional_port: () -> untyped # Returns a string \port suffix, including colon, like ":8080" if the \port # number of this request is not the default HTTP \port 80 or HTTPS \port 443. # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.port_string # => "" # # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.port_string # => ":8080" def port_string: () -> untyped # Returns the requested port, such as 8080, based on SERVER_PORT # # req = ActionDispatch::Request.new 'SERVER_PORT' => '80' # req.server_port # => 80 # # req = ActionDispatch::Request.new 'SERVER_PORT' => '8080' # req.server_port # => 8080 def server_port: () -> untyped # Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify # a different tld_length, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk". def domain: (?untyped tld_length) -> untyped # Returns all the \subdomains as an array, so ["dev", "www"] would be # returned for "dev.www.rubyonrails.org". You can specify a different tld_length, # such as 2 to catch ["www"] instead of ["www", "rubyonrails"] # in "www.rubyonrails.co.uk". def subdomains: (?untyped tld_length) -> untyped # Returns all the \subdomains as a string, so "dev.www" would be # returned for "dev.www.rubyonrails.org". You can specify a different tld_length, # such as 2 to catch "www" instead of "www.rubyonrails" # in "www.rubyonrails.co.uk". def subdomain: (?untyped tld_length) -> untyped end end end module ActionDispatch # :stopdoc: module Journey # The Formatter class is used for formatting URLs. For example, parameters # passed to +url_for+ in Rails will eventually call Formatter#generate. class Formatter attr_reader routes: untyped def initialize: (untyped routes) -> untyped def generate: (untyped name, untyped options, untyped path_parameters, ?untyped? parameterize) -> (::Array[untyped] | untyped) def clear: () -> untyped private def extract_parameterized_parts: (untyped route, untyped options, untyped recall, ?untyped? parameterize) -> untyped def named_routes: () -> untyped def match_route: (untyped name, untyped options) { (untyped) -> untyped } -> untyped def non_recursive: (untyped cache, untyped options) -> untyped module RegexCaseComparator DEFAULT_INPUT: untyped DEFAULT_REGEX: untyped def self.===: (untyped regex) -> untyped end # Returns an array populated with missing keys if any are present. def missing_keys: (untyped route, untyped parts) -> untyped def possibles: (untyped cache, untyped options, ?::Integer depth) -> untyped def build_cache: () -> untyped def cache: () -> untyped end end end module ActionDispatch module Journey module GTG class Builder # :nodoc: # :nodoc: # :nodoc: DUMMY: untyped attr_reader root: untyped attr_reader ast: untyped attr_reader endpoints: untyped def initialize: (untyped root) -> untyped def transition_table: () -> untyped def nullable?: (untyped node) -> untyped def firstpos: (untyped node) -> untyped def lastpos: (untyped node) -> untyped def followpos: (untyped node) -> untyped private def followpos_table: () -> untyped def build_followpos: () -> untyped def symbol: (untyped edge) -> untyped end end end end module ActionDispatch module Journey module GTG class MatchData # :nodoc: # :nodoc: # :nodoc: attr_reader memos: untyped def initialize: (untyped memos) -> untyped end class Simulator # :nodoc: attr_reader tt: untyped def initialize: (untyped transition_table) -> untyped def memos: (untyped string) { () -> untyped } -> untyped end end end end module ActionDispatch module Journey module GTG class TransitionTable # :nodoc: # :nodoc: # :nodoc: include Journey::NFA::Dot attr_reader memos: untyped def initialize: () -> untyped def add_accepting: (untyped state) -> untyped def accepting_states: () -> untyped def accepting?: (untyped state) -> untyped def add_memo: (untyped idx, untyped memo) -> untyped def memo: (untyped idx) -> untyped def eclosure: (untyped t) -> untyped def move: (untyped t, untyped a) -> (::Array[untyped] | untyped) def as_json: (?untyped? options) -> { regexp_states: untyped, string_states: untyped, accepting: untyped } def to_svg: () -> untyped def visualizer: (untyped paths, ?::String title) -> untyped def []=: (untyped from, untyped to, untyped sym) -> untyped def states: () -> untyped def transitions: () -> untyped private def states_hash_for: (untyped sym) -> untyped end end end end module ActionDispatch module Journey module NFA class Visitor < Visitors::Visitor # :nodoc: # :nodoc: # :nodoc: def initialize: (untyped tt) -> untyped def visit_CAT: (untyped node) -> ::Array[untyped] def visit_GROUP: (untyped node) -> ::Array[untyped] def visit_OR: (untyped node) -> ::Array[untyped] def terminal: (untyped node) -> ::Array[untyped] end class Builder # :nodoc: def initialize: (untyped ast) -> untyped def transition_table: () -> untyped end end end end module ActionDispatch module Journey module NFA module Dot # :nodoc: # :nodoc: # :nodoc: def to_dot: () -> ::String end end end end module ActionDispatch module Journey module NFA class MatchData # :nodoc: # :nodoc: # :nodoc: attr_reader memos: untyped def initialize: (untyped memos) -> untyped end class Simulator # :nodoc: attr_reader tt: untyped def initialize: (untyped transition_table) -> untyped def simulate: (untyped string) -> (nil | MatchData) alias =~ simulate alias match simulate end end end end module ActionDispatch module Journey module NFA class TransitionTable # :nodoc: # :nodoc: # :nodoc: include Journey::NFA::Dot attr_accessor accepting: untyped attr_reader memos: untyped def initialize: () -> untyped def accepting?: (untyped state) -> untyped def accepting_states: () -> ::Array[untyped] def add_memo: (untyped idx, untyped memo) -> untyped def memo: (untyped idx) -> untyped def []=: (untyped i, untyped f, untyped s) -> untyped def merge: (untyped left, untyped right) -> untyped def states: () -> untyped # Returns set of NFA states to which there is a transition on ast symbol # +a+ from some state +s+ in +t+. def following_states: (untyped t, untyped a) -> untyped # Returns set of NFA states to which there is a transition on ast symbol # +a+ from some state +s+ in +t+. def move: (untyped t, untyped a) -> untyped def alphabet: () -> untyped # Returns a set of NFA states reachable from some NFA state +s+ in set # +t+ on nil-transitions alone. def eclosure: (untyped t) -> untyped def transitions: () -> untyped private def inverted: () -> untyped end end end end module ActionDispatch module Journey module Nodes class Node # :nodoc: # :nodoc: # :nodoc: include Enumerable[untyped] attr_accessor left: untyped attr_accessor memo: untyped def initialize: (untyped left) -> untyped def each: () { (untyped) -> untyped } -> untyped def to_s: () -> untyped def to_dot: () -> untyped def to_sym: () -> untyped def name: () -> untyped def type: () -> untyped def symbol?: () -> ::FalseClass def literal?: () -> ::FalseClass def terminal?: () -> ::FalseClass def star?: () -> ::FalseClass def cat?: () -> ::FalseClass def group?: () -> ::FalseClass end class Terminal < Node # :nodoc: alias symbol left def terminal?: () -> ::TrueClass end class Literal < Terminal # :nodoc: def literal?: () -> ::TrueClass def type: () -> :LITERAL end class Dummy < Literal # :nodoc: def initialize: (?untyped x) -> untyped def literal?: () -> ::FalseClass end class Slash < Terminal # :nodoc: def type: () -> :SLASH end class Dot < Terminal # :nodoc: def type: () -> :DOT end class Symbol < Terminal # :nodoc: attr_accessor regexp: untyped alias symbol regexp attr_reader name: untyped DEFAULT_EXP: untyped def initialize: (untyped left) -> untyped def default_regexp?: () -> untyped def type: () -> :SYMBOL def symbol?: () -> ::TrueClass end class Unary < Node # :nodoc: def children: () -> ::Array[untyped] end class Group < Unary # :nodoc: def type: () -> :GROUP def group?: () -> ::TrueClass end class Star < Unary # :nodoc: def star?: () -> ::TrueClass def type: () -> :STAR def name: () -> untyped end class Binary < Node # :nodoc: attr_accessor right: untyped def initialize: (untyped left, untyped right) -> untyped def children: () -> ::Array[untyped] end class Cat < Binary # :nodoc: def cat?: () -> ::TrueClass def type: () -> :CAT end class Or < Node # :nodoc: attr_reader children: untyped def initialize: (untyped children) -> untyped def type: () -> :OR end end end end module ActionDispatch module Journey class Parser < Racc::Parser Racc_arg: ::Array[untyped] Racc_token_to_s_table: ::Array[untyped] Racc_debug_parser: bool def _reduce_1: (untyped val, untyped _values) -> Nodes::Cat def _reduce_2: (untyped val, untyped _values) -> untyped def _reduce_7: (untyped val, untyped _values) -> Nodes::Group def _reduce_8: (untyped val, untyped _values) -> Nodes::Or def _reduce_9: (untyped val, untyped _values) -> Nodes::Or def _reduce_10: (untyped val, untyped _values) -> Nodes::Star def _reduce_15: (untyped val, untyped _values) -> Nodes::Slash def _reduce_16: (untyped val, untyped _values) -> Nodes::Symbol def _reduce_17: (untyped val, untyped _values) -> Nodes::Literal def _reduce_18: (untyped val, untyped _values) -> Nodes::Dot def _reduce_none: (untyped val, untyped _values) -> untyped end end end module ActionDispatch # :stopdoc: module Journey class Parser < Racc::Parser include Journey::Nodes def self.parse: (untyped string) -> untyped def initialize: () -> untyped def parse: (untyped string) -> untyped def next_token: () -> untyped end end end module ActionDispatch module Journey module Path class Pattern # :nodoc: # :nodoc: # :nodoc: attr_reader spec: untyped # :nodoc: # :nodoc: # :nodoc: attr_reader requirements: untyped # :nodoc: # :nodoc: # :nodoc: attr_reader anchored: untyped def self.from_string: (untyped string) -> untyped def self.build: (untyped path, untyped requirements, untyped separators, untyped anchored) -> untyped def initialize: (untyped ast, untyped requirements, untyped separators, untyped anchored) -> untyped def build_formatter: () -> untyped def eager_load!: () -> nil def ast: () -> untyped def names: () -> untyped def required_names: () -> untyped def optional_names: () -> untyped class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc: def initialize: (untyped separator, untyped matchers) -> untyped def accept: (untyped node) -> ::Regexp def visit_CAT: (untyped node) -> untyped def visit_SYMBOL: (untyped node) -> (untyped | ::String) def visit_GROUP: (untyped node) -> ::String def visit_LITERAL: (untyped node) -> untyped alias visit_DOT visit_LITERAL def visit_SLASH: (untyped node) -> untyped def visit_STAR: (untyped node) -> ::String def visit_OR: (untyped node) -> ::String end class UnanchoredRegexp < AnchoredRegexp # :nodoc: def accept: (untyped node) -> untyped end class MatchData # :nodoc: attr_reader names: untyped def initialize: (untyped names, untyped offsets, untyped match) -> untyped def captures: () -> untyped def named_captures: () -> untyped def []: (untyped x) -> untyped def length: () -> untyped def post_match: () -> untyped def to_s: () -> untyped end def match: (untyped other) -> (nil | MatchData) alias =~ match def source: () -> untyped def to_regexp: () -> untyped private def regexp_visitor: () -> untyped def offsets: () -> untyped end end end end module ActionDispatch # :stopdoc: module Journey class Route attr_reader app: untyped attr_reader path: untyped attr_reader defaults: untyped attr_reader name: untyped attr_reader precedence: untyped attr_reader constraints: untyped attr_reader internal: untyped attr_reader scope_options: untyped alias conditions constraints module VerbMatchers VERBS: ::Array[untyped] class Unknown attr_reader verb: untyped def initialize: (untyped verb) -> untyped def call: (untyped request) -> untyped end class All def self.call: (untyped _) -> ::TrueClass def self.verb: () -> ::String end VERB_TO_CLASS: untyped end def self.verb_matcher: (untyped verb) -> untyped def self.build: (untyped name, untyped app, untyped path, untyped constraints, untyped required_defaults, untyped defaults) -> untyped # # +path+ is a path constraint. # +constraints+ is a hash of constraints to be applied to this route. def initialize: (untyped name, untyped app, untyped path, untyped constraints, untyped required_defaults, untyped defaults, untyped request_method_match, untyped precedence, untyped scope_options, ?bool internal) -> untyped def eager_load!: () -> nil def ast: () -> untyped # Needed for `rails routes`. Picks up succinctly defined requirements # for a route, for example route # # get 'photo/:id', :controller => 'photos', :action => 'show', # :id => /[A-Z]\d{5}/ # # will have {:controller=>"photos", :action=>"show", :id=>/[A-Z]\d{5}/} # as requirements. def requirements: () -> untyped def segments: () -> untyped def required_keys: () -> untyped def score: (untyped supplied_keys) -> (-1 | untyped) def parts: () -> untyped alias segment_keys parts def format: (untyped path_options) -> untyped def required_parts: () -> untyped def required_default?: (untyped key) -> untyped def required_defaults: () -> untyped def glob?: () -> untyped def dispatcher?: () -> untyped def matches?: (untyped request) -> untyped def ip: () -> untyped def requires_matching_verb?: () -> untyped def verb: () -> untyped private def verbs: () -> untyped def match_verb: (untyped request) -> untyped end end end module ActionDispatch module Journey class Router class Utils # :nodoc: # :nodoc: # :nodoc: # Normalizes URI path. # # Strips off trailing slash and ensures there is a leading slash. # Also converts downcase URL encoded string to uppercase. # # normalize_path("/foo") # => "/foo" # normalize_path("/foo/") # => "/foo" # normalize_path("foo") # => "/foo" # normalize_path("") # => "/" # normalize_path("/%ab") # => "/%AB" def self.normalize_path: (untyped path) -> untyped class UriEncoder # URI path and fragment escaping # https://tools.ietf.org/html/rfc3986 # :nodoc: ENCODE: ::String US_ASCII: untyped UTF_8: untyped EMPTY: untyped DEC2HEX: untyped ALPHA: ::String DIGIT: ::String UNRESERVED: ::String SUB_DELIMS: ::String ESCAPED: untyped FRAGMENT: untyped SEGMENT: untyped PATH: untyped def escape_fragment: (untyped fragment) -> untyped def escape_path: (untyped path) -> untyped def escape_segment: (untyped segment) -> untyped def unescape_uri: (untyped uri) -> untyped private def escape: (untyped component, untyped pattern) -> untyped def percent_encode: (untyped unsafe) -> untyped end ENCODER: untyped def self.escape_path: (untyped path) -> untyped def self.escape_segment: (untyped segment) -> untyped def self.escape_fragment: (untyped fragment) -> untyped # Replaces any escaped sequences with their unescaped representations. # # uri = "/topics?title=Ruby%20on%20Rails" # unescape_uri(uri) #=> "/topics?title=Ruby on Rails" def self.unescape_uri: (untyped uri) -> untyped end end end end module ActionDispatch module Journey class Router # :nodoc: # :nodoc: attr_accessor routes: untyped def initialize: (untyped routes) -> untyped def eager_load!: () -> nil def serve: (untyped req) -> (::Array[untyped] | ::Array[404 | ::Hash[::String, "pass"] | ::Array["Not Found"]]) def recognize: (untyped rails_req) { (untyped, untyped) -> untyped } -> untyped def visualizer: () -> untyped private def partitioned_routes: () -> untyped def ast: () -> untyped def simulator: () -> untyped def custom_routes: () -> untyped def filter_routes: (untyped path) -> (::Array[untyped] | untyped) def find_routes: (untyped req) -> untyped def match_head_routes: (untyped routes, untyped req) -> untyped def match_routes: (untyped routes, untyped req) -> untyped end end end module ActionDispatch module Journey class Routes # :nodoc: # The Routing table. Contains all routes for a system. Routes can be # added to the table by calling Routes#add_route. # :nodoc: include Enumerable[untyped] attr_reader routes: untyped attr_reader custom_routes: untyped attr_reader anchored_routes: untyped def initialize: () -> untyped def empty?: () -> untyped def length: () -> untyped alias size length def last: () -> untyped def each: () { (untyped) -> untyped } -> untyped def clear: () -> untyped def partition_route: (untyped route) -> untyped def ast: () -> untyped def simulator: () -> untyped def add_route: (untyped name, untyped mapping) -> untyped private def clear_cache!: () -> untyped end end end module ActionDispatch module Journey class Scanner # :nodoc: # :nodoc: def initialize: () -> untyped def scan_setup: (untyped str) -> untyped def eos?: () -> untyped def pos: () -> untyped def pre_match: () -> untyped def next_token: () -> (nil | untyped) private # takes advantage of String @- deduping capabilities in Ruby 2.5 upwards # see: https://bugs.ruby-lang.org/issues/13077 def dedup_scan: (untyped regex) -> untyped def scan: () -> untyped end end end module ActionDispatch # :stopdoc: module Journey class Format ESCAPE_PATH: untyped ESCAPE_SEGMENT: untyped class Parameter[T] < ::Struct[T] attr_accessor name(): untyped attr_accessor escaper(): untyped def escape: (untyped value) -> untyped end def self.required_path: (untyped symbol) -> Parameter[untyped] def self.required_segment: (untyped symbol) -> Parameter[untyped] def initialize: (untyped parts) -> untyped def evaluate: (untyped hash) -> (::String | untyped) end module Visitors class Visitor # :nodoc: # :nodoc: DISPATCH_CACHE: ::Hash[untyped, untyped] def accept: (untyped node) -> untyped private def visit: (untyped node) -> untyped def binary: (untyped node) -> untyped def visit_CAT: (untyped n) -> untyped def nary: (untyped node) -> untyped def visit_OR: (untyped n) -> untyped def unary: (untyped node) -> untyped def visit_GROUP: (untyped n) -> untyped def visit_STAR: (untyped n) -> untyped def terminal: (untyped node) -> nil def visit_LITERAL: (untyped n) -> untyped def visit_SYMBOL: (untyped n) -> untyped def visit_SLASH: (untyped n) -> untyped def visit_DOT: (untyped n) -> untyped end class FunctionalVisitor # :nodoc: DISPATCH_CACHE: ::Hash[untyped, untyped] def accept: (untyped node, untyped seed) -> untyped def visit: (untyped node, untyped seed) -> untyped def binary: (untyped node, untyped seed) -> untyped def visit_CAT: (untyped n, untyped seed) -> untyped def nary: (untyped node, untyped seed) -> untyped def visit_OR: (untyped n, untyped seed) -> untyped def unary: (untyped node, untyped seed) -> untyped def visit_GROUP: (untyped n, untyped seed) -> untyped def visit_STAR: (untyped n, untyped seed) -> untyped def terminal: (untyped node, untyped seed) -> untyped def visit_LITERAL: (untyped n, untyped seed) -> untyped def visit_SYMBOL: (untyped n, untyped seed) -> untyped def visit_SLASH: (untyped n, untyped seed) -> untyped def visit_DOT: (untyped n, untyped seed) -> untyped end class FormatBuilder < Visitor # :nodoc: def accept: (untyped node) -> Journey::Format def terminal: (untyped node) -> ::Array[untyped] def binary: (untyped node) -> untyped def visit_GROUP: (untyped n) -> ::Array[Journey::Format] def visit_STAR: (untyped n) -> ::Array[untyped] def visit_SYMBOL: (untyped n) -> untyped end class Each < FunctionalVisitor # Loop through the requirements AST. # :nodoc: def visit: (untyped node, untyped block) -> untyped INSTANCE: untyped end class String < FunctionalVisitor private def binary: (untyped node, untyped seed) -> untyped def nary: (untyped node, untyped seed) -> untyped def terminal: (untyped node, untyped seed) -> untyped def visit_GROUP: (untyped node, untyped seed) -> untyped INSTANCE: untyped end class Dot < FunctionalVisitor # :nodoc: def initialize: () -> untyped def accept: (untyped node, ?::Array[untyped] seed) -> ::String private def binary: (untyped node, untyped seed) -> untyped def nary: (untyped node, untyped seed) -> untyped def unary: (untyped node, untyped seed) -> untyped def visit_GROUP: (untyped node, untyped seed) -> untyped def visit_CAT: (untyped node, untyped seed) -> untyped def visit_STAR: (untyped node, untyped seed) -> untyped def visit_OR: (untyped node, untyped seed) -> untyped def terminal: (untyped node, untyped seed) -> untyped INSTANCE: untyped end end end end module ActionDispatch class ActionableExceptions def initialize: (untyped app) -> untyped def call: (untyped env) -> untyped private def actionable_request?: (untyped request) -> untyped def redirect_to: (untyped location) -> ::Array[302 | ::Hash[::String, ::String | untyped] | ::Array[untyped]] end end module ActionDispatch # Provides callbacks to be executed before and after dispatching the request. class Callbacks include ActiveSupport::Callbacks def self.before: (*untyped args) { () -> untyped } -> untyped def self.after: (*untyped args) { () -> untyped } -> untyped def initialize: (untyped app) -> untyped def call: (untyped env) -> untyped end end module ActionDispatch class Request def cookie_jar: () -> untyped def commit_cookie_jar!: () -> untyped def have_cookie_jar?: () -> untyped def cookie_jar=: (untyped jar) -> untyped def key_generator: () -> untyped def signed_cookie_salt: () -> untyped def encrypted_cookie_salt: () -> untyped def encrypted_signed_cookie_salt: () -> untyped def authenticated_encrypted_cookie_salt: () -> untyped def use_authenticated_cookie_encryption: () -> untyped def encrypted_cookie_cipher: () -> untyped def signed_cookie_digest: () -> untyped def secret_key_base: () -> untyped def cookies_serializer: () -> untyped def cookies_digest: () -> untyped def cookies_rotations: () -> untyped def use_cookies_with_metadata: () -> untyped end # \Cookies are read and written through ActionController#cookies. # # The cookies being read are the ones received along with the request, the cookies # being written will be sent out with the response. Reading a cookie does not get # the cookie object itself back, just the value it holds. # # Examples of writing: # # # Sets a simple session cookie. # # This cookie will be deleted when the user's browser is closed. # cookies[:user_name] = "david" # # # Cookie values are String based. Other data types need to be serialized. # cookies[:lat_lon] = JSON.generate([47.68, -122.37]) # # # Sets a cookie that expires in 1 hour. # cookies[:login] = { value: "XJ-122", expires: 1.hour } # # # Sets a cookie that expires at a specific time. # cookies[:login] = { value: "XJ-122", expires: Time.utc(2020, 10, 15, 5) } # # # Sets a signed cookie, which prevents users from tampering with its value. # # It can be read using the signed method `cookies.signed[:name]` # cookies.signed[:user_id] = current_user.id # # # Sets an encrypted cookie value before sending it to the client which # # prevent users from reading and tampering with its value. # # It can be read using the encrypted method `cookies.encrypted[:name]` # cookies.encrypted[:discount] = 45 # # # Sets a "permanent" cookie (which expires in 20 years from now). # cookies.permanent[:login] = "XJ-122" # # # You can also chain these methods: # cookies.signed.permanent[:login] = "XJ-122" # # Examples of reading: # # cookies[:user_name] # => "david" # cookies.size # => 2 # JSON.parse(cookies[:lat_lon]) # => [47.68, -122.37] # cookies.signed[:login] # => "XJ-122" # cookies.encrypted[:discount] # => 45 # # Example for deleting: # # cookies.delete :user_name # # Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie: # # cookies[:name] = { # value: 'a yummy cookie', # expires: 1.year, # domain: 'domain.com' # } # # cookies.delete(:name, domain: 'domain.com') # # The option symbols for setting cookies are: # # * :value - The cookie's value. # * :path - The path for which this cookie applies. Defaults to the root # of the application. # * :domain - The domain for which this cookie applies so you can # restrict to the domain level. If you use a schema like www.example.com # and want to share session with user.example.com set :domain # to :all. Make sure to specify the :domain option with # :all or Array again when deleting cookies. # # domain: nil # Does not set cookie domain. (default) # domain: :all # Allow the cookie for the top most level # # domain and subdomains. # domain: %w(.example.com .example.org) # Allow the cookie # # for concrete domain names. # # * :tld_length - When using :domain => :all, this option can be used to explicitly # set the TLD length when using a short (<= 3 character) domain that is being interpreted as part of a TLD. # For example, to share cookies between user1.lvh.me and user2.lvh.me, set :tld_length to 2. # * :expires - The time at which this cookie expires, as a \Time or ActiveSupport::Duration object. # * :secure - Whether this cookie is only transmitted to HTTPS servers. # Default is +false+. # * :httponly - Whether this cookie is accessible via scripting or # only HTTP. Defaults to +false+. class Cookies HTTP_HEADER: ::String GENERATOR_KEY: ::String SIGNED_COOKIE_SALT: ::String ENCRYPTED_COOKIE_SALT: ::String ENCRYPTED_SIGNED_COOKIE_SALT: ::String AUTHENTICATED_ENCRYPTED_COOKIE_SALT: ::String USE_AUTHENTICATED_COOKIE_ENCRYPTION: ::String ENCRYPTED_COOKIE_CIPHER: ::String SIGNED_COOKIE_DIGEST: ::String SECRET_KEY_BASE: ::String COOKIES_SERIALIZER: ::String COOKIES_DIGEST: ::String COOKIES_ROTATIONS: ::String USE_COOKIES_WITH_METADATA: ::String # Cookies can typically store 4096 bytes. MAX_COOKIE_SIZE: ::Integer # Raised when storing more than 4K of session data. CookieOverflow: untyped # Include in a cookie jar to allow chaining, e.g. cookies.permanent.signed. module ChainedCookieJars # Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example: # # cookies.permanent[:prefers_open_id] = true # # => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT # # This jar is only meant for writing. You'll read permanent cookies through the regular accessor. # # This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples: # # cookies.permanent.signed[:remember_me] = current_user.id # # => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT def permanent: () -> untyped # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed # cookie was tampered with by the user (or a 3rd party), +nil+ will be returned. # # This jar requires that you set a suitable secret for the verification on your app's +secret_key_base+. # # Example: # # cookies.signed[:discount] = 45 # # => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/ # # cookies.signed[:discount] # => 45 def signed: () -> untyped # Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read. # If the cookie was tampered with by the user (or a 3rd party), +nil+ will be returned. # # If +config.action_dispatch.encrypted_cookie_salt+ and +config.action_dispatch.encrypted_signed_cookie_salt+ # are both set, legacy cookies encrypted with HMAC AES-256-CBC will be transparently upgraded. # # This jar requires that you set a suitable secret for the verification on your app's +secret_key_base+. # # Example: # # cookies.encrypted[:discount] = 45 # # => Set-Cookie: discount=DIQ7fw==--K3n//8vvnSbGq9dA--7Xh91HfLpwzbj1czhBiwOg==; path=/ # # cookies.encrypted[:discount] # => 45 def encrypted: () -> untyped # Returns the +signed+ or +encrypted+ jar, preferring +encrypted+ if +secret_key_base+ is set. # Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores. def signed_or_encrypted: () -> untyped private def upgrade_legacy_hmac_aes_cbc_cookies?: () -> untyped def encrypted_cookie_cipher: () -> untyped def signed_cookie_digest: () -> untyped end class CookieJar # nodoc: include Enumerable[untyped] # nodoc: include ChainedCookieJars # This regular expression is used to split the levels of a domain. # The top level domain can be any string without a period or # **.**, ***.** style TLDs like co.uk or com.au # # www.example.co.uk gives: # $& => example.co.uk # # example.com gives: # $& => example.com # # lots.of.subdomains.example.local gives: # $& => example.local DOMAIN_REGEXP: untyped def self.build: (untyped req, untyped cookies) -> untyped attr_reader request: untyped def initialize: (untyped request) -> untyped def committed?: () -> untyped def commit!: () -> untyped def each: () { (untyped) -> untyped } -> untyped # Returns the value of the cookie by +name+, or +nil+ if no such cookie exists. def []: (untyped name) -> untyped def fetch: (untyped name, *untyped args) { () -> untyped } -> untyped def key?: (untyped name) -> untyped alias has_key? key? # Returns the cookies as Hash. alias to_hash to_h def update: (untyped other_hash) -> untyped def update_cookies_from_jar: () -> untyped def to_header: () -> untyped def handle_options: (untyped options) -> untyped # Sets the cookie named +name+. The second argument may be the cookie's # value or a hash of options as documented above. def []=: (untyped name, untyped options) -> untyped # Removes the cookie on the client machine by setting the value to an empty string # and the expiration date in the past. Like []=, you can pass in # an options hash to delete cookies with extra data such as a :path. def delete: (untyped name, ?::Hash[untyped, untyped] options) -> (nil | untyped) # Whether the given cookie is to be deleted by this CookieJar. # Like []=, you can pass in an options hash to test if a # deletion applies to a specific :path, :domain etc. def deleted?: (untyped name, ?::Hash[untyped, untyped] options) -> untyped # Removes all cookies on the client machine by calling delete for each cookie. def clear: (?::Hash[untyped, untyped] options) -> untyped def write: (untyped headers) -> untyped private def escape: (untyped string) -> untyped def make_set_cookie_header: (untyped header) -> untyped def write_cookie?: (untyped cookie) -> untyped end class AbstractCookieJar # :nodoc: include ChainedCookieJars def initialize: (untyped parent_jar) -> untyped def []: (untyped name) -> untyped def []=: (untyped name, untyped options) -> untyped def request: () -> untyped private def expiry_options: (untyped options) -> untyped def cookie_metadata: (untyped name, untyped options) -> untyped def parse: (untyped name, untyped data, ?purpose: untyped? purpose) -> untyped def commit: (untyped name, untyped options) -> nil end class PermanentCookieJar < AbstractCookieJar private def commit: (untyped name, untyped options) -> untyped end class JsonSerializer # :nodoc: def self.load: (untyped value) -> untyped def self.dump: (untyped value) -> untyped end module SerializedCookieJars # :nodoc: MARSHAL_SIGNATURE: ::String SERIALIZER: untyped def needs_migration?: (untyped value) -> untyped def serialize: (untyped value) -> untyped def deserialize: (untyped name) { (untyped) -> untyped } -> untyped def serializer: () -> untyped def digest: () -> untyped end class SignedKeyRotatingCookieJar < AbstractCookieJar # :nodoc: include SerializedCookieJars def initialize: (untyped parent_jar) -> untyped private def parse: (untyped name, untyped signed_message, ?purpose: untyped? purpose) -> untyped def commit: (untyped name, untyped options) -> untyped end class EncryptedKeyRotatingCookieJar < AbstractCookieJar # :nodoc: include SerializedCookieJars def initialize: (untyped parent_jar) -> untyped private def parse: (untyped name, untyped encrypted_message, ?purpose: untyped? purpose) -> untyped def commit: (untyped name, untyped options) -> untyped end def initialize: (untyped app) -> untyped def call: (untyped env) -> ::Array[untyped] end end module ActionDispatch # This middleware is responsible for logging exceptions and # showing a debugging page in case the request is local. class DebugExceptions def self.register_interceptor: (?untyped? object) { () -> untyped } -> untyped def initialize: (untyped app, ?untyped? routes_app, ?::Symbol response_format, ?untyped interceptors) -> untyped def call: (untyped env) -> untyped private def invoke_interceptors: (untyped request, untyped exception) -> untyped def render_exception: (untyped request, untyped exception) -> untyped def render_for_browser_request: (untyped request, untyped wrapper) -> untyped def render_for_api_request: (untyped content_type, untyped wrapper) -> untyped def create_template: (untyped request, untyped wrapper) -> DebugView def render: (untyped status, untyped body, untyped format) -> ::Array[untyped | ::Hash[::String, ::String | untyped] | ::Array[untyped]] def log_error: (untyped request, untyped wrapper) -> (nil | untyped) def log_array: (untyped logger, untyped array) -> (nil | untyped) def logger: (untyped request) -> untyped def stderr_logger: () -> untyped def routes_inspector: (untyped exception) -> untyped def api_request?: (untyped content_type) -> untyped end end module ActionDispatch # This middleware can be used to diagnose deadlocks in the autoload interlock. # # To use it, insert it near the top of the middleware stack, using # config/application.rb: # # config.middleware.insert_before Rack::Sendfile, ActionDispatch::DebugLocks # # After restarting the application and re-triggering the deadlock condition, # /rails/locks will show a summary of all threads currently known to # the interlock, which lock level they are holding or awaiting, and their # current backtrace. # # Generally a deadlock will be caused by the interlock conflicting with some # other external lock or blocking I/O call. These cannot be automatically # identified, but should be visible in the displayed backtraces. # # NOTE: The formatting and content of this middleware's output is intended for # human consumption, and should be expected to change between releases. # # This middleware exposes operational details of the server, with no access # control. It should only be enabled when in use, and removed thereafter. class DebugLocks def initialize: (untyped app, ?::String path) -> untyped def call: (untyped env) -> untyped private def render_details: (untyped req) -> ::Array[200 | ::Hash[::String, "text/plain" | untyped] | ::Array[untyped]] def blocked_by?: (untyped victim, untyped blocker, untyped all_threads) -> (::FalseClass | untyped) end end module ActionDispatch class DebugView < ActionView::Base # :nodoc: RESCUES_TEMPLATE_PATH: untyped def initialize: (untyped assigns) -> untyped def compiled_method_container: () -> untyped def debug_params: (untyped params) -> untyped def debug_headers: (untyped headers) -> untyped def debug_hash: (untyped object) -> untyped def render: () -> untyped def protect_against_forgery?: () -> ::FalseClass def params_valid?: () -> untyped end end module ActionDispatch class ExceptionWrapper attr_reader backtrace_cleaner: untyped attr_reader exception: untyped attr_reader wrapped_causes: untyped attr_reader line_number: untyped attr_reader file: untyped def initialize: (untyped backtrace_cleaner, untyped exception) -> untyped def unwrapped_exception: () -> untyped def rescue_template: () -> untyped def status_code: () -> untyped def application_trace: () -> untyped def framework_trace: () -> untyped def full_trace: () -> untyped def traces: () -> ::Hash[::String, untyped] def self.status_code_for_exception: (untyped class_name) -> untyped def source_extracts: () -> untyped def trace_to_show: () -> untyped def source_to_show_id: () -> untyped private def backtrace: () -> untyped def causes_for: (untyped exception) { (untyped) -> untyped } -> untyped def wrapped_causes_for: (untyped exception, untyped backtrace_cleaner) -> untyped def clean_backtrace: (*untyped args) -> untyped def source_fragment: (untyped path, untyped line) -> (nil | untyped) def extract_file_and_line_number: (untyped trace) -> ::Array[untyped] def expand_backtrace: () -> untyped end end module ActionDispatch class Executor def initialize: (untyped app, untyped executor) -> untyped def call: (untyped env) -> untyped end end module ActionDispatch # The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed # to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create # action that sets flash[:notice] = "Post successfully created" before redirecting to a display action that can # then expose the flash to its template. Actually, that exposure is automatically done. # # class PostsController < ActionController::Base # def create # # save post # flash[:notice] = "Post successfully created" # redirect_to @post # end # # def show # # doesn't need to assign the flash notice to the template, that's done automatically # end # end # # show.html.erb # <% if flash[:notice] %> #
<%= flash[:notice] %>
# <% end %> # # Since the +notice+ and +alert+ keys are a common idiom, convenience accessors are available: # # flash.alert = "You must be logged in" # flash.notice = "Post successfully created" # # This example places a string in the flash. And of course, you can put as many as you like at a time too. If you want to pass # non-primitive types, you will have to handle that in your application. Example: To show messages with links, you will have to # use sanitize helper. # # Just remember: They'll be gone by the time the next action has been performed. # # See docs on the FlashHash class for more details about the flash. class Flash KEY: ::String module RequestMethods # Access the contents of the flash. Use flash["notice"] to # read a notice you put there or flash["notice"] = "hello" # to put a new one. def flash: () -> untyped def flash=: (untyped flash) -> untyped def flash_hash: () -> untyped def commit_flash: () -> untyped def reset_session: () -> untyped end class FlashNow # nodoc: attr_accessor flash: untyped def initialize: (untyped flash) -> untyped def []=: (untyped k, untyped v) -> untyped def []: (untyped k) -> untyped # Convenience accessor for flash.now[:alert]=. def alert=: (untyped message) -> untyped # Convenience accessor for flash.now[:notice]=. def notice=: (untyped message) -> untyped end class FlashHash include Enumerable[untyped] def self.from_session_value: (untyped value) -> untyped def to_session_value: () -> (nil | ::Hash[::String, ::Array[untyped] | untyped]) def initialize: (?::Hash[untyped, untyped] flashes, ?untyped discard) -> untyped def initialize_copy: (untyped other) -> untyped def []=: (untyped k, untyped v) -> untyped def []: (untyped k) -> untyped def update: (untyped h) -> untyped def keys: () -> untyped def key?: (untyped name) -> untyped def delete: (untyped key) -> untyped def to_hash: () -> untyped def empty?: () -> untyped def clear: () -> untyped def each: () { (untyped) -> untyped } -> untyped alias merge! update def replace: (untyped h) -> untyped # Sets a flash that will not be available to the next action, only to the current. # # flash.now[:message] = "Hello current action" # # This method enables you to use the flash as a central messaging system in your app. # When you need to pass an object to the next action, you use the standard flash assign ([]=). # When you need to pass an object to the current action, you use now, and your object will # vanish when the current action is done. # # Entries set via now are accessed the same way as standard entries: flash['my-key']. # # Also, brings two convenience accessors: # # flash.now.alert = "Beware now!" # # Equivalent to flash.now[:alert] = "Beware now!" # # flash.now.notice = "Good luck now!" # # Equivalent to flash.now[:notice] = "Good luck now!" def now: () -> untyped # Keeps either the entire current flash or a specific flash entry available for the next action: # # flash.keep # keeps the entire flash # flash.keep(:notice) # keeps only the "notice" entry, the rest of the flash is discarded def keep: (?untyped? k) -> untyped # Marks the entire flash or a single flash entry to be discarded by the end of the current action: # # flash.discard # discard the entire flash at the end of the current action # flash.discard(:warning) # discard only the "warning" entry at the end of the current action def discard: (?untyped? k) -> untyped def sweep: () -> untyped # Convenience accessor for flash[:alert]. def alert: () -> untyped # Convenience accessor for flash[:alert]=. def alert=: (untyped message) -> untyped # Convenience accessor for flash[:notice]. def notice: () -> untyped # Convenience accessor for flash[:notice]=. def notice=: (untyped message) -> untyped def now_is_loaded?: () -> untyped private def stringify_array: (untyped array) -> untyped end def self.new: (untyped app) -> untyped end class Request end end module ActionDispatch # This middleware guards from DNS rebinding attacks by explicitly permitting # the hosts a request can be sent to. # # When a request comes to an unauthorized host, the +response_app+ # application will be executed and rendered. If no +response_app+ is given, a # default one will run, which responds with +403 Forbidden+. class HostAuthorization class Permissions # :nodoc: def initialize: (untyped hosts) -> untyped def empty?: () -> untyped def allows?: (untyped host) -> untyped private def sanitize_hosts: (untyped hosts) -> untyped def sanitize_regexp: (untyped host) -> ::Regexp def sanitize_string: (untyped host) -> untyped end DEFAULT_RESPONSE_APP: untyped def initialize: (untyped app, untyped hosts, ?untyped? response_app) -> untyped def call: (untyped env) -> untyped private def authorized?: (untyped request) -> untyped def mark_as_authorized: (untyped request) -> untyped end end module ActionDispatch # When called, this middleware renders an error page. By default if an HTML # response is expected it will render static error pages from the /public # directory. For example when this middleware receives a 500 response it will # render the template found in /public/500.html. # If an internationalized locale is set, this middleware will attempt to render # the template in /public/500..html. If an internationalized template # is not found it will fall back on /public/500.html. # # When a request with a content type other than HTML is made, this middleware # will attempt to convert error information into the appropriate response type. class PublicExceptions attr_accessor public_path: untyped def initialize: (untyped public_path) -> untyped def call: (untyped env) -> untyped private def render: (untyped status, untyped content_type, untyped body) -> untyped def render_format: (untyped status, untyped content_type, untyped body) -> ::Array[untyped | ::Hash[::String, ::String | untyped] | ::Array[untyped]] def render_html: (untyped status) -> untyped end end module ActionDispatch # ActionDispatch::Reloader wraps the request with callbacks provided by ActiveSupport::Reloader # callbacks, intended to assist with code reloading during development. # # By default, ActionDispatch::Reloader is included in the middleware stack # only in the development environment; specifically, when +config.cache_classes+ # is false. class Reloader < Executor end end module ActionDispatch # This middleware calculates the IP address of the remote client that is # making the request. It does this by checking various headers that could # contain the address, and then picking the last-set address that is not # on the list of trusted IPs. This follows the precedent set by e.g. # {the Tomcat server}[https://issues.apache.org/bugzilla/show_bug.cgi?id=50453], # with {reasoning explained at length}[https://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection] # by @gingerlime. A more detailed explanation of the algorithm is given # at GetIp#calculate_ip. # # Some Rack servers concatenate repeated headers, like {HTTP RFC 2616}[https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2] # requires. Some Rack servers simply drop preceding headers, and only report # the value that was {given in the last header}[https://andre.arko.net/2011/12/26/repeated-headers-and-ruby-web-servers]. # If you are behind multiple proxy servers (like NGINX to HAProxy to Unicorn) # then you should test your Rack server to make sure your data is good. # # IF YOU DON'T USE A PROXY, THIS MAKES YOU VULNERABLE TO IP SPOOFING. # This middleware assumes that there is at least one proxy sitting around # and setting headers with the client's remote IP address. If you don't use # a proxy, because you are hosted on e.g. Heroku without SSL, any client can # claim to have any IP address by setting the X-Forwarded-For header. If you # care about that, then you need to explicitly drop or ignore those headers # sometime before this middleware runs. class RemoteIp class IpSpoofAttackError < StandardError end # The default trusted IPs list simply includes IP addresses that are # guaranteed by the IP specification to be private addresses. Those will # not be the ultimate client IP in production, and so are discarded. See # https://en.wikipedia.org/wiki/Private_network for details. TRUSTED_PROXIES: untyped attr_reader check_ip: untyped attr_reader proxies: untyped # Create a new +RemoteIp+ middleware instance. # # The +ip_spoofing_check+ option is on by default. When on, an exception # is raised if it looks like the client is trying to lie about its own IP # address. It makes sense to turn off this check on sites aimed at non-IP # clients (like WAP devices), or behind proxies that set headers in an # incorrect or confusing way (like AWS ELB). # # The +custom_proxies+ argument can take an Array of string, IPAddr, or # Regexp objects which will be used instead of +TRUSTED_PROXIES+. If a # single string, IPAddr, or Regexp object is provided, it will be used in # addition to +TRUSTED_PROXIES+. Any proxy setup will put the value you # want in the middle (or at the beginning) of the X-Forwarded-For list, # with your proxy servers after it. If your proxies aren't removed, pass # them in via the +custom_proxies+ parameter. That way, the middleware will # ignore those IP addresses, and return the one that you want. def initialize: (untyped app, ?bool ip_spoofing_check, ?untyped? custom_proxies) -> untyped # Since the IP address may not be needed, we store the object here # without calculating the IP to keep from slowing down the majority of # requests. For those requests that do need to know the IP, the # GetIp#calculate_ip method will calculate the memoized client IP address. def call: (untyped env) -> untyped # The GetIp class exists as a way to defer processing of the request data # into an actual IP address. If the ActionDispatch::Request#remote_ip method # is called, this class will calculate the value and then memoize it. class GetIp def initialize: (untyped req, untyped check_ip, untyped proxies) -> untyped # Sort through the various IP address headers, looking for the IP most # likely to be the address of the actual remote client making this # request. # # REMOTE_ADDR will be correct if the request is made directly against the # Ruby process, on e.g. Heroku. When the request is proxied by another # server like HAProxy or NGINX, the IP address that made the original # request will be put in an X-Forwarded-For header. If there are multiple # proxies, that header may contain a list of IPs. Other proxy services # set the Client-Ip header instead, so we check that too. # # As discussed in {this post about Rails IP Spoofing}[https://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/], # while the first IP in the list is likely to be the "originating" IP, # it could also have been set by the client maliciously. # # In order to find the first address that is (probably) accurate, we # take the list of IPs, remove known and trusted proxies, and then take # the last address left, which was presumably set by one of those proxies. def calculate_ip: () -> untyped # Memoizes the value returned by #calculate_ip and returns it for # ActionDispatch::Request to use. def to_s: () -> untyped private def ips_from: (untyped header) -> (::Array[untyped] | untyped) def filter_proxies: (untyped ips) -> untyped end end end module ActionDispatch # Makes a unique request id available to the +action_dispatch.request_id+ env variable (which is then accessible # through ActionDispatch::Request#request_id or the alias ActionDispatch::Request#uuid) and sends # the same id to the client via the X-Request-Id header. # # The unique request id is either based on the X-Request-Id header in the request, which would typically be generated # by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the # header is accepted from the outside world, we sanitize it to a max of 255 chars and alphanumeric and dashes only. # # The unique request id can be used to trace a request end-to-end and would typically end up being part of log files # from multiple pieces of the stack. class RequestId X_REQUEST_ID: ::String def initialize: (untyped app) -> untyped def call: (untyped env) -> untyped private def make_request_id: (untyped request_id) -> untyped def internal_request_id: () -> untyped end end module ActionDispatch module Session class SessionRestoreError < StandardError # nodoc: def initialize: () -> untyped end module Compatibility def initialize: (untyped app, ?::Hash[untyped, untyped] options) -> untyped def generate_sid: () -> untyped private def initialize_sid: () -> untyped def make_request: (untyped env) -> ActionDispatch::Request end module StaleSessionCheck def load_session: (untyped env) -> untyped def extract_session_id: (untyped env) -> untyped def stale_session_check!: () { () -> untyped } -> untyped end module SessionObject # :nodoc: def prepare_session: (untyped req) -> untyped def loaded_session?: (untyped session) -> untyped end class AbstractStore < Rack::Session::Abstract::Persisted include Compatibility include StaleSessionCheck include SessionObject private def set_cookie: (untyped request, untyped session_id, untyped cookie) -> untyped end class AbstractSecureStore < Rack::Session::Abstract::PersistedSecure include Compatibility include StaleSessionCheck include SessionObject def generate_sid: () -> Rack::Session::SessionId private def set_cookie: (untyped request, untyped session_id, untyped cookie) -> untyped end end end module ActionDispatch module Session # A session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful # if you don't store critical data in your sessions and you don't need them to live for extended periods # of time. # # ==== Options # * cache - The cache to use. If it is not specified, Rails.cache will be used. # * expire_after - The length of time a session will be stored before automatically expiring. # By default, the :expires_in option of the cache is used. class CacheStore < AbstractSecureStore def initialize: (untyped app, ?::Hash[untyped, untyped] options) -> untyped # Get a session from the cache. def find_session: (untyped env, untyped sid) -> ::Array[untyped] # Set a session in the cache. def write_session: (untyped env, untyped sid, untyped session, untyped options) -> untyped # Remove a session from the cache. def delete_session: (untyped env, untyped sid, untyped options) -> untyped private # Turn the session id into a cache key. def cache_key: (untyped id) -> ::String def get_session_with_fallback: (untyped sid) -> untyped end end end module ActionDispatch module Session # This cookie-based session store is the Rails default. It is # dramatically faster than the alternatives. # # Sessions typically contain at most a user_id and flash message; both fit # within the 4K cookie size limit. A CookieOverflow exception is raised if # you attempt to store more than 4K of data. # # The cookie jar used for storage is automatically configured to be the # best possible option given your application's configuration. # # Your cookies will be encrypted using your apps secret_key_base. This # goes a step further than signed cookies in that encrypted cookies cannot # be altered or read by users. This is the default starting in Rails 4. # # Configure your session store in an initializer: # # Rails.application.config.session_store :cookie_store, key: '_your_app_session' # # In the development and test environments your application's secret key base is # generated by Rails and stored in a temporary file in tmp/development_secret.txt. # In all other environments, it is stored encrypted in the # config/credentials.yml.enc file. # # If your application was not updated to Rails 5.2 defaults, the secret_key_base # will be found in the old config/secrets.yml file. # # Note that changing your secret_key_base will invalidate all existing session. # Additionally, you should take care to make sure you are not relying on the # ability to decode signed cookies generated by your app in external # applications or JavaScript before changing it. # # Because CookieStore extends Rack::Session::Abstract::Persisted, many of the # options described there can be used to customize the session cookie that # is generated. For example: # # Rails.application.config.session_store :cookie_store, expire_after: 14.days # # would set the session cookie to expire automatically 14 days after creation. # Other useful options include :key, :secure and # :httponly. class CookieStore < AbstractSecureStore class SessionId # Note: It inherits unnamed class, but omitted attr_reader cookie_value: untyped def initialize: (untyped session_id, ?::Hash[untyped, untyped] cookie_value) -> untyped end def initialize: (untyped app, ?::Hash[untyped, untyped] options) -> untyped def delete_session: (untyped req, untyped session_id, untyped options) -> untyped def load_session: (untyped req) -> untyped private def extract_session_id: (untyped req) -> untyped def unpacked_cookie_data: (untyped req) -> untyped def persistent_session_id!: (untyped data, ?untyped? sid) -> untyped def write_session: (untyped req, untyped sid, untyped session_data, untyped options) -> SessionId def set_cookie: (untyped request, untyped session_id, untyped cookie) -> untyped def get_cookie: (untyped req) -> untyped def cookie_jar: (untyped request) -> untyped end end end module ActionDispatch module Session # A session store that uses MemCache to implement storage. # # ==== Options # * expire_after - The length of time a session will be stored before automatically expiring. class MemCacheStore < Rack::Session::Dalli include Compatibility include StaleSessionCheck include SessionObject def initialize: (untyped app, ?::Hash[untyped, untyped] options) -> untyped end end end module ActionDispatch # This middleware rescues any exception returned by the application # and calls an exceptions app that will wrap it in a format for the end user. # # The exceptions app should be passed as parameter on initialization # of ShowExceptions. Every time there is an exception, ShowExceptions will # store the exception in env["action_dispatch.exception"], rewrite the # PATH_INFO to the exception status code and call the Rack app. # # If the application returns a "X-Cascade" pass response, this middleware # will send an empty response as result with the correct status code. # If any exception happens inside the exceptions app, this middleware # catches the exceptions and returns a FAILSAFE_RESPONSE. class ShowExceptions FAILSAFE_RESPONSE: ::Array[untyped] def initialize: (untyped app, untyped exceptions_app) -> untyped def call: (untyped env) -> untyped private def render_exception: (untyped request, untyped exception) -> untyped def pass_response: (untyped status) -> ::Array[untyped | ::Hash[::String, ::String | "0"] | ::Array[untyped]] end end module ActionDispatch # This middleware is added to the stack when config.force_ssl = true, and is passed # the options set in +config.ssl_options+. It does three jobs to enforce secure HTTP # requests: # # 1. TLS redirect: Permanently redirects +http://+ requests to +https://+ # with the same URL host, path, etc. Enabled by default. Set +config.ssl_options+ # to modify the destination URL # (e.g. redirect: { host: "secure.widgets.com", port: 8080 }), or set # redirect: false to disable this feature. # # Requests can opt-out of redirection with +exclude+: # # config.ssl_options = { redirect: { exclude: -> request { request.path =~ /healthcheck/ } } } # # Cookies will not be flagged as secure for excluded requests. # # 2. Secure cookies: Sets the +secure+ flag on cookies to tell browsers they # must not be sent along with +http://+ requests. Enabled by default. Set # +config.ssl_options+ with secure_cookies: false to disable this feature. # # 3. HTTP Strict Transport Security (HSTS): Tells the browser to remember # this site as TLS-only and automatically redirect non-TLS requests. # Enabled by default. Configure +config.ssl_options+ with hsts: false to disable. # # Set +config.ssl_options+ with hsts: { ... } to configure HSTS: # # * +expires+: How long, in seconds, these settings will stick. The minimum # required to qualify for browser preload lists is 1 year. Defaults to # 1 year (recommended). # # * +subdomains+: Set to +true+ to tell the browser to apply these settings # to all subdomains. This protects your cookies from interception by a # vulnerable site on a subdomain. Defaults to +true+. # # * +preload+: Advertise that this site may be included in browsers' # preloaded HSTS lists. HSTS protects your site on every visit except the # first visit since it hasn't seen your HSTS header yet. To close this # gap, browser vendors include a baked-in list of HSTS-enabled sites. # Go to https://hstspreload.org to submit your site for inclusion. # Defaults to +false+. # # To turn off HSTS, omitting the header is not enough. Browsers will remember the # original HSTS directive until it expires. Instead, use the header to tell browsers to # expire HSTS immediately. Setting hsts: false is a shortcut for # hsts: { expires: 0 }. class SSL # Default to 1 year, the minimum for browser preload lists. HSTS_EXPIRES_IN: ::Integer def self.default_hsts_options: () -> { expires: untyped, subdomains: ::TrueClass, preload: ::FalseClass } def initialize: (untyped app, ?secure_cookies: bool secure_cookies, ?hsts: ::Hash[untyped, untyped] hsts, ?redirect: ::Hash[untyped, untyped] redirect) -> untyped def call: (untyped env) -> untyped private def set_hsts_header!: (untyped headers) -> untyped def normalize_hsts_options: (untyped options) -> untyped # https://tools.ietf.org/html/rfc6797#section-6.1 def build_hsts_header: (untyped hsts) -> untyped def flag_cookies_as_secure!: (untyped headers) -> untyped def redirect_to_https: (untyped request) -> ::Array[untyped | ::Hash[::String, "text/html" | untyped]] def redirection_status: (untyped request) -> untyped def https_location_for: (untyped request) -> untyped end end module ActionDispatch class MiddlewareStack class Middleware attr_reader args: untyped attr_reader block: untyped attr_reader klass: untyped def initialize: (untyped klass, untyped args, untyped block) -> untyped def name: () -> untyped def ==: (untyped middleware) -> untyped def inspect: () -> untyped def build: (untyped app) -> untyped def build_instrumented: (untyped app) -> InstrumentationProxy end # This class is used to instrument the execution of a single middleware. # It proxies the `call` method transparently and instruments the method # call. class InstrumentationProxy EVENT_NAME: ::String def initialize: (untyped middleware, untyped class_name) -> untyped def call: (untyped env) -> untyped end include Enumerable[untyped] attr_accessor middlewares: untyped def initialize: (*untyped args) { (untyped) -> untyped } -> untyped def each: () { (untyped) -> untyped } -> untyped def size: () -> untyped def last: () -> untyped def []: (untyped i) -> untyped def unshift: (untyped klass, *untyped args) { () -> untyped } -> untyped def initialize_copy: (untyped other) -> untyped def insert: (untyped index, untyped klass, *untyped args) { () -> untyped } -> untyped alias insert_before insert def insert_after: (untyped index, *untyped args) { () -> untyped } -> untyped def swap: (untyped target, *untyped args) { () -> untyped } -> untyped def delete: (untyped target) -> untyped def use: (untyped klass, *untyped args) { () -> untyped } -> untyped def build: (?untyped? app) { () -> untyped } -> untyped private def assert_index: (untyped index, untyped where) -> untyped def build_middleware: (untyped klass, untyped args, untyped block) -> Middleware end end module ActionDispatch # This middleware returns a file's contents from disk in the body response. # When initialized, it can accept optional HTTP headers, which will be set # when a response containing a file's contents is delivered. # # This middleware will render the file specified in env["PATH_INFO"] # where the base path is in the +root+ directory. For example, if the +root+ # is set to +public/+, then a request with env["PATH_INFO"] of # +assets/application.js+ will return a response with the contents of a file # located at +public/assets/application.js+ if the file exists. If the file # does not exist, a 404 "File not Found" response will be returned. class FileHandler def initialize: (untyped root, ?headers: ::Hash[untyped, untyped] headers, ?index: ::String index) -> untyped # Takes a path to a file. If the file is found, has valid encoding, and has # correct read permissions, the return value is a URI-escaped string # representing the filename. Otherwise, false is returned. # # Used by the +Static+ class to check the existence of a valid file # in the server's +public/+ directory (see Static#call). def match?: (untyped path) -> (::FalseClass | untyped) def call: (untyped env) -> untyped def serve: (untyped request) -> untyped private def ext: () -> untyped def content_type: (untyped path) -> untyped def gzip_encoding_accepted?: (untyped request) -> untyped def gzip_file_path: (untyped path) -> untyped end # This middleware will attempt to return the contents of a file's body from # disk in the response. If a file is not found on disk, the request will be # delegated to the application stack. This middleware is commonly initialized # to serve assets from a server's +public/+ directory. # # This middleware verifies the path to ensure that only files # living in the root directory can be rendered. A request cannot # produce a directory traversal using this middleware. Only 'GET' and 'HEAD' # requests will result in a file being returned. class Static def initialize: (untyped app, untyped path, ?headers: ::Hash[untyped, untyped] headers, ?index: ::String index) -> untyped def call: (untyped env) -> untyped end end module ActionDispatch class Railtie < Rails::Railtie end end module ActionDispatch class Request class Session ENV_SESSION_KEY: untyped ENV_SESSION_OPTIONS_KEY: untyped # Singleton object used to determine if an optional param wasn't specified. Unspecified: untyped # Creates a session hash, merging the properties of the previous session if any. def self.create: (untyped store, untyped req, untyped default_options) -> untyped def self.find: (untyped req) -> untyped def self.set: (untyped req, untyped session) -> untyped class Options # nodoc: def self.set: (untyped req, untyped options) -> untyped def self.find: (untyped req) -> untyped def initialize: (untyped by, untyped default_options) -> untyped def []: (untyped key) -> untyped def id: (untyped req) -> untyped def []=: (untyped k, untyped v) -> untyped def to_hash: () -> untyped def values_at: (*untyped args) -> untyped end def initialize: (untyped by, untyped req) -> untyped def id: () -> untyped def options: () -> untyped def destroy: () -> untyped # Returns value of the key stored in the session or # +nil+ if the given key is not found in the session. def []: (untyped key) -> untyped # Returns the nested value specified by the sequence of keys, returning # +nil+ if any intermediate step is +nil+. def dig: (*untyped keys) -> untyped # Returns true if the session has the given key or false. def has_key?: (untyped key) -> untyped alias key? has_key? alias include? has_key? # Returns keys of the session as Array. def keys: () -> untyped # Returns values of the session as Array. def values: () -> untyped # Writes given value to given key of the session. def []=: (untyped key, untyped value) -> untyped # Clears the session. def clear: () -> untyped # Returns the session as Hash. def to_hash: () -> untyped alias to_h to_hash # Updates the session with given Hash. # # session.to_hash # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"} # # session.update({ "foo" => "bar" }) # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"} # # session.to_hash # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"} def update: (untyped hash) -> untyped # Deletes given key from the session. def delete: (untyped key) -> untyped # Returns value of the given key from the session, or raises +KeyError+ # if can't find the given key and no default value is set. # Returns default value if specified. # # session.fetch(:foo) # # => KeyError: key not found: "foo" # # session.fetch(:foo, :bar) # # => :bar # # session.fetch(:foo) do # :bar # end # # => :bar def fetch: (untyped key, ?untyped default) { () -> untyped } -> untyped def inspect: () -> untyped def exists?: () -> untyped def loaded?: () -> untyped def empty?: () -> untyped def merge!: (untyped other) -> untyped def each: () { () -> untyped } -> untyped private def load_for_read!: () -> untyped def load_for_write!: () -> untyped def load!: () -> untyped def stringify_keys: (untyped other) -> untyped end end end module ActionDispatch class Request class Utils def self.each_param_value: (untyped params) { () -> untyped } -> untyped def self.normalize_encode_params: (untyped params) -> untyped def self.check_param_encoding: (untyped params) -> untyped class ParamEncoder # :nodoc: # Convert nested Hash to HashWithIndifferentAccess. def self.normalize_encode_params: (untyped params) -> untyped def self.handle_array: (untyped params) -> untyped end class NoNilParamEncoder < ParamEncoder # Remove nils from the params hash. # :nodoc: def self.handle_array: (untyped params) -> untyped end end end end module ActionDispatch module Routing class Endpoint # :nodoc: def dispatcher?: () -> ::FalseClass def redirect?: () -> ::FalseClass def matches?: (untyped req) -> ::TrueClass def app: () -> untyped def rack_app: () -> untyped def engine?: () -> untyped end end end module ActionDispatch module Routing class RouteWrapper < SimpleDelegator def endpoint: () -> untyped def constraints: () -> untyped def rack_app: () -> untyped def path: () -> untyped def name: () -> untyped def reqs: () -> untyped def controller: () -> untyped def action: () -> untyped def internal?: () -> untyped def engine?: () -> untyped end class RoutesInspector # # This class is just used for displaying route information when someone # executes `rails routes` or looks at the RoutingError page. # People should not use this class. # :nodoc: def initialize: (untyped routes) -> untyped def format: (untyped formatter, ?::Hash[untyped, untyped] filter) -> untyped private def normalize_filter: (untyped filter) -> untyped def filter_routes: (untyped filter) -> untyped def collect_routes: (untyped routes) -> untyped def collect_engine_routes: (untyped route) -> (nil | untyped) end module ConsoleFormatter class Base def initialize: () -> untyped def result: () -> untyped def section_title: (untyped title) -> nil def section: (untyped routes) -> nil def header: (untyped routes) -> nil def no_routes: (untyped routes, untyped filter) -> untyped end class Sheet < Base def section_title: (untyped title) -> untyped def section: (untyped routes) -> untyped def header: (untyped routes) -> untyped private def draw_section: (untyped routes) -> untyped def draw_header: (untyped routes) -> ::String def widths: (untyped routes) -> ::Array[untyped] end class Expanded < Base def section_title: (untyped title) -> untyped def section: (untyped routes) -> untyped private def draw_expanded_section: (untyped routes) -> untyped def route_header: (index: untyped index) -> ::String end end class HtmlTableFormatter def initialize: (untyped view) -> untyped def section_title: (untyped title) -> untyped def section: (untyped routes) -> untyped # The header is part of the HTML page, so we don't construct it here. def header: (untyped routes) -> nil def no_routes: () -> untyped def result: () -> untyped end end end module ActionDispatch module Routing class Mapper URL_OPTIONS: ::Array[untyped] class Constraints < Routing::Endpoint # nodoc: attr_reader app: untyped # nodoc: attr_reader constraints: untyped SERVE: untyped CALL: untyped def initialize: (untyped app, untyped constraints, untyped strategy) -> untyped def dispatcher?: () -> untyped def matches?: (untyped req) -> untyped def serve: (untyped req) -> (::Array[404 | ::Hash[::String, "pass"] | ::Array[untyped]] | untyped) private def constraint_args: (untyped constraint, untyped request) -> untyped end class Mapping # nodoc: ANCHOR_CHARACTERS_REGEX: untyped OPTIONAL_FORMAT_REGEX: untyped attr_reader requirements: untyped attr_reader defaults: untyped attr_reader to: untyped attr_reader default_controller: untyped attr_reader default_action: untyped attr_reader required_defaults: untyped attr_reader ast: untyped attr_reader scope_options: untyped def self.build: (untyped scope, untyped set, untyped ast, untyped controller, untyped default_action, untyped to, untyped via, untyped formatted, untyped options_constraints, untyped anchor, untyped options) -> untyped def self.check_via: (untyped via) -> untyped def self.normalize_path: (untyped path, untyped format) -> untyped def self.optional_format?: (untyped path, untyped format) -> untyped def initialize: (untyped set, untyped ast, untyped defaults, untyped controller, untyped default_action, untyped modyoule, untyped to, untyped formatted, untyped scope_constraints, untyped scope_options, untyped blocks, untyped via, untyped options_constraints, untyped anchor, untyped options) -> untyped def make_route: (untyped name, untyped precedence) -> Journey::Route def application: () -> untyped def path: () -> untyped def conditions: () -> untyped private def build_conditions: (untyped current_conditions, untyped request_class) -> untyped def request_method: () -> untyped public JOINED_SEPARATORS: untyped private def build_path: (untyped ast, untyped requirements, untyped anchor) -> untyped def intern: (untyped object) -> untyped def add_wildcard_options: (untyped options, untyped formatted, untyped path_ast) -> untyped def normalize_options!: (untyped options, untyped path_params, untyped modyoule) -> untyped def split_constraints: (untyped path_params, untyped constraints) -> untyped def normalize_format: (untyped formatted) -> untyped def verify_regexp_requirements: (untyped requirements) -> untyped def normalize_defaults: (untyped options) -> untyped def app: (untyped blocks) -> untyped def check_controller_and_action: (untyped path_params, untyped controller, untyped action) -> untyped def check_part: (untyped name, untyped part, untyped path_params, untyped hash) { (untyped) -> untyped } -> untyped def split_to: (untyped to) -> untyped def add_controller_module: (untyped controller, untyped modyoule) -> untyped def translate_controller: (untyped controller) { () -> untyped } -> untyped def blocks: (untyped callable_constraint) -> ::Array[untyped] def constraints: (untyped options, untyped path_params) -> untyped def dispatcher: (untyped raise_on_name_error) -> Routing::RouteSet::Dispatcher end # Invokes Journey::Router::Utils.normalize_path and ensure that # (:locale) becomes (/:locale) instead of /(:locale). Except # for root cases, where the latter is the correct one. def self.normalize_path: (untyped path) -> untyped def self.normalize_name: (untyped name) -> untyped module Base # Matches a URL pattern to one or more routes. # # You should not use the +match+ method in your router # without specifying an HTTP method. # # If you want to expose your action to both GET and POST, use: # # # sets :controller, :action and :id in params # match ':controller/:action/:id', via: [:get, :post] # # Note that +:controller+, +:action+ and +:id+ are interpreted as URL # query parameters and thus available through +params+ in an action. # # If you want to expose your action to GET, use +get+ in the router: # # Instead of: # # match ":controller/:action/:id" # # Do: # # get ":controller/:action/:id" # # Two of these symbols are special, +:controller+ maps to the controller # and +:action+ to the controller's action. A pattern can also map # wildcard segments (globs) to params: # # get 'songs/*category/:title', to: 'songs#show' # # # 'songs/rock/classic/stairway-to-heaven' sets # # params[:category] = 'rock/classic' # # params[:title] = 'stairway-to-heaven' # # To match a wildcard parameter, it must have a name assigned to it. # Without a variable name to attach the glob parameter to, the route # can't be parsed. # # When a pattern points to an internal route, the route's +:action+ and # +:controller+ should be set in options or hash shorthand. Examples: # # match 'photos/:id' => 'photos#show', via: :get # match 'photos/:id', to: 'photos#show', via: :get # match 'photos/:id', controller: 'photos', action: 'show', via: :get # # A pattern can also point to a +Rack+ endpoint i.e. anything that # responds to +call+: # # match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get # match 'photos/:id', to: PhotoRackApp, via: :get # # Yes, controller actions are just rack endpoints # match 'photos/:id', to: PhotosController.action(:show), via: :get # # Because requesting various HTTP verbs with a single action has security # implications, you must either specify the actions in # the via options or use one of the HttpHelpers[rdoc-ref:HttpHelpers] # instead +match+ # # === Options # # Any options not seen here are passed on as params with the URL. # # [:controller] # The route's controller. # # [:action] # The route's action. # # [:param] # Overrides the default resource identifier +:id+ (name of the # dynamic segment used to generate the routes). # You can access that segment from your controller using # params[<:param>]. # In your router: # # resources :users, param: :name # # The +users+ resource here will have the following routes generated for it: # # GET /users(.:format) # POST /users(.:format) # GET /users/new(.:format) # GET /users/:name/edit(.:format) # GET /users/:name(.:format) # PATCH/PUT /users/:name(.:format) # DELETE /users/:name(.:format) # # You can override ActiveRecord::Base#to_param of a related # model to construct a URL: # # class User < ActiveRecord::Base # def to_param # name # end # end # # user = User.find_by(name: 'Phusion') # user_path(user) # => "/users/Phusion" # # [:path] # The path prefix for the routes. # # [:module] # The namespace for :controller. # # match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get # # => Sekret::PostsController # # See Scoping#namespace for its scope equivalent. # # [:as] # The name used to generate routing helpers. # # [:via] # Allowed HTTP verb(s) for route. # # match 'path', to: 'c#a', via: :get # match 'path', to: 'c#a', via: [:get, :post] # match 'path', to: 'c#a', via: :all # # [:to] # Points to a +Rack+ endpoint. Can be an object that responds to # +call+ or a string representing a controller's action. # # match 'path', to: 'controller#action', via: :get # match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get # match 'path', to: RackApp, via: :get # # [:on] # Shorthand for wrapping routes in a specific RESTful context. Valid # values are +:member+, +:collection+, and +:new+. Only use within # resource(s) block. For example: # # resource :bar do # match 'foo', to: 'c#a', on: :member, via: [:get, :post] # end # # Is equivalent to: # # resource :bar do # member do # match 'foo', to: 'c#a', via: [:get, :post] # end # end # # [:constraints] # Constrains parameters with a hash of regular expressions # or an object that responds to matches?. In addition, constraints # other than path can also be specified with any object # that responds to === (eg. String, Array, Range, etc.). # # match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get # # match 'json_only', constraints: { format: 'json' }, via: :get # # class PermitList # def matches?(request) request.remote_ip == '1.2.3.4' end # end # match 'path', to: 'c#a', constraints: PermitList.new, via: :get # # See Scoping#constraints for more examples with its scope # equivalent. # # [:defaults] # Sets defaults for parameters # # # Sets params[:format] to 'jpg' by default # match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get # # See Scoping#defaults for its scope equivalent. # # [:anchor] # Boolean to anchor a match pattern. Default is true. When set to # false, the pattern matches any request prefixed with the given path. # # # Matches any request starting with 'path' # match 'path', to: 'c#a', anchor: false, via: :get # # [:format] # Allows you to specify the default value for optional +format+ # 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 def app_name: (untyped app, untyped rails_app) -> untyped def define_generate_prefix: (untyped app, untyped name) -> untyped 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 # 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 # 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 # 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 # 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 private def map_method: (untyped method, untyped args) { () -> untyped } -> untyped end # You may wish to organize groups of controllers under a namespace. # Most commonly, you might group a number of administrative controllers # under an +admin+ namespace. You would place these controllers under # the app/controllers/admin directory, and you can group them # together in your router: # # namespace "admin" do # resources :posts, :comments # end # # This will create a number of routes for each of the posts and comments # controller. For Admin::PostsController, Rails will create: # # GET /admin/posts # GET /admin/posts/new # POST /admin/posts # GET /admin/posts/1 # GET /admin/posts/1/edit # PATCH/PUT /admin/posts/1 # DELETE /admin/posts/1 # # If you want to route /posts (without the prefix /admin) to # Admin::PostsController, you could use # # scope module: "admin" do # resources :posts # end # # or, for a single case # # resources :posts, module: "admin" # # If you want to route /admin/posts to +PostsController+ # (without the Admin:: module prefix), you could use # # scope "/admin" do # resources :posts # end # # or, for a single case # # resources :posts, path: "/admin/posts" # # In each of these cases, the named routes remain the same as if you did # not use scope. In the last case, the following paths map to # +PostsController+: # # GET /admin/posts # GET /admin/posts/new # POST /admin/posts # GET /admin/posts/1 # GET /admin/posts/1/edit # 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 def merge_shallow_path_scope: (untyped parent, untyped child) -> untyped def merge_as_scope: (untyped parent, untyped child) -> untyped def merge_shallow_prefix_scope: (untyped parent, untyped child) -> untyped def merge_module_scope: (untyped parent, untyped child) -> untyped def merge_controller_scope: (untyped parent, untyped child) -> untyped def merge_action_scope: (untyped parent, untyped child) -> untyped def merge_via_scope: (untyped parent, untyped child) -> untyped def merge_format_scope: (untyped parent, untyped child) -> untyped def merge_path_names_scope: (untyped parent, untyped child) -> untyped def merge_constraints_scope: (untyped parent, untyped child) -> untyped def merge_defaults_scope: (untyped parent, untyped child) -> untyped def merge_blocks_scope: (untyped parent, untyped child) -> untyped def merge_options_scope: (untyped parent, untyped child) -> untyped def merge_shallow_scope: (untyped parent, untyped child) -> untyped def merge_to_scope: (untyped parent, untyped child) -> untyped end # Resource routing allows you to quickly declare all of the common routes # for a given resourceful controller. Instead of declaring separate routes # for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+ # actions, a resourceful route declares them in a single line of code: # # resources :photos # # Sometimes, you have a resource that clients always look up without # referencing an ID. A common example, /profile always shows the profile of # the currently logged in user. In this case, you can use a singular resource # to map /profile (rather than /profile/:id) to the show action. # # resource :profile # # It's common to have resources that are logically children of other # resources: # # resources :magazines do # resources :ads # end # # You may wish to organize groups of controllers under a namespace. Most # commonly, you might group a number of administrative controllers under # an +admin+ namespace. You would place these controllers under the # app/controllers/admin directory, and you can group them together # in your router: # # namespace "admin" do # resources :posts, :comments # end # # By default the +:id+ parameter doesn't accept dots. If you need to # use dots as part of the +:id+ parameter add a constraint which # overrides this restriction, e.g: # # resources :articles, id: /[^\/]+/ # # This allows any character other than a slash as part of your +:id+. # module Resources # CANONICAL_ACTIONS holds all actions that does not need a prefix or # a path appended since they fit properly in their scope level. VALID_ON_OPTIONS: ::Array[untyped] RESOURCE_OPTIONS: ::Array[untyped] CANONICAL_ACTIONS: ::Array[untyped] class Resource # nodoc: attr_reader controller: untyped # nodoc: attr_reader path: untyped # nodoc: attr_reader param: untyped def initialize: (untyped entities, untyped api_only, untyped shallow, ?::Hash[untyped, untyped] options) -> untyped def default_actions: () -> untyped def actions: () -> untyped def available_actions: () -> untyped def name: () -> untyped def plural: () -> untyped def singular: () -> untyped alias member_name singular # Checks for uncountable plurals, and appends "_index" if the plural # and singular form are the same. def collection_name: () -> untyped def resource_scope: () -> untyped alias collection_scope path def member_scope: () -> ::String alias shallow_scope member_scope def new_scope: (untyped new_path) -> ::String def nested_param: () -> ::Symbol def nested_scope: () -> ::String def shallow?: () -> untyped def singleton?: () -> ::FalseClass end class SingletonResource < Resource # nodoc: def initialize: (untyped entities, untyped api_only, untyped shallow, untyped options) -> untyped def default_actions: () -> untyped def plural: () -> untyped def singular: () -> untyped alias member_name singular alias collection_name singular alias member_scope path alias nested_scope path def singleton?: () -> ::TrueClass end def resources_path_names: (untyped options) -> untyped # Sometimes, you have a resource that clients always look up without # referencing an ID. A common example, /profile always shows the # profile of the currently logged in user. In this case, you can use # a singular resource to map /profile (rather than /profile/:id) to # the show action: # # resource :profile # # This creates six different routes in your application, all mapping to # the +Profiles+ controller (note that the controller is named after # the plural): # # GET /profile/new # GET /profile # GET /profile/edit # PATCH/PUT /profile # DELETE /profile # POST /profile # # === Options # Takes same options as resources[rdoc-ref:#resources] def resource: (*untyped resources) { () -> untyped } -> untyped # In Rails, a resourceful route provides a mapping between HTTP verbs # and URLs and controller actions. By convention, each action also maps # to particular CRUD operations in a database. A single entry in the # routing file, such as # # resources :photos # # creates seven different routes in your application, all mapping to # the +Photos+ controller: # # GET /photos # GET /photos/new # POST /photos # GET /photos/:id # GET /photos/:id/edit # PATCH/PUT /photos/:id # DELETE /photos/:id # # Resources can also be nested infinitely by using this block syntax: # # resources :photos do # resources :comments # end # # This generates the following comments routes: # # GET /photos/:photo_id/comments # GET /photos/:photo_id/comments/new # POST /photos/:photo_id/comments # GET /photos/:photo_id/comments/:id # GET /photos/:photo_id/comments/:id/edit # PATCH/PUT /photos/:photo_id/comments/:id # DELETE /photos/:photo_id/comments/:id # # === Options # Takes same options as match[rdoc-ref:Base#match] as well as: # # [:path_names] # Allows you to change the segment component of the +edit+ and +new+ actions. # Actions not specified are not changed. # # resources :posts, path_names: { new: "brand_new" } # # The above example will now change /posts/new to /posts/brand_new. # # [:path] # Allows you to change the path prefix for the resource. # # resources :posts, path: 'postings' # # The resource and all segments will now route to /postings instead of /posts. # # [:only] # Only generate routes for the given actions. # # resources :cows, only: :show # resources :cows, only: [:show, :index] # # [:except] # Generate all routes except for the given actions. # # resources :cows, except: :show # resources :cows, except: [:show, :index] # # [:shallow] # Generates shallow routes for nested resource(s). When placed on a parent resource, # generates shallow routes for all nested resources. # # resources :posts, shallow: true do # resources :comments # end # # Is the same as: # # resources :posts do # resources :comments, except: [:show, :edit, :update, :destroy] # end # resources :comments, only: [:show, :edit, :update, :destroy] # # This allows URLs for resources that otherwise would be deeply nested such # as a comment on a blog post like /posts/a-long-permalink/comments/1234 # to be shortened to just /comments/1234. # # Set shallow: false on a child resource to ignore a parent's shallow parameter. # # [:shallow_path] # Prefixes nested shallow routes with the specified path. # # scope shallow_path: "sekret" do # resources :posts do # resources :comments, shallow: true # end # end # # The +comments+ resource here will have the following routes generated for it: # # post_comments GET /posts/:post_id/comments(.:format) # post_comments POST /posts/:post_id/comments(.:format) # new_post_comment GET /posts/:post_id/comments/new(.:format) # edit_comment GET /sekret/comments/:id/edit(.:format) # comment GET /sekret/comments/:id(.:format) # comment PATCH/PUT /sekret/comments/:id(.:format) # comment DELETE /sekret/comments/:id(.:format) # # [:shallow_prefix] # Prefixes nested shallow route names with specified prefix. # # scope shallow_prefix: "sekret" do # resources :posts do # resources :comments, shallow: true # end # end # # The +comments+ resource here will have the following routes generated for it: # # post_comments GET /posts/:post_id/comments(.:format) # post_comments POST /posts/:post_id/comments(.:format) # new_post_comment GET /posts/:post_id/comments/new(.:format) # edit_sekret_comment GET /comments/:id/edit(.:format) # sekret_comment GET /comments/:id(.:format) # sekret_comment PATCH/PUT /comments/:id(.:format) # sekret_comment DELETE /comments/:id(.:format) # # [:format] # Allows you to specify the default value for optional +format+ # segment or disable it by supplying +false+. # # [:param] # Allows you to override the default param name of +:id+ in the URL. # # === Examples # # # routes call Admin::PostsController # resources :posts, module: "admin" # # # resource actions are at /admin/posts. # resources :posts, path: "admin/posts" def resources: (*untyped resources) { () -> untyped } -> 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 path, ?::Hash[untyped, untyped] options) -> 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 def apply_common_behavior_for: (untyped method, untyped resources, untyped options) { () -> untyped } -> (::TrueClass | ::FalseClass) def apply_action_options: (untyped options) -> untyped def action_options?: (untyped options) -> untyped def scope_action_options: () -> untyped def resource_scope?: () -> untyped def resource_method_scope?: () -> untyped def nested_scope?: () -> untyped def with_scope_level: (untyped kind) { () -> untyped } -> untyped def resource_scope: (untyped resource) { () -> untyped } -> untyped def nested_options: () -> untyped def shallow_nesting_depth: () -> untyped def param_constraint?: () -> untyped def param_constraint: () -> untyped def canonical_action?: (untyped action) -> untyped def shallow_scope: () { () -> untyped } -> untyped def path_for_action: (untyped action, untyped path) -> (::String | untyped) def action_path: (untyped name) -> untyped def prefix_name_for_action: (untyped as, untyped action) -> untyped def name_for_action: (untyped as, untyped action) -> (nil | untyped) def set_member_mappings_for_resource: () -> untyped def api_only?: () -> untyped def path_scope: (untyped path) { () -> untyped } -> untyped def map_match: (untyped paths, untyped options) -> untyped def get_to_from_path: (untyped path, untyped to, untyped action) -> untyped def using_match_shorthand?: (untyped path) -> untyped def decomposed_match: (untyped path, untyped controller, untyped options, untyped _path, untyped to, untyped via, untyped formatted, untyped anchor, untyped options_constraints) -> untyped def add_route: (untyped action, untyped controller, untyped options, untyped _path, untyped to, untyped via, untyped formatted, untyped anchor, untyped options_constraints) -> untyped def match_root_route: (untyped options) -> untyped end # Routing Concerns allow you to declare common routes that can be reused # inside others resources and routes. # # concern :commentable do # resources :comments # end # # concern :image_attachable do # resources :images, only: :index # end # # These concerns are used in Resources routing: # # resources :messages, concerns: [:commentable, :image_attachable] # # or in a scope or namespace: # # namespace :posts do # 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 # Define custom URL helpers that will be added to the application's # routes. This allows you to override and/or replace the default behavior # of routing helpers, e.g: # # direct :homepage do # "https://rubyonrails.org" # end # # direct :commentable do |model| # [ model, anchor: model.dom_id ] # end # # direct :main do # { controller: "pages", action: "index", subdomain: "www" } # end # # The return value from the block passed to +direct+ must be a valid set of # arguments for +url_for+ which will actually build the URL string. This can # be one of the following: # # * A string, which is treated as a generated URL # * A hash, e.g. { controller: "pages", action: "index" } # * An array, which is passed to +polymorphic_url+ # * An Active Model instance # * An Active Model class # # NOTE: Other URL helpers can be called in the block but be careful not to invoke # your custom URL helper again otherwise it will result in a stack overflow error. # # You can also specify default options that will be passed through to # your URL helper definition, e.g: # # direct :browse, page: 1, size: 10 do |options| # [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ] # end # # In this instance the +params+ object comes from the context in which the # block is executed, e.g. generating a URL inside a controller action or a view. # If the block is executed where there isn't a +params+ object such as this: # # Rails.application.routes.url_helpers.browse_path # # then it will raise a +NameError+. Because of this you need to be aware of the # context in which you will use your custom URL helper when defining it. # # NOTE: The +direct+ method can't be used inside of a scope block such as # +namespace+ or +scope+ and will raise an error if it detects that it is. def direct: (untyped name, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped # Define custom polymorphic mappings of models to URLs. This alters the # behavior of +polymorphic_url+ and consequently the behavior of # +link_to+ and +form_for+ when passed a model instance, e.g: # # resource :basket # # resolve "Basket" do # [:basket] # end # # This will now generate "/basket" when a +Basket+ instance is passed to # +link_to+ or +form_for+ instead of the standard "/baskets/:id". # # NOTE: This custom behavior only applies to simple polymorphic URLs where # a single model instance is passed and not more complicated forms, e.g: # # # config/routes.rb # resource :profile # namespace :admin do # resources :users # end # # resolve("User") { [:profile] } # # # app/views/application/_menu.html.erb # link_to "Profile", @current_user # link_to "Profile", [:admin, @current_user] # # The first +link_to+ will generate "/profile" but the second will generate # the standard polymorphic URL of "/admin/users/1". # # You can pass options to a polymorphic mapping - the arity for the block # needs to be two as the instance is passed as the first argument, e.g: # # resolve "Basket", anchor: "items" do |basket, options| # [:basket, options] # end # # This generates the URL "/basket#items" because when the last item in an # array passed to +polymorphic_url+ is a hash then it's treated as options # to the URL helper that gets called. # # NOTE: The +resolve+ method can't be used inside of a scope block such as # +namespace+ or +scope+ and will raise an error if it detects that it is. def resolve: (*untyped args) { () -> untyped } -> untyped end class Scope # :nodoc: OPTIONS: ::Array[untyped] RESOURCE_SCOPES: ::Array[untyped] RESOURCE_METHOD_SCOPES: ::Array[untyped] attr_reader parent: untyped attr_reader scope_level: untyped def initialize: (untyped hash, ?untyped parent, ?untyped? scope_level) -> untyped def nested?: () -> untyped def null?: () -> untyped def root?: () -> untyped def resources?: () -> untyped def resource_method_scope?: () -> untyped def action_name: (untyped name_prefix, untyped prefix, untyped collection_name, untyped member_name) -> untyped def resource_scope?: () -> untyped def options: () -> untyped def new: (untyped hash) -> untyped def new_level: (untyped level) -> untyped def []: (untyped key) -> untyped include Enumerable[untyped] def each: () { (untyped) -> untyped } -> untyped def frame: () -> untyped NULL: untyped end def initialize: (untyped set) -> untyped include Base include HttpHelpers include Redirection include Scoping include Concerns include Resources include CustomUrls end end end module ActionDispatch module Routing # Polymorphic URL helpers are methods for smart resolution to a named route call when # given an Active Record model instance. They are to be used in combination with # ActionController::Resources. # # These methods are useful when you want to generate the correct URL or path to a RESTful # resource without having to know the exact type of the record in question. # # Nested resources and/or namespaces are also supported, as illustrated in the example: # # polymorphic_url([:admin, @article, @comment]) # # results in: # # admin_article_comment_url(@article, @comment) # # == Usage within the framework # # Polymorphic URL helpers are used in a number of places throughout the \Rails framework: # # * url_for, so you can use it with a record as the argument, e.g. # url_for(@article); # * ActionView::Helpers::FormHelper uses polymorphic_path, so you can write # form_for(@article) without having to specify :url parameter for the form # action; # * redirect_to (which, in fact, uses url_for) so you can write # redirect_to(post) in your controllers; # * ActionView::Helpers::AtomFeedHelper, so you don't have to explicitly specify URLs # for feed entries. # # == Prefixed polymorphic helpers # # In addition to polymorphic_url and polymorphic_path methods, a # number of prefixed helpers are available as a shorthand to action: "..." # in options. Those are: # # * edit_polymorphic_url, edit_polymorphic_path # * new_polymorphic_url, new_polymorphic_path # # Example usage: # # edit_polymorphic_path(@post) # => "/posts/1/edit" # polymorphic_path(@post, format: :pdf) # => "/posts/1.pdf" # # == Usage with mounted engines # # If you are using a mounted engine and you need to use a polymorphic_url # pointing at the engine's routes, pass in the engine's route proxy as the first # argument to the method. For example: # # polymorphic_url([blog, @post]) # calls blog.post_path(@post) # form_for([blog, @post]) # => "/blog/posts/1" # module PolymorphicRoutes # Constructs a call to a named RESTful route for the given record and returns the # resulting URL string. For example: # # # calls post_url(post) # polymorphic_url(post) # => "http://example.com/posts/1" # polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1" # polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1" # polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1" # polymorphic_url(Comment) # => "http://example.com/comments" # # ==== Options # # * :action - Specifies the action prefix for the named route: # :new or :edit. Default is no prefix. # * :routing_type - Allowed values are :path or :url. # Default is :url. # # Also includes all the options from url_for. These include such # things as :anchor or :trailing_slash. Example usage # is given below: # # polymorphic_url([blog, post], anchor: 'my_anchor') # # => "http://example.com/blogs/1/posts/1#my_anchor" # polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app") # # => "http://example.com/my_app/blogs/1/posts/1#my_anchor" # # For all of these options, see the documentation for {url_for}[rdoc-ref:ActionDispatch::Routing::UrlFor]. # # ==== Functionality # # # an Article record # polymorphic_url(record) # same as article_url(record) # # # a Comment record # polymorphic_url(record) # same as comment_url(record) # # # it recognizes new records and maps to the collection # record = Comment.new # polymorphic_url(record) # same as comments_url() # # # the class of a record will also map to the collection # polymorphic_url(Comment) # same as comments_url() # def polymorphic_url: (untyped record_or_hash_or_array, ?::Hash[untyped, untyped] options) -> untyped # Returns the path component of a URL for the given record. def polymorphic_path: (untyped record_or_hash_or_array, ?::Hash[untyped, untyped] options) -> untyped private def polymorphic_url_for_action: (untyped action, untyped record_or_hash, untyped options) -> untyped def polymorphic_path_for_action: (untyped action, untyped record_or_hash, untyped options) -> untyped def polymorphic_mapping: (untyped record) -> untyped class HelperMethodBuilder # :nodoc: CACHE: ::Hash[untyped, untyped] def self.get: (untyped action, untyped `type`) -> untyped def self.url: () -> untyped def self.path: () -> untyped def self.build: (untyped action, untyped `type`) -> untyped def self.singular: (untyped prefix, untyped suffix) -> untyped def self.plural: (untyped prefix, untyped suffix) -> untyped def self.polymorphic_method: (untyped recipient, untyped record_or_hash_or_array, untyped action, untyped `type`, untyped options) -> untyped attr_reader suffix: untyped attr_reader prefix: untyped def initialize: (untyped key_strategy, untyped prefix, untyped suffix) -> untyped def handle_string: (untyped record) -> ::Array[untyped | ::Array[untyped]] def handle_string_call: (untyped target, untyped str) -> untyped def handle_class: (untyped klass) -> ::Array[untyped | ::Array[untyped]] def handle_class_call: (untyped target, untyped klass) -> untyped def handle_model: (untyped record) -> ::Array[untyped] def handle_model_call: (untyped target, untyped record) -> untyped def handle_list: (untyped list) -> ::Array[untyped] private def polymorphic_mapping: (untyped target, untyped record) -> untyped def get_method_for_class: (untyped klass) -> untyped def get_method_for_string: (untyped str) -> ::String end end end end module ActionDispatch module Routing class Redirect < Endpoint # :nodoc: attr_reader status: untyped # :nodoc: attr_reader block: untyped def initialize: (untyped status, untyped block) -> untyped def redirect?: () -> ::TrueClass def call: (untyped env) -> untyped def serve: (untyped req) -> ::Array[untyped | ::Array[untyped]] def path: (untyped params, untyped request) -> untyped def inspect: () -> ::String private def relative_path?: (untyped path) -> untyped def escape: (untyped params) -> untyped def escape_fragment: (untyped params) -> untyped def escape_path: (untyped params) -> untyped end class PathRedirect < Redirect URL_PARTS: untyped def path: (untyped params, untyped request) -> untyped def inspect: () -> ::String private def interpolation_required?: (untyped string, untyped params) -> untyped end class OptionRedirect < Redirect # :nodoc: alias options block def path: (untyped params, untyped request) -> untyped def inspect: () -> ::String end module Redirection # Redirect any path to another path: # # get "/stories" => redirect("/posts") # # This will redirect the user, while ignoring certain parts of the request, including query string, etc. # /stories, /stories?foo=bar, etc all redirect to /posts. # # You can also use interpolation in the supplied redirect argument: # # get 'docs/:article', to: redirect('/wiki/%{article}') # # Note that if you return a path without a leading slash then the URL is prefixed with the # current SCRIPT_NAME environment variable. This is typically '/' but may be different in # a mounted engine or where the application is deployed to a subdirectory of a website. # # Alternatively you can use one of the other syntaxes: # # The block version of redirect allows for the easy encapsulation of any logic associated with # the redirect in question. Either the params and request are supplied as arguments, or just # params, depending of how many arguments your block accepts. A string is required as a # return value. # # get 'jokes/:number', to: redirect { |params, request| # path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp") # "http://#{request.host_with_port}/#{path}" # } # # Note that the +do end+ syntax for the redirect block wouldn't work, as Ruby would pass # the block to +get+ instead of +redirect+. Use { ... } instead. # # The options version of redirect allows you to supply only the parts of the URL which need # to change, it also supports interpolation of the path similar to the first example. # # get 'stores/:name', to: redirect(subdomain: 'stores', path: '/%{name}') # get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}') # get '/stories', to: redirect(path: '/posts') # # This will redirect the user, while changing only the specified parts of the request, # for example the +path+ option in the last example. # /stories, /stories?foo=bar, redirect to /posts and /posts?foo=bar respectively. # # Finally, an object which responds to call can be supplied to redirect, allowing you to reuse # common redirect routes. The call method must accept two arguments, params and request, and return # a string. # # get 'accounts/:name' => redirect(SubdomainRedirector.new('api')) # def redirect: (*untyped args) { () -> untyped } -> (OptionRedirect | PathRedirect | Redirect) end end end module ActionDispatch module Routing # :stopdoc: class RouteSet # Since the router holds references to many parts of the system # like engines, controllers and the application itself, inspecting # the route set can actually be really slow, therefore we default # alias inspect to to_s. alias inspect to_s class Dispatcher < Routing::Endpoint def initialize: (untyped raise_on_name_error) -> untyped def dispatcher?: () -> ::TrueClass def serve: (untyped req) -> untyped private def controller: (untyped req) -> untyped def dispatch: (untyped controller, untyped action, untyped req, untyped res) -> untyped end class StaticDispatcher < Dispatcher def initialize: (untyped controller_class) -> untyped private def controller: (untyped _) -> untyped end # A NamedRouteCollection instance is a collection of named routes, and also # maintains an anonymous module that can be used to install helpers for the # named routes. class NamedRouteCollection include Enumerable[untyped] private attr_reader routes: untyped public attr_reader url_helpers_module: untyped attr_reader path_helpers_module: untyped def initialize: () -> untyped def route_defined?: (untyped name) -> untyped def helper_names: () -> untyped def clear!: () -> untyped def add: (untyped name, untyped route) -> untyped def get: (untyped name) -> untyped def key?: (untyped name) -> (nil | untyped) alias []= add alias [] get alias clear clear! def each: () { ([untyped, untyped]) -> untyped } -> untyped def names: () -> untyped def length: () -> untyped # Given a +name+, defines name_path and name_url helpers. # Used by 'direct', 'resolve', and 'polymorphic' route helpers. def add_url_helper: (untyped name, untyped defaults) { () -> untyped } -> untyped class UrlHelper def self.create: (untyped route, untyped options, untyped route_name, untyped url_strategy) -> untyped def self.optimize_helper?: (untyped route) -> untyped attr_reader url_strategy: untyped attr_reader route_name: untyped class OptimizedUrlHelper < UrlHelper attr_reader arg_size: untyped def initialize: (untyped route, untyped options, untyped route_name, untyped url_strategy) -> untyped def call: (untyped t, untyped args, untyped inner_options) -> untyped private def optimized_helper: (untyped args) -> untyped def optimize_routes_generation?: (untyped t) -> untyped def parameterize_args: (untyped args) { (untyped) -> untyped } -> untyped def raise_generation_error: (untyped args) -> untyped end def initialize: (untyped route, untyped options, untyped route_name, untyped url_strategy) -> untyped def call: (untyped t, untyped args, untyped inner_options) -> untyped def handle_positional_args: (untyped controller_options, untyped inner_options, untyped args, untyped result, untyped path_params) -> untyped end private # Create a URL helper allowing ordered parameters to be associated # with corresponding dynamic segments, so you can do: # # foo_url(bar, baz, bang) # # Instead of: # # foo_url(bar: bar, baz: baz, bang: bang) # # Also allow options hash, so you can do: # # foo_url(bar, baz, bang, sort_by: 'baz') # def define_url_helper: (untyped mod, untyped route, untyped name, untyped opts, untyped route_key, untyped url_strategy) -> untyped end # strategy for building URLs to send to the client PATH: untyped UNKNOWN: untyped attr_accessor formatter: untyped attr_accessor set: untyped attr_accessor named_routes: untyped attr_accessor default_scope: untyped attr_accessor router: untyped attr_accessor disable_clear_and_finalize: untyped attr_accessor resources_path_names: untyped attr_accessor default_url_options: untyped attr_reader env_key: untyped attr_reader polymorphic_mappings: untyped alias routes set def self.default_resources_path_names: () -> { new: "new", edit: "edit" } def self.new_with_config: (untyped config) -> untyped class Config[T] < ::Struct[T] attr_accessor relative_url_root(): untyped attr_accessor api_only(): untyped end DEFAULT_CONFIG: untyped def initialize: (?untyped config) -> untyped def eager_load!: () -> nil def relative_url_root: () -> untyped def api_only?: () -> untyped def request_class: () -> untyped private def make_request: (untyped env) -> untyped public def draw: () { () -> untyped } -> nil def append: () { () -> untyped } -> untyped def prepend: () { () -> untyped } -> untyped private def eval_block: (untyped block) -> untyped public def finalize!: () -> (nil | untyped) def clear!: () -> untyped module MountedHelpers extend ActiveSupport::Concern include UrlFor end # Contains all the mounted helpers across different # engines and the `main_app` helper for the application. # You can include this in your classes if you want to # access routes for other engines. def mounted_helpers: () -> untyped def define_mounted_helper: (untyped name, ?untyped? script_namer) -> (nil | untyped) def url_helpers: (?bool supports_path) -> untyped def empty?: () -> untyped def add_route: (untyped mapping, untyped name) -> untyped def add_polymorphic_mapping: (untyped klass, untyped options) { () -> untyped } -> untyped def add_url_helper: (untyped name, untyped options) { () -> untyped } -> untyped class CustomUrlHelper attr_reader name: untyped attr_reader defaults: untyped attr_reader block: untyped def initialize: (untyped name, untyped defaults) { () -> untyped } -> untyped def call: (untyped t, untyped args, ?bool only_path) -> untyped private def eval_block: (untyped t, untyped args, untyped options) -> untyped def merge_defaults: (untyped options) -> untyped end class Generator PARAMETERIZE: untyped attr_reader options: untyped attr_reader recall: untyped attr_reader set: untyped attr_reader named_route: untyped def initialize: (untyped named_route, untyped options, untyped recall, untyped set) -> untyped def controller: () -> untyped def current_controller: () -> untyped def use_recall_for: (untyped key) -> untyped def normalize_options!: () -> untyped # This pulls :controller, :action, and :id out of the recall. # The recall key is only used if there is no key in the options # or if the key in the options is identical. If any of # :controller, :action or :id is not found, don't pull any # more keys from the recall. def normalize_controller_action_id!: () -> (nil | untyped) # if the current controller is "foo/bar/baz" and controller: "baz/bat" # is specified, the controller becomes "foo/baz/bat" def use_relative_controller!: () -> untyped # Remove leading slashes from controllers def normalize_controller!: () -> untyped # Generates a path from routes, returns [path, params]. # If no route is generated the formatter will raise ActionController::UrlGenerationError def generate: () -> untyped def different_controller?: () -> (::FalseClass | untyped) private def named_route_exists?: () -> untyped def segment_keys: () -> untyped end # Generate the path indicated by the arguments, and return an array of # the keys that were not used to generate it. def extra_keys: (untyped options, ?::Hash[untyped, untyped] recall) -> untyped def generate_extras: (untyped options, ?::Hash[untyped, untyped] recall) -> untyped private def generate: (untyped route_key, untyped options, ?::Hash[untyped, untyped] recall) -> untyped public RESERVED_OPTIONS: ::Array[untyped] def optimize_routes_generation?: () -> untyped def find_script_name: (untyped options) -> untyped def find_relative_url_root: (untyped options) -> untyped def path_for: (untyped options, ?untyped? route_name) -> untyped # The +options+ argument must be a hash whose keys are *symbols*. def url_for: (untyped options, ?untyped? route_name, ?untyped url_strategy) -> untyped def call: (untyped env) -> untyped def recognize_path: (untyped path, ?::Hash[untyped, untyped] environment) -> untyped def recognize_path_with_request: (untyped req, untyped path, untyped extras, ?raise_on_missing: bool raise_on_missing) -> untyped end end end module ActionDispatch module Routing class RoutesProxy # nodoc: include ActionDispatch::Routing::UrlFor attr_accessor scope: untyped attr_accessor routes: untyped alias _routes routes def initialize: (untyped routes, untyped scope, untyped helpers, ?untyped? script_namer) -> untyped def url_options: () -> untyped private def respond_to_missing?: (untyped method, untyped _) -> untyped def method_missing: (untyped method, *untyped args) -> untyped # Keeps the part of the script name provided by the global # context via ENV["SCRIPT_NAME"], which `mount` doesn't know # about since it depends on the specific request, but use our # script name resolver for the mount point dependent part. def merge_script_names: (untyped previous_script_name, untyped new_script_name) -> untyped end end end module ActionDispatch module Routing # In config/routes.rb you define URL-to-controller mappings, but the reverse # is also possible: a URL can be generated from one of your routing definitions. # URL generation functionality is centralized in this module. # # See ActionDispatch::Routing for general information about routing and routes.rb. # # Tip: If you need to generate URLs from your models or some other place, # then ActionController::UrlFor is what you're looking for. Read on for # an introduction. In general, this module should not be included on its own, # as it is usually included by url_helpers (as in Rails.application.routes.url_helpers). # # == URL generation from parameters # # As you may know, some functions, such as ActionController::Base#url_for # and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set # of parameters. For example, you've probably had the chance to write code # like this in one of your views: # # <%= link_to('Click here', controller: 'users', # action: 'new', message: 'Welcome!') %> # # => Click here # # link_to, and all other functions that require URL generation functionality, # actually use ActionController::UrlFor under the hood. And in particular, # they use the ActionController::UrlFor#url_for method. One can generate # the same path as the above example by using the following code: # # include UrlFor # url_for(controller: 'users', # action: 'new', # message: 'Welcome!', # only_path: true) # # => "/users/new?message=Welcome%21" # # Notice the only_path: true part. This is because UrlFor has no # information about the website hostname that your Rails app is serving. So if you # want to include the hostname as well, then you must also pass the :host # argument: # # include UrlFor # url_for(controller: 'users', # action: 'new', # message: 'Welcome!', # host: 'www.example.com') # # => "http://www.example.com/users/new?message=Welcome%21" # # By default, all controllers and views have access to a special version of url_for, # that already knows what the current hostname is. So if you use url_for in your # controllers or your views, then you don't need to explicitly pass the :host # argument. # # For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for. # So within mailers, you only have to type +url_for+ instead of 'ActionController::UrlFor#url_for' # in full. However, mailers don't have hostname information, and you still have to provide # the +:host+ argument or set the default host that will be used in all mailers using the # configuration option +config.action_mailer.default_url_options+. For more information on # url_for in mailers read the ActionMailer#Base documentation. # # # == URL generation for named routes # # UrlFor also allows one to access methods that have been auto-generated from # named routes. For example, suppose that you have a 'users' resource in your # config/routes.rb: # # resources :users # # This generates, among other things, the method users_path. By default, # this method is accessible from your controllers, views and mailers. If you need # to access this auto-generated method from other places (such as a model), then # you can do that by including Rails.application.routes.url_helpers in your class: # # class User < ActiveRecord::Base # include Rails.application.routes.url_helpers # # def base_uri # user_path(self) # end # end # # User.find(1).base_uri # => "/users/1" # module UrlFor extend ActiveSupport::Concern include PolymorphicRoutes def initialize: () -> untyped # Hook overridden in controller to add request information # with +default_url_options+. Application logic should not # go into url_options. def url_options: () -> untyped # Generate a URL based on the options provided, default_url_options and the # routes defined in routes.rb. The following options are supported: # # * :only_path - If true, the relative URL is returned. Defaults to +false+. # * :protocol - The protocol to connect to. Defaults to 'http'. # * :host - Specifies the host the link should be targeted at. # If :only_path is false, this option must be # provided either explicitly, or via +default_url_options+. # * :subdomain - Specifies the subdomain of the link, using the +tld_length+ # to split the subdomain from the host. # If false, removes all subdomains from the host part of the link. # * :domain - Specifies the domain of the link, using the +tld_length+ # to split the domain from the host. # * :tld_length - Number of labels the TLD id composed of, only used if # :subdomain or :domain are supplied. Defaults to # ActionDispatch::Http::URL.tld_length, which in turn defaults to 1. # * :port - Optionally specify the port to connect to. # * :anchor - An anchor name to be appended to the path. # * :params - The query parameters to be appended to the path. # * :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/" # * :script_name - Specifies application path relative to domain root. If provided, prepends application path. # # Any other key (:controller, :action, etc.) given to # +url_for+ is forwarded to the Routes module. # # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', port: '8080' # # => 'http://somehost.org:8080/tasks/testing' # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', anchor: 'ok', only_path: true # # => '/tasks/testing#ok' # url_for controller: 'tasks', action: 'testing', trailing_slash: true # # => 'http://somehost.org/tasks/testing/' # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', number: '33' # # => 'http://somehost.org/tasks/testing?number=33' # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp" # # => 'http://somehost.org/myapp/tasks/testing' # url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp", only_path: true # # => '/myapp/tasks/testing' # # Missing routes keys may be filled in from the current request's parameters # (e.g. +:controller+, +:action+, +:id+ and any other parameters that are # placed in the path). Given that the current action has been reached # through GET /users/1: # # url_for(only_path: true) # => '/users/1' # url_for(only_path: true, action: 'edit') # => '/users/1/edit' # url_for(only_path: true, action: 'edit', id: 2) # => '/users/2/edit' # # Notice that no +:id+ parameter was provided to the first +url_for+ call # and the helper used the one from the route's path. Any path parameter # implicitly used by +url_for+ can always be overwritten like shown on the # last +url_for+ calls. def url_for: (?untyped? options) -> untyped def full_url_for: (?untyped? options) -> untyped # Allows calling direct or regular named route. # # resources :buckets # # direct :recordable do |recording| # route_for(:bucket, recording.bucket) # end # # direct :threadable do |threadable| # route_for(:recordable, threadable.parent) # end # # This maintains the context of the original caller on # whether to return a path or full URL, e.g: # # threadable_path(threadable) # => "/buckets/1" # threadable_url(threadable) # => "http://example.com/buckets/1" # def route_for: (untyped name, *untyped args) -> untyped def optimize_routes_generation?: () -> untyped private def _with_routes: (untyped routes) { () -> untyped } -> untyped def _routes_context: () -> untyped end end end module ActionDispatch # The routing module provides URL rewriting in native Ruby. It's a way to # redirect incoming requests to controllers and actions. This replaces # mod_rewrite rules. Best of all, Rails' \Routing works with any web server. # Routes are defined in config/routes.rb. # # Think of creating routes as drawing a map for your requests. The map tells # them where to go based on some predefined pattern: # # Rails.application.routes.draw do # Pattern 1 tells some request to go to one place # Pattern 2 tell them to go to another # ... # end # # The following symbols are special: # # :controller maps to your controller name # :action maps to an action with your controllers # # Other names simply map to a parameter as in the case of :id. # # == Resources # # Resource routing allows you to quickly declare all of the common routes # for a given resourceful controller. Instead of declaring separate routes # for your +index+, +show+, +new+, +edit+, +create+, +update+ and +destroy+ # actions, a resourceful route declares them in a single line of code: # # resources :photos # # Sometimes, you have a resource that clients always look up without # referencing an ID. A common example, /profile always shows the profile of # the currently logged in user. In this case, you can use a singular resource # to map /profile (rather than /profile/:id) to the show action. # # resource :profile # # It's common to have resources that are logically children of other # resources: # # resources :magazines do # resources :ads # end # # You may wish to organize groups of controllers under a namespace. Most # commonly, you might group a number of administrative controllers under # an +admin+ namespace. You would place these controllers under the # app/controllers/admin directory, and you can group them together # in your router: # # namespace "admin" do # resources :posts, :comments # end # # Alternatively, you can add prefixes to your path without using a separate # directory by using +scope+. +scope+ takes additional options which # apply to all enclosed routes. # # scope path: "/cpanel", as: 'admin' do # resources :posts, :comments # end # # For more, see Routing::Mapper::Resources#resources, # Routing::Mapper::Scoping#namespace, and # Routing::Mapper::Scoping#scope. # # == Non-resourceful routes # # For routes that don't fit the resources mold, you can use the HTTP helper # methods get, post, patch, put and delete. # # get 'post/:id', to: 'posts#show' # post 'post/:id', to: 'posts#create_comment' # # Now, if you POST to /posts/:id, it will route to the create_comment action. A GET on the same # URL will route to the show action. # # If your route needs to respond to more than one HTTP method (or all methods) then using the # :via option on match is preferable. # # match 'post/:id', to: 'posts#show', via: [:get, :post] # # == Named routes # # Routes can be named by passing an :as option, # allowing for easy reference within your source as +name_of_route_url+ # for the full URL and +name_of_route_path+ for the URI path. # # Example: # # # In config/routes.rb # get '/login', to: 'accounts#login', as: 'login' # # # With render, redirect_to, tests, etc. # redirect_to login_url # # Arguments can be passed as well. # # redirect_to show_item_path(id: 25) # # Use root as a shorthand to name a route for the root path "/". # # # In config/routes.rb # root to: 'blogs#index' # # # would recognize http://www.example.com/ as # params = { controller: 'blogs', action: 'index' } # # # and provide these named routes # root_url # => 'http://www.example.com/' # root_path # => '/' # # Note: when using +controller+, the route is simply named after the # method you call on the block parameter rather than map. # # # In config/routes.rb # controller :blog do # get 'blog/show', to: :list # get 'blog/delete', to: :delete # get 'blog/edit', to: :edit # end # # # provides named routes for show, delete, and edit # link_to @article.title, blog_show_path(id: @article.id) # # == Pretty URLs # # Routes can generate pretty URLs. For example: # # get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: { # year: /\d{4}/, # month: /\d{1,2}/, # day: /\d{1,2}/ # } # # Using the route above, the URL "http://localhost:3000/articles/2005/11/06" # maps to # # params = {year: '2005', month: '11', day: '06'} # # == Regular Expressions and parameters # You can specify a regular expression to define a format for a parameter. # # controller 'geocode' do # get 'geocode/:postalcode', to: :show, constraints: { # postalcode: /\d{5}(-\d{4})?/ # } # end # # Constraints can include the 'ignorecase' and 'extended syntax' regular # expression modifiers: # # controller 'geocode' do # get 'geocode/:postalcode', to: :show, constraints: { # postalcode: /hx\d\d\s\d[a-z]{2}/i # } # end # # controller 'geocode' do # get 'geocode/:postalcode', to: :show, constraints: { # postalcode: /# Postalcode format # \d{5} #Prefix # (-\d{4})? #Suffix # /x # } # end # # Using the multiline modifier will raise an +ArgumentError+. # Encoding regular expression modifiers are silently ignored. The # match will always use the default encoding or ASCII. # # == External redirects # # You can redirect any path to another path using the redirect helper in your router: # # get "/stories", to: redirect("/posts") # # == Unicode character routes # # You can specify unicode character routes in your router: # # get "(trim non-ascii characters)", to: "welcome#index" # # == Routing to Rack Applications # # Instead of a String, like posts#index, which corresponds to the # index action in the PostsController, you can specify any Rack application # as the endpoint for a matcher: # # get "/application.js", to: Sprockets # # == Reloading routes # # You can reload routes if you feel you must: # # Rails.application.reload_routes! # # This will clear all named routes and reload config/routes.rb if the file has been modified from # last load. To absolutely force reloading, use reload!. # # == Testing Routes # # The two main methods for testing your routes: # # === +assert_routing+ # # def test_movie_route_properly_splits # opts = {controller: "plugin", action: "checkout", id: "2"} # assert_routing "plugin/checkout/2", opts # end # # +assert_routing+ lets you test whether or not the route properly resolves into options. # # === +assert_recognizes+ # # def test_route_has_options # opts = {controller: "plugin", action: "show", id: "12"} # assert_recognizes opts, "/plugins/show/12" # end # # Note the subtle difference between the two: +assert_routing+ tests that # a URL fits options while +assert_recognizes+ tests that a URL # breaks into parameters properly. # # In tests you can simply pass the URL or named route to +get+ or +post+. # # def send_to_jail # get '/jail' # assert_response :success # end # # def goes_to_login # get login_url # #... # end # # == View a list of all your routes # # rails routes # # Target a specific controller with -c, or grep routes # using -g. Useful in conjunction with --expanded # which displays routes vertically. module Routing extend ActiveSupport::Autoload SEPARATORS: ::Array[untyped] HTTP_METHODS: ::Array[untyped] end end module ActionDispatch # = System Testing # # System tests let you test applications in the browser. Because system # tests use a real browser experience, you can test all of your JavaScript # easily from your test suite. # # To create a system test in your application, extend your test class # from ApplicationSystemTestCase. System tests use Capybara as a # base and allow you to configure the settings through your # application_system_test_case.rb file that is generated with a new # application or scaffold. # # Here is an example system test: # # require 'application_system_test_case' # # class Users::CreateTest < ApplicationSystemTestCase # test "adding a new user" do # visit users_path # click_on 'New User' # # fill_in 'Name', with: 'Arya' # click_on 'Create User' # # assert_text 'Arya' # end # end # # When generating an application or scaffold, an +application_system_test_case.rb+ # file will also be generated containing the base class for system testing. # This is where you can change the driver, add Capybara settings, and other # configuration for your system tests. # # require "test_helper" # # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase # driven_by :selenium, using: :chrome, screen_size: [1400, 1400] # end # # By default, ActionDispatch::SystemTestCase is driven by the # Selenium driver, with the Chrome browser, and a browser size of 1400x1400. # # Changing the driver configuration options is easy. Let's say you want to use # the Firefox browser instead of Chrome. In your +application_system_test_case.rb+ # file add the following: # # require "test_helper" # # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase # driven_by :selenium, using: :firefox # end # # +driven_by+ has a required argument for the driver name. The keyword # arguments are +:using+ for the browser and +:screen_size+ to change the # size of the browser screen. These two options are not applicable for # headless drivers and will be silently ignored if passed. # # Headless browsers such as headless Chrome and headless Firefox are also supported. # You can use these browsers by setting the +:using+ argument to +:headless_chrome+ or +:headless_firefox+. # # To use a headless driver, like Poltergeist, update your Gemfile to use # Poltergeist instead of Selenium and then declare the driver name in the # +application_system_test_case.rb+ file. In this case, you would leave out # the +:using+ option because the driver is headless, but you can still use # +:screen_size+ to change the size of the browser screen, also you can use # +:options+ to pass options supported by the driver. Please refer to your # driver documentation to learn about supported options. # # require "test_helper" # require "capybara/poltergeist" # # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase # driven_by :poltergeist, screen_size: [1400, 1400], options: # { js_errors: true } # end # # Some drivers require browser capabilities to be passed as a block instead # of through the +options+ hash. # # As an example, if you want to add mobile emulation on chrome, you'll have to # create an instance of selenium's +Chrome::Options+ object and add # capabilities with a block. # # The block will be passed an instance of ::Options where you can # define the capabilities you want. Please refer to your driver documentation # to learn about supported options. # # class ApplicationSystemTestCase < ActionDispatch::SystemTestCase # driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option| # driver_option.add_emulation(device_name: 'iPhone 6') # driver_option.add_extension('path/to/chrome_extension.crx') # end # end # # Because ActionDispatch::SystemTestCase is a shim between Capybara # and Rails, any driver that is supported by Capybara is supported by system # tests as long as you include the required gems and files. class SystemTestCase < ActiveSupport::TestCase include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize: () -> untyped def self.start_application: () -> untyped # System Test configuration options # # The default settings are Selenium, using Chrome, with a screen size # of 1400x1400. # # Examples: # # driven_by :poltergeist # # driven_by :selenium, screen_size: [800, 800] # # driven_by :selenium, using: :chrome # # driven_by :selenium, using: :headless_chrome # # driven_by :selenium, using: :firefox # # driven_by :selenium, using: :headless_firefox def self.driven_by: (untyped driver, ?options: ::Hash[untyped, untyped] options, ?screen_size: ::Array[untyped] screen_size, ?using: ::Symbol using) { () -> untyped } -> untyped def method_missing: (untyped method, *untyped args) { () -> untyped } -> untyped end end module ActionDispatch module SystemTesting class Browser # :nodoc: attr_reader name: untyped def initialize: (untyped name) -> untyped def type: () -> untyped def options: () -> untyped def capabilities: () -> untyped # driver_path can be configured as a proc. The webdrivers gem uses this # proc to update web drivers. Running this proc early allows us to only # update the webdriver once and avoid race conditions when using # parallel tests. def preload: () -> untyped private def headless_chrome_browser_options: () -> untyped def headless_firefox_browser_options: () -> untyped end end end module ActionDispatch module SystemTesting class Driver # :nodoc: def initialize: (untyped name, **untyped options) { () -> untyped } -> untyped def use: () -> untyped private def registerable?: () -> untyped def register: () -> untyped def define_browser_capabilities: (untyped capabilities) -> untyped def browser_options: () -> untyped def register_selenium: (untyped app) -> untyped def register_poltergeist: (untyped app) -> Capybara::Poltergeist::Driver def register_webkit: (untyped app) -> untyped def setup: () -> untyped end end end module ActionDispatch module SystemTesting class Server attr_accessor self.silence_puma: untyped def run: () -> untyped private def setup: () -> untyped def set_server: () -> untyped def set_port: () -> untyped end end end module ActionDispatch module SystemTesting module TestHelpers # Screenshot helper for system testing. module ScreenshotHelper # Takes a screenshot of the current page in the browser. # # +take_screenshot+ can be used at any point in your system tests to take # a screenshot of the current state. This can be useful for debugging or # automating visual testing. # # The screenshot will be displayed in your console, if supported. # # You can set the +RAILS_SYSTEM_TESTING_SCREENSHOT+ environment variable to # control the output. Possible values are: # * [+simple+ (default)] Only displays the screenshot path. # This is the default value. # * [+inline+] Display the screenshot in the terminal using the # iTerm image protocol (https://iterm2.com/documentation-images.html). # * [+artifact+] Display the screenshot in the terminal, using the terminal # artifact format (https://buildkite.github.io/terminal-to-html/inline-images/). def take_screenshot: () -> untyped # Takes a screenshot of the current page in the browser if the test # failed. # # +take_failed_screenshot+ is included in application_system_test_case.rb # that is generated with the application. To take screenshots when a test # fails add +take_failed_screenshot+ to the teardown block before clearing # sessions. def take_failed_screenshot: () -> untyped private def image_name: () -> untyped def image_path: () -> untyped def absolute_image_path: () -> untyped def save_image: () -> untyped def output_type: () -> untyped def display_image: () -> untyped def inline_base64: (untyped path) -> untyped def failed?: () -> untyped def supports_screenshot?: () -> untyped end end end end module ActionDispatch module SystemTesting module TestHelpers module SetupAndTeardown # :nodoc: DEFAULT_HOST: ::String def host!: (untyped host) -> untyped def before_setup: () -> untyped def before_teardown: () -> untyped def after_teardown: () -> untyped end end end end module ActionDispatch # This is a class that abstracts away an asserted response. It purposely # does not inherit from Response because it doesn't need it. That means it # does not have headers or a body. class AssertionResponse attr_reader code: untyped attr_reader name: untyped GENERIC_RESPONSE_CODES: ::Hash[untyped, untyped] # Accepts a specific response status code as an Integer (404) or String # ('404') or a response status range as a Symbol pseudo-code (:success, # indicating any 200-299 status code). def initialize: (untyped code_or_name) -> untyped def code_and_name: () -> ::String private def code_from_name: (untyped name) -> untyped def name_from_code: (untyped code) -> untyped end end module ActionDispatch module Assertions # A small suite of assertions that test responses from \Rails applications. module ResponseAssertions RESPONSE_PREDICATES: ::Hash[untyped, untyped] # Asserts that the response is one of the following types: # # * :success - Status code was in the 200-299 range # * :redirect - Status code was in the 300-399 range # * :missing - Status code was 404 # * :error - Status code was in the 500-599 range # # You can also pass an explicit status number like assert_response(501) # or its symbolic equivalent assert_response(:not_implemented). # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list. # # # Asserts that the response was a redirection # assert_response :redirect # # # Asserts that the response code was status code 401 (unauthorized) # assert_response 401 def assert_response: (untyped `type`, ?untyped? message) -> untyped # Asserts that the redirection options passed in match those of the redirect called in the latest action. # This match can be partial, such that assert_redirected_to(controller: "weblog") will also # match the redirection of redirect_to(controller: "weblog", action: "show") and so on. # # # Asserts that the redirection was to the "index" action on the WeblogController # assert_redirected_to controller: "weblog", action: "index" # # # Asserts that the redirection was to the named route login_url # assert_redirected_to login_url # # # Asserts that the redirection was to the URL for @customer # assert_redirected_to @customer # # # Asserts that the redirection matches the regular expression # assert_redirected_to %r(\Ahttp://example.org) def assert_redirected_to: (?::Hash[untyped, untyped] options, ?untyped? message) -> (::TrueClass | untyped) private # Proxy to to_param if the object will respond to it. def parameterize: (untyped value) -> untyped def normalize_argument_to_redirection: (untyped fragment) -> untyped def generate_response_message: (untyped expected, ?untyped actual) -> untyped def response_body_if_short: () -> ::String def location_if_redirected: () -> ::String def code_with_name: (untyped code_or_name) -> untyped end end end module ActionDispatch module Assertions # Suite of assertions to test routes generated by \Rails and the handling of requests made to them. module RoutingAssertions def setup: () -> untyped # Asserts that the routing of the given +path+ was handled correctly and that the parsed options (given in the +expected_options+ hash) # match +path+. Basically, it asserts that \Rails recognizes the route given by +expected_options+. # # Pass a hash in the second argument (+path+) to specify the request method. This is useful for routes # requiring a specific HTTP method. The hash should contain a :path with the incoming request path # and a :method containing the required HTTP verb. # # # Asserts that POSTing to /items will call the create action on ItemsController # assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post}) # # You can also pass in +extras+ with a hash containing URL parameters that would normally be in the query string. This can be used # to assert that values in the query string will end up in the params hash correctly. To test query strings you must use the extras # argument because appending the query string on the path directly will not work. For example: # # # Asserts that a path of '/items/list/1?view=print' returns the correct options # assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" }) # # The +message+ parameter allows you to pass in an error message that is displayed upon failure. # # # Check the default route (i.e., the index action) # assert_recognizes({controller: 'items', action: 'index'}, 'items') # # # Test a specific action # assert_recognizes({controller: 'items', action: 'list'}, 'items/list') # # # Test an action with a parameter # assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1') # # # Test a custom route # assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1') def assert_recognizes: (untyped expected_options, untyped path, ?::Hash[untyped, untyped] extras, ?untyped? msg) -> untyped # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+. # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures. # # The +defaults+ parameter is unused. # # # Asserts that the default action is generated for a route with no action # assert_generates "/items", controller: "items", action: "index" # # # Tests that the list action is properly routed # assert_generates "/items/list", controller: "items", action: "list" # # # Tests the generation of a route with a parameter # assert_generates "/items/list/1", { controller: "items", action: "list", id: "1" } # # # Asserts that the generated route gives us our custom route # assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" } def assert_generates: (untyped expected_path, untyped options, ?::Hash[untyped, untyped] defaults, ?::Hash[untyped, untyped] extras, ?untyped? message) -> untyped # Asserts that path and options match both ways; in other words, it verifies that path generates # options and then that options generates path. This essentially combines +assert_recognizes+ # and +assert_generates+ into one step. # # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The # +message+ parameter allows you to specify a custom error message to display upon failure. # # # Asserts a basic route: a controller with the default action (index) # assert_routing '/home', controller: 'home', action: 'index' # # # Test a route generated with a specific controller, action, and parameter (id) # assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23 # # # Asserts a basic route (controller + default action), with an error message if it fails # assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly' # # # Tests a route, providing a defaults hash # assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"} # # # Tests a route with an HTTP method # assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" }) def assert_routing: (untyped path, untyped options, ?::Hash[untyped, untyped] defaults, ?::Hash[untyped, untyped] extras, ?untyped? message) -> untyped # A helper to make it easier to test different route configurations. # This method temporarily replaces @routes with a new RouteSet instance. # # The new instance is yielded to the passed block. Typically the block # will create some routes using set.draw { match ... }: # # with_routing do |set| # set.draw do # resources :users # end # assert_equal "/users", users_path # end # def with_routing: () { (untyped) -> untyped } -> untyped # ROUTES TODO: These assertions should really work in an integration context def method_missing: (untyped selector, *untyped args) { () -> untyped } -> untyped private # Recognizes the route for a given path. def recognized_request_for: (untyped path, ?::Hash[untyped, untyped] extras, untyped msg) -> untyped def fail_on: (untyped exception_class, untyped message) { () -> untyped } -> untyped end end end module ActionDispatch module Assertions extend ActiveSupport::Concern include ResponseAssertions include RoutingAssertions include Rails::Dom::Testing::Assertions def html_document: () -> untyped end end module ActionDispatch module Integration # nodoc: module RequestHelpers # Performs a GET request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def get: (untyped path, **untyped args) -> untyped # Performs a POST request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def post: (untyped path, **untyped args) -> untyped # Performs a PATCH request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def patch: (untyped path, **untyped args) -> untyped # Performs a PUT request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def put: (untyped path, **untyped args) -> untyped # Performs a DELETE request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def delete: (untyped path, **untyped args) -> untyped # Performs a HEAD request with the given parameters. See ActionDispatch::Integration::Session#process # for more details. def head: (untyped path, **untyped args) -> untyped # Follow a single redirect response. If the last response was not a # redirect, an exception will be raised. Otherwise, the redirect is # performed on the location header. Any arguments are passed to the # underlying call to `get`. def follow_redirect!: (**untyped args) -> untyped end # An instance of this class represents a set of requests and responses # performed sequentially by a test process. Because you can instantiate # multiple sessions and run them side-by-side, you can also mimic (to some # limited extent) multiple simultaneous users interacting with your system. # # Typically, you will instantiate a new session using # IntegrationTest#open_session, rather than instantiating # Integration::Session directly. class Session DEFAULT_HOST: ::String include Minitest::Assertions include TestProcess include RequestHelpers include Assertions # The hostname used in the last request. def host: () -> untyped attr_writer host: untyped # The remote_addr used in the last request. attr_accessor remote_addr: untyped # The Accept header to send. attr_accessor accept: untyped # A map of the cookies returned by the last response, and which will be # sent with the next request. def cookies: () -> untyped # A reference to the controller instance used by the last request. attr_reader controller: untyped # A reference to the request instance used by the last request. attr_reader request: untyped # A reference to the response instance used by the last request. attr_reader response: untyped # A running counter of the number of requests processed. attr_accessor request_count: untyped include ActionDispatch::Routing::UrlFor # Create and initialize a new Session instance. def initialize: (untyped app) -> untyped def url_options: () -> untyped # Resets the instance. This can be used to reset the state information # in an existing session instance, so it can be used from a clean-slate # condition. # # session.reset! def reset!: () -> untyped # Specify whether or not the session should mimic a secure HTTPS request. # # session.https! # session.https!(false) def https!: (?bool flag) -> untyped # Returns +true+ if the session is mimicking a secure HTTPS request. # # if session.https? # ... # end def https?: () -> untyped # Performs the actual request. # # - +method+: The HTTP method (GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS) # as a symbol. # - +path+: The URI (as a String) on which you want to perform the # request. # - +params+: The HTTP parameters that you want to pass. This may # be +nil+, # a Hash, or a String that is appropriately encoded # (application/x-www-form-urlencoded or # multipart/form-data). # - +headers+: Additional headers to pass, as a Hash. The headers will be # merged into the Rack env hash. # - +env+: Additional env to pass, as a Hash. The headers will be # merged into the Rack env hash. # - +xhr+: Set to `true` if you want to make and Ajax request. # Adds request headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH. # The headers will be merged into the Rack env hash. # - +as+: Used for encoding the request with different content type. # Supports `:json` by default and will set the appropriate request headers. # The headers will be merged into the Rack env hash. # # This method is rarely used directly. Use +#get+, +#post+, or other standard # HTTP methods in integration tests. +#process+ is only required when using a # request method that doesn't have a method defined in the integration tests. # # This method returns the response status, after performing the request. # Furthermore, if this method was called from an ActionDispatch::IntegrationTest object, # then that object's @response instance variable will point to a Response object # which one can use to inspect the details of the response. # # Example: # process :get, '/author', params: { since: 201501011400 } def process: (untyped method, untyped path, ?as: untyped? as, ?xhr: bool xhr, ?env: untyped? env, ?headers: untyped? headers, ?params: untyped? params) -> untyped # Set the host name to use in the next request. # # session.host! "www.example.com" alias host! host= private def _mock_session: () -> untyped def build_full_uri: (untyped path, untyped env) -> ::String def build_expanded_path: (untyped path) { (untyped) -> untyped } -> untyped end module Runner include ActionDispatch::Assertions APP_SESSIONS: ::Hash[untyped, untyped] attr_reader app: untyped attr_accessor root_session: untyped def initialize: (*untyped args) { () -> untyped } -> untyped def before_setup: () -> untyped def integration_session: () -> untyped # Reset the current session. This is useful for testing multiple sessions # in a single test case. def reset!: () -> untyped def create_session: (untyped app) -> untyped def remove!: () -> untyped # Open a new session instance. If a block is given, the new session is # yielded to the block before being returned. # # session = open_session do |sess| # sess.extend(CustomAssertions) # end # # By default, a single session is automatically created for you, but you # can use this method to open multiple sessions that ought to be tested # simultaneously. def open_session: () { (untyped) -> untyped } -> untyped def assertions: () -> untyped def assertions=: (untyped assertions) -> untyped def copy_session_variables!: () -> untyped def default_url_options: () -> untyped def default_url_options=: (untyped options) -> untyped private def respond_to_missing?: (untyped method, untyped _) -> untyped # Delegate unhandled messages to the current session instance. def method_missing: (untyped method, *untyped args) { () -> untyped } -> untyped end end class IntegrationTest < ActiveSupport::TestCase include TestProcess::FixtureFile module UrlOptions extend ActiveSupport::Concern def url_options: () -> untyped end module Behavior extend ActiveSupport::Concern include Integration::Runner include ActionController::TemplateAssertions include ActionDispatch::Routing::UrlFor include UrlOptions module ClassMethods def app: () -> untyped def app=: (untyped app) -> untyped def register_encoder: (*untyped args, **untyped options) -> untyped end def app: () -> untyped def document_root_element: () -> untyped end include Behavior end end module ActionDispatch class RequestEncoder # :nodoc: class IdentityEncoder def content_type: () -> nil def accept_header: () -> nil def encode_params: (untyped params) -> untyped def response_parser: () -> untyped end attr_reader response_parser: untyped def initialize: (untyped mime_name, untyped param_encoder, untyped response_parser) -> untyped def content_type: () -> untyped def accept_header: () -> untyped def encode_params: (untyped params) -> untyped def self.parser: (untyped content_type) -> untyped def self.encoder: (untyped name) -> untyped def self.register_encoder: (untyped mime_name, ?response_parser: untyped? response_parser, ?param_encoder: untyped? param_encoder) -> untyped end end module ActionDispatch module TestProcess module FixtureFile # Shortcut for Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.fixture_path, path), type): # # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png') } # # To upload binary files on Windows, pass :binary as the last parameter. # This will not affect other platforms: # # post :change_avatar, params: { avatar: fixture_file_upload('files/spongebob.png', 'image/png', :binary) } def fixture_file_upload: (untyped path, ?untyped? mime_type, ?bool binary) -> Rack::Test::UploadedFile end include FixtureFile def assigns: (?untyped? key) -> untyped def session: () -> untyped def flash: () -> untyped def cookies: () -> untyped def redirect_to_url: () -> untyped end end module ActionDispatch class TestRequest < Request DEFAULT_ENV: untyped # Create a new test request with default +env+ values. def self.create: (?::Hash[untyped, untyped] env) -> untyped def self.default_env: () -> untyped def request_method=: (untyped method) -> untyped def host=: (untyped host) -> untyped def port=: (untyped number) -> untyped def request_uri=: (untyped uri) -> untyped def path=: (untyped path) -> untyped def action=: (untyped action_name) -> untyped def if_modified_since=: (untyped last_modified) -> untyped def if_none_match=: (untyped etag) -> untyped def remote_addr=: (untyped addr) -> untyped def user_agent=: (untyped user_agent) -> untyped def accept=: (untyped mime_types) -> untyped end end module ActionDispatch # Integration test methods such as ActionDispatch::Integration::Session#get # and ActionDispatch::Integration::Session#post return objects of class # TestResponse, which represent the HTTP response results of the requested # controller actions. # # See Response for more information on controller response objects. class TestResponse < Response def self.from_response: (untyped response) -> untyped def parsed_body: () -> untyped def response_parser: () -> untyped end end module Rack end module ActionDispatch extend ActiveSupport::Autoload class IllegalStateError < StandardError end class MissingController[T] < NameError[T] end module Http extend ActiveSupport::Autoload end module Session end end module ActionPack # Returns the version of the currently loaded Action Pack as a Gem::Version def self.gem_version: () -> Gem::Version module VERSION MAJOR: ::Integer MINOR: ::Integer TINY: ::Integer PRE: ::String STRING: untyped end end module ActionPack # Returns the version of the currently loaded ActionPack as a Gem::Version def self.version: () -> untyped end