module ActionView # nodoc: # = Action View Base # # Action View templates can be written in several ways. # If the template file has a .erb extension, then it uses the erubi[https://rubygems.org/gems/erubi] # template system which can embed Ruby into an HTML document. # If the template file has a .builder extension, then Jim Weirich's Builder::XmlMarkup library is used. # # == ERB # # You trigger ERB by using embeddings such as <% %>, <% -%>, and <%= %>. The <%= %> tag set is used when you want output. Consider the # following loop for names: # # Names of all the people # <% @people.each do |person| %> # Name: <%= person.name %>
# <% end %> # # The loop is setup in regular embedding tags <% %>, and the name is written using the output embedding tag <%= %>. Note that this # is not just a usage suggestion. Regular output functions like print or puts won't work with ERB templates. So this would be wrong: # # <%# WRONG %> # Hi, Mr. <% puts "Frodo" %> # # If you absolutely must write from within a function use +concat+. # # When on a line that only contains whitespaces except for the tag, <% %> suppresses leading and trailing whitespace, # including the trailing newline. <% %> and <%- -%> are the same. # Note however that <%= %> and <%= -%> are different: only the latter removes trailing whitespaces. # # === Using sub templates # # Using sub templates allows you to sidestep tedious replication and extract common display structures in shared templates. The # classic example is the use of a header and footer (even though the Action Pack-way would be to use Layouts): # # <%= render "shared/header" %> # Something really specific and terrific # <%= render "shared/footer" %> # # As you see, we use the output embeddings for the render methods. The render call itself will just return a string holding the # result of the rendering. The output embedding writes it to the current template. # # But you don't have to restrict yourself to static includes. Templates can share variables amongst themselves by using instance # variables defined using the regular embedding tags. Like this: # # <% @page_title = "A Wonderful Hello" %> # <%= render "shared/header" %> # # Now the header can pick up on the @page_title variable and use it for outputting a title tag: # # <%= @page_title %> # # === Passing local variables to sub templates # # You can pass local variables to sub templates by using a hash with the variable names as keys and the objects as values: # # <%= render "shared/header", { headline: "Welcome", person: person } %> # # These can now be accessed in shared/header with: # # Headline: <%= headline %> # First name: <%= person.first_name %> # # The local variables passed to sub templates can be accessed as a hash using the local_assigns hash. This lets you access the # variables as: # # Headline: <%= local_assigns[:headline] %> # # This is useful in cases where you aren't sure if the local variable has been assigned. Alternatively, you could also use # defined? headline to first check if the variable has been assigned before using it. # # === Template caching # # By default, Rails will compile each template to a method in order to render it. When you alter a template, # Rails will check the file's modification time and recompile it in development mode. # # == Builder # # Builder templates are a more programmatic alternative to ERB. They are especially useful for generating XML content. An XmlMarkup object # named +xml+ is automatically made available to templates with a .builder extension. # # Here are some basic examples: # # xml.em("emphasized") # => emphasized # xml.em { xml.b("emph & bold") } # => emph & bold # xml.a("A Link", "href" => "http://onestepback.org") # => A Link # xml.target("name" => "compile", "option" => "fast") # => # # NOTE: order of attributes is not specified. # # Any method with a block will be treated as an XML markup tag with nested markup in the block. For example, the following: # # xml.div do # xml.h1(@person.name) # xml.p(@person.bio) # end # # would produce something like: # #
#

David Heinemeier Hansson

#

A product of Danish Design during the Winter of '79...

#
# # Here is a full-length RSS example actually used on Basecamp: # # xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do # xml.channel do # xml.title(@feed_title) # xml.link(@url) # xml.description "Basecamp: Recent items" # xml.language "en-us" # xml.ttl "40" # # @recent_items.each do |item| # xml.item do # xml.title(item_title(item)) # xml.description(item_description(item)) if item_description(item) # xml.pubDate(item_pubDate(item)) # xml.guid(@person.firm.account.url + @recent_items.url(item)) # xml.link(@person.firm.account.url + @recent_items.url(item)) # # xml.tag!("dc:creator", item.author_name) if item_has_creator?(item) # end # end # end # end # # For more information on Builder please consult the {source # code}[https://github.com/jimweirich/builder]. class Base include Helpers include ::ERB::Util include Context def self.cache_template_loading: () -> untyped def self.cache_template_loading=: (untyped value) -> untyped def self.xss_safe?: () -> ::TrueClass def self.with_empty_template_cache: () -> untyped def self.changed?: (untyped other) -> untyped attr_reader view_renderer: untyped attr_reader lookup_context: untyped def assign: (untyped new_assigns) -> untyped def self.build_lookup_context: (untyped context) -> untyped def self.empty: () -> untyped def self.with_view_paths: (untyped view_paths, ?::Hash[untyped, untyped] assigns, ?untyped? controller) -> untyped def self.with_context: (untyped context, ?::Hash[untyped, untyped] assigns, ?untyped? controller) -> untyped NULL: untyped def initialize: (?untyped? lookup_context, ?::Hash[untyped, untyped] assigns, ?untyped? controller, ?untyped formats) -> untyped def _run: (untyped method, untyped template, untyped locals, untyped buffer) { () -> untyped } -> untyped def compiled_method_container: () -> untyped def in_rendering_context: (untyped options) { (untyped) -> untyped } -> untyped end end module ActionView class OutputBuffer < ActiveSupport::SafeBuffer # Used as a buffer for views # # The main difference between this and ActiveSupport::SafeBuffer # is for the methods `<<` and `safe_expr_append=` the inputs are # checked for nil before they are assigned and `to_s` is called on # the input. For example: # # obuf = ActionView::OutputBuffer.new "hello" # obuf << 5 # puts obuf # => "hello5" # # sbuf = ActiveSupport::SafeBuffer.new "hello" # sbuf << 5 # puts sbuf # => "hello\u0005" # # nodoc: def initialize: () -> untyped def <<: (untyped value) -> untyped alias append= << def safe_expr_append=: (untyped val) -> untyped alias safe_append= safe_concat end class StreamingBuffer # nodoc: def initialize: (untyped block) -> untyped def <<: (untyped value) -> untyped alias concat << alias append= << def safe_concat: (untyped value) -> untyped alias safe_append= safe_concat def html_safe?: () -> ::TrueClass def html_safe: () -> untyped end end module ActionView class CacheExpiry class Executor def initialize: (watcher: untyped watcher) -> untyped def before: (untyped target) -> untyped end def initialize: (watcher: untyped watcher) -> untyped def clear_cache_if_necessary: () -> untyped def clear_cache: () -> untyped def dirs_to_watch: () -> untyped def all_view_paths: () -> untyped end end module ActionView # = Action View Context # # Action View contexts are supplied to Action Controller to render a template. # The default Action View context is ActionView::Base. # # In order to work with Action Controller, a Context must just include this # module. The initialization of the variables used by the context # (@output_buffer, @view_flow, and @virtual_path) is responsibility of the # object that includes this module (although you can call _prepare_context # defined below). module Context attr_accessor output_buffer: untyped attr_accessor view_flow: untyped # Prepares the context by setting the appropriate instance variables. def _prepare_context: () -> untyped # Encapsulates the interaction with the view flow so it # returns the correct buffer on +yield+. This is usually # overwritten by helpers to add more behavior. def _layout_for: (?untyped? name) -> untyped end end module ActionView class DependencyTracker def self.find_dependencies: (untyped name, untyped template, ?untyped? view_paths) -> (::Array[untyped] | untyped) def self.register_tracker: (untyped `extension`, untyped tracker) -> untyped def self.remove_tracker: (untyped handler) -> untyped class ERBTracker # :nodoc: EXPLICIT_DEPENDENCY: untyped # A valid ruby identifier - suitable for class, method and specially variable names IDENTIFIER: untyped # Any kind of variable name. e.g. @instance, @@class, $global or local. # Possibly following a method call chain VARIABLE_OR_METHOD_CHAIN: untyped # A simple string literal. e.g. "School's out!" STRING: untyped # Part of any hash containing the :partial key PARTIAL_HASH_KEY: untyped # Part of any hash containing the :layout key LAYOUT_HASH_KEY: untyped # Matches: # partial: "comments/comment", collection: @all_comments => "comments/comment" # (object: @single_comment, partial: "comments/comment") => "comments/comment" # # "comments/comments" # 'comments/comments' # ('comments/comments') # # (@topic) => "topics/topic" # topics => "topics/topic" # (message.topics) => "topics/topic" RENDER_ARGUMENTS: untyped LAYOUT_DEPENDENCY: untyped def self.supports_view_paths?: () -> ::TrueClass def self.call: (untyped name, untyped template, ?untyped? view_paths) -> untyped def initialize: (untyped name, untyped template, ?untyped? view_paths) -> untyped def dependencies: () -> untyped attr_reader name: untyped attr_reader template: untyped def source: () -> untyped def directory: () -> untyped def render_dependencies: () -> untyped def add_dependencies: (untyped render_dependencies, untyped arguments, untyped pattern) -> untyped def add_dynamic_dependency: (untyped dependencies, untyped dependency) -> untyped def add_static_dependency: (untyped dependencies, untyped dependency) -> untyped def resolve_directories: (untyped wildcard_dependencies) -> (::Array[untyped] | untyped) def explicit_dependencies: () -> untyped end end end module ActionView class Digestor # Supported options: # # * name - Template name # * format - Template format # * finder - An instance of ActionView::LookupContext # * dependencies - An array of dependent views def self.digest: (name: untyped name, finder: untyped finder, ?format: untyped? format, ?dependencies: untyped? dependencies) -> untyped def self.logger: () -> untyped # Create a dependency tree for template named +name+. def self.tree: (untyped name, untyped finder, ?bool partial, ?::Hash[untyped, untyped] seen) -> untyped def self.find_template: (untyped finder, untyped name, untyped prefixes, untyped partial, untyped keys) -> untyped class Node attr_reader name: untyped attr_reader logical_name: untyped attr_reader template: untyped attr_reader children: untyped def self.create: (untyped name, untyped logical_name, untyped template, untyped partial) -> untyped def initialize: (untyped name, untyped logical_name, untyped template, ?untyped children) -> untyped def digest: (untyped finder, ?untyped stack) -> untyped def dependency_digest: (untyped finder, untyped stack) -> untyped def to_dep_map: () -> untyped end class Partial < Node end class Missing < Node def digest: (untyped finder, ?untyped _) -> ::String end class Injected < Node def digest: (untyped finder, ?untyped _) -> untyped end class NullLogger def self.debug: (untyped _) -> nil def self.error: (untyped _) -> nil end end end module ActionView class OutputFlow # nodoc: attr_reader content: untyped def initialize: () -> untyped # Called by _layout_for to read stored values. def get: (untyped key) -> untyped # Called by each renderer object to set the layout contents. def set: (untyped key, untyped value) -> untyped # Called by content_for def append: (untyped key, untyped value) -> untyped alias append! append end class StreamingFlow < OutputFlow # nodoc: def initialize: (untyped view, untyped fiber) -> untyped # Try to get stored content. If the content # is not available and we're inside the layout fiber, # then it will begin waiting for the given key and yield. def get: (untyped key) -> untyped # Appends the contents for the given key. This is called # by providing and resuming back to the fiber, # if that's the key it's waiting for. def append!: (untyped key, untyped value) -> untyped def inside_fiber?: () -> untyped end end module ActionView # Returns the version of the currently loaded Action View 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 ActionView module Helpers extend ::ActionView::Helpers::UrlHelper::ClassMethods extend ::ActionView::Helpers::SanitizeHelper::ClassMethods # = Active Model Helpers # nodoc: module ActiveModelHelper end module ActiveModelInstanceTag def object: () -> untyped def content_tag: (untyped `type`, untyped options) -> untyped def tag: (untyped `type`, untyped options) -> untyped def error_wrapping: (untyped html_tag) -> untyped def error_message: () -> untyped def object_has_errors?: () -> untyped def select_markup_helper?: (untyped `type`) -> untyped def tag_generate_errors?: (untyped options) -> untyped end end end module ActionView module Helpers # = Action View Asset Tag Helpers # nodoc: # This module provides methods for generating HTML that links views to assets such # as images, JavaScripts, stylesheets, and feeds. These methods do not verify # the assets exist before linking to them: # # image_tag("rails.png") # # => # stylesheet_link_tag("application") # # => module AssetTagHelper extend ActiveSupport::Concern include AssetUrlHelper include TagHelper # Returns an HTML script tag for each of the +sources+ provided. # # Sources may be paths to JavaScript files. Relative paths are assumed to be relative # to assets/javascripts, full paths are assumed to be relative to the document # root. Relative paths are idiomatic, use absolute paths only when needed. # # When passing paths, the ".js" extension is optional. If you do not want ".js" # appended to the path extname: false can be set on the options. # # You can modify the HTML attributes of the script tag by passing a hash as the # last argument. # # When the Asset Pipeline is enabled, you can pass the name of your manifest as # source, and include other JavaScript or CoffeeScript files inside the manifest. # # If the server supports Early Hints header links for these assets will be # automatically pushed. # # ==== Options # # When the last parameter is a hash you can add HTML attributes using that # parameter. The following options are supported: # # * :extname - Append an extension to the generated URL unless the extension # already exists. This only applies for relative URLs. # * :protocol - Sets the protocol of the generated URL. This option only # applies when a relative URL and +host+ options are provided. # * :host - When a relative URL is provided the host is added to the # that path. # * :skip_pipeline - This option is used to bypass the asset pipeline # when it is set to true. # * :nonce - When set to true, adds an automatic nonce value if # you have Content Security Policy enabled. # # ==== Examples # # javascript_include_tag "xmlhr" # # => # # javascript_include_tag "xmlhr", host: "localhost", protocol: "https" # # => # # javascript_include_tag "template.jst", extname: false # # => # # javascript_include_tag "xmlhr.js" # # => # # javascript_include_tag "common.javascript", "/elsewhere/cools" # # => # # # # javascript_include_tag "http://www.example.com/xmlhr" # # => # # javascript_include_tag "http://www.example.com/xmlhr.js" # # => # # javascript_include_tag "http://www.example.com/xmlhr.js", nonce: true # # => def javascript_include_tag: (*untyped sources) -> untyped # Returns a stylesheet link tag for the sources specified as arguments. If # you don't specify an extension, .css will be appended automatically. # You can modify the link attributes by passing a hash as the last argument. # For historical reasons, the 'media' attribute will always be present and defaults # to "screen", so you must explicitly set it to "all" for the stylesheet(s) to # apply to all media types. # # If the server supports Early Hints header links for these assets will be # automatically pushed. # # stylesheet_link_tag "style" # # => # # stylesheet_link_tag "style.css" # # => # # stylesheet_link_tag "http://www.example.com/style.css" # # => # # stylesheet_link_tag "style", media: "all" # # => # # stylesheet_link_tag "style", media: "print" # # => # # stylesheet_link_tag "random.styles", "/css/stylish" # # => # # def stylesheet_link_tag: (*untyped sources) -> untyped # Returns a link tag that browsers and feed readers can use to auto-detect # an RSS, Atom, or JSON feed. The +type+ can be :rss (default), # :atom, or :json. Control the link options in url_for format # using the +url_options+. You can modify the LINK tag itself in +tag_options+. # # ==== Options # # * :rel - Specify the relation of this link, defaults to "alternate" # * :type - Override the auto-generated mime type # * :title - Specify the title of the link, defaults to the +type+ # # ==== Examples # # auto_discovery_link_tag # # => # auto_discovery_link_tag(:atom) # # => # auto_discovery_link_tag(:json) # # => # auto_discovery_link_tag(:rss, {action: "feed"}) # # => # auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"}) # # => # auto_discovery_link_tag(:rss, {controller: "news", action: "feed"}) # # => # auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"}) # # => def auto_discovery_link_tag: (?::Symbol `type`, ?::Hash[untyped, untyped] url_options, ?::Hash[untyped, untyped] tag_options) -> untyped # Returns a link tag for a favicon managed by the asset pipeline. # # If a page has no link like the one generated by this helper, browsers # ask for /favicon.ico automatically, and cache the file if the # request succeeds. If the favicon changes it is hard to get it updated. # # To have better control applications may let the asset pipeline manage # their favicon storing the file under app/assets/images, and # using this helper to generate its corresponding link tag. # # The helper gets the name of the favicon file as first argument, which # defaults to "favicon.ico", and also supports +:rel+ and +:type+ options # to override their defaults, "shortcut icon" and "image/x-icon" # respectively: # # favicon_link_tag # # => # # favicon_link_tag 'myicon.ico' # # => # # Mobile Safari looks for a different link tag, pointing to an image that # will be used if you add the page to the home screen of an iOS device. # The following call would generate such a tag: # # favicon_link_tag 'mb-icon.png', rel: 'apple-touch-icon', type: 'image/png' # # => def favicon_link_tag: (?::String source, ?::Hash[untyped, untyped] options) -> untyped # Returns a link tag that browsers can use to preload the +source+. # The +source+ can be the path of a resource managed by asset pipeline, # a full path, or an URI. # # ==== Options # # * :type - Override the auto-generated mime type, defaults to the mime type for +source+ extension. # * :as - Override the auto-generated value for as attribute, calculated using +source+ extension and mime type. # * :crossorigin - Specify the crossorigin attribute, required to load cross-origin resources. # * :nopush - Specify if the use of server push is not desired for the resource. Defaults to +false+. # # ==== Examples # # preload_link_tag("custom_theme.css") # # => # # preload_link_tag("/videos/video.webm") # # => # # preload_link_tag(post_path(format: :json), as: "fetch") # # => # # preload_link_tag("worker.js", as: "worker") # # => # # preload_link_tag("//example.com/font.woff2") # # => # # preload_link_tag("//example.com/font.woff2", crossorigin: "use-credentials") # # => # # preload_link_tag("/media/audio.ogg", nopush: true) # # => # def preload_link_tag: (untyped source, ?::Hash[untyped, untyped] options) -> untyped # Returns an HTML image tag for the +source+. The +source+ can be a full # path, a file, or an Active Storage attachment. # # ==== Options # # You can add HTML attributes using the +options+. The +options+ supports # additional keys for convenience and conformance: # # * :size - Supplied as "{Width}x{Height}" or "{Number}", so "30x45" becomes # width="30" and height="45", and "50" becomes width="50" and height="50". # :size will be ignored if the value is not in the correct format. # * :srcset - If supplied as a hash or array of [source, descriptor] # pairs, each image path will be expanded before the list is formatted as a string. # # ==== Examples # # Assets (images that are part of your app): # # image_tag("icon") # # => # image_tag("icon.png") # # => # image_tag("icon.png", size: "16x10", alt: "Edit Entry") # # => Edit Entry # image_tag("/icons/icon.gif", size: "16") # # => # image_tag("/icons/icon.gif", height: '32', width: '32') # # => # image_tag("/icons/icon.gif", class: "menu_icon") # # => # image_tag("/icons/icon.gif", data: { title: 'Rails Application' }) # # => # image_tag("icon.png", srcset: { "icon_2x.png" => "2x", "icon_4x.png" => "4x" }) # # => # image_tag("pic.jpg", srcset: [["pic_1024.jpg", "1024w"], ["pic_1980.jpg", "1980w"]], sizes: "100vw") # # => # # Active Storage blobs (images that are uploaded by the users of your app): # # image_tag(user.avatar) # # => # image_tag(user.avatar.variant(resize_to_limit: [100, 100])) # # => # image_tag(user.avatar.variant(resize_to_limit: [100, 100]), size: '100') # # => def image_tag: (untyped source, ?::Hash[untyped, untyped] options) -> untyped # Returns an HTML video tag for the +sources+. If +sources+ is a string, # a single video tag will be returned. If +sources+ is an array, a video # tag with nested source tags for each source will be returned. The # +sources+ can be full paths or files that exist in your public videos # directory. # # ==== Options # # When the last parameter is a hash you can add HTML attributes using that # parameter. The following options are supported: # # * :poster - Set an image (like a screenshot) to be shown # before the video loads. The path is calculated like the +src+ of +image_tag+. # * :size - Supplied as "{Width}x{Height}" or "{Number}", so "30x45" becomes # width="30" and height="45", and "50" becomes width="50" and height="50". # :size will be ignored if the value is not in the correct format. # * :poster_skip_pipeline will bypass the asset pipeline when using # the :poster option instead using an asset in the public folder. # # ==== Examples # # video_tag("trailer") # # => # video_tag("trailer.ogg") # # => # video_tag("trailer.ogg", controls: true, preload: 'none') # # => # video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png") # # => # video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png", poster_skip_pipeline: true) # # => # video_tag("/trailers/hd.avi", size: "16x16") # # => # video_tag("/trailers/hd.avi", size: "16") # # => # video_tag("/trailers/hd.avi", height: '32', width: '32') # # => # video_tag("trailer.ogg", "trailer.flv") # # => # video_tag(["trailer.ogg", "trailer.flv"]) # # => # video_tag(["trailer.ogg", "trailer.flv"], size: "160x120") # # => def video_tag: (*untyped sources) -> untyped # Returns an HTML audio tag for the +sources+. If +sources+ is a string, # a single audio tag will be returned. If +sources+ is an array, an audio # tag with nested source tags for each source will be returned. The # +sources+ can be full paths or files that exist in your public audios # directory. # # When the last parameter is a hash you can add HTML attributes using that # parameter. # # audio_tag("sound") # # => # audio_tag("sound.wav") # # => # audio_tag("sound.wav", autoplay: true, controls: true) # # => # audio_tag("sound.wav", "sound.mid") # # => def audio_tag: (*untyped sources) -> untyped def multiple_sources_tag_builder: (untyped `type`, untyped sources) { (untyped) -> untyped } -> untyped def resolve_image_source: (untyped source, untyped skip_pipeline) -> untyped def extract_dimensions: (untyped size) -> untyped def check_for_image_tag_errors: (untyped options) -> untyped def resolve_link_as: (untyped extname, untyped mime_type) -> untyped end end end module ActionView module Helpers # = Action View Asset URL Helpers # nodoc: # This module provides methods for generating asset paths and # URLs. # # image_path("rails.png") # # => "/assets/rails.png" # # image_url("rails.png") # # => "http://www.example.com/assets/rails.png" # # === Using asset hosts # # By default, Rails links to these assets on the current host in the public # folder, but you can direct Rails to link to assets from a dedicated asset # server by setting ActionController::Base.asset_host in the application # configuration, typically in config/environments/production.rb. # For example, you'd define assets.example.com to be your asset # host this way, inside the configure block of your environment-specific # configuration files or config/application.rb: # # config.action_controller.asset_host = "assets.example.com" # # Helpers take that into account: # # image_tag("rails.png") # # => # stylesheet_link_tag("application") # # => # # Browsers open a limited number of simultaneous connections to a single # host. The exact number varies by browser and version. This limit may cause # some asset downloads to wait for previous assets to finish before they can # begin. You can use the %d wildcard in the +asset_host+ to # distribute the requests over four hosts. For example, # assets%d.example.com will spread the asset requests over # "assets0.example.com", ..., "assets3.example.com". # # image_tag("rails.png") # # => # stylesheet_link_tag("application") # # => # # This may improve the asset loading performance of your application. # It is also possible the combination of additional connection overhead # (DNS, SSL) and the overall browser connection limits may result in this # solution being slower. You should be sure to measure your actual # performance across targeted browsers both before and after this change. # # To implement the corresponding hosts you can either setup four actual # hosts or use wildcard DNS to CNAME the wildcard to a single asset host. # You can read more about setting up your DNS CNAME records from your ISP. # # Note: This is purely a browser performance optimization and is not meant # for server load balancing. See https://www.die.net/musings/page_load_time/ # for background and https://www.browserscope.org/?category=network for # connection limit data. # # Alternatively, you can exert more control over the asset host by setting # +asset_host+ to a proc like this: # # ActionController::Base.asset_host = Proc.new { |source| # "http://assets#{Digest::MD5.hexdigest(source).to_i(16) % 2 + 1}.example.com" # } # image_tag("rails.png") # # => # stylesheet_link_tag("application") # # => # # The example above generates "http://assets1.example.com" and # "http://assets2.example.com". This option is useful for example if # you need fewer/more than four hosts, custom host names, etc. # # As you see the proc takes a +source+ parameter. That's a string with the # absolute path of the asset, for example "/assets/rails.png". # # ActionController::Base.asset_host = Proc.new { |source| # if source.ends_with?('.css') # "http://stylesheets.example.com" # else # "http://assets.example.com" # end # } # image_tag("rails.png") # # => # stylesheet_link_tag("application") # # => # # Alternatively you may ask for a second parameter +request+. That one is # particularly useful for serving assets from an SSL-protected page. The # example proc below disables asset hosting for HTTPS connections, while # still sending assets for plain HTTP requests from asset hosts. If you don't # have SSL certificates for each of the asset hosts this technique allows you # to avoid warnings in the client about mixed media. # Note that the +request+ parameter might not be supplied, e.g. when the assets # are precompiled with the command `rails assets:precompile`. Make sure to use a # +Proc+ instead of a lambda, since a +Proc+ allows missing parameters and sets them # to +nil+. # # config.action_controller.asset_host = Proc.new { |source, request| # if request && request.ssl? # "#{request.protocol}#{request.host_with_port}" # else # "#{request.protocol}assets.example.com" # end # } # # You can also implement a custom asset host object that responds to +call+ # and takes either one or two parameters just like the proc. # # config.action_controller.asset_host = AssetHostingWithMinimumSsl.new( # "http://asset%d.example.com", "https://asset1.example.com" # ) # module AssetUrlHelper URI_REGEXP: untyped # This is the entry point for all assets. # When using the asset pipeline (i.e. sprockets and sprockets-rails), the # behavior is "enhanced". You can bypass the asset pipeline by passing in # skip_pipeline: true to the options. # # All other asset *_path helpers delegate through this method. # # === With the asset pipeline # # All options passed to +asset_path+ will be passed to +compute_asset_path+ # which is implemented by sprockets-rails. # # asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js" # # === Without the asset pipeline (skip_pipeline: true) # # Accepts a type option that can specify the asset's extension. No error # checking is done to verify the source passed into +asset_path+ is valid # and that the file exists on disk. # # asset_path("application.js", skip_pipeline: true) # => "application.js" # asset_path("filedoesnotexist.png", skip_pipeline: true) # => "filedoesnotexist.png" # asset_path("application", type: :javascript, skip_pipeline: true) # => "/javascripts/application.js" # asset_path("application", type: :stylesheet, skip_pipeline: true) # => "/stylesheets/application.css" # # === Options applying to all assets # # Below lists scenarios that apply to +asset_path+ whether or not you're # using the asset pipeline. # # - All fully qualified URLs are returned immediately. This bypasses the # asset pipeline and all other behavior described. # # asset_path("http://www.example.com/js/xmlhr.js") # => "http://www.example.com/js/xmlhr.js" # # - All assets that begin with a forward slash are assumed to be full # URLs and will not be expanded. This will bypass the asset pipeline. # # asset_path("/foo.png") # => "/foo.png" # # - All blank strings will be returned immediately. This bypasses the # asset pipeline and all other behavior described. # # asset_path("") # => "" # # - If config.relative_url_root is specified, all assets will have that # root prepended. # # Rails.application.config.relative_url_root = "bar" # asset_path("foo.js", skip_pipeline: true) # => "bar/foo.js" # # - A different asset host can be specified via config.action_controller.asset_host # this is commonly used in conjunction with a CDN. # # Rails.application.config.action_controller.asset_host = "assets.example.com" # asset_path("foo.js", skip_pipeline: true) # => "http://assets.example.com/foo.js" # # - An extension name can be specified manually with extname. # # asset_path("foo", skip_pipeline: true, extname: ".js") # => "/foo.js" # asset_path("foo.css", skip_pipeline: true, extname: ".js") # => "/foo.css.js" def asset_path: (untyped source, ?::Hash[untyped, untyped] options) -> (::String | untyped) alias path_to_asset asset_path # Computes the full URL to an asset in the public directory. This # will use +asset_path+ internally, so most of their behaviors # will be the same. If :host options is set, it overwrites global # +config.action_controller.asset_host+ setting. # # All other options provided are forwarded to +asset_path+ call. # # asset_url "application.js" # => http://example.com/assets/application.js # asset_url "application.js", host: "http://cdn.example.com" # => http://cdn.example.com/assets/application.js # def asset_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_asset asset_url ASSET_EXTENSIONS: ::Hash[untyped, untyped] # Compute extname to append to asset path. Returns +nil+ if # nothing should be added. def compute_asset_extname: (untyped source, ?::Hash[untyped, untyped] options) -> (nil | untyped) # Maps asset types to public directory. ASSET_PUBLIC_DIRECTORIES: ::Hash[untyped, untyped] # Computes asset path to public directory. Plugins and # extensions can override this method to point to custom assets # or generate digested paths or query strings. def compute_asset_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias public_compute_asset_path compute_asset_path # Pick an asset host for this source. Returns +nil+ if no host is set, # the host if no wildcard is set, the host interpolated with the # numbers 0-3 if it contains %d (the number is the source hash mod 4), # or the value returned from invoking call on an object responding to call # (proc or otherwise). def compute_asset_host: (?::String source, ?::Hash[untyped, untyped] options) -> (nil | untyped) # Computes the path to a JavaScript asset in the public javascripts directory. # If the +source+ filename has no extension, .js will be appended (except for explicit URIs) # Full paths from the document root will be passed through. # Used internally by +javascript_include_tag+ to build the script path. # # javascript_path "xmlhr" # => /assets/xmlhr.js # javascript_path "dir/xmlhr.js" # => /assets/dir/xmlhr.js # javascript_path "/dir/xmlhr" # => /dir/xmlhr.js # javascript_path "http://www.example.com/js/xmlhr" # => http://www.example.com/js/xmlhr # javascript_path "http://www.example.com/js/xmlhr.js" # => http://www.example.com/js/xmlhr.js def javascript_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_javascript javascript_path # Computes the full URL to a JavaScript asset in the public javascripts directory. # This will use +javascript_path+ internally, so most of their behaviors will be the same. # Since +javascript_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # javascript_url "js/xmlhr.js", host: "http://stage.example.com" # => http://stage.example.com/assets/js/xmlhr.js # def javascript_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_javascript javascript_url # Computes the path to a stylesheet asset in the public stylesheets directory. # If the +source+ filename has no extension, .css will be appended (except for explicit URIs). # Full paths from the document root will be passed through. # Used internally by +stylesheet_link_tag+ to build the stylesheet path. # # stylesheet_path "style" # => /assets/style.css # stylesheet_path "dir/style.css" # => /assets/dir/style.css # stylesheet_path "/dir/style.css" # => /dir/style.css # stylesheet_path "http://www.example.com/css/style" # => http://www.example.com/css/style # stylesheet_path "http://www.example.com/css/style.css" # => http://www.example.com/css/style.css def stylesheet_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_stylesheet stylesheet_path # Computes the full URL to a stylesheet asset in the public stylesheets directory. # This will use +stylesheet_path+ internally, so most of their behaviors will be the same. # Since +stylesheet_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # stylesheet_url "css/style.css", host: "http://stage.example.com" # => http://stage.example.com/assets/css/style.css # def stylesheet_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_stylesheet stylesheet_url # Computes the path to an image asset. # Full paths from the document root will be passed through. # Used internally by +image_tag+ to build the image path: # # image_path("edit") # => "/assets/edit" # image_path("edit.png") # => "/assets/edit.png" # image_path("icons/edit.png") # => "/assets/icons/edit.png" # image_path("/icons/edit.png") # => "/icons/edit.png" # image_path("http://www.example.com/img/edit.png") # => "http://www.example.com/img/edit.png" # # If you have images as application resources this method may conflict with their named routes. # The alias +path_to_image+ is provided to avoid that. Rails uses the alias internally, and # plugin authors are encouraged to do so. def image_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_image image_path # Computes the full URL to an image asset. # This will use +image_path+ internally, so most of their behaviors will be the same. # Since +image_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # image_url "edit.png", host: "http://stage.example.com" # => http://stage.example.com/assets/edit.png # def image_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_image image_url # Computes the path to a video asset in the public videos directory. # Full paths from the document root will be passed through. # Used internally by +video_tag+ to build the video path. # # video_path("hd") # => /videos/hd # video_path("hd.avi") # => /videos/hd.avi # video_path("trailers/hd.avi") # => /videos/trailers/hd.avi # video_path("/trailers/hd.avi") # => /trailers/hd.avi # video_path("http://www.example.com/vid/hd.avi") # => http://www.example.com/vid/hd.avi def video_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_video video_path # Computes the full URL to a video asset in the public videos directory. # This will use +video_path+ internally, so most of their behaviors will be the same. # Since +video_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # video_url "hd.avi", host: "http://stage.example.com" # => http://stage.example.com/videos/hd.avi # def video_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_video video_url # Computes the path to an audio asset in the public audios directory. # Full paths from the document root will be passed through. # Used internally by +audio_tag+ to build the audio path. # # audio_path("horse") # => /audios/horse # audio_path("horse.wav") # => /audios/horse.wav # audio_path("sounds/horse.wav") # => /audios/sounds/horse.wav # audio_path("/sounds/horse.wav") # => /sounds/horse.wav # audio_path("http://www.example.com/sounds/horse.wav") # => http://www.example.com/sounds/horse.wav def audio_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_audio audio_path # Computes the full URL to an audio asset in the public audios directory. # This will use +audio_path+ internally, so most of their behaviors will be the same. # Since +audio_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # audio_url "horse.wav", host: "http://stage.example.com" # => http://stage.example.com/audios/horse.wav # def audio_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_audio audio_url # Computes the path to a font asset. # Full paths from the document root will be passed through. # # font_path("font") # => /fonts/font # font_path("font.ttf") # => /fonts/font.ttf # font_path("dir/font.ttf") # => /fonts/dir/font.ttf # font_path("/dir/font.ttf") # => /dir/font.ttf # font_path("http://www.example.com/dir/font.ttf") # => http://www.example.com/dir/font.ttf def font_path: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias path_to_font font_path # Computes the full URL to a font asset. # This will use +font_path+ internally, so most of their behaviors will be the same. # Since +font_url+ is based on +asset_url+ method you can set :host options. If :host # options is set, it overwrites global +config.action_controller.asset_host+ setting. # # font_url "font.ttf", host: "http://stage.example.com" # => http://stage.example.com/fonts/font.ttf # def font_url: (untyped source, ?::Hash[untyped, untyped] options) -> untyped alias url_to_font font_url end end end module ActionView module Helpers # = Action View Atom Feed Helpers # nodoc: module AtomFeedHelper # Adds easy defaults to writing Atom feeds with the Builder template engine (this does not work on ERB or any other # template languages). # # Full usage example: # # config/routes.rb: # Rails.application.routes.draw do # resources :posts # root to: "posts#index" # end # # app/controllers/posts_controller.rb: # class PostsController < ApplicationController # # GET /posts.html # # GET /posts.atom # def index # @posts = Post.all # # respond_to do |format| # format.html # format.atom # end # end # end # # app/views/posts/index.atom.builder: # atom_feed do |feed| # feed.title("My great blog!") # feed.updated(@posts[0].created_at) if @posts.length > 0 # # @posts.each do |post| # feed.entry(post) do |entry| # entry.title(post.title) # entry.content(post.body, type: 'html') # # entry.author do |author| # author.name("DHH") # end # end # end # end # # The options for atom_feed are: # # * :language: Defaults to "en-US". # * :root_url: The HTML alternative that this feed is doubling for. Defaults to / on the current host. # * :url: The URL for this feed. Defaults to the current URL. # * :id: The id for this feed. Defaults to "tag:localhost,2005:/posts", in this case. # * :schema_date: The date at which the tag scheme for the feed was first used. A good default is the year you # created the feed. See http://feedvalidator.org/docs/error/InvalidTAG.html for more information. If not specified, # 2005 is used (as an "I don't care" value). # * :instruct: Hash of XML processing instructions in the form {target => {attribute => value, }} or {target => [{attribute => value, }, ]} # # Other namespaces can be added to the root element: # # app/views/posts/index.atom.builder: # atom_feed({'xmlns:app' => 'http://www.w3.org/2007/app', # 'xmlns:openSearch' => 'http://a9.com/-/spec/opensearch/1.1/'}) do |feed| # feed.title("My great blog!") # feed.updated((@posts.first.created_at)) # feed.tag!('openSearch:totalResults', 10) # # @posts.each do |post| # feed.entry(post) do |entry| # entry.title(post.title) # entry.content(post.body, type: 'html') # entry.tag!('app:edited', Time.now) # # entry.author do |author| # author.name("DHH") # end # end # end # end # # The Atom spec defines five elements (content rights title subtitle # summary) which may directly contain xhtml content if type: 'xhtml' # is specified as an attribute. If so, this helper will take care of # the enclosing div and xhtml namespace declaration. Example usage: # # entry.summary type: 'xhtml' do |xhtml| # xhtml.p pluralize(order.line_items.count, "line item") # xhtml.p "Shipped to #{order.address}" # xhtml.p "Paid by #{order.pay_type}" # end # # # atom_feed yields an +AtomFeedBuilder+ instance. Nested elements yield # an +AtomBuilder+ instance. def atom_feed: (?::Hash[untyped, untyped] options) { (untyped) -> untyped } -> untyped class AtomBuilder # nodoc: XHTML_TAG_NAMES: untyped def initialize: (untyped xml) -> untyped # Delegate to xml builder, first wrapping the element in an xhtml # namespaced div element if the method and arguments indicate # that an xhtml_block? is desired. def method_missing: (untyped method, *untyped arguments) { () -> untyped } -> untyped # True if the method name matches one of the five elements defined # in the Atom spec as potentially containing XHTML content and # if type: 'xhtml' is, in fact, specified. def xhtml_block?: (untyped method, untyped arguments) -> untyped end class AtomFeedBuilder < AtomBuilder # nodoc: def initialize: (untyped xml, untyped view, ?::Hash[untyped, untyped] feed_options) -> untyped # Accepts a Date or Time object and inserts it in the proper format. If +nil+ is passed, current time in UTC is used. def updated: (?untyped? date_or_time) -> untyped # Creates an entry tag for a specific record and prefills the id using class and id. # # Options: # # * :published: Time first published. Defaults to the created_at attribute on the record if one such exists. # * :updated: Time of update. Defaults to the updated_at attribute on the record if one such exists. # * :url: The URL for this entry or +false+ or +nil+ for not having a link tag. Defaults to the +polymorphic_url+ for the record. # * :id: The ID for this entry. Defaults to "tag:#{@view.request.host},#{@feed_options[:schema_date]}:#{record.class}/#{record.id}" # * :type: The TYPE for this entry. Defaults to "text/html". def entry: (untyped record, ?::Hash[untyped, untyped] options) { (untyped) -> untyped } -> untyped end end end end module ActionView module Helpers # = Action View Cache Helper # nodoc: module CacheHelper # This helper exposes a method for caching fragments of a view # rather than an entire action or page. This technique is useful # caching pieces like menus, lists of new topics, static HTML # fragments, and so on. This method takes a block that contains # the content you wish to cache. # # The best way to use this is by doing recyclable key-based cache expiration # on top of a cache store like Memcached or Redis that'll automatically # kick out old entries. # # When using this method, you list the cache dependency as the name of the cache, like so: # # <% cache project do %> # All the topics on this project # <%= render project.topics %> # <% end %> # # This approach will assume that when a new topic is added, you'll touch # the project. The cache key generated from this call will be something like: # # views/template/action.html.erb:7a1156131a6928cb0026877f8b749ac9/projects/123 # ^template path ^template tree digest ^class ^id # # This cache key is stable, but it's combined with a cache version derived from the project # record. When the project updated_at is touched, the #cache_version changes, even # if the key stays stable. This means that unlike a traditional key-based cache expiration # approach, you won't be generating cache trash, unused keys, simply because the dependent # record is updated. # # If your template cache depends on multiple sources (try to avoid this to keep things simple), # you can name all these dependencies as part of an array: # # <% cache [ project, current_user ] do %> # All the topics on this project # <%= render project.topics %> # <% end %> # # This will include both records as part of the cache key and updating either of them will # expire the cache. # # ==== \Template digest # # The template digest that's added to the cache key is computed by taking an MD5 of the # contents of the entire template file. This ensures that your caches will automatically # expire when you change the template file. # # Note that the MD5 is taken of the entire template file, not just what's within the # cache do/end call. So it's possible that changing something outside of that call will # still expire the cache. # # Additionally, the digestor will automatically look through your template file for # explicit and implicit dependencies, and include those as part of the digest. # # The digestor can be bypassed by passing skip_digest: true as an option to the cache call: # # <% cache project, skip_digest: true do %> # All the topics on this project # <%= render project.topics %> # <% end %> # # ==== Implicit dependencies # # Most template dependencies can be derived from calls to render in the template itself. # Here are some examples of render calls that Cache Digests knows how to decode: # # render partial: "comments/comment", collection: commentable.comments # render "comments/comments" # render 'comments/comments' # render('comments/comments') # # render "header" translates to render("comments/header") # # render(@topic) translates to render("topics/topic") # render(topics) translates to render("topics/topic") # render(message.topics) translates to render("topics/topic") # # It's not possible to derive all render calls like that, though. # Here are a few examples of things that can't be derived: # # render group_of_attachments # render @project.documents.where(published: true).order('created_at') # # You will have to rewrite those to the explicit form: # # render partial: 'attachments/attachment', collection: group_of_attachments # render partial: 'documents/document', collection: @project.documents.where(published: true).order('created_at') # # === Explicit dependencies # # Sometimes you'll have template dependencies that can't be derived at all. This is typically # the case when you have template rendering that happens in helpers. Here's an example: # # <%= render_sortable_todolists @project.todolists %> # # You'll need to use a special comment format to call those out: # # <%# Template Dependency: todolists/todolist %> # <%= render_sortable_todolists @project.todolists %> # # In some cases, like a single table inheritance setup, you might have # a bunch of explicit dependencies. Instead of writing every template out, # you can use a wildcard to match any template in a directory: # # <%# Template Dependency: events/* %> # <%= render_categorizable_events @person.events %> # # This marks every template in the directory as a dependency. To find those # templates, the wildcard path must be absolutely defined from app/views or paths # otherwise added with +prepend_view_path+ or +append_view_path+. # This way the wildcard for app/views/recordings/events would be recordings/events/* etc. # # The pattern used to match explicit dependencies is /# Template Dependency: (\S+)/, # so it's important that you type it out just so. # You can only declare one template dependency per line. # # === External dependencies # # If you use a helper method, for example, inside a cached block and # you then update that helper, you'll have to bump the cache as well. # It doesn't really matter how you do it, but the MD5 of the template file # must change. One recommendation is to simply be explicit in a comment, like: # # <%# Helper Dependency Updated: May 6, 2012 at 6pm %> # <%= some_helper_method(person) %> # # Now all you have to do is change that timestamp when the helper method changes. # # === Collection Caching # # When rendering a collection of objects that each use the same partial, a :cached # option can be passed. # # For collections rendered such: # # <%= render partial: 'projects/project', collection: @projects, cached: true %> # # The cached: true will make Action View's rendering read several templates # from cache at once instead of one call per template. # # Templates in the collection not already cached are written to cache. # # Works great alongside individual template fragment caching. # For instance if the template the collection renders is cached like: # # # projects/_project.html.erb # <% cache project do %> # <%# ... %> # <% end %> # # Any collection renders will find those cached templates when attempting # to read multiple templates at once. # # If your collection cache depends on multiple sources (try to avoid this to keep things simple), # you can name all these dependencies as part of a block that returns an array: # # <%= render partial: 'projects/project', collection: @projects, cached: -> project { [ project, current_user ] } %> # # This will include both records as part of the cache key and updating either of them will # expire the cache. def cache: (?::Hash[untyped, untyped] name, ?::Hash[untyped, untyped] options) { () -> untyped } -> nil # Cache fragments of a view if +condition+ is true # # <% cache_if admin?, project do %> # All the topics on this project # <%= render project.topics %> # <% end %> def cache_if: (untyped condition, ?::Hash[untyped, untyped] name, ?::Hash[untyped, untyped] options) { () -> untyped } -> nil # Cache fragments of a view unless +condition+ is true # # <% cache_unless admin?, project do %> # All the topics on this project # <%= render project.topics %> # <% end %> def cache_unless: (untyped condition, ?::Hash[untyped, untyped] name, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped # This helper returns the name of a cache key for a given fragment cache # call. By supplying skip_digest: true to cache, the digestion of cache # fragments can be manually bypassed. This is useful when cache fragments # cannot be manually expired unless you know the exact key which is the # case when using memcached. # # The digest will be generated using +virtual_path:+ if it is provided. # def cache_fragment_name: (?::Hash[untyped, untyped] name, ?skip_digest: untyped? skip_digest, ?virtual_path: untyped? virtual_path, ?digest_path: untyped? digest_path) -> untyped def digest_path_from_template: (untyped template) -> untyped def fragment_name_with_digest: (untyped name, untyped virtual_path, untyped digest_path) -> untyped def fragment_for: (?::Hash[untyped, untyped] name, ?untyped? options) { () -> untyped } -> untyped def read_fragment_for: (untyped name, untyped options) -> untyped def write_fragment_for: (untyped name, untyped options) { () -> untyped } -> untyped end end end module ActionView module Helpers # = Action View Capture Helper # nodoc: # CaptureHelper exposes methods to let you extract generated markup which # can be used in other parts of a template or layout file. # # It provides a method to capture blocks into variables through capture and # a way to capture a block of markup for use in a layout through {content_for}[rdoc-ref:ActionView::Helpers::CaptureHelper#content_for]. module CaptureHelper # The capture method extracts part of a template as a String object. # You can then use this object anywhere in your templates, layout, or helpers. # # The capture method can be used in ERB templates... # # <% @greeting = capture do %> # Welcome to my shiny new web page! The date and time is # <%= Time.now %> # <% end %> # # ...and Builder (RXML) templates. # # @timestamp = capture do # "The current timestamp is #{Time.now}." # end # # You can then use that variable anywhere else. For example: # # # <%= @greeting %> # # <%= @greeting %> # # # # The return of capture is the string generated by the block. For Example: # # @greeting # => "Welcome to my shiny new web page! The date and time is 2018-09-06 11:09:16 -0500" # def capture: (*untyped args) { (untyped) -> untyped } -> untyped # Calling content_for stores a block of markup in an identifier for later use. # In order to access this stored content in other templates, helper modules # or the layout, you would pass the identifier as an argument to content_for. # # Note: yield can still be used to retrieve the stored content, but calling # yield doesn't work in helper modules, while content_for does. # # <% content_for :not_authorized do %> # alert('You are not authorized to do that!') # <% end %> # # You can then use content_for :not_authorized anywhere in your templates. # # <%= content_for :not_authorized if current_user.nil? %> # # This is equivalent to: # # <%= yield :not_authorized if current_user.nil? %> # # content_for, however, can also be used in helper modules. # # module StorageHelper # def stored_content # content_for(:storage) || "Your storage is empty" # end # end # # This helper works just like normal helpers. # # <%= stored_content %> # # You can also use the yield syntax alongside an existing call to # yield in a layout. For example: # # <%# This is the layout %> # # # My Website # <%= yield :script %> # # # <%= yield %> # # # # And now, we'll create a view that has a content_for call that # creates the script identifier. # # <%# This is our view %> # Please login! # # <% content_for :script do %> # # <% end %> # # Then, in another view, you could to do something like this: # # <%= link_to 'Logout', action: 'logout', remote: true %> # # <% content_for :script do %> # <%= javascript_include_tag :defaults %> # <% end %> # # That will place +script+ tags for your default set of JavaScript files on the page; # this technique is useful if you'll only be using these scripts in a few views. # # Note that content_for concatenates (default) the blocks it is given for a particular # identifier in order. For example: # # <% content_for :navigation do %> #
  • <%= link_to 'Home', action: 'index' %>
  • # <% end %> # # And in another place: # # <% content_for :navigation do %> #
  • <%= link_to 'Login', action: 'login' %>
  • # <% end %> # # Then, in another template or layout, this code would render both links in order: # # # # If the flush parameter is +true+ content_for replaces the blocks it is given. For example: # # <% content_for :navigation do %> #
  • <%= link_to 'Home', action: 'index' %>
  • # <% end %> # # <%# Add some other content, or use a different template: %> # # <% content_for :navigation, flush: true do %> #
  • <%= link_to 'Login', action: 'login' %>
  • # <% end %> # # Then, in another template or layout, this code would render only the last link: # # # # Lastly, simple content can be passed as a parameter: # # <% content_for :script, javascript_include_tag(:defaults) %> # # WARNING: content_for is ignored in caches. So you shouldn't use it for elements that will be fragment cached. def content_for: (untyped name, ?untyped? content, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped # The same as +content_for+ but when used with streaming flushes # straight back to the layout. In other words, if you want to # concatenate several times to the same buffer when rendering a given # template, you should use +content_for+, if not, use +provide+ to tell # the layout to stop looking for more contents. def provide: (untyped name, ?untyped? content) { () -> untyped } -> untyped # content_for? checks whether any content has been captured yet using content_for. # Useful to render parts of your layout differently based on what is in your views. # # <%# This is the layout %> # # # My Website # <%= yield :script %> # # # <%= yield %> # <%= yield :right_col %> # # def content_for?: (untyped name) -> untyped def with_output_buffer: (?untyped? buf) { () -> untyped } -> untyped end end end module ActionView module Helpers module ControllerHelper CONTROLLER_DELEGATES: ::Array[untyped] def assign_controller: (untyped controller) -> untyped def logger: () -> untyped def respond_to?: (untyped method_name, ?bool include_private) -> untyped end end end module ActionView module Helpers # = Action View CSP Helper # nodoc: module CspHelper # Returns a meta tag "csp-nonce" with the per-session nonce value # for allowing inline # # +html_options+ may be a hash of attributes for the \ # # Instead of passing the content as an argument, you can also use a block # in which case, you pass your +html_options+ as the first parameter. # # <%= javascript_tag defer: 'defer' do -%> # alert('All is good') # <% end -%> # # If you have a content security policy enabled then you can add an automatic # nonce value by passing nonce: true as part of +html_options+. Example: # # <%= javascript_tag nonce: true do -%> # alert('All is good') # <% end -%> def javascript_tag: (?untyped? content_or_options_with_block, ?::Hash[untyped, untyped] html_options) { () -> untyped } -> untyped def javascript_cdata_section: (untyped content) -> untyped end end end module ActionView module Helpers # = Action View Number Helpers # nodoc: # Provides methods for converting numbers into formatted strings. # Methods are provided for phone numbers, currency, percentage, # precision, positional notation, file size and pretty printing. # # Most methods expect a +number+ argument, and will return it # unchanged if can't be converted into a valid number. module NumberHelper # Raised when argument +number+ param given to the helpers is invalid and # the option :raise is set to +true+. class InvalidNumberError < StandardError attr_accessor number: untyped def initialize: (untyped number) -> untyped end # Formats a +number+ into a phone number (US by default e.g., (555) # 123-9876). You can customize the format in the +options+ hash. # # ==== Options # # * :area_code - Adds parentheses around the area code. # * :delimiter - Specifies the delimiter to use # (defaults to "-"). # * :extension - Specifies an extension to add to the # end of the generated number. # * :country_code - Sets the country code for the phone # number. # * :pattern - Specifies how the number is divided into three # groups with the custom regexp to override the default format. # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_to_phone(5551234) # => 555-1234 # number_to_phone("5551234") # => 555-1234 # number_to_phone(1235551234) # => 123-555-1234 # number_to_phone(1235551234, area_code: true) # => (123) 555-1234 # number_to_phone(1235551234, delimiter: " ") # => 123 555 1234 # number_to_phone(1235551234, area_code: true, extension: 555) # => (123) 555-1234 x 555 # number_to_phone(1235551234, country_code: 1) # => +1-123-555-1234 # number_to_phone("123a456") # => 123a456 # number_to_phone("1234a567", raise: true) # => InvalidNumberError # # number_to_phone(1235551234, country_code: 1, extension: 1343, delimiter: ".") # # => +1.123.555.1234 x 1343 # # number_to_phone(75561234567, pattern: /(\d{1,4})(\d{4})(\d{4})$/, area_code: true) # # => "(755) 6123-4567" # number_to_phone(13312345678, pattern: /(\d{3})(\d{4})(\d{4})$/) # # => "133-1234-5678" def number_to_phone: (untyped number, ?::Hash[untyped, untyped] options) -> (nil | untyped) # Formats a +number+ into a currency string (e.g., $13.65). You # can customize the format in the +options+ hash. # # The currency unit and number formatting of the current locale will be used # unless otherwise specified in the provided options. No currency conversion # is performed. If the user is given a way to change their locale, they will # also be able to change the relative value of the currency displayed with # this helper. If your application will ever support multiple locales, you # may want to specify a constant :locale option or consider # using a library capable of currency conversion. # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :precision - Sets the level of precision (defaults # to 2). # * :unit - Sets the denomination of the currency # (defaults to "$"). # * :separator - Sets the separator between the units # (defaults to "."). # * :delimiter - Sets the thousands delimiter (defaults # to ","). # * :format - Sets the format for non-negative numbers # (defaults to "%u%n"). Fields are %u for the # currency, and %n for the number. # * :negative_format - Sets the format for negative # numbers (defaults to prepending a hyphen to the formatted # number given by :format). Accepts the same fields # than :format, except %n is here the # absolute value of the number. # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # * :strip_insignificant_zeros - If +true+ removes # insignificant zeros after the decimal separator (defaults to # +false+). # # ==== Examples # # number_to_currency(1234567890.50) # => $1,234,567,890.50 # number_to_currency(1234567890.506) # => $1,234,567,890.51 # number_to_currency(1234567890.506, precision: 3) # => $1,234,567,890.506 # number_to_currency(1234567890.506, locale: :fr) # => 1 234 567 890,51 (trim non-ascii characters) # number_to_currency("123a456") # => $123a456 # # number_to_currency("123a456", raise: true) # => InvalidNumberError # # number_to_currency(-0.456789, precision: 0) # # => "$0" # number_to_currency(-1234567890.50, negative_format: "(%u%n)") # # => ($1,234,567,890.50) # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "") # # => R$1234567890,50 # number_to_currency(1234567890.50, unit: "R$", separator: ",", delimiter: "", format: "%n %u") # # => 1234567890,50 R$ # number_to_currency(1234567890.50, strip_insignificant_zeros: true) # # => "$1,234,567,890.5" def number_to_currency: (untyped number, ?::Hash[untyped, untyped] options) -> untyped # Formats a +number+ as a percentage string (e.g., 65%). You can # customize the format in the +options+ hash. # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :precision - Sets the precision of the number # (defaults to 3). # * :significant - If +true+, precision will be the number # of significant_digits. If +false+, the number of fractional # digits (defaults to +false+). # * :separator - Sets the separator between the # fractional and integer digits (defaults to "."). # * :delimiter - Sets the thousands delimiter (defaults # to ""). # * :strip_insignificant_zeros - If +true+ removes # insignificant zeros after the decimal separator (defaults to # +false+). # * :format - Specifies the format of the percentage # string The number field is %n (defaults to "%n%"). # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_to_percentage(100) # => 100.000% # number_to_percentage("98") # => 98.000% # number_to_percentage(100, precision: 0) # => 100% # number_to_percentage(1000, delimiter: '.', separator: ',') # => 1.000,000% # number_to_percentage(302.24398923423, precision: 5) # => 302.24399% # number_to_percentage(1000, locale: :fr) # => 1 000,000% # number_to_percentage("98a") # => 98a% # number_to_percentage(100, format: "%n %") # => 100.000 % # # number_to_percentage("98a", raise: true) # => InvalidNumberError def number_to_percentage: (untyped number, ?::Hash[untyped, untyped] options) -> untyped # Formats a +number+ with grouped thousands using +delimiter+ # (e.g., 12,324). You can customize the format in the +options+ # hash. # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :delimiter - Sets the thousands delimiter (defaults # to ","). # * :separator - Sets the separator between the # fractional and integer digits (defaults to "."). # * :delimiter_pattern - Sets a custom regular expression used for # deriving the placement of delimiter. Helpful when using currency formats # like INR. # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_with_delimiter(12345678) # => 12,345,678 # number_with_delimiter("123456") # => 123,456 # number_with_delimiter(12345678.05) # => 12,345,678.05 # number_with_delimiter(12345678, delimiter: ".") # => 12.345.678 # number_with_delimiter(12345678, delimiter: ",") # => 12,345,678 # number_with_delimiter(12345678.05, separator: " ") # => 12,345,678 05 # number_with_delimiter(12345678.05, locale: :fr) # => 12 345 678,05 # number_with_delimiter("112a") # => 112a # number_with_delimiter(98765432.98, delimiter: " ", separator: ",") # # => 98 765 432,98 # # number_with_delimiter("123456.78", # delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/) # => "1,23,456.78" # # number_with_delimiter("112a", raise: true) # => raise InvalidNumberError def number_with_delimiter: (untyped number, ?::Hash[untyped, untyped] options) -> untyped # Formats a +number+ with the specified level of # :precision (e.g., 112.32 has a precision of 2 if # +:significant+ is +false+, and 5 if +:significant+ is +true+). # You can customize the format in the +options+ hash. # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :precision - Sets the precision of the number # (defaults to 3). # * :significant - If +true+, precision will be the number # of significant_digits. If +false+, the number of fractional # digits (defaults to +false+). # * :separator - Sets the separator between the # fractional and integer digits (defaults to "."). # * :delimiter - Sets the thousands delimiter (defaults # to ""). # * :strip_insignificant_zeros - If +true+ removes # insignificant zeros after the decimal separator (defaults to # +false+). # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_with_precision(111.2345) # => 111.235 # number_with_precision(111.2345, precision: 2) # => 111.23 # number_with_precision(13, precision: 5) # => 13.00000 # number_with_precision(389.32314, precision: 0) # => 389 # number_with_precision(111.2345, significant: true) # => 111 # number_with_precision(111.2345, precision: 1, significant: true) # => 100 # number_with_precision(13, precision: 5, significant: true) # => 13.000 # number_with_precision(111.234, locale: :fr) # => 111,234 # # number_with_precision(13, precision: 5, significant: true, strip_insignificant_zeros: true) # # => 13 # # number_with_precision(389.32314, precision: 4, significant: true) # => 389.3 # number_with_precision(1111.2345, precision: 2, separator: ',', delimiter: '.') # # => 1.111,23 def number_with_precision: (untyped number, ?::Hash[untyped, untyped] options) -> untyped # Formats the bytes in +number+ into a more understandable # representation (e.g., giving it 1500 yields 1.5 KB). This # method is useful for reporting file sizes to users. You can # customize the format in the +options+ hash. # # See number_to_human if you want to pretty-print a # generic number. # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :precision - Sets the precision of the number # (defaults to 3). # * :significant - If +true+, precision will be the number # of significant_digits. If +false+, the number of fractional # digits (defaults to +true+) # * :separator - Sets the separator between the # fractional and integer digits (defaults to "."). # * :delimiter - Sets the thousands delimiter (defaults # to ""). # * :strip_insignificant_zeros - If +true+ removes # insignificant zeros after the decimal separator (defaults to # +true+) # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_to_human_size(123) # => 123 Bytes # number_to_human_size(1234) # => 1.21 KB # number_to_human_size(12345) # => 12.1 KB # number_to_human_size(1234567) # => 1.18 MB # number_to_human_size(1234567890) # => 1.15 GB # number_to_human_size(1234567890123) # => 1.12 TB # number_to_human_size(1234567890123456) # => 1.1 PB # number_to_human_size(1234567890123456789) # => 1.07 EB # number_to_human_size(1234567, precision: 2) # => 1.2 MB # number_to_human_size(483989, precision: 2) # => 470 KB # number_to_human_size(1234567, precision: 2, separator: ',') # => 1,2 MB # number_to_human_size(1234567890123, precision: 5) # => "1.1228 TB" # number_to_human_size(524288000, precision: 5) # => "500 MB" def number_to_human_size: (untyped number, ?::Hash[untyped, untyped] options) -> untyped # Pretty prints (formats and approximates) a number in a way it # is more readable by humans (eg.: 1200000000 becomes "1.2 # Billion"). This is useful for numbers that can get very large # (and too hard to read). # # See number_to_human_size if you want to print a file # size. # # You can also define your own unit-quantifier names if you want # to use other decimal units (eg.: 1500 becomes "1.5 # kilometers", 0.150 becomes "150 milliliters", etc). You may # define a wide range of unit quantifiers, even fractional ones # (centi, deci, mili, etc). # # ==== Options # # * :locale - Sets the locale to be used for formatting # (defaults to current locale). # * :precision - Sets the precision of the number # (defaults to 3). # * :significant - If +true+, precision will be the number # of significant_digits. If +false+, the number of fractional # digits (defaults to +true+) # * :separator - Sets the separator between the # fractional and integer digits (defaults to "."). # * :delimiter - Sets the thousands delimiter (defaults # to ""). # * :strip_insignificant_zeros - If +true+ removes # insignificant zeros after the decimal separator (defaults to # +true+) # * :units - A Hash of unit quantifier names. Or a # string containing an i18n scope where to find this hash. It # might have the following keys: # * *integers*: :unit, :ten, # :hundred, :thousand, :million, # :billion, :trillion, # :quadrillion # * *fractionals*: :deci, :centi, # :mili, :micro, :nano, # :pico, :femto # * :format - Sets the format of the output string # (defaults to "%n %u"). The field types are: # * %u - The quantifier (ex.: 'thousand') # * %n - The number # * :raise - If true, raises +InvalidNumberError+ when # the argument is invalid. # # ==== Examples # # number_to_human(123) # => "123" # number_to_human(1234) # => "1.23 Thousand" # number_to_human(12345) # => "12.3 Thousand" # number_to_human(1234567) # => "1.23 Million" # number_to_human(1234567890) # => "1.23 Billion" # number_to_human(1234567890123) # => "1.23 Trillion" # number_to_human(1234567890123456) # => "1.23 Quadrillion" # number_to_human(1234567890123456789) # => "1230 Quadrillion" # number_to_human(489939, precision: 2) # => "490 Thousand" # number_to_human(489939, precision: 4) # => "489.9 Thousand" # number_to_human(1234567, precision: 4, # significant: false) # => "1.2346 Million" # number_to_human(1234567, precision: 1, # separator: ',', # significant: false) # => "1,2 Million" # # number_to_human(500000000, precision: 5) # => "500 Million" # number_to_human(12345012345, significant: false) # => "12.345 Billion" # # Non-significant zeros after the decimal separator are stripped # out by default (set :strip_insignificant_zeros to # +false+ to change that): # # number_to_human(12.00001) # => "12" # number_to_human(12.00001, strip_insignificant_zeros: false) # => "12.0" # # ==== Custom Unit Quantifiers # # You can also use your own custom unit quantifiers: # number_to_human(500000, units: {unit: "ml", thousand: "lt"}) # => "500 lt" # # If in your I18n locale you have: # distance: # centi: # one: "centimeter" # other: "centimeters" # unit: # one: "meter" # other: "meters" # thousand: # one: "kilometer" # other: "kilometers" # billion: "gazillion-distance" # # Then you could do: # # number_to_human(543934, units: :distance) # => "544 kilometers" # number_to_human(54393498, units: :distance) # => "54400 kilometers" # number_to_human(54393498000, units: :distance) # => "54.4 gazillion-distance" # number_to_human(343, units: :distance, precision: 1) # => "300 meters" # number_to_human(1, units: :distance) # => "1 meter" # number_to_human(0.34, units: :distance) # => "34 centimeters" # def number_to_human: (untyped number, ?::Hash[untyped, untyped] options) -> untyped def delegate_number_helper_method: (untyped method, untyped number, untyped options) -> (nil | untyped) def escape_unsafe_options: (untyped options) -> untyped def escape_units: (untyped units) -> untyped def wrap_with_output_safety_handling: (untyped number, untyped raise_on_invalid) { () -> untyped } -> untyped def valid_float?: (untyped number) -> untyped def parse_float: (untyped number, untyped raise_error) -> untyped end end end module ActionView module Helpers # nodoc: # = Action View Raw Output Helper # nodoc: module OutputSafetyHelper # This method outputs without escaping a string. Since escaping tags is # now default, this can be used when you don't want Rails to automatically # escape tags. This is not recommended if the data is coming from the user's # input. # # For example: # # raw @user.name # # => 'Jimmy Tables' def raw: (untyped stringish) -> untyped # This method returns an HTML safe string similar to what Array#join # would return. The array is flattened, and all items, including # the supplied separator, are HTML escaped unless they are HTML # safe, and the returned string is marked as HTML safe. # # safe_join([raw("

    foo

    "), "

    bar

    "], "
    ") # # => "

    foo

    <br /><p>bar</p>" # # safe_join([raw("

    foo

    "), raw("

    bar

    ")], raw("
    ")) # # => "

    foo


    bar

    " # def safe_join: (untyped array, ?untyped sep) -> untyped # Converts the array to a comma-separated sentence where the last element is # joined by the connector word. This is the html_safe-aware version of # ActiveSupport's {Array#to_sentence}[https://api.rubyonrails.org/classes/Array.html#method-i-to_sentence]. # def to_sentence: (untyped array, ?::Hash[untyped, untyped] options) -> untyped end end end module ActionView module Helpers # nodoc: # = Action View Rendering # # Implements methods that allow rendering from a view context. # In order to use this module, all you need is to implement # view_renderer that returns an ActionView::Renderer object. module RenderingHelper # Returns the result of a render that's dictated by the options hash. The primary options are: # # * :partial - See ActionView::PartialRenderer. # * :file - Renders an explicit template file (this used to be the old default), add :locals to pass in those. # * :inline - Renders an inline template similar to how it's done in the controller. # * :plain - Renders the text passed in out. Setting the content # type as text/plain. # * :html - Renders the HTML safe string passed in out, otherwise # performs HTML escape on the string first. Setting the content type as # text/html. # * :body - Renders the text passed in, and inherits the content # type of text/plain from ActionDispatch::Response # object. # # If no options hash is passed or :update specified, the default is to render a partial and use the second parameter # as the locals hash. def render: (?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] locals) { () -> untyped } -> untyped # Overwrites _layout_for in the context object so it supports the case a block is # passed to a partial. Returns the contents that are yielded to a layout, given a # name or a block. # # You can think of a layout as a method that is called with a block. If the user calls # yield :some_name, the block, by default, returns content_for(:some_name). # If the user calls simply +yield+, the default block returns content_for(:layout). # # The user can override this default by passing a block to the layout: # # # The template # <%= render layout: "my_layout" do %> # Content # <% end %> # # # The layout # # <%= yield %> # # # In this case, instead of the default block, which would return content_for(:layout), # this method returns the block that was passed in to render :layout, and the response # would be # # # Content # # # Finally, the block can take block arguments, which can be passed in by +yield+: # # # The template # <%= render layout: "my_layout" do |customer| %> # Hello <%= customer.name %> # <% end %> # # # The layout # # <%= yield Struct.new(:name).new("David") %> # # # In this case, the layout would receive the block passed into render :layout, # and the struct specified would be passed into the block as an argument. The result # would be # # # Hello David # # def _layout_for: (*untyped args) { () -> untyped } -> untyped end end end module ActionView module Helpers # = Action View Sanitize Helpers # nodoc: # The SanitizeHelper module provides a set of methods for scrubbing text of undesired HTML elements. # These helper methods extend Action View making them callable within your template files. module SanitizeHelper extend ActiveSupport::Concern # Sanitizes HTML input, stripping all but known-safe tags and attributes. # # It also strips href/src attributes with unsafe protocols like # javascript:, while also protecting against attempts to use Unicode, # ASCII, and hex character references to work around these protocol filters. # All special characters will be escaped. # # The default sanitizer is Rails::Html::SafeListSanitizer. See {Rails HTML # Sanitizers}[https://github.com/rails/rails-html-sanitizer] for more information. # # Custom sanitization rules can also be provided. # # Please note that sanitizing user-provided text does not guarantee that the # resulting markup is valid or even well-formed. # # ==== Options # # * :tags - An array of allowed tags. # * :attributes - An array of allowed attributes. # * :scrubber - A {Rails::Html scrubber}[https://github.com/rails/rails-html-sanitizer] # or {Loofah::Scrubber}[https://github.com/flavorjones/loofah] object that # defines custom sanitization rules. A custom scrubber takes precedence over # custom tags and attributes. # # ==== Examples # # Normal use: # # <%= sanitize @comment.body %> # # Providing custom lists of permitted tags and attributes: # # <%= sanitize @comment.body, tags: %w(strong em a), attributes: %w(href) %> # # Providing a custom Rails::Html scrubber: # # class CommentScrubber < Rails::Html::PermitScrubber # def initialize # super # self.tags = %w( form script comment blockquote ) # self.attributes = %w( style ) # end # # def skip_node?(node) # node.text? # end # end # # <%= sanitize @comment.body, scrubber: CommentScrubber.new %> # # See {Rails HTML Sanitizer}[https://github.com/rails/rails-html-sanitizer] for # documentation about Rails::Html scrubbers. # # Providing a custom Loofah::Scrubber: # # scrubber = Loofah::Scrubber.new do |node| # node.remove if node.name == 'script' # end # # <%= sanitize @comment.body, scrubber: scrubber %> # # See {Loofah's documentation}[https://github.com/flavorjones/loofah] for more # information about defining custom Loofah::Scrubber objects. # # To set the default allowed tags or attributes across your application: # # # In config/application.rb # config.action_view.sanitized_allowed_tags = ['strong', 'em', 'a'] # config.action_view.sanitized_allowed_attributes = ['href', 'title'] def sanitize: (untyped html, ?::Hash[untyped, untyped] options) -> untyped # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute. def sanitize_css: (untyped style) -> untyped # Strips all HTML tags from +html+, including comments and special characters. # # strip_tags("Strip these tags!") # # => Strip these tags! # # strip_tags("Bold no more! See more here...") # # => Bold no more! See more here... # # strip_tags("
    Welcome to my website!
    ") # # => Welcome to my website! # # strip_tags("> A quote from Smith & Wesson") # # => > A quote from Smith & Wesson def strip_tags: (untyped html) -> untyped # Strips all link tags from +html+ leaving just the link text. # # strip_links('Ruby on Rails') # # => Ruby on Rails # # strip_links('Please e-mail me at me@email.com.') # # => Please e-mail me at me@email.com. # # strip_links('Blog: Visit.') # # => Blog: Visit. # # strip_links('<malformed & link') # # => <malformed & link def strip_links: (untyped html) -> untyped module ClassMethods # nodoc: attr_writer full_sanitizer: untyped # nodoc: attr_writer link_sanitizer: untyped # nodoc: attr_writer safe_list_sanitizer: untyped def sanitizer_vendor: () -> untyped def sanitized_allowed_tags: () -> untyped def sanitized_allowed_attributes: () -> untyped # Gets the Rails::Html::FullSanitizer instance used by +strip_tags+. Replace with # any object that responds to +sanitize+. # # class Application < Rails::Application # config.action_view.full_sanitizer = MySpecialSanitizer.new # end def full_sanitizer: () -> untyped # Gets the Rails::Html::LinkSanitizer instance used by +strip_links+. # Replace with any object that responds to +sanitize+. # # class Application < Rails::Application # config.action_view.link_sanitizer = MySpecialSanitizer.new # end def link_sanitizer: () -> untyped # Gets the Rails::Html::SafeListSanitizer instance used by sanitize and +sanitize_css+. # Replace with any object that responds to +sanitize+. # # class Application < Rails::Application # config.action_view.safe_list_sanitizer = MySpecialSanitizer.new # end def safe_list_sanitizer: () -> untyped end end end end module ActionView module Helpers # = Action View Tag Helpers # nodoc: # Provides methods to generate HTML tags programmatically both as a modern # HTML5 compliant builder style and legacy XHTML compliant tags. module TagHelper extend ActiveSupport::Concern include CaptureHelper include OutputSafetyHelper BOOLEAN_ATTRIBUTES: untyped TAG_PREFIXES: untyped PRE_CONTENT_STRINGS: untyped class TagBuilder # nodoc: include CaptureHelper include OutputSafetyHelper VOID_ELEMENTS: untyped def initialize: (untyped view_context) -> untyped def tag_string: (untyped name, ?untyped? content, ?escape_attributes: bool escape_attributes, **untyped options) { () -> untyped } -> untyped def content_tag_string: (untyped name, untyped content, untyped options, ?bool escape) -> untyped def tag_options: (untyped options, ?bool escape) -> (nil | untyped) def boolean_tag_option: (untyped key) -> ::String def tag_option: (untyped key, untyped value, untyped escape) -> ::String def prefix_tag_option: (untyped prefix, untyped key, untyped value, untyped escape) -> untyped def respond_to_missing?: (*untyped args) -> ::TrueClass def method_missing: (untyped called, *untyped args, **untyped options) { () -> untyped } -> untyped end # Returns an HTML tag. # # === Building HTML tags # # Builds HTML5 compliant tags with a tag proxy. Every tag can be built with: # # tag.(optional content, options) # # where tag name can be e.g. br, div, section, article, or any tag really. # # ==== Passing content # # Tags can pass content to embed within it: # # tag.h1 'All titles fit to print' # =>

    All titles fit to print

    # # tag.div tag.p('Hello world!') # =>

    Hello world!

    # # Content can also be captured with a block, which is useful in templates: # # <%= tag.p do %> # The next great American novel starts here. # <% end %> # # =>

    The next great American novel starts here.

    # # ==== Options # # Use symbol keyed options to add attributes to the generated tag. # # tag.section class: %w( kitties puppies ) # # =>
    # # tag.section id: dom_id(@post) # # =>
    # # Pass +true+ for any attributes that can render with no values, like +disabled+ and +readonly+. # # tag.input type: 'text', disabled: true # # => # # HTML5 data-* attributes can be set with a single +data+ key # pointing to a hash of sub-attributes. # # To play nicely with JavaScript conventions, sub-attributes are dasherized. # # tag.article data: { user_id: 123 } # # =>
    # # Thus data-user-id can be accessed as dataset.userId. # # Data attribute values are encoded to JSON, with the exception of strings, symbols and # BigDecimals. # This may come in handy when using jQuery's HTML5-aware .data() # from 1.4.3. # # tag.div data: { city_state: %w( Chicago IL ) } # # =>
    # # The generated attributes are escaped by default. This can be disabled using # +escape_attributes+. # # tag.img src: 'open & shut.png' # # => # # tag.img src: 'open & shut.png', escape_attributes: false # # => # # The tag builder respects # {HTML5 void elements}[https://www.w3.org/TR/html5/syntax.html#void-elements] # if no content is passed, and omits closing tags for those elements. # # # A standard element: # tag.div # =>
    # # # A void element: # tag.br # =>
    # # === Legacy syntax # # The following format is for legacy syntax support. It will be deprecated in future versions of Rails. # # tag(name, options = nil, open = false, escape = true) # # It returns an empty HTML tag of type +name+ which by default is XHTML # compliant. Set +open+ to true to create an open tag compatible # with HTML 4.0 and below. Add HTML attributes by passing an attributes # hash to +options+. Set +escape+ to false to disable attribute value # escaping. # # ==== Options # # You can use symbols or strings for the attribute names. # # Use +true+ with boolean attributes that can render with no value, like # +disabled+ and +readonly+. # # HTML5 data-* attributes can be set with a single +data+ key # pointing to a hash of sub-attributes. # # ==== Examples # # tag("br") # # =>
    # # tag("br", nil, true) # # =>
    # # tag("input", type: 'text', disabled: true) # # => # # tag("input", type: 'text', class: ["strong", "highlight"]) # # => # # tag("img", src: "open & shut.png") # # => # # tag("img", { src: "open & shut.png" }, false, false) # # => # # tag("div", data: { name: 'Stephen', city_state: %w(Chicago IL) }) # # =>
    def tag: (?untyped? name, ?untyped? options, ?bool open, ?bool escape) -> untyped # Returns an HTML block tag of type +name+ surrounding the +content+. Add # HTML attributes by passing an attributes hash to +options+. # Instead of passing the content as an argument, you can also use a block # in which case, you pass your +options+ as the second parameter. # Set escape to false to disable attribute value escaping. # Note: this is legacy syntax, see +tag+ method description for details. # # ==== Options # The +options+ hash can be used with attributes with no value like (disabled and # readonly), which you can give a value of true in the +options+ hash. You can use # symbols or strings for the attribute names. # # ==== Examples # content_tag(:p, "Hello world!") # # =>

    Hello world!

    # content_tag(:div, content_tag(:p, "Hello world!"), class: "strong") # # =>

    Hello world!

    # content_tag(:div, "Hello world!", class: ["strong", "highlight"]) # # =>
    Hello world!
    # content_tag("select", options, multiple: true) # # => # # <%= content_tag :div, class: "strong" do -%> # Hello world! # <% end -%> # # =>
    Hello world!
    def content_tag: (untyped name, ?untyped? content_or_options_with_block, ?untyped? options, ?bool escape) { () -> untyped } -> untyped # Returns a CDATA section with the given +content+. CDATA sections # are used to escape blocks of text containing characters which would # otherwise be recognized as markup. CDATA sections begin with the string # and end with (and may not contain) the string ]]>. # # cdata_section("") # # => ]]> # # cdata_section(File.read("hello_world.txt")) # # => # # cdata_section("hello]]>world") # # => world]]> def cdata_section: (untyped content) -> untyped # Returns an escaped version of +html+ without affecting existing escaped entities. # # escape_once("1 < 2 & 3") # # => "1 < 2 & 3" # # escape_once("<< Accept & Checkout") # # => "<< Accept & Checkout" def escape_once: (untyped html) -> untyped def tag_builder: () -> untyped end end end module ActionView module Helpers module Tags class Base # :nodoc: # :nodoc: include Helpers::ActiveModelInstanceTag # :nodoc: # :nodoc: include Helpers::TagHelper # :nodoc: # :nodoc: include Helpers::FormTagHelper include FormOptionsHelper attr_reader object: untyped def initialize: (untyped object_name, untyped method_name, untyped template_object, ?::Hash[untyped, untyped] options) -> untyped # This is what child classes implement. def render: () -> untyped def value: () -> untyped def value_before_type_cast: () -> untyped def value_came_from_user?: () -> untyped def retrieve_object: (untyped object) -> untyped def retrieve_autoindex: (untyped pre_match) -> untyped def add_default_name_and_id_for_value: (untyped tag_value, untyped options) -> untyped def add_default_name_and_id: (untyped options) -> untyped def tag_name: (?bool multiple, ?untyped? index) -> untyped def tag_id: (?untyped? index) -> untyped def sanitized_object_name: () -> untyped def sanitized_method_name: () -> untyped def sanitized_value: (untyped value) -> untyped def select_content_tag: (untyped option_tags, untyped options, untyped html_options) -> untyped def placeholder_required?: (untyped html_options) -> untyped def add_options: (untyped option_tags, untyped options, ?untyped? value) -> untyped def name_and_id_index: (untyped options) -> untyped def generate_ids?: () -> untyped end end end end module ActionView module Helpers module Tags class CheckBox < Base # :nodoc: # nodoc: include Checkable def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped checked_value, untyped unchecked_value, untyped options) -> untyped def render: () -> untyped def checked?: (untyped value) -> untyped def hidden_field_for_checkbox: (untyped options) -> untyped end end end end module ActionView module Helpers module Tags module Checkable # :nodoc: # :nodoc: def input_checked?: (untyped options) -> untyped end end end end module ActionView module Helpers module Tags class CollectionCheckBoxes < Base # :nodoc: # :nodoc: include CollectionHelpers class CheckBoxBuilder < CollectionHelpers::Builder # :nodoc: def check_box: (?::Hash[untyped, untyped] extra_html_options) -> untyped end def render: () { () -> untyped } -> untyped def render_component: (untyped builder) -> untyped def hidden_field_name: () -> ::String end end end end module ActionView module Helpers module Tags module CollectionHelpers class Builder # :nodoc: # :nodoc: # :nodoc: attr_reader object: untyped # :nodoc: # :nodoc: # :nodoc: attr_reader text: untyped # :nodoc: # :nodoc: # :nodoc: attr_reader value: untyped def initialize: (untyped template_object, untyped object_name, untyped method_name, untyped object, untyped sanitized_attribute_name, untyped text, untyped value, untyped input_html_options) -> untyped def label: (?::Hash[untyped, untyped] label_html_options) { () -> untyped } -> untyped end def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped collection, untyped value_method, untyped text_method, untyped options, untyped html_options) -> untyped def instantiate_builder: (untyped builder_class, untyped item, untyped value, untyped text, untyped html_options) -> untyped # Generate default options for collection helpers, such as :checked and # :disabled. def default_html_options_for_collection: (untyped item, untyped value) -> untyped def sanitize_attribute_name: (untyped value) -> ::String def render_collection: () { (untyped, untyped, untyped, untyped) -> untyped } -> untyped def render_collection_for: (untyped builder_class) { () -> untyped } -> untyped def hidden_field: () -> untyped def hidden_field_name: () -> ::String end end end end module ActionView module Helpers module Tags class CollectionRadioButtons < Base # :nodoc: # :nodoc: include CollectionHelpers class RadioButtonBuilder < CollectionHelpers::Builder # :nodoc: def radio_button: (?::Hash[untyped, untyped] extra_html_options) -> untyped end def render: () { () -> untyped } -> untyped def render_component: (untyped builder) -> untyped end end end end module ActionView module Helpers module Tags class CollectionSelect < Base # :nodoc: # nodoc: def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped collection, untyped value_method, untyped text_method, untyped options, untyped html_options) -> untyped def render: () -> untyped end end end end module ActionView module Helpers module Tags class ColorField < TextField # :nodoc: # :nodoc: def render: () -> untyped def validate_color_string: (untyped string) -> untyped end end end end module ActionView module Helpers module Tags class DateField < DatetimeField def format_date: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class DateSelect < Base # :nodoc: # :nodoc: def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped options, untyped html_options) -> untyped def render: () -> untyped def self.select_type: () -> untyped def select_type: () -> untyped def datetime_selector: (untyped options, untyped html_options) -> DateTimeSelector def default_datetime: (untyped options) -> (nil | untyped) end end end end module ActionView module Helpers module Tags class DatetimeField < TextField # :nodoc: # :nodoc: def render: () -> untyped def format_date: (untyped value) -> untyped def datetime_value: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class DatetimeLocalField < DatetimeField def self.field_type: () -> untyped def format_date: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class DatetimeSelect < DateSelect end end end end module ActionView module Helpers module Tags class EmailField < TextField end end end end module ActionView module Helpers module Tags class FileField < TextField end end end end module ActionView module Helpers module Tags class GroupedCollectionSelect < Base # :nodoc: # :nodoc: def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped collection, untyped group_method, untyped group_label_method, untyped option_key_method, untyped option_value_method, untyped options, untyped html_options) -> untyped def render: () -> untyped end end end end module ActionView module Helpers module Tags class HiddenField < TextField end end end end module ActionView module Helpers module Tags class Label < Base class LabelBuilder # :nodoc: # :nodoc: # :nodoc: attr_reader object: untyped def initialize: (untyped template_object, untyped object_name, untyped method_name, untyped object, untyped tag_value) -> untyped def translation: () -> untyped end def initialize: (untyped object_name, untyped method_name, untyped template_object, ?untyped? content_or_options, ?untyped? options) -> untyped def render: () { () -> untyped } -> untyped def render_component: (untyped builder) -> untyped end end end end module ActionView module Helpers module Tags class MonthField < DatetimeField def format_date: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class NumberField < TextField # :nodoc: # :nodoc: def render: () -> untyped end end end end module ActionView module Helpers module Tags class PasswordField < TextField # :nodoc: # :nodoc: def render: () -> untyped end end end end module ActionView module Helpers module Tags module Placeholderable # :nodoc: # :nodoc: def initialize: () -> untyped end end end end module ActionView module Helpers module Tags class RadioButton < Base # :nodoc: # :nodoc: include Checkable def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped tag_value, untyped options) -> untyped def render: () -> untyped def checked?: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class RangeField < NumberField end end end end module ActionView module Helpers module Tags class SearchField < TextField # :nodoc: # :nodoc: def render: () -> untyped end end end end module ActionView module Helpers module Tags class Select < Base # :nodoc: # :nodoc: def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped choices, untyped options, untyped html_options) { () -> untyped } -> untyped def render: () -> untyped # Grouped choices look like this: # # [nil, []] # { nil => [] } def grouped_choices?: () -> untyped end end end end module ActionView module Helpers module Tags class TelField < TextField end end end end module ActionView module Helpers module Tags class TextArea < Base # :nodoc: # :nodoc: include Placeholderable def render: () -> untyped end end end end module ActionView module Helpers module Tags class TextField < Base # :nodoc: # :nodoc: include Placeholderable def render: () -> untyped def self.field_type: () -> untyped def field_type: () -> untyped end end end end module ActionView module Helpers module Tags class TimeField < DatetimeField def format_date: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags class TimeSelect < DateSelect end end end end module ActionView module Helpers module Tags class TimeZoneSelect < Base # :nodoc: # :nodoc: def initialize: (untyped object_name, untyped method_name, untyped template_object, untyped priority_zones, untyped options, untyped html_options) -> untyped def render: () -> untyped end end end end module ActionView module Helpers module Tags class Translator # :nodoc: # :nodoc: def initialize: (untyped object, untyped object_name, untyped method_and_value, scope: untyped scope) -> untyped def translate: () -> untyped attr_reader object_name: untyped attr_reader method_and_value: untyped attr_reader scope: untyped attr_reader model: untyped def i18n_default: () -> untyped def human_attribute_name: () -> untyped end end end end module ActionView module Helpers module Tags class UrlField < TextField end end end end module ActionView module Helpers module Tags class WeekField < DatetimeField def format_date: (untyped value) -> untyped end end end end module ActionView module Helpers module Tags # nodoc: # nodoc: extend ActiveSupport::Autoload end end end module ActionView module Helpers # = Action View Text Helpers # nodoc: # The TextHelper module provides a set of methods for filtering, formatting # and transforming strings, which can reduce the amount of inline Ruby code in # your views. These helper methods extend Action View making them callable # within your template files. # # ==== Sanitization # # Most text helpers that generate HTML output sanitize the given input by default, # but do not escape it. This means HTML tags will appear in the page but all malicious # code will be removed. Let's look at some examples using the +simple_format+ method: # # simple_format('Example') # # => "

    Example

    " # # simple_format('Example') # # => "

    Example

    " # # If you want to escape all content, you should invoke the +h+ method before # calling the text helper. # # simple_format h('Example') # # => "

    <a href=\"http://example.com/\">Example</a>

    " module TextHelper extend ActiveSupport::Concern include SanitizeHelper extend ::ActionView::Helpers::SanitizeHelper::ClassMethods include TagHelper include OutputSafetyHelper # The preferred method of outputting text in your views is to use the # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods # do not operate as expected in an eRuby code block. If you absolutely must # output text within a non-output code block (i.e., <% %>), you can use the concat method. # # <% # concat "hello" # # is the equivalent of <%= "hello" %> # # if logged_in # concat "Logged in!" # else # concat link_to('login', action: :login) # end # # will either display "Logged in!" or a login link # %> def concat: (untyped string) -> untyped def safe_concat: (untyped string) -> untyped # Truncates a given +text+ after a given :length if +text+ is longer than :length # (defaults to 30). The last characters will be replaced with the :omission (defaults to "...") # for a total length not exceeding :length. # # Pass a :separator to truncate +text+ at a natural break. # # Pass a block if you want to show extra content when the text is truncated. # # The result is marked as HTML-safe, but it is escaped by default, unless :escape is # +false+. Care should be taken if +text+ contains HTML tags or entities, because truncation # may produce invalid HTML (such as unbalanced or incomplete tags). # # truncate("Once upon a time in a world far far away") # # => "Once upon a time in a world..." # # truncate("Once upon a time in a world far far away", length: 17) # # => "Once upon a ti..." # # truncate("Once upon a time in a world far far away", length: 17, separator: ' ') # # => "Once upon a..." # # truncate("And they found that many people were sleeping better.", length: 25, omission: '... (continued)') # # => "And they f... (continued)" # # truncate("

    Once upon a time in a world far far away

    ") # # => "<p>Once upon a time in a wo..." # # truncate("

    Once upon a time in a world far far away

    ", escape: false) # # => "

    Once upon a time in a wo..." # # truncate("Once upon a time in a world far far away") { link_to "Continue", "#" } # # => "Once upon a time in a wo...Continue" def truncate: (untyped text, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped # Highlights one or more +phrases+ everywhere in +text+ by inserting it into # a :highlighter string. The highlighter can be specialized by passing :highlighter # as a single-quoted string with \1 where the phrase is to be inserted (defaults to # '\1') or passing a block that receives each matched term. By default +text+ # is sanitized to prevent possible XSS attacks. If the input is trustworthy, passing false # for :sanitize will turn sanitizing off. # # highlight('You searched for: rails', 'rails') # # => You searched for: rails # # highlight('You searched for: rails', /for|rails/) # # => You searched for: rails # # highlight('You searched for: ruby, rails, dhh', 'actionpack') # # => You searched for: ruby, rails, dhh # # highlight('You searched for: rails', ['for', 'rails'], highlighter: '\1') # # => You searched for: rails # # highlight('You searched for: rails', 'rails', highlighter: '\1') # # => You searched for: rails # # highlight('You searched for: rails', 'rails') { |match| link_to(search_path(q: match, match)) } # # => You searched for: rails # # highlight('ruby on rails', 'rails', sanitize: false) # # => ruby on rails def highlight: (untyped text, untyped phrases, ?::Hash[untyped, untyped] options) { (untyped) -> untyped } -> untyped # Extracts an excerpt from +text+ that matches the first instance of +phrase+. # The :radius option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters # defined in :radius (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+, # then the :omission option (which defaults to "...") will be prepended/appended accordingly. Use the # :separator option to choose the delimitation. The resulting string will be stripped in any case. If the +phrase+ # isn't found, +nil+ is returned. # # excerpt('This is an example', 'an', radius: 5) # # => ...s is an exam... # # excerpt('This is an example', 'is', radius: 5) # # => This is a... # # excerpt('This is an example', 'is') # # => This is an example # # excerpt('This next thing is an example', 'ex', radius: 2) # # => ...next... # # excerpt('This is also an example', 'an', radius: 8, omission: ' ') # # => is also an example # # excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1) # # => ...a very beautiful... def excerpt: (untyped text, untyped phrase, ?::Hash[untyped, untyped] options) -> (nil | untyped) # Attempts to pluralize the +singular+ word unless +count+ is 1. If # +plural+ is supplied, it will use that when count is > 1, otherwise # it will use the Inflector to determine the plural form for the given locale, # which defaults to I18n.locale # # The word will be pluralized using rules defined for the locale # (you must define your own inflection rules for languages other than English). # See ActiveSupport::Inflector.pluralize # # pluralize(1, 'person') # # => 1 person # # pluralize(2, 'person') # # => 2 people # # pluralize(3, 'person', plural: 'users') # # => 3 users # # pluralize(0, 'person') # # => 0 people # # pluralize(2, 'Person', locale: :de) # # => 2 Personen def pluralize: (untyped count, untyped singular, ?untyped? plural_arg, ?plural: untyped plural, ?locale: untyped locale) -> ::String # Wraps the +text+ into lines no longer than +line_width+ width. This method # breaks on the first whitespace character that does not exceed +line_width+ # (which is 80 by default). # # word_wrap('Once upon a time') # # => Once upon a time # # word_wrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...') # # => Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding\na successor to the throne turned out to be more trouble than anyone could have\nimagined... # # word_wrap('Once upon a time', line_width: 8) # # => Once\nupon a\ntime # # word_wrap('Once upon a time', line_width: 1) # # => Once\nupon\na\ntime # # You can also specify a custom +break_sequence+ ("\n" by default) # # word_wrap('Once upon a time', line_width: 1, break_sequence: "\r\n") # # => Once\r\nupon\r\na\r\ntime def word_wrap: (untyped text, ?line_width: ::Integer line_width, ?break_sequence: ::String break_sequence) -> untyped # Returns +text+ transformed into HTML using simple formatting rules. # Two or more consecutive newlines(\n\n or \r\n\r\n) are # considered a paragraph and wrapped in

    tags. One newline # (\n or \r\n) is considered a linebreak and a #
    tag is appended. This method does not remove the # newlines from the +text+. # # You can pass any HTML attributes into html_options. These # will be added to all created paragraphs. # # ==== Options # * :sanitize - If +false+, does not sanitize +text+. # * :wrapper_tag - String representing the wrapper tag, defaults to "p" # # ==== Examples # my_text = "Here is some basic text...\n...with a line break." # # simple_format(my_text) # # => "

    Here is some basic text...\n
    ...with a line break.

    " # # simple_format(my_text, {}, wrapper_tag: "div") # # => "
    Here is some basic text...\n
    ...with a line break.
    " # # more_text = "We want to put a paragraph...\n\n...right there." # # simple_format(more_text) # # => "

    We want to put a paragraph...

    \n\n

    ...right there.

    " # # simple_format("Look ma! A class!", class: 'description') # # => "

    Look ma! A class!

    " # # simple_format("Unblinkable.") # # => "

    Unblinkable.

    " # # simple_format("Blinkable! It's true.", {}, sanitize: false) # # => "

    Blinkable! It's true.

    " def simple_format: (untyped text, ?::Hash[untyped, untyped] html_options, ?::Hash[untyped, untyped] options) -> untyped # Creates a Cycle object whose _to_s_ method cycles through elements of an # array every time it is called. This can be used for example, to alternate # classes for table rows. You can use named cycles to allow nesting in loops. # Passing a Hash as the last parameter with a :name key will create a # named cycle. The default name for a cycle without a +:name+ key is # "default". You can manually reset a cycle by calling reset_cycle # and passing the name of the cycle. The current cycle string can be obtained # anytime using the current_cycle method. # # # Alternate CSS classes for even and odd numbers... # @items = [1,2,3,4] # # <% @items.each do |item| %> # "> # # # <% end %> #
    <%= item %>
    # # # # Cycle CSS classes for rows, and text colors for values within each row # @items = x = [{first: 'Robert', middle: 'Daniel', last: 'James'}, # {first: 'Emily', middle: 'Shannon', maiden: 'Pike', last: 'Hicks'}, # {first: 'June', middle: 'Dae', last: 'Jones'}] # <% @items.each do |item| %> # "> # # <% item.values.each do |value| %> # <%# Create a named cycle "colors" %> # "> # <%= value %> # # <% end %> # <% reset_cycle("colors") %> # # # <% end %> def cycle: (untyped first_value, *untyped values) -> untyped # Returns the current cycle string after a cycle has been started. Useful # for complex table highlighting or any other design need which requires # the current cycle string in more than one place. # # # Alternate background colors # @items = [1,2,3,4] # <% @items.each do |item| %> #
    "> # <%= item %> #
    # <% end %> def current_cycle: (?::String name) -> untyped # Resets a cycle so that it starts from the first element the next time # it is called. Pass in +name+ to reset a named cycle. # # # Alternate CSS classes for even and odd numbers... # @items = [[1,2,3,4], [5,6,3], [3,4,5,6,7,4]] # # <% @items.each do |item| %> # "> # <% item.each do |value| %> # "> # <%= value %> # # <% end %> # # <% reset_cycle("colors") %> # # <% end %> #
    def reset_cycle: (?::String name) -> untyped class Cycle # nodoc: attr_reader values: untyped def initialize: (untyped first_value, *untyped values) -> untyped def reset: () -> untyped def current_value: () -> untyped def to_s: () -> untyped def next_index: () -> untyped def previous_index: () -> untyped def step_index: (untyped n) -> untyped end # The cycle helpers need to store the cycles in a place that is # guaranteed to be reset every time a page is rendered, so it # uses an instance variable of ActionView::Base. def get_cycle: (untyped name) -> untyped def set_cycle: (untyped name, untyped cycle_object) -> untyped def split_paragraphs: (untyped text) -> (::Array[untyped] | untyped) def cut_excerpt_part: (untyped part_position, untyped part, untyped separator, untyped options) -> untyped end end end module ActionView module Helpers # = Action View Translation Helpers # nodoc: module TranslationHelper extend ActiveSupport::Concern include TagHelper # Delegates to I18n#translate but also performs three additional # functions. # # First, it will ensure that any thrown +MissingTranslation+ messages will # be rendered as inline spans that: # # * Have a translation-missing class applied # * Contain the missing key as the value of the +title+ attribute # * Have a titleized version of the last key segment as text # # For example, the value returned for the missing translation key # "blog.post.title" will be: # # Title # # This allows for views to display rather reasonable strings while still # giving developers a way to find missing translations. # # If you would prefer missing translations to raise an error, you can # opt out of span-wrapping behavior globally by setting # ActionView::Base.raise_on_missing_translations = true or # individually by passing raise: true as an option to # translate. # # Second, if the key starts with a period translate will scope # the key by the current partial. Calling translate(".foo") from # the people/index.html.erb template is equivalent to calling # translate("people.index.foo"). This makes it less # repetitive to translate many keys within the same partial and provides # a convention to scope keys consistently. # # Third, the translation will be marked as html_safe if the key # has the suffix "_html" or the last element of the key is "html". Calling # translate("footer_html") or translate("footer.html") # will return an HTML safe string that won't be escaped by other HTML # helper methods. This naming convention helps to identify translations # that include HTML tags so that you know what kind of output to expect # when you call translate in a template and translators know which keys # they can provide HTML values for. def translate: (untyped key, **untyped options) -> untyped alias t translate # Delegates to I18n.localize with no additional functionality. # # See https://www.rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/Base:localize # for more information. def localize: (untyped object, **untyped options) -> untyped alias l localize def scope_key_by_partial: (untyped key) -> untyped def html_safe_translation_key?: (untyped key) -> untyped end end end module ActionView module Helpers # = Action View URL Helpers # nodoc: # Provides a set of methods for making links and getting URLs that # depend on the routing subsystem (see ActionDispatch::Routing). # This allows you to use the same format for links in views # and controllers. module UrlHelper # This helper may be included in any class that includes the # URL helpers of a routes (routes.url_helpers). Some methods # provided here will only work in the context of a request # (link_to_unless_current, for instance), which must be provided # as a method called #request on the context. BUTTON_TAG_METHOD_VERBS: ::Array[untyped] extend ActiveSupport::Concern include TagHelper module ClassMethods def _url_for_modules: () -> untyped end def url_for: (?untyped? options) -> untyped def _back_url: () -> untyped def _filtered_referrer: () -> untyped # Creates an anchor element of the given +name+ using a URL created by the set of +options+. # See the valid options in the documentation for +url_for+. It's also possible to # pass a String instead of an options hash, which generates an anchor element that uses the # value of the String as the href for the link. Using a :back Symbol instead # of an options hash will generate a link to the referrer (a JavaScript back link # will be used in place of a referrer if none exists). If +nil+ is passed as the name # the value of the link itself will become the name. # # ==== Signatures # # link_to(body, url, html_options = {}) # # url is a String; you can use URL helpers like # # posts_path # # link_to(body, url_options = {}, html_options = {}) # # url_options, except :method, is passed to url_for # # link_to(options = {}, html_options = {}) do # # name # end # # link_to(url, html_options = {}) do # # name # end # # ==== Options # * :data - This option can be used to add custom data attributes. # * method: symbol of HTTP verb - This modifier will dynamically # create an HTML form and immediately submit the form for processing using # the HTTP verb specified. Useful for having links perform a POST operation # in dangerous actions like deleting a record (which search bots can follow # while spidering your site). Supported verbs are :post, :delete, :patch, and :put. # Note that if the user has JavaScript disabled, the request will fall back # to using GET. If href: '#' is used and the user has JavaScript # disabled clicking the link will have no effect. If you are relying on the # POST behavior, you should check for it in your controller's action by using # the request object's methods for post?, delete?, patch?, or put?. # * remote: true - This will allow the unobtrusive JavaScript # driver to make an Ajax request to the URL in question instead of following # the link. The drivers each provide mechanisms for listening for the # completion of the Ajax request and performing JavaScript operations once # they're complete # # ==== Data attributes # # * confirm: 'question?' - This will allow the unobtrusive JavaScript # driver to prompt with the question specified (in this case, the # resulting text would be question?. If the user accepts, the # link is processed normally, otherwise no action is taken. # * :disable_with - Value of this parameter will be used as the # name for a disabled version of the link. This feature is provided by # the unobtrusive JavaScript driver. # # ==== Examples # Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments # and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base # your application on resources and use # # link_to "Profile", profile_path(@profile) # # => Profile # # or the even pithier # # link_to "Profile", @profile # # => Profile # # in place of the older more verbose, non-resource-oriented # # link_to "Profile", controller: "profiles", action: "show", id: @profile # # => Profile # # Similarly, # # link_to "Profiles", profiles_path # # => Profiles # # is better than # # link_to "Profiles", controller: "profiles" # # => Profiles # # When name is +nil+ the href is presented instead # # link_to nil, "http://example.com" # # => http://www.example.com # # You can use a block as well if your link target is hard to fit into the name parameter. ERB example: # # <%= link_to(@profile) do %> # <%= @profile.name %> -- Check it out! # <% end %> # # => # David -- Check it out! # # # Classes and ids for CSS are easy to produce: # # link_to "Articles", articles_path, id: "news", class: "article" # # => Articles # # Be careful when using the older argument style, as an extra literal hash is needed: # # link_to "Articles", { controller: "articles" }, id: "news", class: "article" # # => Articles # # Leaving the hash off gives the wrong link: # # link_to "WRONG!", controller: "articles", id: "news", class: "article" # # => WRONG! # # +link_to+ can also produce links with anchors or query strings: # # link_to "Comment wall", profile_path(@profile, anchor: "wall") # # => Comment wall # # link_to "Ruby on Rails search", controller: "searches", query: "ruby on rails" # # => Ruby on Rails search # # link_to "Nonsense search", searches_path(foo: "bar", baz: "quux") # # => Nonsense search # # The only option specific to +link_to+ (:method) is used as follows: # # link_to("Destroy", "http://www.example.com", method: :delete) # # => Destroy # # You can also use custom data attributes using the :data option: # # link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" } # # => Visit Other Site # # Also you can set any link attributes such as target, rel, type: # # link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow" # # => External link def link_to: (?untyped? name, ?untyped? options, ?untyped? html_options) { () -> untyped } -> untyped # Generates a form containing a single button that submits to the URL created # by the set of +options+. This is the safest method to ensure links that # cause changes to your data are not triggered by search bots or accelerators. # If the HTML button does not work with your layout, you can also consider # using the +link_to+ method with the :method modifier as described in # the +link_to+ documentation. # # By default, the generated form element has a class name of button_to # to allow styling of the form itself and its children. This can be changed # using the :form_class modifier within +html_options+. You can control # the form submission and input element behavior using +html_options+. # This method accepts the :method modifier described in the +link_to+ documentation. # If no :method modifier is given, it will default to performing a POST operation. # You can also disable the button by passing disabled: true in +html_options+. # If you are using RESTful routes, you can pass the :method # to change the HTTP verb used to submit the form. # # ==== Options # The +options+ hash accepts the same options as +url_for+. # # There are a few special +html_options+: # * :method - Symbol of HTTP verb. Supported verbs are :post, :get, # :delete, :patch, and :put. By default it will be :post. # * :disabled - If set to true, it will generate a disabled button. # * :data - This option can be used to add custom data attributes. # * :remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the # submit behavior. By default this behavior is an ajax submit. # * :form - This hash will be form attributes # * :form_class - This controls the class of the form within which the submit button will # be placed # * :params - Hash of parameters to be rendered as hidden fields within the form. # # ==== Data attributes # # * :confirm - This will use the unobtrusive JavaScript driver to # prompt with the question specified. If the user accepts, the link is # processed normally, otherwise no action is taken. # * :disable_with - Value of this parameter will be # used as the value for a disabled version of the submit # button when the form is submitted. This feature is provided # by the unobtrusive JavaScript driver. # # ==== Examples # <%= button_to "New", action: "new" %> # # => "
    # # # #
    " # # <%= button_to "New", new_article_path %> # # => "
    # # # #
    " # # <%= button_to [:make_happy, @user] do %> # Make happy <%= @user.name %> # <% end %> # # => "
    # # # #
    " # # <%= button_to "New", { action: "new" }, form_class: "new-thing" %> # # => "
    # # # #
    " # # # <%= button_to "Create", { action: "create" }, remote: true, form: { "data-type" => "json" } %> # # => "
    # # # # # #
    " # # # <%= button_to "Delete Image", { action: "delete", id: @image.id }, # method: :delete, data: { confirm: "Are you sure?" } %> # # => "
    # # # # # # # #
    " # # # <%= button_to('Destroy', 'http://www.example.com', # method: "delete", remote: true, data: { confirm: 'Are you sure?', disable_with: 'loading...' }) %> # # => "
    # # # # # # # #
    " # # def button_to: (?untyped? name, ?untyped? options, ?untyped? html_options) { () -> untyped } -> untyped # Creates a link tag of the given +name+ using a URL created by the set of # +options+ unless the current request URI is the same as the links, in # which case only the name is returned (or the given block is yielded, if # one exists). You can give +link_to_unless_current+ a block which will # specialize the default behavior (e.g., show a "Start Here" link rather # than the link's text). # # ==== Examples # Let's say you have a navigation menu... # # # # If in the "about" action, it will render... # # # # ...but if in the "index" action, it will render: # # # # The implicit block given to +link_to_unless_current+ is evaluated if the current # action is the action given. So, if we had a comments page and wanted to render a # "Go Back" link instead of a link to the comments page, we could do something like this... # # <%= # link_to_unless_current("Comment", { controller: "comments", action: "new" }) do # link_to("Go back", { controller: "posts", action: "index" }) # end # %> def link_to_unless_current: (untyped name, ?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] html_options) { () -> untyped } -> untyped # Creates a link tag of the given +name+ using a URL created by the set of # +options+ unless +condition+ is true, in which case only the name is # returned. To specialize the default behavior (i.e., show a login link rather # than just the plaintext link text), you can pass a block that # accepts the name or the full argument list for +link_to_unless+. # # ==== Examples # <%= link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) %> # # If the user is logged in... # # => Reply # # <%= # link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) do |name| # link_to(name, { controller: "accounts", action: "signup" }) # end # %> # # If the user is logged in... # # => Reply # # If not... # # => Reply def link_to_unless: (untyped condition, untyped name, ?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] html_options) { () -> untyped } -> untyped # Creates a link tag of the given +name+ using a URL created by the set of # +options+ if +condition+ is true, otherwise only the name is # returned. To specialize the default behavior, you can pass a block that # accepts the name or the full argument list for +link_to_unless+ (see the examples # in +link_to_unless+). # # ==== Examples # <%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %> # # If the user isn't logged in... # # => Login # # <%= # link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) do # link_to(@current_user.login, { controller: "accounts", action: "show", id: @current_user }) # end # %> # # If the user isn't logged in... # # => Login # # If they are logged in... # # => my_username def link_to_if: (untyped condition, untyped name, ?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] html_options) { () -> untyped } -> untyped # Creates a mailto link tag to the specified +email_address+, which is # also used as the name of the link unless +name+ is specified. Additional # HTML attributes for the link can be passed in +html_options+. # # +mail_to+ has several methods for customizing the email itself by # passing special keys to +html_options+. # # ==== Options # * :subject - Preset the subject line of the email. # * :body - Preset the body of the email. # * :cc - Carbon Copy additional recipients on the email. # * :bcc - Blind Carbon Copy additional recipients on the email. # * :reply_to - Preset the Reply-To field of the email. # # ==== Obfuscation # Prior to Rails 4.0, +mail_to+ provided options for encoding the address # in order to hinder email harvesters. To take advantage of these options, # install the +actionview-encoded_mail_to+ gem. # # ==== Examples # mail_to "me@domain.com" # # => me@domain.com # # mail_to "me@domain.com", "My email" # # => My email # # mail_to "me@domain.com", "My email", cc: "ccaddress@domain.com", # subject: "This is an example email" # # => My email # # You can use a block as well if your link target is hard to fit into the name parameter. ERB example: # # <%= mail_to "me@domain.com" do %> # Email me: me@domain.com # <% end %> # # => # Email me: me@domain.com # def mail_to: (untyped email_address, ?untyped? name, ?::Hash[untyped, untyped] html_options) { () -> untyped } -> untyped # True if the current request URI was generated by the given +options+. # # ==== Examples # Let's say we're in the http://www.example.com/shop/checkout?order=desc&page=1 action. # # current_page?(action: 'process') # # => false # # current_page?(action: 'checkout') # # => true # # current_page?(controller: 'library', action: 'checkout') # # => false # # current_page?(controller: 'shop', action: 'checkout') # # => true # # current_page?(controller: 'shop', action: 'checkout', order: 'asc') # # => false # # current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '1') # # => true # # current_page?(controller: 'shop', action: 'checkout', order: 'desc', page: '2') # # => false # # current_page?('http://www.example.com/shop/checkout') # # => true # # current_page?('http://www.example.com/shop/checkout', check_parameters: true) # # => false # # current_page?('/shop/checkout') # # => true # # current_page?('http://www.example.com/shop/checkout?order=desc&page=1') # # => true # # Let's say we're in the http://www.example.com/products action with method POST in case of invalid product. # # current_page?(controller: 'product', action: 'index') # # => false # # We can also pass in the symbol arguments instead of strings. # def current_page?: (untyped options, ?check_parameters: bool check_parameters) -> (::FalseClass | untyped) def convert_options_to_data_attributes: (untyped options, untyped html_options) -> untyped def link_to_remote_options?: (untyped options) -> untyped def add_method_to_attributes!: (untyped html_options, untyped method) -> untyped STRINGIFIED_COMMON_METHODS: untyped def method_not_get_method?: (untyped method) -> (::FalseClass | untyped) def token_tag: (?untyped? token, ?form_options: ::Hash[untyped, untyped] form_options) -> untyped def method_tag: (untyped method) -> untyped # Returns an array of hashes each containing :name and :value keys # suitable for use as the names and values of form input fields: # # to_form_params(name: 'David', nationality: 'Danish') # # => [{name: 'name', value: 'David'}, {name: 'nationality', value: 'Danish'}] # # to_form_params(country: { name: 'Denmark' }) # # => [{name: 'country[name]', value: 'Denmark'}] # # to_form_params(countries: ['Denmark', 'Sweden']}) # # => [{name: 'countries[]', value: 'Denmark'}, {name: 'countries[]', value: 'Sweden'}] # # An optional namespace can be passed to enclose key names: # # to_form_params({ name: 'Denmark' }, 'country') # # => [{name: 'country[name]', value: 'Denmark'}] def to_form_params: (untyped attribute, ?untyped? namespace) -> untyped end end end module ActionView module Helpers # nodoc: # nodoc: extend ActiveSupport::Autoload def self.eager_load!: () -> untyped extend ActiveSupport::Concern include ActiveSupport::Benchmarkable include ActiveModelHelper include AssetTagHelper include AssetUrlHelper include AtomFeedHelper include CacheHelper include CaptureHelper include ControllerHelper include CspHelper include CsrfHelper include DateHelper include DebugHelper include FormHelper include FormOptionsHelper include FormTagHelper include JavaScriptHelper include NumberHelper include OutputSafetyHelper include RenderingHelper include SanitizeHelper include TagHelper include TextHelper include TranslationHelper include UrlHelper end end module ActionView # Layouts reverse the common pattern of including shared headers and footers in many templates to isolate changes in # repeated setups. The inclusion pattern has pages that look like this: # # <%= render "shared/header" %> # Hello World # <%= render "shared/footer" %> # # This approach is a decent way of keeping common structures isolated from the changing content, but it's verbose # and if you ever want to change the structure of these two includes, you'll have to change all the templates. # # With layouts, you can flip it around and have the common structure know where to insert changing content. This means # that the header and footer are only mentioned in one place, like this: # # // The header part of this layout # <%= yield %> # // The footer part of this layout # # And then you have content pages that look like this: # # hello world # # At rendering time, the content page is computed and then inserted in the layout, like this: # # // The header part of this layout # hello world # // The footer part of this layout # # == Accessing shared variables # # Layouts have access to variables specified in the content pages and vice versa. This allows you to have layouts with # references that won't materialize before rendering time: # #

    <%= @page_title %>

    # <%= yield %> # # ...and content pages that fulfill these references _at_ rendering time: # # <% @page_title = "Welcome" %> # Off-world colonies offers you a chance to start a new life # # The result after rendering is: # #

    Welcome

    # Off-world colonies offers you a chance to start a new life # # == Layout assignment # # You can either specify a layout declaratively (using the #layout class method) or give # it the same name as your controller, and place it in app/views/layouts. # If a subclass does not have a layout specified, it inherits its layout using normal Ruby inheritance. # # For instance, if you have PostsController and a template named app/views/layouts/posts.html.erb, # that template will be used for all actions in PostsController and controllers inheriting # from PostsController. # # If you use a module, for instance Weblog::PostsController, you will need a template named # app/views/layouts/weblog/posts.html.erb. # # Since all your controllers inherit from ApplicationController, they will use # app/views/layouts/application.html.erb if no other layout is specified # or provided. # # == Inheritance Examples # # class BankController < ActionController::Base # # bank.html.erb exists # # class ExchangeController < BankController # # exchange.html.erb exists # # class CurrencyController < BankController # # class InformationController < BankController # layout "information" # # class TellerController < InformationController # # teller.html.erb exists # # class EmployeeController < InformationController # # employee.html.erb exists # layout nil # # class VaultController < BankController # layout :access_level_layout # # class TillController < BankController # layout false # # In these examples, we have three implicit lookup scenarios: # * The +BankController+ uses the "bank" layout. # * The +ExchangeController+ uses the "exchange" layout. # * The +CurrencyController+ inherits the layout from BankController. # # However, when a layout is explicitly set, the explicitly set layout wins: # * The +InformationController+ uses the "information" layout, explicitly set. # * The +TellerController+ also uses the "information" layout, because the parent explicitly set it. # * The +EmployeeController+ uses the "employee" layout, because it set the layout to +nil+, resetting the parent configuration. # * The +VaultController+ chooses a layout dynamically by calling the access_level_layout method. # * The +TillController+ does not use a layout at all. # # == Types of layouts # # Layouts are basically just regular templates, but the name of this template needs not be specified statically. Sometimes # you want to alternate layouts depending on runtime information, such as whether someone is logged in or not. This can # be done either by specifying a method reference as a symbol or using an inline method (as a proc). # # The method reference is the preferred approach to variable layouts and is used like this: # # class WeblogController < ActionController::Base # layout :writers_and_readers # # def index # # fetching posts # end # # private # def writers_and_readers # logged_in? ? "writer_layout" : "reader_layout" # end # end # # Now when a new request for the index action is processed, the layout will vary depending on whether the person accessing # is logged in or not. # # If you want to use an inline method, such as a proc, do something like this: # # class WeblogController < ActionController::Base # layout proc { |controller| controller.logged_in? ? "writer_layout" : "reader_layout" } # end # # If an argument isn't given to the proc, it's evaluated in the context of # the current controller anyway. # # class WeblogController < ActionController::Base # layout proc { logged_in? ? "writer_layout" : "reader_layout" } # end # # Of course, the most common way of specifying a layout is still just as a plain template name: # # class WeblogController < ActionController::Base # layout "weblog_standard" # end # # The template will be looked always in app/views/layouts/ folder. But you can point # layouts folder direct also. layout "layouts/demo" is the same as layout "demo". # # Setting the layout to +nil+ forces it to be looked up in the filesystem and fallbacks to the parent behavior if none exists. # Setting it to +nil+ is useful to re-enable template lookup overriding a previous configuration set in the parent: # # class ApplicationController < ActionController::Base # layout "application" # end # # class PostsController < ApplicationController # # Will use "application" layout # end # # class CommentsController < ApplicationController # # Will search for "comments" layout and fallback "application" layout # layout nil # end # # == Conditional layouts # # If you have a layout that by default is applied to all the actions of a controller, you still have the option of rendering # a given action or set of actions without a layout, or restricting a layout to only a single action or a set of actions. The # :only and :except options can be passed to the layout call. For example: # # class WeblogController < ActionController::Base # layout "weblog_standard", except: :rss # # # ... # # end # # This will assign "weblog_standard" as the WeblogController's layout for all actions except for the +rss+ action, which will # be rendered directly, without wrapping a layout around the rendered view. # # Both the :only and :except condition can accept an arbitrary number of method references, so # #except: [ :rss, :text_only ] is valid, as is except: :rss. # # == Using a different layout in the action render call # # If most of your actions use the same layout, it makes perfect sense to define a controller-wide layout as described above. # Sometimes you'll have exceptions where one action wants to use a different layout than the rest of the controller. # You can do this by passing a :layout option to the render call. For example: # # class WeblogController < ActionController::Base # layout "weblog_standard" # # def help # render action: "help", layout: "help" # end # end # # This will override the controller-wide "weblog_standard" layout, and will render the help action with the "help" layout instead. module Layouts extend ActiveSupport::Concern include ActionView::Rendering extend ::ActionView::Rendering::ClassMethods module ClassMethods def inherited: (untyped klass) -> untyped module LayoutConditions # Determines whether the current action has a layout definition by # checking the action name against the :only and :except conditions # set by the layout method. # # ==== Returns # * Boolean - True if the action has a layout definition, false otherwise. def _conditional_layout?: () -> (nil | untyped) end # Specify the layout to use for this class. # # If the specified layout is a: # String:: the String is the template name # Symbol:: call the method specified by the symbol # Proc:: call the passed Proc # false:: There is no layout # true:: raise an ArgumentError # nil:: Force default layout behavior with inheritance # # Return value of +Proc+ and +Symbol+ arguments should be +String+, +false+, +true+ or +nil+ # with the same meaning as described above. # ==== Parameters # * layout - The layout to use. # # ==== Options (conditions) # * :only - A list of actions to apply this layout to. # * :except - Apply this layout to all actions but this one. def layout: (untyped layout, ?::Hash[untyped, untyped] conditions) -> untyped def _write_layout_method: () -> untyped # If no layout is supplied, look for a template named the return # value of this method. # # ==== Returns # * String - A template name def _implied_layout_name: () -> untyped end def _normalize_options: (untyped options) -> untyped def initialize: () -> untyped # Controls whether an action should be rendered using a layout. # If you want to disable any layout settings for the # current action so that it is rendered without a layout then # either override this method in your controller to return false # for that action or set the action_has_layout attribute # to false before rendering. def action_has_layout?: () -> untyped def _conditional_layout?: () -> ::TrueClass # This will be overwritten by _write_layout_method def _layout: () -> nil # Determine the layout for a given name, taking into account the name type. # # ==== Parameters # * name - The name of the template def _layout_for_option: (untyped name) -> untyped def _normalize_layout: (untyped value) -> untyped # Returns the default layout for this controller. # Optionally raises an exception if the layout could not be found. # # ==== Parameters # * formats - The formats accepted to this layout # * require_layout - If set to +true+ and layout is not found, # an +ArgumentError+ exception is raised (defaults to +false+) # # ==== Returns # * template - The template object for the default layout (or +nil+) def _default_layout: (untyped lookup_context, untyped formats, ?bool require_layout) -> untyped def _include_layout?: (untyped options) -> untyped end end module ActionView # = Action View Log Subscriber # # Provides functionality so that Rails can output logs from Action View. class LogSubscriber < ActiveSupport::LogSubscriber VIEWS_PATTERN: untyped def initialize: () -> untyped def render_template: (untyped event) -> untyped def render_partial: (untyped event) -> untyped def render_collection: (untyped event) -> untyped def start: (untyped name, untyped id, untyped payload) -> untyped def logger: () -> untyped EMPTY: ::String def from_rails_root: (untyped string) -> untyped def rails_root: () -> untyped def render_count: (untyped payload) -> untyped def cache_message: (untyped payload) -> untyped def log_rendering_start: (untyped payload) -> untyped end end module ActionView class LookupContext # = Action View Lookup Context # # LookupContext is the object responsible for holding all information # required for looking up templates, i.e. view paths and details. # LookupContext is also responsible for generating a key, given to # view paths, used in the resolver cache lookup. Since this key is generated # only once during the request, it speeds up all cache accesses. # nodoc: attr_accessor prefixes: untyped # = Action View Lookup Context # # LookupContext is the object responsible for holding all information # required for looking up templates, i.e. view paths and details. # LookupContext is also responsible for generating a key, given to # view paths, used in the resolver cache lookup. Since this key is generated # only once during the request, it speeds up all cache accesses. # nodoc: attr_accessor rendered_format: untyped def self.register_detail: (untyped name) { () -> untyped } -> untyped module Accessors # Holds accessors for the registered details. # nodoc: DEFAULT_PROCS: ::Hash[untyped, untyped] end class DetailsKey # nodoc: alias eql? equal? def self.digest_cache: (untyped details) -> untyped def self.details_cache_key: (untyped details) -> untyped def self.clear: () -> untyped def self.digest_caches: () -> untyped def self.view_context_class: (untyped klass) -> untyped end # Add caching behavior on top of Details. module DetailsCache attr_accessor cache: untyped def details_key: () -> untyped # Temporary skip passing the details_key forward. def disable_cache: () { () -> untyped } -> untyped def _set_detail: (untyped key, untyped value) -> untyped end # Helpers related to template lookup using the lookup context information. module ViewPaths attr_reader view_paths: untyped attr_reader html_fallback_for_js: untyped def find: (untyped name, ?untyped prefixes, ?bool partial, ?untyped keys, ?::Hash[untyped, untyped] options) -> untyped alias find_template find alias find_file find def find_all: (untyped name, ?untyped prefixes, ?bool partial, ?untyped keys, ?::Hash[untyped, untyped] options) -> untyped def exists?: (untyped name, ?untyped prefixes, ?bool partial, ?untyped keys, **untyped options) -> untyped alias template_exists? exists? def any?: (untyped name, ?untyped prefixes, ?bool partial) -> untyped alias any_templates? any? # Adds fallbacks to the view paths. Useful in cases when you are rendering # a :file. def with_fallbacks: () { () -> untyped } -> untyped # Whenever setting view paths, makes a copy so that we can manipulate them in # instance objects as we wish. def build_view_paths: (untyped paths) -> ActionView::PathSet def args_for_lookup: (untyped name, untyped prefixes, untyped partial, untyped keys, untyped details_options) -> ::Array[untyped] def detail_args_for: (untyped options) -> (untyped | ::Array[untyped]) def args_for_any: (untyped name, untyped prefixes, untyped partial) -> ::Array[untyped] def detail_args_for_any: () -> untyped # Support legacy foo.erb names even though we now ignore .erb # as well as incorrectly putting part of the path in the template # name instead of the prefix. def normalize_name: (untyped name, untyped prefixes) -> untyped end include Accessors include DetailsCache include ViewPaths def initialize: (untyped view_paths, ?::Hash[untyped, untyped] details, ?untyped prefixes) -> untyped def digest_cache: () -> untyped def with_prepended_formats: (untyped formats) -> untyped def initialize_details: (untyped target, untyped details) -> untyped # Override formats= to expand ["*/*"] values and automatically # add :html as fallback to :js. def formats=: (untyped values) -> untyped # Override locale to return a symbol instead of array. def locale: () -> untyped # Overload locale= to also set the I18n.locale. If the current I18n.config object responds # to original_config, it means that it has a copy of the original I18n configuration and it's # acting as proxy, which we need to skip. def locale=: (untyped value) -> untyped end end module ActionView module ModelNaming # nodoc: # Converts the given object to an ActiveModel compliant one. def convert_to_model: (untyped object) -> untyped def model_name_from_record_or_class: (untyped record_or_class) -> untyped end end module ActionView class PathSet # nodoc: # = Action View PathSet # # This class is used to store and access paths in Action View. A number of # operations are defined so that you can search among the paths in this # set and also perform operations on other +PathSet+ objects. # # A +LookupContext+ will use a +PathSet+ to store the paths in its context. # nodoc: include Enumerable[untyped, untyped] attr_reader paths: untyped def initialize: (?untyped paths) -> untyped def initialize_copy: (untyped other) -> untyped def to_ary: () -> untyped def compact: () -> PathSet def +: (untyped array) -> PathSet def find: (*untyped args) -> untyped alias find_file find def find_all: (untyped path, ?untyped prefixes, *untyped args) -> untyped def exists?: (untyped path, untyped prefixes, *untyped args) -> untyped def find_all_with_query: (untyped query) -> (untyped | ::Array[untyped]) def _find_all: (untyped path, untyped prefixes, untyped args) -> (untyped | ::Array[untyped]) def typecast: (untyped paths) -> untyped end end module ActionView class Railtie < Rails::Engine # = Action View Railtie # :nodoc: NULL_OPTION: untyped end end module ActionView # RecordIdentifier encapsulates methods used by various ActionView helpers # to associate records with DOM elements. # # Consider for example the following code that form of post: # # <%= form_for(post) do |f| %> # <%= f.text_field :body %> # <% end %> # # When +post+ is a new, unsaved ActiveRecord::Base instance, the resulting HTML # is: # #
    # #
    # # When +post+ is a persisted ActiveRecord::Base instance, the resulting HTML # is: # #
    # #
    # # In both cases, the +id+ and +class+ of the wrapping DOM element are # automatically generated, following naming conventions encapsulated by the # RecordIdentifier methods #dom_id and #dom_class: # # dom_id(Post.new) # => "new_post" # dom_class(Post.new) # => "post" # dom_id(Post.find 42) # => "post_42" # dom_class(Post.find 42) # => "post" # # Note that these methods do not strictly require +Post+ to be a subclass of # ActiveRecord::Base. # Any +Post+ class will work as long as its instances respond to +to_key+ # and +model_name+, given that +model_name+ responds to +param_key+. # For instance: # # class Post # attr_accessor :to_key # # def model_name # OpenStruct.new param_key: 'post' # end # # def self.find(id) # new.tap { |post| post.to_key = [id] } # end # end module RecordIdentifier extend ModelNaming include ModelNaming JOIN: ::String NEW: ::String # The DOM class convention is to use the singular form of an object or class. # # dom_class(post) # => "post" # dom_class(Person) # => "person" # # If you need to address multiple instances of the same class in the same view, you can prefix the dom_class: # # dom_class(post, :edit) # => "edit_post" # dom_class(Person, :edit) # => "edit_person" def dom_class: (untyped record_or_class, ?untyped? prefix) -> untyped # The DOM id convention is to use the singular form of an object or class with the id following an underscore. # If no id is found, prefix with "new_" instead. # # dom_id(Post.find(45)) # => "post_45" # dom_id(Post.new) # => "new_post" # # If you need to address multiple instances of the same class in the same view, you can prefix the dom_id: # # dom_id(Post.find(45), :edit) # => "edit_post_45" # dom_id(Post.new, :custom) # => "custom_post" def dom_id: (untyped record, ?untyped? prefix) -> untyped def record_key_for_dom_id: (untyped record) -> untyped end end module ActionView class AbstractRenderer def initialize: (untyped lookup_context) -> untyped def render: () -> untyped class RenderedCollection # :nodoc: def self.empty: (untyped format) -> EmptyCollection attr_reader rendered_templates: untyped def initialize: (untyped rendered_templates, untyped spacer) -> untyped def body: () -> untyped def format: () -> untyped class EmptyCollection attr_reader format: untyped def initialize: (untyped format) -> untyped def body: () -> nil end end class RenderedTemplate # :nodoc: attr_reader body: untyped # :nodoc: attr_reader layout: untyped # :nodoc: attr_reader template: untyped def initialize: (untyped body, untyped layout, untyped template) -> untyped def format: () -> untyped EMPTY_SPACER: untyped end def extract_details: (untyped options) -> untyped def instrument: (untyped name, **untyped options) { (untyped) -> untyped } -> untyped def prepend_formats: (untyped formats) -> (nil | untyped) def build_rendered_template: (untyped content, untyped template, ?untyped? layout) -> RenderedTemplate def build_rendered_collection: (untyped templates, untyped spacer) -> RenderedCollection end end module ActionView module CollectionCaching # :nodoc: extend ActiveSupport::Concern def cache_collection_render: (untyped instrumentation_payload, untyped view, untyped template) { () -> untyped } -> untyped def callable_cache_key?: () -> untyped def collection_by_cache_keys: (untyped view, untyped template) -> untyped def expanded_cache_key: (untyped key, untyped view, untyped template, untyped digest_path) -> untyped # `order_by` is an enumerable object containing keys of the cache, # all keys are passed in whether found already or not. # # `cached_partials` is a hash. If the value exists # it represents the rendered partial from the cache # otherwise `Hash#fetch` will take the value of its block. # # This method expects a block that will return the rendered # partial. An example is to render all results # for each element that was not found in the cache and store it as an array. # Order it so that the first empty cache element in `cached_partials` # corresponds to the first element in `rendered_partials`. # # If the partial is not already cached it will also be # written back to the underlying cache store. def fetch_or_cache_partial: (untyped cached_partials, untyped template, order_by: untyped order_by) { () -> untyped } -> untyped end end module ActionView class PartialIteration # The number of iterations that will be done by the partial. attr_reader size: untyped # The current iteration of the partial. attr_reader index: untyped def initialize: (untyped size) -> untyped # Check if this is the first iteration of the partial. def first?: () -> untyped # Check if this is the last iteration of the partial. def last?: () -> untyped def iterate!: () -> untyped end # = Action View Partials # # There's also a convenience method for rendering sub templates within the current controller that depends on a # single object (we call this kind of sub templates for partials). It relies on the fact that partials should # follow the naming convention of being prefixed with an underscore -- as to separate them from regular # templates that could be rendered on their own. # # In a template for Advertiser#account: # # <%= render partial: "account" %> # # This would render "advertiser/_account.html.erb". # # In another template for Advertiser#buy, we could have: # # <%= render partial: "account", locals: { account: @buyer } %> # # <% @advertisements.each do |ad| %> # <%= render partial: "ad", locals: { ad: ad } %> # <% end %> # # This would first render advertiser/_account.html.erb with @buyer passed in as the local variable +account+, then # render advertiser/_ad.html.erb and pass the local variable +ad+ to the template for display. # # == The :as and :object options # # By default ActionView::PartialRenderer doesn't have any local variables. # The :object option can be used to pass an object to the partial. For instance: # # <%= render partial: "account", object: @buyer %> # # would provide the @buyer object to the partial, available under the local variable +account+ and is # equivalent to: # # <%= render partial: "account", locals: { account: @buyer } %> # # With the :as option we can specify a different name for said local variable. For example, if we # wanted it to be +user+ instead of +account+ we'd do: # # <%= render partial: "account", object: @buyer, as: 'user' %> # # This is equivalent to # # <%= render partial: "account", locals: { user: @buyer } %> # # == \Rendering a collection of partials # # The example of partial use describes a familiar pattern where a template needs to iterate over an array and # render a sub template for each of the elements. This pattern has been implemented as a single method that # accepts an array and renders a partial by the same name as the elements contained within. So the three-lined # example in "Using partials" can be rewritten with a single line: # # <%= render partial: "ad", collection: @advertisements %> # # This will render advertiser/_ad.html.erb and pass the local variable +ad+ to the template for display. An # iteration object will automatically be made available to the template with a name of the form # +partial_name_iteration+. The iteration object has knowledge about which index the current object has in # the collection and the total size of the collection. The iteration object also has two convenience methods, # +first?+ and +last?+. In the case of the example above, the template would be fed +ad_iteration+. # For backwards compatibility the +partial_name_counter+ is still present and is mapped to the iteration's # +index+ method. # # The :as option may be used when rendering partials. # # You can specify a partial to be rendered between elements via the :spacer_template option. # The following example will render advertiser/_ad_divider.html.erb between each ad partial: # # <%= render partial: "ad", collection: @advertisements, spacer_template: "ad_divider" %> # # If the given :collection is +nil+ or empty, render will return +nil+. This will allow you # to specify a text which will be displayed instead by using this form: # # <%= render(partial: "ad", collection: @advertisements) || "There's no ad to be displayed" %> # # == \Rendering shared partials # # Two controllers can share a set of partials and render them like this: # # <%= render partial: "advertisement/ad", locals: { ad: @advertisement } %> # # This will render the partial advertisement/_ad.html.erb regardless of which controller this is being called from. # # == \Rendering objects that respond to +to_partial_path+ # # Instead of explicitly naming the location of a partial, you can also let PartialRenderer do the work # and pick the proper path by checking +to_partial_path+ method. # # # @account.to_partial_path returns 'accounts/account', so it can be used to replace: # # <%= render partial: "accounts/account", locals: { account: @account} %> # <%= render partial: @account %> # # # @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+, # # that's why we can replace: # # <%= render partial: "posts/post", collection: @posts %> # <%= render partial: @posts %> # # == \Rendering the default case # # If you're not going to be using any of the options like collections or layouts, you can also use the short-hand # defaults of render to render partials. Examples: # # # Instead of <%= render partial: "account" %> # <%= render "account" %> # # # Instead of <%= render partial: "account", locals: { account: @buyer } %> # <%= render "account", account: @buyer %> # # # @account.to_partial_path returns 'accounts/account', so it can be used to replace: # # <%= render partial: "accounts/account", locals: { account: @account} %> # <%= render @account %> # # # @posts is an array of Post instances, so every post record returns 'posts/post' on +to_partial_path+, # # that's why we can replace: # # <%= render partial: "posts/post", collection: @posts %> # <%= render @posts %> # # == \Rendering partials with layouts # # Partials can have their own layouts applied to them. These layouts are different than the ones that are # specified globally for the entire action, but they work in a similar fashion. Imagine a list with two types # of users: # # <%# app/views/users/index.html.erb %> # Here's the administrator: # <%= render partial: "user", layout: "administrator", locals: { user: administrator } %> # # Here's the editor: # <%= render partial: "user", layout: "editor", locals: { user: editor } %> # # <%# app/views/users/_user.html.erb %> # Name: <%= user.name %> # # <%# app/views/users/_administrator.html.erb %> #
    # Budget: $<%= user.budget %> # <%= yield %> #
    # # <%# app/views/users/_editor.html.erb %> #
    # Deadline: <%= user.deadline %> # <%= yield %> #
    # # ...this will return: # # Here's the administrator: #
    # Budget: $<%= user.budget %> # Name: <%= user.name %> #
    # # Here's the editor: #
    # Deadline: <%= user.deadline %> # Name: <%= user.name %> #
    # # If a collection is given, the layout will be rendered once for each item in # the collection. For example, these two snippets have the same output: # # <%# app/views/users/_user.html.erb %> # Name: <%= user.name %> # # <%# app/views/users/index.html.erb %> # <%# This does not use layouts %> #
      # <% users.each do |user| -%> #
    • # <%= render partial: "user", locals: { user: user } %> #
    • # <% end -%> #
    # # <%# app/views/users/_li_layout.html.erb %> #
  • # <%= yield %> #
  • # # <%# app/views/users/index.html.erb %> #
      # <%= render partial: "user", layout: "li_layout", collection: users %> #
    # # Given two users whose names are Alice and Bob, these snippets return: # #
      #
    • # Name: Alice #
    • #
    • # Name: Bob #
    • #
    # # The current object being rendered, as well as the object_counter, will be # available as local variables inside the layout template under the same names # as available in the partial. # # You can also apply a layout to a block within any template: # # <%# app/views/users/_chief.html.erb %> # <%= render(layout: "administrator", locals: { user: chief }) do %> # Title: <%= chief.title %> # <% end %> # # ...this will return: # #
    # Budget: $<%= user.budget %> # Title: <%= chief.name %> #
    # # As you can see, the :locals hash is shared between both the partial and its layout. # # If you pass arguments to "yield" then this will be passed to the block. One way to use this is to pass # an array to layout and treat it as an enumerable. # # <%# app/views/users/_user.html.erb %> #
    # Budget: $<%= user.budget %> # <%= yield user %> #
    # # <%# app/views/users/index.html.erb %> # <%= render layout: @users do |user| %> # Title: <%= user.title %> # <% end %> # # This will render the layout for each user and yield to the block, passing the user, each time. # # You can also yield multiple times in one layout and use block arguments to differentiate the sections. # # <%# app/views/users/_user.html.erb %> #
    # <%= yield user, :header %> # Budget: $<%= user.budget %> # <%= yield user, :footer %> #
    # # <%# app/views/users/index.html.erb %> # <%= render layout: @users do |user, section| %> # <%- case section when :header -%> # Title: <%= user.title %> # <%- when :footer -%> # Deadline: <%= user.deadline %> # <%- end -%> # <% end %> class PartialRenderer < AbstractRenderer include CollectionCaching PREFIXED_PARTIAL_NAMES: untyped def initialize: () -> untyped def render: (untyped context, untyped options, untyped block) -> untyped def render_collection: (untyped view, untyped template) -> untyped def render_partial: (untyped view, untyped template) -> untyped # Sets up instance variables needed for rendering a partial. This method # finds the options and details and extracts them. The method also contains # logic that handles the type of object passed in as the partial. # # If +options[:partial]+ is a string, then the @path instance variable is # set to that string. Otherwise, the +options[:partial]+ object must # respond to +to_partial_path+ in order to setup the path. def setup: (untyped context, untyped options, untyped as, untyped block) -> untyped def as_variable: (untyped options) -> untyped def collection_from_options: () -> untyped def collection_from_object: () -> untyped def find_partial: (untyped path, untyped template_keys) -> untyped def find_template: (untyped path, untyped locals) -> untyped def collection_with_template: (untyped view, untyped template) -> untyped def collection_without_template: (untyped view) -> untyped # Obtains the path to where the object's partial is located. If the object # responds to +to_partial_path+, then +to_partial_path+ will be called and # will provide the path. If the object does not respond to +to_partial_path+, # then an +ArgumentError+ is raised. # # If +prefix_partial_path_with_controller_namespace+ is true, then this # method will prefix the partial paths with a namespace. def partial_path: (untyped object, untyped view) -> untyped def prefixed_partial_names: () -> untyped def merge_prefix_into_object_path: (untyped prefix, untyped object_path) -> untyped def retrieve_template_keys: (untyped variable) -> untyped def retrieve_variable: (untyped path, untyped as) -> ::Array[untyped] IDENTIFIER_ERROR_MESSAGE: ::String OPTION_AS_ERROR_MESSAGE: ::String def raise_invalid_identifier: (untyped path) -> untyped def raise_invalid_option_as: (untyped as) -> untyped end end module ActionView # This is the main entry point for rendering. It basically delegates # to other objects like TemplateRenderer and PartialRenderer which # actually renders the template. # # The Renderer will parse the options from the +render+ or +render_body+ # method and render a partial or a template based on the options. The # +TemplateRenderer+ and +PartialRenderer+ objects are wrappers which do all # the setup and logic necessary to render a view and a new object is created # each time +render+ is called. class Renderer attr_accessor lookup_context: untyped def initialize: (untyped lookup_context) -> untyped # Main render entry point shared by Action View and Action Controller. def render: (untyped context, untyped options) -> untyped def render_to_object: (untyped context, untyped options) -> untyped # Render but returns a valid Rack body. If fibers are defined, we return # a streaming body that renders the template piece by piece. # # Note that partials are not supported to be rendered with streaming, # so in such cases, we just wrap them in an array. def render_body: (untyped context, untyped options) -> untyped def render_template: (untyped context, untyped options) -> untyped def render_partial: (untyped context, untyped options) { () -> untyped } -> untyped def cache_hits: () -> untyped def render_template_to_object: (untyped context, untyped options) -> untyped def render_partial_to_object: (untyped context, untyped options) { () -> untyped } -> untyped end end module ActionView class StreamingTemplateRenderer < TemplateRenderer class Body # == TODO # # * Support streaming from child templates, partials and so on. # * Rack::Cache needs to support streaming bodies # nodoc: # A valid Rack::Body (i.e. it responds to each). # It is initialized with a block that, when called, starts # rendering the template. # nodoc: def initialize: () { () -> untyped } -> untyped def each: () { () -> untyped } -> untyped # This is the same logging logic as in ShowExceptions middleware. def log_error: (untyped exception) -> (nil | untyped) end def render_template: (untyped view, untyped template, ?untyped? layout_name, ?::Hash[untyped, untyped] locals) -> (::Array[untyped] | untyped) def delayed_render: (untyped buffer, untyped template, untyped layout, untyped view, untyped locals) -> untyped end end module ActionView class TemplateRenderer < AbstractRenderer # nodoc: def render: (untyped context, untyped options) -> untyped # Determine the template to be rendered using the given options. def determine_template: (untyped options) -> untyped # Renders the given template. A string representing the layout can be # supplied as well. def render_template: (untyped view, untyped template, untyped layout_name, untyped locals) -> untyped def render_with_layout: (untyped view, untyped template, untyped path, untyped locals) { (untyped) -> untyped } -> untyped # This is the method which actually finds the layout using details in the lookup # context object. If no layout is found, it checks if at least a layout with # the given name exists across all details before raising the error. def find_layout: (untyped layout, untyped keys, untyped formats) -> untyped def resolve_layout: (untyped layout, untyped keys, untyped formats) -> untyped end end module ActionView class I18nProxy < ::I18n::Config # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, # it will trigger the lookup_context and consequently expire the cache. # nodoc: attr_reader original_config: untyped # This is a class to fix I18n global state. Whenever you provide I18n.locale during a request, # it will trigger the lookup_context and consequently expire the cache. # nodoc: attr_reader lookup_context: untyped def initialize: (untyped original_config, untyped lookup_context) -> untyped def locale: () -> untyped def locale=: (untyped value) -> untyped end module Rendering extend ActiveSupport::Concern include ActionView::ViewPaths extend ::ActionView::ViewPaths::ClassMethods attr_reader rendered_format: untyped def initialize: () -> untyped def process: () -> untyped module ClassMethods def _routes: () -> nil def _helpers: () -> nil def build_view_context_class: (untyped klass, untyped supports_path, untyped routes, untyped helpers) -> untyped def view_context_class: () -> untyped end def view_context_class: () -> untyped # An instance of a view class. The default view class is ActionView::Base. # # The view class must have the following methods: # # * View.new(lookup_context, assigns, controller) (trim non-ascii characters) Create a new # ActionView instance for a controller and we can also pass the arguments. # # * View#render(option) (trim non-ascii characters) Returns String with the rendered template. # # Override this method in a module to change the default behavior. def view_context: () -> untyped def view_renderer: () -> untyped def render_to_body: (?::Hash[untyped, untyped] options) -> untyped # Find and render a template based on the options given. def _render_template: (untyped options) -> untyped # Assign the rendered format to look up context. def _process_format: (untyped format) -> untyped # Normalize args by converting render "foo" to render :action => "foo" and # render "foo/bar" to render :template => "foo/bar". def _normalize_args: (?untyped? action, ?::Hash[untyped, untyped] options) -> untyped # Normalize options. def _normalize_options: (untyped options) -> untyped end end module ActionView module RoutingUrlFor # Returns the URL for the set of +options+ provided. This takes the # same options as +url_for+ in Action Controller (see the # documentation for ActionController::Base#url_for). Note that by default # :only_path is true so you'll get the relative "/controller/action" # instead of the fully qualified URL like "http://example.com/controller/action". # # ==== Options # * :anchor - Specifies the anchor name to be appended to the path. # * :only_path - If true, returns the relative URL (omitting the protocol, host name, and port) (true by default unless :host is specified). # * :trailing_slash - If true, adds a trailing slash, as in "/archive/2005/". Note that this # is currently not recommended since it breaks caching. # * :host - Overrides the default (current) host if provided. # * :protocol - Overrides the default (current) protocol if provided. # * :user - Inline HTTP authentication (only plucked out if :password is also present). # * :password - Inline HTTP authentication (only plucked out if :user is also present). # # ==== Relying on named routes # # Passing a record (like an Active Record) instead of a hash as the options parameter will # trigger the named route for that record. The lookup will happen on the name of the class. So passing a # Workshop object will attempt to use the +workshop_path+ route. If you have a nested route, such as # +admin_workshop_path+ you'll have to call that explicitly (it's impossible for +url_for+ to guess that route). # # ==== Implicit Controller Namespacing # # Controllers passed in using the +:controller+ option will retain their namespace unless it is an absolute one. # # ==== Examples # <%= url_for(action: 'index') %> # # => /blogs/ # # <%= url_for(action: 'find', controller: 'books') %> # # => /books/find # # <%= url_for(action: 'login', controller: 'members', only_path: false, protocol: 'https') %> # # => https://www.example.com/members/login/ # # <%= url_for(action: 'play', anchor: 'player') %> # # => /messages/play/#player # # <%= url_for(action: 'jump', anchor: 'tax&ship') %> # # => /testing/jump/#tax&ship # # <%= url_for(Workshop.new) %> # # relies on Workshop answering a persisted? call (and in this case returning false) # # => /workshops # # <%= url_for(@workshop) %> # # calls @workshop.to_param which by default returns the id # # => /workshops/5 # # # to_param can be re-defined in a model to provide different URL names: # # => /workshops/1-workshop-name # # <%= url_for("http://www.example.com") %> # # => http://www.example.com # # <%= url_for(:back) %> # # if request.env["HTTP_REFERER"] is set to "http://www.example.com" # # => http://www.example.com # # <%= url_for(:back) %> # # if request.env["HTTP_REFERER"] is not set or is blank # # => javascript:history.back() # # <%= url_for(action: 'index', controller: 'users') %> # # Assuming an "admin" namespace # # => /admin/users # # <%= url_for(action: 'index', controller: '/users') %> # # Specify absolute path with beginning slash # # => /users def url_for: (?untyped? options) -> untyped def url_options: () -> untyped def _routes_context: () -> untyped def optimize_routes_generation?: () -> untyped def _generate_paths_by_default: () -> ::TrueClass def ensure_only_path_option: (untyped options) -> untyped end end module ActionView class ActionViewError < StandardError end class EncodingError < StandardError end class WrongEncodingError < EncodingError # nodoc: def initialize: (untyped string, untyped encoding) -> untyped def message: () -> ::String end class MissingTemplate < ActionViewError # nodoc: attr_reader path: untyped def initialize: (untyped paths, untyped path, untyped prefixes, untyped partial, untyped details) -> untyped end class Template class Error < ActionViewError # The Template::Error exception is raised when the compilation or rendering of the template # fails. This exception then gathers a bunch of intimate details and uses it to report a # precise exception message. # nodoc: SOURCE_CODE_RADIUS: ::Integer # Override to prevent #cause resetting during re-raise. attr_reader cause: untyped def initialize: (untyped template) -> untyped def file_name: () -> untyped def sub_template_message: () -> untyped def source_extract: (?::Integer indentation) -> (::Array[untyped] | untyped) def sub_template_of: (untyped template_path) -> untyped def line_number: () -> untyped def annotated_source_code: () -> untyped def source_location: () -> untyped def formatted_code_for: (untyped source_code, untyped line_counter, untyped indent) -> untyped end end # It is actual TemplateError = Template::Error, but we can't write it in RBS class TemplateError < Template::Error end class SyntaxErrorInTemplate < TemplateError # nodoc def initialize: (untyped template, untyped offending_code_string) -> untyped def message: () -> ::String def annotated_source_code: () -> untyped end end module ActionView module Template::Handlers class Builder def call: (untyped template, untyped source) -> untyped def require_engine: () -> untyped end end end module ActionView class Template module Handlers class ERB class Erubi < ::Erubi::Engine # :nodoc: all def initialize: (untyped input, ?::Hash[untyped, untyped] properties) -> untyped def evaluate: (untyped action_view_erb_handler_context) -> untyped def add_text: (untyped text) -> (nil | untyped) BLOCK_EXPR: untyped def add_expression: (untyped indicator, untyped code) -> untyped def add_code: (untyped code) -> untyped def add_postamble: (untyped _) -> untyped def flush_newline_if_pending: (untyped src) -> untyped end end end end end module ActionView class Template module Handlers class ERB ENCODING_TAG: untyped def self.call: (untyped template, untyped source) -> untyped def supports_streaming?: () -> ::TrueClass def handles_encoding?: () -> ::TrueClass def call: (untyped template, untyped source) -> untyped def valid_encoding: (untyped string, untyped encoding) -> untyped end end end end module ActionView module Template::Handlers class Html < Raw def call: (untyped template, untyped source) -> ::String end end end module ActionView module Template::Handlers class Raw def call: (untyped template, untyped source) -> ::String end end end module ActionView class Template module Handlers def self.extended: (untyped base) -> untyped def self.extensions: () -> untyped class LegacyHandlerWrapper < SimpleDelegator # :nodoc: def call: (untyped view, untyped source) -> untyped end # Register an object that knows how to handle template files with the given # extensions. This can be used to implement new template types. # The handler must respond to +:call+, which will be passed the template # and should return the rendered template as a String. def register_template_handler: (*untyped extensions, untyped handler) -> untyped # Opposite to register_template_handler. def unregister_template_handler: (*untyped extensions) -> untyped def template_handler_extensions: () -> untyped def registered_template_handler: (untyped `extension`) -> untyped def register_default_template_handler: (untyped `extension`, untyped klass) -> untyped def handler_for_extension: (untyped `extension`) -> untyped end end end module ActionView class Template class HTML # nodoc: # = Action View HTML Template # nodoc: # nodoc: attr_reader type: untyped def initialize: (untyped string, ?untyped? `type`) -> untyped def identifier: () -> "html template" alias inspect identifier def to_str: () -> untyped def render: (*untyped args) -> untyped def format: () -> untyped def formats: () -> untyped end end end module ActionView class Template class Inline < Template Finalizer: untyped def compile: (untyped mod) -> untyped end end end module ActionView class Template class RawFile # nodoc: # = Action View RawFile Template # nodoc: # nodoc: attr_accessor type: untyped # nodoc: # = Action View RawFile Template # nodoc: # nodoc: attr_accessor format: untyped def initialize: (untyped filename) -> untyped def identifier: () -> untyped def render: (*untyped args) -> untyped def formats: () -> untyped end end end module ActionView # = Action View Resolver class Resolver # Keeps all information about view path and builds virtual path. class Path attr_reader name: untyped attr_reader prefix: untyped attr_reader partial: untyped attr_reader virtual: untyped alias partial? partial def self.build: (untyped name, untyped prefix, untyped partial) -> untyped def initialize: (untyped name, untyped prefix, untyped partial, untyped virtual) -> untyped def to_str: () -> untyped alias to_s to_str end class Cache # Threadsafe template cache # nodoc: class SmallCache < Concurrent::Map def initialize: (?::Hash[untyped, untyped] options) -> untyped end # preallocate all the default blocks for performance/memory consumption reasons PARTIAL_BLOCK: untyped PREFIX_BLOCK: untyped NAME_BLOCK: untyped KEY_BLOCK: untyped # usually a majority of template look ups return nothing, use this canonical preallocated array to save memory NO_TEMPLATES: untyped def initialize: () -> untyped def inspect: () -> ::String # Cache the templates returned by the block def cache: (untyped key, untyped name, untyped prefix, untyped partial, untyped locals) { () -> untyped } -> untyped def cache_query: (untyped query) { () -> untyped } -> untyped def clear: () -> untyped def size: () -> untyped def canonical_no_templates: (untyped templates) -> untyped end alias self.caching? self.caching def initialize: () -> untyped def clear_cache: () -> untyped # Normalizes the arguments and passes it on to find_templates. def find_all: (untyped name, ?untyped? prefix, ?bool partial, ?::Hash[untyped, untyped] details, ?untyped? key, ?untyped locals) -> untyped alias find_all_anywhere find_all def find_all_with_query: (untyped query) -> untyped def _find_all: (untyped name, untyped prefix, untyped partial, untyped details, untyped key, untyped locals) -> untyped # This is what child classes implement. No defaults are needed # because Resolver guarantees that the arguments are present and # normalized. def find_templates: (untyped name, untyped prefix, untyped partial, untyped details, ?untyped locals) -> untyped # Handles templates caching. If a key is given and caching is on # always check the cache before hitting the resolver. Otherwise, # it always hits the resolver but if the key is present, check if the # resolver is fresher before returning it. def cached: (untyped key, untyped path_info, untyped details, untyped locals) { () -> untyped } -> untyped end class PathResolver < Resolver # An abstract class that implements a Resolver with path semantics. # nodoc: EXTENSIONS: ::Hash[untyped, untyped] DEFAULT_PATTERN: ::String def initialize: (?untyped? pattern) -> untyped def clear_cache: () -> untyped def _find_all: (untyped name, untyped prefix, untyped partial, untyped details, untyped key, untyped locals) -> untyped def query: (untyped path, untyped details, untyped formats, untyped locals, cache: untyped cache) -> untyped def build_unbound_template: (untyped template, untyped virtual_path) -> UnboundTemplate def reject_files_external_to_app: (untyped files) -> untyped def find_template_paths_from_details: (untyped path, untyped details) -> untyped def find_template_paths: (untyped query) -> untyped def inside_path?: (untyped path, untyped filename) -> untyped # Helper for building query glob string based on resolver's pattern. def build_query: (untyped path, untyped details) -> untyped def escape_entry: (untyped entry) -> untyped # Extract handler, formats and variant from path. If a format cannot be found neither # from the path, or the handler, we should return the array of formats given # to the resolver. def extract_handler_and_format_and_variant: (untyped path) -> ::Array[untyped] end # A resolver that loads files from the filesystem. class FileSystemResolver < PathResolver attr_reader path: untyped def initialize: (untyped path, ?untyped? pattern) -> untyped def to_s: () -> untyped alias to_path to_s def eql?: (untyped resolver) -> untyped alias == eql? end class OptimizedFileSystemResolver < FileSystemResolver # An Optimized resolver for Rails' most common case. # nodoc: def initialize: (untyped path) -> untyped def find_template_paths_from_details: (untyped path, untyped details) -> untyped def build_regex: (untyped path, untyped details) -> ::Regexp end class FallbackFileSystemResolver < FileSystemResolver def self.instances: () -> ::Array[untyped] def build_unbound_template: (untyped template, untyped _) -> untyped def reject_files_external_to_app: (untyped files) -> untyped end end module ActionView class Template module Sources class File def initialize: (untyped filename) -> untyped def to_s: () -> untyped end end end end module ActionView class Template module Sources extend ActiveSupport::Autoload end end end module ActionView class Template class Text # nodoc: # = Action View Text Template # nodoc: # nodoc: attr_accessor type: untyped def initialize: (untyped string) -> untyped def identifier: () -> "text template" alias inspect identifier def to_str: () -> untyped def render: (*untyped args) -> untyped def format: () -> :text def formats: () -> untyped end end end module ActionView class Template # nodoc: class Types class Type SET: untyped def self.[]: (untyped `type`) -> untyped attr_reader symbol: untyped def initialize: (untyped symbol) -> untyped def to_s: () -> untyped alias to_str to_s def ref: () -> untyped alias to_sym ref def ==: (untyped `type`) -> untyped end def self.delegate_to: (untyped klass) -> untyped def self.[]: (untyped `type`) -> untyped def self.symbols: () -> untyped end end end module ActionView # = Action View Template class Template extend ActiveSupport::Autoload def self.finalize_compiled_template_methods: () -> untyped def self.finalize_compiled_template_methods=: (untyped _) -> untyped extend Template::Handlers attr_reader identifier: untyped attr_reader handler: untyped attr_reader original_encoding: untyped attr_reader updated_at: untyped attr_reader variable: untyped attr_reader format: untyped attr_reader variant: untyped attr_reader locals: untyped attr_reader virtual_path: untyped def initialize: (untyped source, untyped identifier, untyped handler, ?format: untyped? format, ?variant: untyped? variant, ?locals: untyped? locals, ?virtual_path: untyped? virtual_path, ?updated_at: untyped? updated_at) -> untyped def virtual_path=: (untyped _) -> nil def locals=: (untyped _) -> nil def formats=: (untyped _) -> nil def formats: () -> untyped def variants=: (untyped _) -> nil def variants: () -> ::Array[untyped] def refresh: (untyped _) -> untyped # Returns whether the underlying handler supports streaming. If so, # a streaming buffer *may* be passed when it starts rendering. def supports_streaming?: () -> untyped # Render a template. If the template was not compiled yet, it is done # exactly before rendering. # # This method is instrumented as "!render_template.action_view". Notice that # we use a bang in this instrumentation because you don't want to # consume this in production. This is only slow if it's being listened to. def render: (untyped view, untyped locals, ?untyped buffer) { () -> untyped } -> untyped def `type`: () -> untyped def short_identifier: () -> untyped def inspect: () -> ::String def source: () -> untyped # This method is responsible for properly setting the encoding of the # source. Until this point, we assume that the source is BINARY data. # If no additional information is supplied, we assume the encoding is # the same as Encoding.default_external. # # The user can also specify the encoding via a comment on the first # line of the template (# encoding: NAME-OF-ENCODING). This will work # with any template engine, as we process out the encoding comment # before passing the source on to the template engine, leaving a # blank line in its stead. def encode!: () -> untyped def marshal_dump: () -> ::Array[untyped] def marshal_load: (untyped array) -> untyped # Compile a template. This method ensures a template is compiled # just once and removes the source after it is compiled. def compile!: (untyped view) -> (nil | untyped) class LegacyTemplate # :nodoc: attr_reader source: untyped def initialize: (untyped template, untyped source) -> untyped end # Among other things, this method is responsible for properly setting # the encoding of the compiled template. # # If the template engine handles encodings, we send the encoded # String to the engine without further processing. This allows # the template engine to support additional mechanisms for # specifying the encoding. For instance, ERB supports <%# encoding: %> # # Otherwise, after we figure out the correct encoding, we then # encode the source into Encoding.default_internal. # In general, this means that templates will be UTF-8 inside of Rails, # regardless of the original source encoding. def compile: (untyped mod) -> untyped def handle_render_error: (untyped view, untyped e) -> untyped def locals_code: () -> untyped def method_name: () -> untyped def identifier_method_name: () -> untyped def instrument: (untyped action) { () -> untyped } -> untyped def instrument_render_template: () { () -> untyped } -> untyped def instrument_payload: () -> { virtual_path: untyped, identifier: untyped } end end module ActionView # = Action View Test Case class TestCase < ActiveSupport::TestCase class TestController < ActionController::Base include ActionDispatch::TestProcess attr_accessor request: untyped attr_accessor response: untyped attr_accessor params: untyped attr_writer controller_path: untyped def controller_path=: (untyped path) -> untyped def initialize: () -> untyped end module Behavior extend ActiveSupport::Concern include ActionDispatch::Assertions include ActionDispatch::TestProcess include Rails::Dom::Testing::Assertions include ActionController::TemplateAssertions include ActionView::Context include ActionDispatch::Routing::PolymorphicRoutes include AbstractController::Helpers extend ::AbstractController::Helpers::ClassMethods include ActionView::Helpers include ActionView::RecordIdentifier include ActionView::RoutingUrlFor include ActiveSupport::Testing::ConstantLookup extend ::ActiveSupport::Testing::ConstantLookup::ClassMethods attr_accessor controller: untyped attr_accessor output_buffer: untyped attr_accessor rendered: untyped module ClassMethods def tests: (untyped helper_class) -> untyped def determine_default_helper_class: (untyped name) -> untyped def helper_method: (*untyped methods) -> untyped attr_writer helper_class: untyped def helper_class: () -> untyped def new: () -> untyped def include_helper_modules!: () -> untyped end def setup_with_controller: () -> untyped def config: () -> untyped def render: (?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] local_assigns) { () -> untyped } -> untyped def rendered_views: () -> untyped def _routes: () -> untyped # Need to experiment if this priority is the best one: rendered => output_buffer class RenderedViewsCollection def initialize: () -> untyped def add: (untyped view, untyped locals) -> untyped def locals_for: (untyped view) -> untyped def rendered_views: () -> untyped def view_rendered?: (untyped view, untyped expected_locals) -> untyped end # Need to experiment if this priority is the best one: rendered => output_buffer def document_root_element: () -> untyped def say_no_to_protect_against_forgery!: () -> untyped def make_test_case_available_to_view!: () -> untyped module Locals attr_accessor rendered_views: untyped def render: (?::Hash[untyped, untyped] options, ?::Hash[untyped, untyped] local_assigns) -> untyped end # The instance of ActionView::Base that is used by +render+. def view: () -> untyped alias _view view INTERNAL_IVARS: ::Array[untyped] def _user_defined_ivars: () -> untyped # Returns a Hash of instance variables and their values, as defined by # the user in the test case, which are then assigned to the view being # rendered. This is generally intended for internal use and extension # frameworks. def view_assigns: () -> untyped def method_missing: (untyped selector, *untyped args) -> untyped def respond_to_missing?: (untyped name, ?bool include_private) -> untyped end extend ::ActionView::TestCase::Behavior::ClassMethods include Behavior end end module ActionView # nodoc: # Use FixtureResolver in your tests to simulate the presence of files on the # file system. This is used internally by Rails' own test suite, and is # useful for testing extensions that have no way of knowing what the file # system will look like at runtime. class FixtureResolver < OptimizedFileSystemResolver def initialize: (?::Hash[untyped, untyped] hash, ?untyped? pattern) -> untyped def data: () -> untyped def to_s: () -> untyped def query: (untyped path, untyped exts, untyped _, untyped locals, cache: untyped cache) -> untyped end class NullResolver < PathResolver def query: (untyped path, untyped exts, untyped _, untyped locals, cache: untyped cache) -> ::Array[ActionView::Template] end end module ActionView class UnboundTemplate def initialize: (untyped source, untyped identifer, untyped handler, untyped options) -> untyped def bind_locals: (untyped locals) -> untyped def build_template: (untyped locals) -> Template end end module ActionView # Returns the version of the currently loaded ActionView as a Gem::Version def self.version: () -> untyped end module ActionView module ViewPaths extend ActiveSupport::Concern module ClassMethods def _view_paths: () -> untyped def _view_paths=: (untyped paths) -> untyped def _prefixes: () -> untyped # Override this method in your controller if you want to change paths prefixes for finding views. # Prefixes defined here will still be added to parents' ._prefixes. def local_prefixes: () -> ::Array[untyped] end def self.get_view_paths: (untyped klass) -> untyped def self.set_view_paths: (untyped klass, untyped paths) -> untyped def self.all_view_paths: () -> untyped def _prefixes: () -> untyped # LookupContext is the object responsible for holding all # information required for looking up templates, i.e. view paths and # details. Check ActionView::LookupContext for more information. def lookup_context: () -> untyped def details_for_lookup: () -> ::Hash[untyped, untyped] # Append a path to the list of view paths for the current LookupContext. # # ==== Parameters # * path - If a String is provided, it gets converted into # the default view path. You may also provide a custom view path # (see ActionView::PathSet for more information) def append_view_path: (untyped path) -> untyped # Prepend a path to the list of view paths for the current LookupContext. # # ==== Parameters # * path - If a String is provided, it gets converted into # the default view path. You may also provide a custom view path # (see ActionView::PathSet for more information) def prepend_view_path: (untyped path) -> untyped module ClassMethods # Append a path to the list of view paths for this controller. # # ==== Parameters # * path - If a String is provided, it gets converted into # the default view path. You may also provide a custom view path # (see ActionView::PathSet for more information) def append_view_path: (untyped path) -> untyped # Prepend a path to the list of view paths for this controller. # # ==== Parameters # * path - If a String is provided, it gets converted into # the default view path. You may also provide a custom view path # (see ActionView::PathSet for more information) def prepend_view_path: (untyped path) -> untyped # A list of all of the default view paths for this controller. def view_paths: () -> untyped # Set the view paths. # # ==== Parameters # * paths - If a PathSet is provided, use that; # otherwise, process the parameter into a PathSet. def view_paths=: (untyped paths) -> untyped end end end module ActionView extend ActiveSupport::Autoload ENCODING_FLAG: ::String def self.eager_load!: () -> untyped end