diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f00e29cb8c..6e020b5d3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: with: submodules: true - name: fetch Rails tags - run: cd rails && git fetch --depth=1 origin refs/tags/v7*:refs/tags/v7* refs/tags/v6*:refs/tags/v6* refs/tags/v5*:refs/tags/v5* + run: cd rails && git fetch --depth=1 origin refs/tags/v7*:refs/tags/v7* refs/tags/v6*:refs/tags/v6* refs/tags/v5*:refs/tags/v5* - uses: ruby/setup-ruby@v1 with: ruby-version: 2.7 diff --git a/Rakefile b/Rakefile index 086f80cf0a..c0e3fc4ff7 100644 --- a/Rakefile +++ b/Rakefile @@ -5,22 +5,31 @@ require 'bundler' SOURCE_DIR = 'src' INDEX_HTML = 'files/railties/RDOC_MAIN_rdoc.html' +NEW_INDEX_HTML = 'files/railties/RDOC_MAIN_md.html' desc 'Generate documentation for default Rails version and build Jekyll site' task build: :switch_default_rails do generate_rails_rdoc - generate_src + generate_src(target_version: default_rails_version) sh 'bundle exec jekyll build' end desc 'Switch to default Rails version' task :switch_default_rails do - switch_rails(config['default_rails_version']) + switch_rails(default_rails_version) end desc 'Generate adn build documentation for older versions of Rails' task :build_multi do - config['rails_versions'].each do |version, detail| + # WORKAROUND: use `reverse_each` instead of `each` to avoid nokogiri installation error + config['rails_versions'].reverse_each do |version, detail| + if detail['latest'] + puts "=== Skip Rails v#{version} because it's latest version ===" + next + else + puts "=== Build Rails v#{version} documentation ===" + end + dir = "#{SOURCE_DIR}/#{version}" mkdir dir unless Dir.exist?(dir) @@ -29,11 +38,16 @@ task :build_multi do generate_rails_rdoc generate_src(target_version: version) end + puts sh 'bundle exec jekyll build' end def config - YAML.load_file('./_config.yml') + @config ||= YAML.load_file('./_config.yml') +end + +def default_rails_version + config['default_rails_version'] end def switch_rails(version) @@ -46,10 +60,9 @@ end def generate_rails_rdoc cd 'rails' do Bundler.with_unbundled_env do - # TODO: use `BUNDLE_ONLY`(require bundler 2.3.19+). - ENV['BUNDLE_WITHOUT'] = %w[db job storage cable ujs test rubocop view].join(':') + ENV['BUNDLE_WITHOUT'] = %w[db view job storage cable ujs test rubocop lint mdl].join(':') - # replace sdoc gem + # Replace sdoc gem with my forked one gemfile = File.read('Gemfile') gemfile.gsub!(/"sdoc".*$/, '"sdoc", github: "toshimaru/sdoc", branch: "railsdoc"') File.write('Gemfile', gemfile) @@ -61,15 +74,18 @@ def generate_rails_rdoc end end -def generate_src(target_version: nil) +def generate_src(target_version:) copy_sources = Dir.glob('rails/doc/rdoc/*').reject { |path| path.end_with?('panel', 'js', 'created.rid') } - target_dir = "#{SOURCE_DIR}/#{target_version}" + target_dir = target_version == default_rails_version ? SOURCE_DIR : "#{SOURCE_DIR}/#{target_version}" cp_r copy_sources, target_dir cd target_dir do - cp INDEX_HTML, 'index.html' - return if target_version.nil? + if Gem::Version.new(target_version) >= Gem::Version.new('7.1') + cp NEW_INDEX_HTML, 'index.html' + return + end + cp INDEX_HTML, 'index.html' # Prepend version number to the absolute path in navigation.html content = File.read('navigation.html') content.gsub!(' + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ diff --git a/src/7.0/classes/AbstractController/ActionNotFound.html b/src/7.0/classes/AbstractController/ActionNotFound.html new file mode 100644 index 0000000000..67da374235 --- /dev/null +++ b/src/7.0/classes/AbstractController/ActionNotFound.html @@ -0,0 +1,66 @@ +--- +title: AbstractController::ActionNotFound +layout: default +--- +
+ +
+
+ +
+ +

Raised when a non-existing controller action is triggered.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Base.html b/src/7.0/classes/AbstractController/Base.html new file mode 100644 index 0000000000..3ef39d55c5 --- /dev/null +++ b/src/7.0/classes/AbstractController/Base.html @@ -0,0 +1,749 @@ +--- +title: AbstractController::Base +layout: default +--- +
+ +
+
+ +
+ +

AbstractController::Base is a low-level API. Nobody should be using it directly, and subclasses (like ActionController::Base) are expected to provide their own render method, since rendering means different things depending on the context.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + abstract
+ [R] + abstract?
+ + + + +

Class Public methods

+ +
+

+ + abstract!() + +

+ + +
+

Define a controller as abstract. See internal_methods for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 55
+def abstract!
+  @abstract = true
+end
+
+
+ +
+ +
+

+ + action_methods() + +

+ + +
+

A list of method names that should be considered actions. This includes all public instance methods on a controller, less any internal methods (see internal_methods), adding back in any methods that are internal, but still exist on the class itself.

+ +

Returns

+
  • +

    Set - A set of all methods that should be considered actions.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 89
+def action_methods
+  @action_methods ||= begin
+    # All public instance methods of this class, including ancestors
+    methods = (public_instance_methods(true) -
+      # Except for public instance methods of Base and its ancestors
+      internal_methods +
+      # Be sure to include shadowed public instance methods of this class
+      public_instance_methods(false))
+
+    methods.map!(&:to_s)
+
+    methods.to_set
+  end
+end
+
+
+ +
+ +
+

+ + clear_action_methods!() + +

+ + +
+

action_methods are cached and there is sometimes a need to refresh them. ::clear_action_methods! allows you to do that, so next time you run action_methods, they will be recalculated.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 107
+def clear_action_methods!
+  @action_methods = nil
+end
+
+
+ +
+ +
+

+ + controller_path() + +

+ + +
+

Returns the full controller name, underscored, without the ending Controller.

+ +
class MyApp::MyPostsController < AbstractController::Base
+
+end
+
+MyApp::MyPostsController.controller_path # => "my_app/my_posts"
+
+ +

Returns

+
  • +

    String

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 121
+def controller_path
+  @controller_path ||= name.delete_suffix("Controller").underscore unless anonymous?
+end
+
+
+ +
+ +
+

+ + internal_methods() + +

+ + +
+

A list of all internal methods for a controller. This finds the first abstract superclass of a controller, and gets a list of all public instance methods on that abstract class. Public instance methods of a controller would normally be considered action methods, so methods declared on abstract classes are being removed. (ActionController::Metal and ActionController::Base are defined as abstract)

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 74
+def internal_methods
+  controller = self
+
+  controller = controller.superclass until controller.abstract?
+  controller.public_instance_methods(true)
+end
+
+
+ +
+ +
+

+ + method_added(name) + +

+ + +
+

Refresh the cached action_methods when a new action_method is added.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 126
+def method_added(name)
+  super
+  clear_action_methods!
+end
+
+
+ +
+ +
+

+ + supports_path?() + +

+ + +
+

Returns true if the given controller is capable of rendering a path. A subclass of AbstractController::Base may return false. An Email controller for example does not support paths, only full URLs.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 190
+def self.supports_path?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + action_methods() + +

+ + +
+

Delegates to the class’s ::action_methods.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 161
+def action_methods
+  self.class.action_methods
+end
+
+
+ +
+ +
+

+ + action_name + +

+ + +
+

Returns the name of the action this controller is processing.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 40
+attr_internal :action_name
+
+
+
+ +
+ +
+

+ + available_action?(action_name) + +

+ + +
+

Returns true if a method for the action is available and can be dispatched, false otherwise.

+ +

Notice that action_methods.include?("foo") may return false and available_action?("foo") returns true because this method considers actions that are also available through other means, for example, implicit render ones.

+ +

Parameters

+
  • +

    action_name - The name of an action to be tested

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 175
+def available_action?(action_name)
+  _find_action_name(action_name)
+end
+
+
+ +
+ +
+

+ + controller_path() + +

+ + +
+

Delegates to the class’s ::controller_path.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 156
+def controller_path
+  self.class.controller_path
+end
+
+
+ +
+ +
+

+ + formats + +

+ + +
+

Returns the formats that can be processed by the controller.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 44
+attr_internal :formats
+
+
+
+ +
+ +
+

+ + performed?() + +

+ + +
+

Tests if a response body is set. Used to determine if the process_action callback needs to be terminated in AbstractController::Callbacks.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 182
+def performed?
+  response_body
+end
+
+
+ +
+ +
+

+ + process(action, *args) + +

+ + +
+

Calls the action going through the entire action dispatch stack.

+ +

The actual method that is called is determined by calling method_for_action. If no method can handle the action, then an AbstractController::ActionNotFound error is raised.

+ +

Returns

+
  • +

    self

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 142
+def process(action, *args)
+  @_action_name = action.to_s
+
+  unless action_name = _find_action_name(@_action_name)
+    raise ActionNotFound.new("The action '#{action}' could not be found for #{self.class.name}", self, action)
+  end
+
+  @_response_body = nil
+
+  process_action(action_name, *args)
+end
+
+
+ +
+ +
+

+ + response_body + +

+ + +
+

Returns the body of the HTTP response sent by the controller.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/base.rb, line 36
+attr_internal :response_body
+
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Caching.html b/src/7.0/classes/AbstractController/Caching.html new file mode 100644 index 0000000000..119f69c64c --- /dev/null +++ b/src/7.0/classes/AbstractController/Caching.html @@ -0,0 +1,188 @@ +--- +title: AbstractController::Caching +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + view_cache_dependencies() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching.rb, line 52
+def view_cache_dependencies
+  self.class._view_cache_dependencies.filter_map { |dep| instance_exec(&dep) }
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + cache(key, options = {}, &block) + +

+ + +
+

Convenience accessor.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching.rb, line 58
+def cache(key, options = {}, &block) # :doc:
+  if cache_configured?
+    cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller), options, &block)
+  else
+    yield
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Caching/ClassMethods.html b/src/7.0/classes/AbstractController/Caching/ClassMethods.html new file mode 100644 index 0000000000..fdc8d3fd24 --- /dev/null +++ b/src/7.0/classes/AbstractController/Caching/ClassMethods.html @@ -0,0 +1,101 @@ +--- +title: AbstractController::Caching::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + view_cache_dependency(&dependency) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching.rb, line 47
+def view_cache_dependency(&dependency)
+  self._view_cache_dependencies += [dependency]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Caching/ConfigMethods.html b/src/7.0/classes/AbstractController/Caching/ConfigMethods.html new file mode 100644 index 0000000000..834086bec7 --- /dev/null +++ b/src/7.0/classes/AbstractController/Caching/ConfigMethods.html @@ -0,0 +1,140 @@ +--- +title: AbstractController::Caching::ConfigMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + cache_store() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching.rb, line 13
+def cache_store
+  config.cache_store
+end
+
+
+ +
+ +
+

+ + cache_store=(store) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching.rb, line 17
+def cache_store=(store)
+  config.cache_store = ActiveSupport::Cache.lookup_store(*store)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Caching/Fragments.html b/src/7.0/classes/AbstractController/Caching/Fragments.html new file mode 100644 index 0000000000..80875d5efb --- /dev/null +++ b/src/7.0/classes/AbstractController/Caching/Fragments.html @@ -0,0 +1,325 @@ +--- +title: AbstractController::Caching::Fragments +layout: default +--- +
+ +
+
+ +
+ +

Fragment caching is used for caching various blocks within views without caching the entire action as a whole. This is useful when certain elements of an action change frequently or depend on complicated state while other parts rarely change or can be shared amongst multiple parties. The caching is done using the cache helper available in the Action View. See ActionView::Helpers::CacheHelper for more information.

+ +

While it’s strongly recommended that you use key-based cache expiration (see links in CacheHelper for more information), it is also possible to manually expire caches. For example:

+ +
expire_fragment('name_of_cache')
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + combined_fragment_cache_key(key) + +

+ + +
+

Given a key (as described in expire_fragment), returns a key array suitable for use in reading, writing, or expiring a cached fragment. All keys begin with :views, followed by ENV["RAILS_CACHE_ID"] or ENV["RAILS_APP_VERSION"] if set, followed by any controller-wide key prefix values, ending with the specified key value.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 68
+def combined_fragment_cache_key(key)
+  head = self.class.fragment_cache_keys.map { |k| instance_exec(&k) }
+  tail = key.is_a?(Hash) ? url_for(key).split("://").last : key
+
+  cache_key = [:views, ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"], head, tail]
+  cache_key.flatten!(1)
+  cache_key.compact!
+  cache_key
+end
+
+
+ +
+ +
+

+ + expire_fragment(key, options = nil) + +

+ + +
+

Removes fragments from the cache.

+ +

key can take one of three forms:

+
  • +

    String - This would normally take the form of a path, like pages/45/notes.

    +
  • +

    Hash - Treated as an implicit call to url_for, like { controller: 'pages', action: 'notes', id: 45}

    +
  • +

    Regexp - Will remove any fragment that matches, so %r{pages/\d*/notes} might remove all notes. Make sure you don’t use anchors in the regex (^ or $) because the actual filename matched looks like ./cache/filename/path.cache. Note: Regexp expiration is only supported on caches that can iterate over all keys (unlike memcached).

    +
+ +

options is passed through to the cache store’s delete method (or delete_matched, for Regexp keys).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 132
+def expire_fragment(key, options = nil)
+  return unless cache_configured?
+  key = combined_fragment_cache_key(key) unless key.is_a?(Regexp)
+
+  instrument_fragment_cache :expire_fragment, key do
+    if key.is_a?(Regexp)
+      cache_store.delete_matched(key, options)
+    else
+      cache_store.delete(key, options)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + fragment_exist?(key, options = nil) + +

+ + +
+

Check if a cached fragment from the location signified by key exists (see expire_fragment for acceptable formats).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 105
+def fragment_exist?(key, options = nil)
+  return unless cache_configured?
+  key = combined_fragment_cache_key(key)
+
+  instrument_fragment_cache :exist_fragment?, key do
+    cache_store.exist?(key, options)
+  end
+end
+
+
+ +
+ +
+

+ + read_fragment(key, options = nil) + +

+ + +
+

Reads a cached fragment from the location signified by key (see expire_fragment for acceptable formats).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 93
+def read_fragment(key, options = nil)
+  return unless cache_configured?
+
+  key = combined_fragment_cache_key(key)
+  instrument_fragment_cache :read_fragment, key do
+    result = cache_store.read(key, options)
+    result.respond_to?(:html_safe) ? result.html_safe : result
+  end
+end
+
+
+ +
+ +
+

+ + write_fragment(key, content, options = nil) + +

+ + +
+

Writes content to the location signified by key (see expire_fragment for acceptable formats).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 80
+def write_fragment(key, content, options = nil)
+  return content unless cache_configured?
+
+  key = combined_fragment_cache_key(key)
+  instrument_fragment_cache :write_fragment, key do
+    content = content.to_str
+    cache_store.write(key, content, options)
+  end
+  content
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Caching/Fragments/ClassMethods.html b/src/7.0/classes/AbstractController/Caching/Fragments/ClassMethods.html new file mode 100644 index 0000000000..fe251c5a39 --- /dev/null +++ b/src/7.0/classes/AbstractController/Caching/Fragments/ClassMethods.html @@ -0,0 +1,117 @@ +--- +title: AbstractController::Caching::Fragments::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fragment_cache_key(value = nil, &key) + +

+ + +
+

Allows you to specify controller-wide key prefixes for cache fragments. Pass either a constant value, or a block which computes a value each time a cache key is generated.

+ +

For example, you may want to prefix all fragment cache keys with a global version identifier, so you can easily invalidate all caches.

+ +
class ApplicationController
+  fragment_cache_key "v1"
+end
+
+ +

When it’s time to invalidate all fragments, simply change the string constant. Or, progressively roll out the cache invalidation using a computed value:

+ +
class ApplicationController
+  fragment_cache_key do
+    @account.id.odd? ? "v1" : "v2"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/caching/fragments.rb, line 57
+def fragment_cache_key(value = nil, &key)
+  self.fragment_cache_keys += [key || -> { value }]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Callbacks.html b/src/7.0/classes/AbstractController/Callbacks.html new file mode 100644 index 0000000000..81c7096aa1 --- /dev/null +++ b/src/7.0/classes/AbstractController/Callbacks.html @@ -0,0 +1,116 @@ +--- +title: AbstractController::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Abstract Controller Callbacks

+ +

Abstract Controller provides hooks during the life cycle of a controller action. Callbacks allow you to trigger logic during this cycle. Available callbacks are:

+
  • +

    after_action

    +
  • +

    append_after_action

    +
  • +

    append_around_action

    +
  • +

    append_before_action

    +
  • +

    around_action

    +
  • +

    before_action

    +
  • +

    prepend_after_action

    +
  • +

    prepend_around_action

    +
  • +

    prepend_before_action

    +
  • +

    skip_after_action

    +
  • +

    skip_around_action

    +
  • +

    skip_before_action

    +
+ +

NOTE: Calling the same callback multiple times will overwrite previous callback definitions.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Callbacks/ClassMethods.html b/src/7.0/classes/AbstractController/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..746dcd4822 --- /dev/null +++ b/src/7.0/classes/AbstractController/Callbacks/ClassMethods.html @@ -0,0 +1,641 @@ +--- +title: AbstractController::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _insert_callbacks(callbacks, block = nil) + +

+ + +
+

Take callback names and an optional callback proc, normalize them, then call the block with each callback. This allows us to abstract the normalization across several methods that use it.

+ +

Parameters

+
  • +

    callbacks - An array of callbacks, with an optional options hash as the last parameter.

    +
  • +

    block - A proc that should be added to the callbacks.

    +
+ +

Block Parameters

+
  • +

    name - The callback to be added.

    +
  • +

    options - A hash of options to be used when adding the callback.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 96
+def _insert_callbacks(callbacks, block = nil)
+  options = callbacks.extract_options!
+  _normalize_callback_options(options)
+  callbacks.push(block) if block
+  callbacks.each do |callback|
+    yield callback, options
+  end
+end
+
+
+ +
+ +
+

+ + _normalize_callback_options(options) + +

+ + +
+

If :only or :except are used, convert the options into the :if and :unless options of ActiveSupport::Callbacks.

+ +

The basic idea is that :only => :index gets converted to :if => proc {|c| c.action_name == "index" }.

+ +

Note that :only has priority over :if in case they are used together.

+ +
only: :index, if: -> { true } # the :if option will be ignored.
+
+ +

Note that :if has priority over :except in case they are used together.

+ +
except: :index, if: -> { true } # the :except option will be ignored.
+
+ +

Options

+
  • +

    only - The callback should be run only for this action.

    +
  • +

    except - The callback should be run for all actions except this action.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 72
+def _normalize_callback_options(options)
+  _normalize_callback_option(options, :only, :if)
+  _normalize_callback_option(options, :except, :unless)
+end
+
+
+ +
+ +
+

+ + after_action(names, block) + + +

+ + +
+

Append a callback after actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 146
+      
+
+
+ +
+ +
+

+ + append_after_action(names, block) + + +

+ + +
+

Append a callback after actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 167
+      
+
+
+ +
+ +
+

+ + append_around_action(names, block) + + +

+ + +
+

Append a callback around actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 195
+      
+
+
+ +
+ +
+

+ + append_before_action(names, block) + + +

+ + +
+

Append a callback before actions. See _insert_callbacks for parameter details.

+ +

If the callback renders or redirects, the action will not run. If there are additional callbacks scheduled to run after that callback, they are also cancelled.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 135
+      
+
+
+ +
+ +
+

+ + around_action(names, block) + + +

+ + +
+

Append a callback around actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 174
+      
+
+
+ +
+ +
+

+ + before_action(names, block) + + +

+ + +
+

Append a callback before actions. See _insert_callbacks for parameter details.

+ +

If the callback renders or redirects, the action will not run. If there are additional callbacks scheduled to run after that callback, they are also cancelled.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 106
+      
+
+
+ +
+ +
+

+ + prepend_after_action(names, block) + + +

+ + +
+

Prepend a callback after actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 153
+      
+
+
+ +
+ +
+

+ + prepend_around_action(names, block) + + +

+ + +
+

Prepend a callback around actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 181
+      
+
+
+ +
+ +
+

+ + prepend_before_action(names, block) + + +

+ + +
+

Prepend a callback before actions. See _insert_callbacks for parameter details.

+ +

If the callback renders or redirects, the action will not run. If there are additional callbacks scheduled to run after that callback, they are also cancelled.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 117
+      
+
+
+ +
+ +
+

+ + skip_after_action(names) + + +

+ + +
+

Skip a callback after actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 160
+      
+
+
+ +
+ +
+

+ + skip_around_action(names) + + +

+ + +
+

Skip a callback around actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 188
+      
+
+
+ +
+ +
+

+ + skip_before_action(names) + + +

+ + +
+

Skip a callback before actions. See _insert_callbacks for parameter details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/callbacks.rb, line 128
+      
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Collector.html b/src/7.0/classes/AbstractController/Collector.html new file mode 100644 index 0000000000..51a6922d3b --- /dev/null +++ b/src/7.0/classes/AbstractController/Collector.html @@ -0,0 +1,107 @@ +--- +title: AbstractController::Collector +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + generate_method_for_mime(mime) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/collector.rb, line 7
+    def self.generate_method_for_mime(mime)
+      sym = mime.is_a?(Symbol) ? mime : mime.to_sym
+      class_eval <<-RUBY, __FILE__, __LINE__ + 1
+        def #{sym}(*args, &block)
+          custom(Mime[:#{sym}], *args, &block)
+        end
+        ruby2_keywords(:#{sym})
+      RUBY
+    end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/DoubleRenderError.html b/src/7.0/classes/AbstractController/DoubleRenderError.html new file mode 100644 index 0000000000..1c2f5acbcf --- /dev/null +++ b/src/7.0/classes/AbstractController/DoubleRenderError.html @@ -0,0 +1,125 @@ +--- +title: AbstractController::DoubleRenderError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_MESSAGE="Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like \"redirect_to(...) and return\"."
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 12
+def initialize(message = nil)
+  super(message || DEFAULT_MESSAGE)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Helpers.html b/src/7.0/classes/AbstractController/Helpers.html new file mode 100644 index 0000000000..febd0e1efa --- /dev/null +++ b/src/7.0/classes/AbstractController/Helpers.html @@ -0,0 +1,121 @@ +--- +title: AbstractController::Helpers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _helpers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 40
+def _helpers
+  self.class._helpers
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Helpers/ClassMethods.html b/src/7.0/classes/AbstractController/Helpers/ClassMethods.html new file mode 100644 index 0000000000..6b4448af51 --- /dev/null +++ b/src/7.0/classes/AbstractController/Helpers/ClassMethods.html @@ -0,0 +1,426 @@ +--- +title: AbstractController::Helpers::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [W] + _helpers
+ + + + + +

Instance Public methods

+ +
+

+ + _helpers_for_modification() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 188
+def _helpers_for_modification
+  unless @_helpers
+    self._helpers = define_helpers_module(self, superclass._helpers)
+  end
+  _helpers
+end
+
+
+ +
+ +
+

+ + clear_helpers() + +

+ + +
+

Clears up all existing helpers in this class, only keeping the helper with the same name as this class.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 162
+def clear_helpers
+  inherited_helper_methods = _helper_methods
+  self._helpers = Module.new
+  self._helper_methods = Array.new
+
+  inherited_helper_methods.each { |meth| helper_method meth }
+  default_helper_module! unless anonymous?
+end
+
+
+ +
+ +
+

+ + helper(*args, &block) + +

+ + +
+

Includes the given modules in the template class.

+ +

Modules can be specified in different ways. All of the following calls include FooHelper:

+ +
# Module, recommended.
+helper FooHelper
+
+# String/symbol without the "helper" suffix, camel or snake case.
+helper "Foo"
+helper :Foo
+helper "foo"
+helper :foo
+
+ +

The last two assume that "foo".camelize returns “Foo”.

+ +

When strings or symbols are passed, the method finds the actual module object using String#constantize. Therefore, if the module has not been yet loaded, it has to be autoloadable, which is normally the case.

+ +

Namespaces are supported. The following calls include Foo::BarHelper:

+ +
# Module, recommended.
+helper Foo::BarHelper
+
+# String/symbol without the "helper" suffix, camel or snake case.
+helper "Foo::Bar"
+helper :"Foo::Bar"
+helper "foo/bar"
+helper :"foo/bar"
+
+ +

The last two assume that "foo/bar".camelize returns “Foo::Bar”.

+ +

The method accepts a block too. If present, the block is evaluated in the context of the controller helper module. This simple call makes the wadus method available in templates of the enclosing controller:

+ +
helper do
+  def wadus
+    "wadus"
+  end
+end
+
+ +

Furthermore, all the above styles can be mixed together:

+ +
helper FooHelper, "woo", "bar/baz" do
+  def wadus
+    "wadus"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 151
+def helper(*args, &block)
+  modules_for_helpers(args).each do |mod|
+    next if _helpers.include?(mod)
+    _helpers_for_modification.include(mod)
+  end
+
+  _helpers_for_modification.module_eval(&block) if block_given?
+end
+
+
+ +
+ +
+

+ + helper_method(*methods) + +

+ + +
+

Declare a controller method as a helper. For example, the following makes the current_user and logged_in? controller methods available to the view:

+ +
class ApplicationController < ActionController::Base
+  helper_method :current_user, :logged_in?
+
+  private
+    def current_user
+      @current_user ||= User.find_by(id: session[:user])
+    end
+
+    def logged_in?
+      current_user != nil
+    end
+end
+
+ +

In a view:

+ +
<% if logged_in? -%>Welcome, <%= current_user.name %><% end -%>
+
+ +

Parameters

+
  • +

    method[, method] - A name or names of a method on the controller to be made available on the view.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 80
+      def helper_method(*methods)
+        methods.flatten!
+        self._helper_methods += methods
+
+        location = caller_locations(1, 1).first
+        file, line = location.path, location.lineno
+
+        methods.each do |method|
+          # def current_user(*args, &block)
+          #   controller.send(:'current_user', *args, &block)
+          # end
+          _helpers_for_modification.class_eval <<~ruby_eval.lines.map(&:strip).join(";"), file, line
+            def #{method}(*args, &block)
+              controller.send(:'#{method}', *args, &block)
+            end
+            ruby2_keywords(:'#{method}')
+          ruby_eval
+        end
+      end
+
+
+ +
+ +
+

+ + inherited(klass) + +

+ + +
+

When a class is inherited, wrap its helper module in a new module. This ensures that the parent class’s module can be changed independently of the child class’s.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 48
+def inherited(klass)
+  # Inherited from parent by default
+  klass._helpers = nil
+
+  klass.class_eval { default_helper_module! } unless klass.anonymous?
+  super
+end
+
+
+ +
+ +
+

+ + modules_for_helpers(modules_or_helper_prefixes) + +

+ + +
+

Given an array of values like the ones accepted by helper, this method returns an array with the corresponding modules, in the same order.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 173
+def modules_for_helpers(modules_or_helper_prefixes)
+  modules_or_helper_prefixes.flatten.map! do |module_or_helper_prefix|
+    case module_or_helper_prefix
+    when Module
+      module_or_helper_prefix
+    when String, Symbol
+      helper_prefix = module_or_helper_prefix.to_s
+      helper_prefix = helper_prefix.camelize unless helper_prefix.start_with?(/[A-Z]/)
+      "#{helper_prefix}Helper".constantize
+    else
+      raise ArgumentError, "helper must be a String, Symbol, or Module"
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Helpers/MissingHelperError.html b/src/7.0/classes/AbstractController/Helpers/MissingHelperError.html new file mode 100644 index 0000000000..dd8cab6735 --- /dev/null +++ b/src/7.0/classes/AbstractController/Helpers/MissingHelperError.html @@ -0,0 +1,115 @@ +--- +title: AbstractController::Helpers::MissingHelperError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(error, path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/helpers.rb, line 27
+def initialize(error, path)
+  @error = error
+  @path  = "helpers/#{path}.rb"
+  set_backtrace error.backtrace
+
+  if /^#{path}(\.rb)?$/.match?(error.path)
+    super("Missing helper file helpers/%s.rb" % path)
+  else
+    raise error
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Railties.html b/src/7.0/classes/AbstractController/Railties.html new file mode 100644 index 0000000000..f899f383c9 --- /dev/null +++ b/src/7.0/classes/AbstractController/Railties.html @@ -0,0 +1,67 @@ +--- +title: AbstractController::Railties +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Railties/RoutesHelpers.html b/src/7.0/classes/AbstractController/Railties/RoutesHelpers.html new file mode 100644 index 0000000000..900b3c719a --- /dev/null +++ b/src/7.0/classes/AbstractController/Railties/RoutesHelpers.html @@ -0,0 +1,126 @@ +--- +title: AbstractController::Railties::RoutesHelpers +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + with(routes, include_path_helpers = true) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/railties/routes_helpers.rb, line 8
+def self.with(routes, include_path_helpers = true)
+  Module.new do
+    define_method(:inherited) do |klass|
+      super(klass)
+
+      namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) }
+      actual_routes = namespace ? namespace.railtie_routes_url_helpers._routes : routes
+
+      if namespace
+        klass.include(namespace.railtie_routes_url_helpers(include_path_helpers))
+      else
+        klass.include(routes.url_helpers(include_path_helpers))
+      end
+
+      # In the case that we have ex.
+      #   class A::Foo < ApplicationController
+      #   class Bar < A::Foo
+      # We will need to redefine _routes because it will not be correct
+      # via inheritance.
+      unless klass._routes.equal?(actual_routes)
+        klass.redefine_singleton_method(:_routes) { actual_routes }
+        klass.include(Module.new do
+          define_method(:_routes) { @_routes || actual_routes }
+        end)
+      end
+    end
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Rendering.html b/src/7.0/classes/AbstractController/Rendering.html new file mode 100644 index 0000000000..858a92344b --- /dev/null +++ b/src/7.0/classes/AbstractController/Rendering.html @@ -0,0 +1,435 @@ +--- +title: AbstractController::Rendering +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_PROTECTED_INSTANCE_VARIABLES=%i(@_action_name @_response_body @_formats @_prefixes)
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + render(*args, &block) + +

+ + +
+

Normalizes arguments and options, and then delegates to render_to_body and sticks the result in self.response_body.

+ +

Supported options depend on the underlying render_to_body implementation.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 25
+def render(*args, &block)
+  options = _normalize_render(*args, &block)
+  rendered_body = render_to_body(options)
+  if options[:html]
+    _set_html_content_type
+  else
+    _set_rendered_content_type rendered_format
+  end
+  _set_vary_header
+  self.response_body = rendered_body
+end
+
+
+ +
+ +
+

+ + render_to_body(options = {}) + +

+ + +
+

Performs the actual template rendering.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 49
+def render_to_body(options = {})
+end
+
+
+ +
+ +
+

+ + render_to_string(*args, &block) + +

+ + +
+

Similar to render, but only returns the rendered template as a string, instead of setting self.response_body.

+ +

If a component extends the semantics of response_body (as ActionController extends it to be anything that responds to the method each), this method needs to be overridden in order to still return a string.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 43
+def render_to_string(*args, &block)
+  options = _normalize_render(*args, &block)
+  render_to_body(options)
+end
+
+
+ +
+ +
+

+ + rendered_format() + +

+ + +
+

Returns Content-Type of rendered content.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 53
+def rendered_format
+  Mime[:text]
+end
+
+
+ +
+ +
+

+ + view_assigns() + +

+ + +
+

This method should return a hash with assigns. You can overwrite this configuration per controller.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 61
+def view_assigns
+  variables = instance_variables - _protected_ivars
+
+  variables.each_with_object({}) do |name, hash|
+    hash[name.slice(1, name.length)] = instance_variable_get(name)
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + _normalize_args(action = nil, options = {}) + +

+ + +
+

Normalize args by converting render "foo" to render :action => "foo" and render "foo/bar" to render :file => "foo/bar".

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 73
+def _normalize_args(action = nil, options = {}) # :doc:
+  if action.respond_to?(:permitted?)
+    if action.permitted?
+      action
+    else
+      raise ArgumentError, "render parameters are not permitted"
+    end
+  elsif action.is_a?(Hash)
+    action
+  else
+    options
+  end
+end
+
+
+ +
+ +
+

+ + _normalize_options(options) + +

+ + +
+

Normalize options.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 88
+def _normalize_options(options) # :doc:
+  options
+end
+
+
+ +
+ +
+

+ + _process_options(options) + +

+ + +
+

Process extra options.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/rendering.rb, line 93
+def _process_options(options) # :doc:
+  options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/Translation.html b/src/7.0/classes/AbstractController/Translation.html new file mode 100644 index 0000000000..948ed60576 --- /dev/null +++ b/src/7.0/classes/AbstractController/Translation.html @@ -0,0 +1,216 @@ +--- +title: AbstractController::Translation +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + l(object, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: localize +
+ + + +
+ +
+

+ + localize(object, **options) + +

+ + +
+

Delegates to I18n.localize.

+
+ + + +
+ Also aliased as: l +
+ + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/translation.rb, line 33
+def localize(object, **options)
+  I18n.localize(object, **options)
+end
+
+
+ +
+ +
+

+ + t(key, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: translate +
+ + + +
+ +
+

+ + translate(key, **options) + +

+ + +
+

Delegates to I18n.translate.

+ +

When the given key starts with a period, it will be scoped by the current controller and action. So if you call translate(".foo") from PeopleController#index, it will convert the call to I18n.translate("people.index.foo"). This makes it less repetitive to translate many keys within the same controller / action and gives you a simple framework for scoping them consistently.

+
+ + + +
+ Also aliased as: t +
+ + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/translation.rb, line 17
+def translate(key, **options)
+  if key&.start_with?(".")
+    path = controller_path.tr("/", ".")
+    defaults = [:"#{path}#{key}"]
+    defaults << options[:default] if options[:default]
+    options[:default] = defaults.flatten
+    key = "#{path}.#{action_name}#{key}"
+  end
+
+  i18n_raise = options.fetch(:raise, self.raise_on_missing_translations)
+
+  ActiveSupport::HtmlSafeTranslation.translate(key, **options, raise: i18n_raise)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/UrlFor.html b/src/7.0/classes/AbstractController/UrlFor.html new file mode 100644 index 0000000000..70a19009a1 --- /dev/null +++ b/src/7.0/classes/AbstractController/UrlFor.html @@ -0,0 +1,137 @@ +--- +title: AbstractController::UrlFor +layout: default +--- +
+ +
+
+ +
+ +

Includes url_for into the host class (e.g. an abstract controller or mailer). The class has to provide a RouteSet by implementing the _routes methods. Otherwise, an exception will be raised.

+ +

Note that this module is completely decoupled from HTTP - the only requirement is a valid _routes implementation.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _routes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/url_for.rb, line 14
+def _routes
+  raise "In order to use #url_for, you must include routing helpers explicitly. " \
+        "For instance, `include Rails.application.routes.url_helpers`."
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/AbstractController/UrlFor/ClassMethods.html b/src/7.0/classes/AbstractController/UrlFor/ClassMethods.html new file mode 100644 index 0000000000..3d63386f83 --- /dev/null +++ b/src/7.0/classes/AbstractController/UrlFor/ClassMethods.html @@ -0,0 +1,144 @@ +--- +title: AbstractController::UrlFor::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _routes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/url_for.rb, line 20
+def _routes
+  nil
+end
+
+
+ +
+ +
+

+ + action_methods() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/abstract_controller/url_for.rb, line 24
+def action_methods
+  @action_methods ||= if _routes
+    super - _routes.named_routes.helper_names
+  else
+    super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable.html b/src/7.0/classes/ActionCable.html new file mode 100644 index 0000000000..23397e3e1d --- /dev/null +++ b/src/7.0/classes/ActionCable.html @@ -0,0 +1,262 @@ +--- +title: ActionCable +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Action Cable as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Action Cable as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel.html b/src/7.0/classes/ActionCable/Channel.html new file mode 100644 index 0000000000..0419c8373a --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel.html @@ -0,0 +1,108 @@ +--- +title: ActionCable::Channel +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Base.html b/src/7.0/classes/ActionCable/Channel/Base.html new file mode 100644 index 0000000000..d2bbe4312c --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Base.html @@ -0,0 +1,869 @@ +--- +title: ActionCable::Channel::Base +layout: default +--- +
+ +
+
+ +
+ +

The channel provides the basic structure of grouping behavior into logical units when communicating over the WebSocket connection. You can think of a channel like a form of controller, but one that’s capable of pushing content to the subscriber in addition to simply responding to the subscriber’s direct requests.

+ +

Channel instances are long-lived. A channel object will be instantiated when the cable consumer becomes a subscriber, and then lives until the consumer disconnects. This may be seconds, minutes, hours, or even days. That means you have to take special care not to do anything silly in a channel that would balloon its memory footprint or whatever. The references are forever, so they won’t be released as is normally the case with a controller instance that gets thrown away after every request.

+ +

Long-lived channels (and connections) also mean you’re responsible for ensuring that the data is fresh. If you hold a reference to a user record, but the name is changed while that reference is held, you may be sending stale data if you don’t take precautions to avoid it.

+ +

The upside of long-lived channel instances is that you can use instance variables to keep reference to objects that future subscriber requests can interact with. Here’s a quick example:

+ +
class ChatChannel < ApplicationCable::Channel
+  def subscribed
+    @room = Chat::Room[params[:room_number]]
+  end
+
+  def speak(data)
+    @room.speak data, user: current_user
+  end
+end
+
+ +

The speak action simply uses the Chat::Room object that was created when the channel was first subscribed to by the consumer when that subscriber wants to say something in the room.

+ +

Action processing

+ +

Unlike subclasses of ActionController::Base, channels do not follow a RESTful constraint form for their actions. Instead, Action Cable operates through a remote-procedure call model. You can declare any public method on the channel (optionally taking a data argument), and this method is automatically exposed as callable to the client.

+ +

Example:

+ +
class AppearanceChannel < ApplicationCable::Channel
+  def subscribed
+    @connection_token = generate_connection_token
+  end
+
+  def unsubscribed
+    current_user.disappear @connection_token
+  end
+
+  def appear(data)
+    current_user.appear @connection_token, on: data['appearing_on']
+  end
+
+  def away
+    current_user.away @connection_token
+  end
+
+  private
+    def generate_connection_token
+      SecureRandom.hex(36)
+    end
+end
+
+ +

In this example, the subscribed and unsubscribed methods are not callable methods, as they were already declared in ActionCable::Channel::Base, but #appear and #away are. #generate_connection_token is also not callable, since it’s a private method. You’ll see that appear accepts a data parameter, which it then uses as part of its model call. #away does not, since it’s simply a trigger action.

+ +

Also note that in this example, current_user is available because it was marked as an identifying attribute on the connection. All such identifiers will automatically create a delegation method of the same name on the channel instance.

+ +

Rejecting subscription requests

+ +

A channel can reject a subscription request in the subscribed callback by invoking the reject method:

+ +
class ChatChannel < ApplicationCable::Channel
+  def subscribed
+    @room = Chat::Room[params[:room_number]]
+    reject unless current_user.can_access?(@room)
+  end
+end
+
+ +

In this example, the subscription will be rejected if the current_user does not have access to the chat room. On the client-side, the Channel#rejected callback will get invoked when the server rejects the subscription request.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + connection
+ [R] + identifier
+ [R] + params
+ + + + +

Class Public methods

+ +
+

+ + action_methods() + +

+ + +
+

A list of method names that should be considered actions. This includes all public instance methods on a channel, less any internal methods (defined on Base), adding back in any methods that are internal, but still exist on the class itself.

+ +

Returns

+
  • +

    Set - A set of all methods that should be considered actions.

    +
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 117
+def action_methods
+  @action_methods ||= begin
+    # All public instance methods of this class, including ancestors
+    methods = (public_instance_methods(true) -
+      # Except for public instance methods of Base and its ancestors
+      ActionCable::Channel::Base.public_instance_methods(true) +
+      # Be sure to include shadowed public instance methods of this class
+      public_instance_methods(false)).uniq.map(&:to_s)
+    methods.to_set
+  end
+end
+
+
+ +
+ +
+

+ + new(connection, identifier, params = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 144
+def initialize(connection, identifier, params = {})
+  @connection = connection
+  @identifier = identifier
+  @params     = params
+
+  # When a channel is streaming via pubsub, we want to delay the confirmation
+  # transmission until pubsub subscription is confirmed.
+  #
+  # The counter starts at 1 because it's awaiting a call to #subscribe_to_channel
+  @defer_subscription_confirmation_counter = Concurrent::AtomicFixnum.new(1)
+
+  @reject_subscription = nil
+  @subscription_confirmation_sent = nil
+
+  delegate_connection_identifiers
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + clear_action_methods!() + +

+ + +
+

action_methods are cached and there is sometimes need to refresh them. ::clear_action_methods! allows you to do that, so next time you run action_methods, they will be recalculated.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 133
+def clear_action_methods! # :doc:
+  @action_methods = nil
+end
+
+
+ +
+ +
+

+ + method_added(name) + +

+ + +
+

Refresh the cached action_methods when a new action_method is added.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 138
+def method_added(name) # :doc:
+  super
+  clear_action_methods!
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + perform_action(data) + +

+ + +
+

Extract the action name from the passed data and process it via the channel. The process will ensure that the action requested is a public method on the channel declared by the user (so not one of the callbacks like subscribed).

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 164
+def perform_action(data)
+  action = extract_action(data)
+
+  if processable_action?(action)
+    payload = { channel_class: self.class.name, action: action, data: data }
+    ActiveSupport::Notifications.instrument("perform_action.action_cable", payload) do
+      dispatch_action(action, data)
+    end
+  else
+    logger.error "Unable to process #{action_signature(action, data)}"
+  end
+end
+
+
+ +
+ +
+

+ + subscribe_to_channel() + +

+ + +
+

This method is called after subscription has been added to the connection and confirms or rejects the subscription.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 179
+def subscribe_to_channel
+  run_callbacks :subscribe do
+    subscribed
+  end
+
+  reject_subscription if subscription_rejected?
+  ensure_confirmation_sent
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + defer_subscription_confirmation!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 228
+def defer_subscription_confirmation! # :doc:
+  @defer_subscription_confirmation_counter.increment
+end
+
+
+ +
+ +
+

+ + defer_subscription_confirmation?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 232
+def defer_subscription_confirmation? # :doc:
+  @defer_subscription_confirmation_counter.value > 0
+end
+
+
+ +
+ +
+

+ + ensure_confirmation_sent() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 222
+def ensure_confirmation_sent # :doc:
+  return if subscription_rejected?
+  @defer_subscription_confirmation_counter.decrement
+  transmit_subscription_confirmation unless defer_subscription_confirmation?
+end
+
+
+ +
+ +
+

+ + reject() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 240
+def reject # :doc:
+  @reject_subscription = true
+end
+
+
+ +
+ +
+

+ + subscribed() + +

+ + +
+

Called once a consumer has become a subscriber of the channel. Usually the place to set up any streams you want this channel to be sending to the subscriber.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 199
+def subscribed # :doc:
+  # Override in subclasses
+end
+
+
+ +
+ +
+

+ + subscription_confirmation_sent?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 236
+def subscription_confirmation_sent? # :doc:
+  @subscription_confirmation_sent
+end
+
+
+ +
+ +
+

+ + subscription_rejected?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 244
+def subscription_rejected? # :doc:
+  @reject_subscription
+end
+
+
+ +
+ +
+

+ + transmit(data, via: nil) + +

+ + +
+

Transmit a hash of data to the subscriber. The hash will automatically be wrapped in a JSON envelope with the proper channel identifier marked as the recipient.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 211
+def transmit(data, via: nil) # :doc:
+  status = "#{self.class.name} transmitting #{data.inspect.truncate(300)}"
+  status += " (via #{via})" if via
+  logger.debug(status)
+
+  payload = { channel_class: self.class.name, data: data, via: via }
+  ActiveSupport::Notifications.instrument("transmit.action_cable", payload) do
+    connection.transmit identifier: @identifier, message: data
+  end
+end
+
+
+ +
+ +
+

+ + unsubscribed() + +

+ + +
+

Called once a consumer has cut its cable connection. Can be used for cleaning up connections or marking users as offline or the like.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/base.rb, line 205
+def unsubscribed # :doc:
+  # Override in subclasses
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Broadcasting.html b/src/7.0/classes/ActionCable/Channel/Broadcasting.html new file mode 100644 index 0000000000..ce5e867c32 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Broadcasting.html @@ -0,0 +1,67 @@ +--- +title: ActionCable::Channel::Broadcasting +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Broadcasting/ClassMethods.html b/src/7.0/classes/ActionCable/Channel/Broadcasting/ClassMethods.html new file mode 100644 index 0000000000..d82e3c3268 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Broadcasting/ClassMethods.html @@ -0,0 +1,145 @@ +--- +title: ActionCable::Channel::Broadcasting::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + broadcast_to(model, message) + +

+ + +
+

Broadcast a hash to a unique broadcasting for this model in this channel.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/broadcasting.rb, line 14
+def broadcast_to(model, message)
+  ActionCable.server.broadcast(broadcasting_for(model), message)
+end
+
+
+ +
+ +
+

+ + broadcasting_for(model) + +

+ + +
+

Returns a unique broadcasting identifier for this model in this channel:

+ +
CommentsChannel.broadcasting_for("all") # => "comments:all"
+
+ +

You can pass any object as a target (e.g. Active Record model), and it would be serialized into a string under the hood.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/broadcasting.rb, line 24
+def broadcasting_for(model)
+  serialize_broadcasting([ channel_name, model ])
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Callbacks.html b/src/7.0/classes/ActionCable/Channel/Callbacks.html new file mode 100644 index 0000000000..15d3c0940f --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Callbacks.html @@ -0,0 +1,81 @@ +--- +title: ActionCable::Channel::Callbacks +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Callbacks/ClassMethods.html b/src/7.0/classes/ActionCable/Channel/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..852c3d143b --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Callbacks/ClassMethods.html @@ -0,0 +1,282 @@ +--- +title: ActionCable::Channel::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_subscribe(*methods, &block) + +

+ + +
+ +
+ + + +
+ Also aliased as: on_subscribe +
+ + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/callbacks.rb, line 21
+def after_subscribe(*methods, &block)
+  set_callback(:subscribe, :after, *methods, &block)
+end
+
+
+ +
+ +
+

+ + after_unsubscribe(*methods, &block) + +

+ + +
+ +
+ + + +
+ Also aliased as: on_unsubscribe +
+ + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/callbacks.rb, line 30
+def after_unsubscribe(*methods, &block)
+  set_callback(:unsubscribe, :after, *methods, &block)
+end
+
+
+ +
+ +
+

+ + before_subscribe(*methods, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/callbacks.rb, line 17
+def before_subscribe(*methods, &block)
+  set_callback(:subscribe, :before, *methods, &block)
+end
+
+
+ +
+ +
+

+ + before_unsubscribe(*methods, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/callbacks.rb, line 26
+def before_unsubscribe(*methods, &block)
+  set_callback(:unsubscribe, :before, *methods, &block)
+end
+
+
+ +
+ +
+

+ + on_subscribe(*methods, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: after_subscribe +
+ + + +
+ +
+

+ + on_unsubscribe(*methods, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: after_unsubscribe +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/ChannelStub.html b/src/7.0/classes/ActionCable/Channel/ChannelStub.html new file mode 100644 index 0000000000..732d65cc54 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/ChannelStub.html @@ -0,0 +1,332 @@ +--- +title: ActionCable::Channel::ChannelStub +layout: default +--- +
+ +
+
+ +
+ +

Stub stream_from to track streams for the channel. Add public aliases for subscription_confirmation_sent? and subscription_rejected?.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + confirmed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 22
+def confirmed?
+  subscription_confirmation_sent?
+end
+
+
+ +
+ +
+

+ + rejected?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 26
+def rejected?
+  subscription_rejected?
+end
+
+
+ +
+ +
+

+ + start_periodic_timers() + +

+ + +
+

Make periodic timers no-op

+
+ + + +
+ Also aliased as: stop_periodic_timers +
+ + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 43
+def start_periodic_timers; end
+
+
+ +
+ +
+

+ + stop_all_streams() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 34
+def stop_all_streams
+  @_streams = []
+end
+
+
+ +
+ +
+

+ + stop_periodic_timers() + +

+ + +
+ +
+ + + + + +
+ Alias for: start_periodic_timers +
+ + + +
+ +
+

+ + stream_from(broadcasting, *) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 30
+def stream_from(broadcasting, *)
+  streams << broadcasting
+end
+
+
+ +
+ +
+

+ + streams() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 38
+def streams
+  @_streams ||= []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/ConnectionStub.html b/src/7.0/classes/ActionCable/Channel/ConnectionStub.html new file mode 100644 index 0000000000..a3c7d868d1 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/ConnectionStub.html @@ -0,0 +1,234 @@ +--- +title: ActionCable::Channel::ConnectionStub +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + identifiers
+ [R] + logger
+ [R] + subscriptions
+ [R] + transmissions
+ + + + +

Class Public methods

+ +
+

+ + new(identifiers = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 50
+def initialize(identifiers = {})
+  @transmissions = []
+
+  identifiers.each do |identifier, val|
+    define_singleton_method(identifier) { val }
+  end
+
+  @subscriptions = ActionCable::Connection::Subscriptions.new(self)
+  @identifiers = identifiers.keys
+  @logger = ActiveSupport::TaggedLogging.new ActiveSupport::Logger.new(StringIO.new)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + connection_identifier() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 66
+def connection_identifier
+  @connection_identifier ||= connection_gid(identifiers.filter_map { |id| send(id.to_sym) if id })
+end
+
+
+ +
+ +
+

+ + transmit(cable_message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 62
+def transmit(cable_message)
+  transmissions << cable_message.with_indifferent_access
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Naming.html b/src/7.0/classes/ActionCable/Channel/Naming.html new file mode 100644 index 0000000000..eb241dd959 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Naming.html @@ -0,0 +1,67 @@ +--- +title: ActionCable::Channel::Naming +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Naming/ClassMethods.html b/src/7.0/classes/ActionCable/Channel/Naming/ClassMethods.html new file mode 100644 index 0000000000..a3c413bfbd --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Naming/ClassMethods.html @@ -0,0 +1,106 @@ +--- +title: ActionCable::Channel::Naming::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + channel_name() + +

+ + +
+

Returns the name of the channel, underscored, without the Channel ending. If the channel is in a namespace, then the namespaces are represented by single colon separators in the channel name.

+ +
ChatChannel.channel_name # => 'chat'
+Chats::AppearancesChannel.channel_name # => 'chats:appearances'
+FooChats::BarAppearancesChannel.channel_name # => 'foo_chats:bar_appearances'
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/naming.rb, line 16
+def channel_name
+  @channel_name ||= name.delete_suffix("Channel").gsub("::", ":").underscore
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/NonInferrableChannelError.html b/src/7.0/classes/ActionCable/Channel/NonInferrableChannelError.html new file mode 100644 index 0000000000..25fd1a36a3 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/NonInferrableChannelError.html @@ -0,0 +1,109 @@ +--- +title: ActionCable::Channel::NonInferrableChannelError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 11
+def initialize(name)
+  super "Unable to determine the channel to test from #{name}. " +
+    "You'll need to specify it using `tests YourChannel` in your " +
+    "test case definition."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/PeriodicTimers.html b/src/7.0/classes/ActionCable/Channel/PeriodicTimers.html new file mode 100644 index 0000000000..594e79922a --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/PeriodicTimers.html @@ -0,0 +1,67 @@ +--- +title: ActionCable::Channel::PeriodicTimers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/PeriodicTimers/ClassMethods.html b/src/7.0/classes/ActionCable/Channel/PeriodicTimers/ClassMethods.html new file mode 100644 index 0000000000..34261485e4 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/PeriodicTimers/ClassMethods.html @@ -0,0 +1,129 @@ +--- +title: ActionCable::Channel::PeriodicTimers::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + periodically(callback_or_method_name = nil, every:, &block) + +

+ + +
+

Periodically performs a task on the channel, like updating an online user counter, polling a backend for new status messages, sending regular “heartbeat” messages, or doing some internal work and giving progress updates.

+ +

Pass a method name or lambda argument or provide a block to call. Specify the calling period in seconds using the every: keyword argument.

+ +
periodically :transmit_progress, every: 5.seconds
+
+periodically every: 3.minutes do
+  transmit action: :update_count, count: current_count
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/periodic_timers.rb, line 31
+def periodically(callback_or_method_name = nil, every:, &block)
+  callback =
+    if block_given?
+      raise ArgumentError, "Pass a block or provide a callback arg, not both" if callback_or_method_name
+      block
+    else
+      case callback_or_method_name
+      when Proc
+        callback_or_method_name
+      when Symbol
+        -> { __send__ callback_or_method_name }
+      else
+        raise ArgumentError, "Expected a Symbol method name or a Proc, got #{callback_or_method_name.inspect}"
+      end
+    end
+
+  unless every.kind_of?(Numeric) && every > 0
+    raise ArgumentError, "Expected every: to be a positive number of seconds, got #{every.inspect}"
+  end
+
+  self.periodic_timers += [[ callback, every: every ]]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/Streams.html b/src/7.0/classes/ActionCable/Channel/Streams.html new file mode 100644 index 0000000000..dc402086d0 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/Streams.html @@ -0,0 +1,387 @@ +--- +title: ActionCable::Channel::Streams +layout: default +--- +
+ +
+
+ +
+ +

Streams allow channels to route broadcastings to the subscriber. A broadcasting is, as discussed elsewhere, a pubsub queue where any data placed into it is automatically sent to the clients that are connected at that time. It’s purely an online queue, though. If you’re not streaming a broadcasting at the very moment it sends out an update, you will not get that update, even if you connect after it has been sent.

+ +

Most commonly, the streamed broadcast is sent straight to the subscriber on the client-side. The channel just acts as a connector between the two parties (the broadcaster and the channel subscriber). Here’s an example of a channel that allows subscribers to get all new comments on a given page:

+ +
class CommentsChannel < ApplicationCable::Channel
+  def follow(data)
+    stream_from "comments_for_#{data['recording_id']}"
+  end
+
+  def unfollow
+    stop_all_streams
+  end
+end
+
+ +

Based on the above example, the subscribers of this channel will get whatever data is put into the, let’s say, comments_for_45 broadcasting as soon as it’s put there.

+ +

An example broadcasting for this channel looks like so:

+ +
ActionCable.server.broadcast "comments_for_45", { author: 'DHH', content: 'Rails is just swell' }
+
+ +

If you have a stream that is related to a model, then the broadcasting used can be generated from the model and channel. The following example would subscribe to a broadcasting like comments:Z2lkOi8vVGVzdEFwcC9Qb3N0LzE.

+ +
class CommentsChannel < ApplicationCable::Channel
+  def subscribed
+    post = Post.find(params[:id])
+    stream_for post
+  end
+end
+
+ +

You can then broadcast to this channel using:

+ +
CommentsChannel.broadcast_to(@post, @comment)
+
+ +

If you don’t just want to parlay the broadcast unfiltered to the subscriber, you can also supply a callback that lets you alter what is sent out. The below example shows how you can use this to provide performance introspection in the process:

+ +
class ChatChannel < ApplicationCable::Channel
+  def subscribed
+    @room = Chat::Room[params[:room_number]]
+
+    stream_for @room, coder: ActiveSupport::JSON do |message|
+      if message['originated_at'].present?
+        elapsed_time = (Time.now.to_f - message['originated_at']).round(2)
+
+        ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing
+        logger.info "Message took #{elapsed_time}s to arrive"
+      end
+
+      transmit message
+    end
+  end
+end
+
+ +

You can stop streaming from all broadcasts by calling stop_all_streams.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + stop_all_streams() + +

+ + +
+

Unsubscribes all streams associated with this channel from the pubsub queue.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 120
+def stop_all_streams
+  streams.each do |broadcasting, callback|
+    pubsub.unsubscribe broadcasting, callback
+    logger.info "#{self.class.name} stopped streaming from #{broadcasting}"
+  end.clear
+end
+
+
+ +
+ +
+

+ + stop_stream_for(model) + +

+ + +
+

Unsubscribes streams for the model.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 115
+def stop_stream_for(model)
+  stop_stream_from(broadcasting_for(model))
+end
+
+
+ +
+ +
+

+ + stop_stream_from(broadcasting) + +

+ + +
+

Unsubscribes streams from the named broadcasting.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 106
+def stop_stream_from(broadcasting)
+  callback = streams.delete(broadcasting)
+  if callback
+    pubsub.unsubscribe(broadcasting, callback)
+    logger.info "#{self.class.name} stopped streaming from #{broadcasting}"
+  end
+end
+
+
+ +
+ +
+

+ + stream_for(model, callback = nil, coder: nil, &block) + +

+ + +
+

Start streaming the pubsub queue for the model in this channel. Optionally, you can pass a callback that’ll be used instead of the default of just transmitting the updates straight to the subscriber.

+ +

Pass coder: ActiveSupport::JSON to decode messages as JSON before passing to the callback. Defaults to coder: nil which does no decoding, passes raw messages.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 101
+def stream_for(model, callback = nil, coder: nil, &block)
+  stream_from(broadcasting_for(model), callback || block, coder: coder)
+end
+
+
+ +
+ +
+

+ + stream_from(broadcasting, callback = nil, coder: nil, &block) + +

+ + +
+

Start streaming from the named broadcasting pubsub queue. Optionally, you can pass a callback that’ll be used instead of the default of just transmitting the updates straight to the subscriber. Pass coder: ActiveSupport::JSON to decode messages as JSON before passing to the callback. Defaults to coder: nil which does no decoding, passes raw messages.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 76
+def stream_from(broadcasting, callback = nil, coder: nil, &block)
+  broadcasting = String(broadcasting)
+
+  # Don't send the confirmation until pubsub#subscribe is successful
+  defer_subscription_confirmation!
+
+  # Build a stream handler by wrapping the user-provided callback with
+  # a decoder or defaulting to a JSON-decoding retransmitter.
+  handler = worker_pool_stream_handler(broadcasting, callback || block, coder: coder)
+  streams[broadcasting] = handler
+
+  connection.server.event_loop.post do
+    pubsub.subscribe(broadcasting, handler, lambda do
+      ensure_confirmation_sent
+      logger.info "#{self.class.name} is streaming from #{broadcasting}"
+    end)
+  end
+end
+
+
+ +
+ +
+

+ + stream_or_reject_for(model) + +

+ + +
+

Calls stream_for with the given model if it’s present to start streaming, otherwise rejects the subscription.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/streams.rb, line 129
+def stream_or_reject_for(model)
+  if model
+    stream_for model
+  else
+    reject
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/TestCase.html b/src/7.0/classes/ActionCable/Channel/TestCase.html new file mode 100644 index 0000000000..15e433bfba --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/TestCase.html @@ -0,0 +1,195 @@ +--- +title: ActionCable::Channel::TestCase +layout: default +--- +
+ +
+
+ +
+ +

Superclass for Action Cable channel functional tests.

+ +

Basic example

+ +

Functional tests are written as follows:

+
  1. +

    First, one uses the subscribe method to simulate subscription creation.

    +
  2. +

    Then, one asserts whether the current state is as expected. “State” can be anything: transmitted messages, subscribed streams, etc.

    +
+ +

For example:

+ +
class ChatChannelTest < ActionCable::Channel::TestCase
+  def test_subscribed_with_room_number
+    # Simulate a subscription creation
+    subscribe room_number: 1
+
+    # Asserts that the subscription was successfully created
+    assert subscription.confirmed?
+
+    # Asserts that the channel subscribes connection to a stream
+    assert_has_stream "chat_1"
+
+    # Asserts that the channel subscribes connection to a specific
+    # stream created for a model
+    assert_has_stream_for Room.find(1)
+  end
+
+  def test_does_not_stream_with_incorrect_room_number
+    subscribe room_number: -1
+
+    # Asserts that not streams was started
+    assert_no_streams
+  end
+
+  def test_does_not_subscribe_without_room_number
+    subscribe
+
+    # Asserts that the subscription was rejected
+    assert subscription.rejected?
+  end
+end
+
+ +

You can also perform actions:

+ +
def test_perform_speak
+  subscribe room_number: 1
+
+  perform :speak, message: "Hello, Rails!"
+
+  assert_equal "Hello, Rails!", transmissions.last["text"]
+end
+
+ +

Special methods

+ +

ActionCable::Channel::TestCase will also automatically provide the following instance methods for use in the tests:

+
connection +
+

An ActionCable::Channel::ConnectionStub, representing the current HTTP connection.

+
subscription +
+

An instance of the current channel, created when you call subscribe.

+
transmissions +
+

A list of all messages that have been transmitted into the channel.

+
+ +

Channel is automatically inferred

+ +

ActionCable::Channel::TestCase will automatically infer the channel under test from the test class name. If the channel cannot be inferred from the test class name, you can explicitly set it with tests.

+ +
class SpecialEdgeCaseChannelTest < ActionCable::Channel::TestCase
+  tests SpecialChannel
+end
+
+ +

Specifying connection identifiers

+ +

You need to set up your connection manually to provide values for the identifiers. To do this just use:

+ +
stub_connection(user: users(:john))
+
+ +

Testing broadcasting

+ +

ActionCable::Channel::TestCase enhances ActionCable::TestHelper assertions (e.g. assert_broadcasts) to handle broadcasting to models:

+ +
# in your channel
+def speak(data)
+  broadcast_to room, text: data["message"]
+end
+
+def test_speak
+  subscribe room_id: rooms(:chat).id
+
+  assert_broadcast_on(rooms(:chat), text: "Hello, Rails!") do
+    perform :speak, message: "Hello, Rails!"
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/TestCase/Behavior.html b/src/7.0/classes/ActionCable/Channel/TestCase/Behavior.html new file mode 100644 index 0000000000..ceec1ac0e2 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/TestCase/Behavior.html @@ -0,0 +1,561 @@ +--- +title: ActionCable::Channel::TestCase::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
CHANNEL_IDENTIFIER="test_stub"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + connection
+ [R] + subscription
+ + + + + +

Instance Public methods

+ +
+

+ + assert_broadcast_on(stream_or_object, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 273
+def assert_broadcast_on(stream_or_object, *args)
+  super(broadcasting_for(stream_or_object), *args)
+end
+
+
+ +
+ +
+

+ + assert_broadcasts(stream_or_object, *args) + +

+ + +
+

Enhance TestHelper assertions to handle non-String broadcastings

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 269
+def assert_broadcasts(stream_or_object, *args)
+  super(broadcasting_for(stream_or_object), *args)
+end
+
+
+ +
+ +
+

+ + assert_has_stream(stream) + +

+ + +
+

Asserts that the specified stream has been started.

+ +
def test_assert_started_stream
+  subscribe
+  assert_has_stream 'messages'
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 295
+def assert_has_stream(stream)
+  assert subscription.streams.include?(stream), "Stream #{stream} has not been started"
+end
+
+
+ +
+ +
+

+ + assert_has_stream_for(object) + +

+ + +
+

Asserts that the specified stream for a model has started.

+ +
def test_assert_started_stream_for
+  subscribe id: 42
+  assert_has_stream_for User.find(42)
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 306
+def assert_has_stream_for(object)
+  assert_has_stream(broadcasting_for(object))
+end
+
+
+ +
+ +
+

+ + assert_no_streams() + +

+ + +
+

Asserts that no streams have been started.

+ +
def test_assert_no_started_stream
+  subscribe
+  assert_no_streams
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 284
+def assert_no_streams
+  assert subscription.streams.empty?, "No streams started was expected, but #{subscription.streams.count} found"
+end
+
+
+ +
+ +
+

+ + perform(action, data = {}) + +

+ + +
+

Perform action on a channel.

+ +

NOTE: Must be subscribed.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 256
+def perform(action, data = {})
+  check_subscribed!
+  subscription.perform_action(data.stringify_keys.merge("action" => action.to_s))
+end
+
+
+ +
+ +
+

+ + stub_connection(identifiers = {}) + +

+ + +
+

Set up test connection with the specified identifiers:

+ +
class ApplicationCable < ActionCable::Connection::Base
+  identified_by :user, :token
+end
+
+stub_connection(user: users[:john], token: 'my-secret-token')
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 234
+def stub_connection(identifiers = {})
+  @connection = ConnectionStub.new(identifiers)
+end
+
+
+ +
+ +
+

+ + subscribe(params = {}) + +

+ + +
+

Subscribe to the channel under test. Optionally pass subscription parameters as a Hash.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 239
+def subscribe(params = {})
+  @connection ||= stub_connection
+  @subscription = self.class.channel_class.new(connection, CHANNEL_IDENTIFIER, params.with_indifferent_access)
+  @subscription.singleton_class.include(ChannelStub)
+  @subscription.subscribe_to_channel
+  @subscription
+end
+
+
+ +
+ +
+

+ + transmissions() + +

+ + +
+

Returns messages transmitted into channel

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 262
+def transmissions
+  # Return only directly sent message (via #transmit)
+  connection.transmissions.filter_map { |data| data["message"] }
+end
+
+
+ +
+ +
+

+ + unsubscribe() + +

+ + +
+

Unsubscribe the subscription under test.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 248
+def unsubscribe
+  check_subscribed!
+  subscription.unsubscribe_from_channel
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Channel/TestCase/Behavior/ClassMethods.html b/src/7.0/classes/ActionCable/Channel/TestCase/Behavior/ClassMethods.html new file mode 100644 index 0000000000..e9a4261c11 --- /dev/null +++ b/src/7.0/classes/ActionCable/Channel/TestCase/Behavior/ClassMethods.html @@ -0,0 +1,194 @@ +--- +title: ActionCable::Channel::TestCase::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + channel_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 210
+def channel_class
+  if channel = self._channel_class
+    channel
+  else
+    tests determine_default_channel(name)
+  end
+end
+
+
+ +
+ +
+

+ + determine_default_channel(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 218
+def determine_default_channel(name)
+  channel = determine_constant_from_test_name(name) do |constant|
+    Class === constant && constant < ActionCable::Channel::Base
+  end
+  raise NonInferrableChannelError.new(name) if channel.nil?
+  channel
+end
+
+
+ +
+ +
+

+ + tests(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/channel/test_case.rb, line 199
+def tests(channel)
+  case channel
+  when String, Symbol
+    self._channel_class = channel.to_s.camelize.constantize
+  when Module
+    self._channel_class = channel
+  else
+    raise NonInferrableChannelError.new(channel)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection.html b/src/7.0/classes/ActionCable/Connection.html new file mode 100644 index 0000000000..d773efe601 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection.html @@ -0,0 +1,122 @@ +--- +title: ActionCable::Connection +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Assertions.html b/src/7.0/classes/ActionCable/Connection/Assertions.html new file mode 100644 index 0000000000..ad7a97277f --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Assertions.html @@ -0,0 +1,105 @@ +--- +title: ActionCable::Connection::Assertions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_reject_connection(&block) + +

+ + +
+

Asserts that the connection is rejected (via reject_unauthorized_connection).

+ +
# Asserts that connection without user_id fails
+assert_reject_connection { connect params: { user_id: '' } }
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 25
+def assert_reject_connection(&block)
+  assert_raises(Authorization::UnauthorizedError, "Expected to reject connection but no rejection was made", &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Authorization.html b/src/7.0/classes/ActionCable/Connection/Authorization.html new file mode 100644 index 0000000000..9fe149024b --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Authorization.html @@ -0,0 +1,117 @@ +--- +title: ActionCable::Connection::Authorization +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + reject_unauthorized_connection() + +

+ + +
+

Closes the WebSocket connection if it is open and returns a 404 “File not Found” response.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/authorization.rb, line 9
+def reject_unauthorized_connection
+  logger.error "An unauthorized connection attempt was rejected"
+  raise UnauthorizedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Authorization/UnauthorizedError.html b/src/7.0/classes/ActionCable/Connection/Authorization/UnauthorizedError.html new file mode 100644 index 0000000000..de4698c7b2 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Authorization/UnauthorizedError.html @@ -0,0 +1,60 @@ +--- +title: ActionCable::Connection::Authorization::UnauthorizedError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Base.html b/src/7.0/classes/ActionCable/Connection/Base.html new file mode 100644 index 0000000000..8d09f815e5 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Base.html @@ -0,0 +1,500 @@ +--- +title: ActionCable::Connection::Base +layout: default +--- +
+ +
+
+ +
+ +

For every WebSocket connection the Action Cable server accepts, a Connection object will be instantiated. This instance becomes the parent of all of the channel subscriptions that are created from there on. Incoming messages are then routed to these channel subscriptions based on an identifier sent by the Action Cable consumer. The Connection itself does not deal with any specific application logic beyond authentication and authorization.

+ +

Here’s a basic example:

+ +
module ApplicationCable
+  class Connection < ActionCable::Connection::Base
+    identified_by :current_user
+
+    def connect
+      self.current_user = find_verified_user
+      logger.add_tags current_user.name
+    end
+
+    def disconnect
+      # Any cleanup work needed when the cable connection is cut.
+    end
+
+    private
+      def find_verified_user
+        User.find_by_identity(cookies.encrypted[:identity_id]) ||
+          reject_unauthorized_connection
+      end
+  end
+end
+
+ +

First, we declare that this connection can be identified by its current_user. This allows us to later be able to find all connections established for that current_user (and potentially disconnect them). You can declare as many identification indexes as you like. Declaring an identification means that an attr_accessor is automatically set for that key.

+ +

Second, we rely on the fact that the WebSocket connection is established with the cookies from the domain being sent along. This makes it easy to use signed cookies that were set when logging in via a web interface to authorize the WebSocket connection.

+ +

Finally, we add a tag to the connection-specific logger with the name of the current user to easily distinguish their messages in the log.

+ +

Pretty simple, eh?

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + env
+ [R] + logger
+ [R] + protocol
+ [R] + server
+ [R] + subscriptions
+ [R] + worker_pool
+ + + + +

Class Public methods

+ +
+

+ + new(server, env, coder: ActiveSupport::JSON) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 55
+def initialize(server, env, coder: ActiveSupport::JSON)
+  @server, @env, @coder = server, env, coder
+
+  @worker_pool = server.worker_pool
+  @logger = new_tagged_logger
+
+  @websocket      = ActionCable::Connection::WebSocket.new(env, self, event_loop)
+  @subscriptions  = ActionCable::Connection::Subscriptions.new(self)
+  @message_buffer = ActionCable::Connection::MessageBuffer.new(self)
+
+  @_internal_subscriptions = nil
+  @started_at = Time.now
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + beat() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 125
+def beat
+  transmit type: ActionCable::INTERNAL[:message_types][:ping], message: Time.now.to_i
+end
+
+
+ +
+ +
+

+ + close(reason: nil, reconnect: true) + +

+ + +
+

Close the WebSocket connection.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 100
+def close(reason: nil, reconnect: true)
+  transmit(
+    type: ActionCable::INTERNAL[:message_types][:disconnect],
+    reason: reason,
+    reconnect: reconnect
+  )
+  websocket.close
+end
+
+
+ +
+ +
+

+ + send_async(method, *arguments) + +

+ + +
+

Invoke a method on the connection asynchronously through the pool of thread workers.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 110
+def send_async(method, *arguments)
+  worker_pool.async_invoke(self, method, *arguments)
+end
+
+
+ +
+ +
+

+ + statistics() + +

+ + +
+

Return a basic hash of statistics for the connection keyed with identifier, started_at, subscriptions, and request_id. This can be returned by a health check against the connection.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 116
+def statistics
+  {
+    identifier: connection_identifier,
+    started_at: @started_at,
+    subscriptions: subscriptions.identifiers,
+    request_id: @env["action_dispatch.request_id"]
+  }
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + cookies() + +

+ + +
+

The cookies of the request that initiated the WebSocket connection. Useful for performing authorization checks.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 159
+def cookies # :doc:
+  request.cookie_jar
+end
+
+
+ +
+ +
+

+ + request() + +

+ + +
+

The request that initiated the WebSocket connection is available here. This gives access to the environment, cookies, etc.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/base.rb, line 151
+def request # :doc:
+  @request ||= begin
+    environment = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
+    ActionDispatch::Request.new(environment || env)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Identification.html b/src/7.0/classes/ActionCable/Connection/Identification.html new file mode 100644 index 0000000000..05450b039a --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Identification.html @@ -0,0 +1,118 @@ +--- +title: ActionCable::Connection::Identification +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + connection_identifier() + +

+ + +
+

Return a single connection identifier that combines the value of all the registered identifiers into a single gid.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/identification.rb, line 27
+def connection_identifier
+  unless defined? @connection_identifier
+    @connection_identifier = connection_gid identifiers.filter_map { |id| instance_variable_get("@#{id}") }
+  end
+
+  @connection_identifier
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/Identification/ClassMethods.html b/src/7.0/classes/ActionCable/Connection/Identification/ClassMethods.html new file mode 100644 index 0000000000..0fe02be0ca --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/Identification/ClassMethods.html @@ -0,0 +1,104 @@ +--- +title: ActionCable::Connection::Identification::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + identified_by(*identifiers) + +

+ + +
+

Mark a key as being a connection identifier index that can then be used to find the specific connection again later. Common identifiers are current_user and current_account, but could be anything, really.

+ +

Note that anything marked as an identifier will automatically create a delegate by the same name on any channel instances created off the connection.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/identification.rb, line 20
+def identified_by(*identifiers)
+  Array(identifiers).each { |identifier| attr_accessor identifier }
+  self.identifiers += identifiers
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/InternalChannel.html b/src/7.0/classes/ActionCable/Connection/InternalChannel.html new file mode 100644 index 0000000000..b0b4bbc0de --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/InternalChannel.html @@ -0,0 +1,60 @@ +--- +title: ActionCable::Connection::InternalChannel +layout: default +--- +
+ +
+
+ +
+ +

Makes it possible for the RemoteConnection to disconnect a specific connection.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/NonInferrableConnectionError.html b/src/7.0/classes/ActionCable/Connection/NonInferrableConnectionError.html new file mode 100644 index 0000000000..d863298366 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/NonInferrableConnectionError.html @@ -0,0 +1,109 @@ +--- +title: ActionCable::Connection::NonInferrableConnectionError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 13
+def initialize(name)
+  super "Unable to determine the connection to test from #{name}. " +
+    "You'll need to specify it using `tests YourConnection` in your " +
+    "test case definition."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/StreamEventLoop.html b/src/7.0/classes/ActionCable/Connection/StreamEventLoop.html new file mode 100644 index 0000000000..d9d74828e4 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/StreamEventLoop.html @@ -0,0 +1,367 @@ +--- +title: ActionCable::Connection::StreamEventLoop +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 9
+def initialize
+  @nio = @executor = @thread = nil
+  @map = {}
+  @stopping = false
+  @todo = Queue.new
+
+  @spawn_mutex = Mutex.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attach(io, stream) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 29
+def attach(io, stream)
+  @todo << lambda do
+    @map[io] = @nio.register(io, :r)
+    @map[io].value = stream
+  end
+  wakeup
+end
+
+
+ +
+ +
+

+ + detach(io, stream) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 37
+def detach(io, stream)
+  @todo << lambda do
+    @nio.deregister io
+    @map.delete io
+    io.close
+  end
+  wakeup
+end
+
+
+ +
+ +
+

+ + post(task = nil, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 22
+def post(task = nil, &block)
+  task ||= block
+
+  spawn
+  @executor << task
+end
+
+
+ +
+ +
+

+ + stop() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 55
+def stop
+  @stopping = true
+  wakeup if @nio
+end
+
+
+ +
+ +
+

+ + timer(interval, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 18
+def timer(interval, &block)
+  Concurrent::TimerTask.new(execution_interval: interval, &block).tap(&:execute)
+end
+
+
+ +
+ +
+

+ + writes_pending(io) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/stream_event_loop.rb, line 46
+def writes_pending(io)
+  @todo << lambda do
+    if monitor = @map[io]
+      monitor.interests = :rw
+    end
+  end
+  wakeup
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TaggedLoggerProxy.html b/src/7.0/classes/ActionCable/Connection/TaggedLoggerProxy.html new file mode 100644 index 0000000000..dd8a7666f2 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TaggedLoggerProxy.html @@ -0,0 +1,257 @@ +--- +title: ActionCable::Connection::TaggedLoggerProxy +layout: default +--- +
+ +
+
+ +
+ +

Allows the use of per-connection tags against the server logger. This wouldn’t work using the traditional ActiveSupport::TaggedLogging enhanced Rails.logger, as that logger will reset the tags between requests. The connection is long-lived, so it needs its own set of tags for its independent duration.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + tags
+ + + + +

Class Public methods

+ +
+

+ + new(logger, tags:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/tagged_logger_proxy.rb, line 11
+def initialize(logger, tags:)
+  @logger = logger
+  @tags = tags.flatten
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_tags(*tags) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/tagged_logger_proxy.rb, line 16
+def add_tags(*tags)
+  @tags += tags.flatten
+  @tags = @tags.uniq
+end
+
+
+ +
+ +
+

+ + tag(logger, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/tagged_logger_proxy.rb, line 21
+def tag(logger, &block)
+  if logger.respond_to?(:tagged)
+    current_tags = tags - logger.formatter.current_tags
+    logger.tagged(*current_tags, &block)
+  else
+    yield
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + log(type, message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/tagged_logger_proxy.rb, line 37
+def log(type, message) # :doc:
+  tag(@logger) { @logger.send type, message }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestCase.html b/src/7.0/classes/ActionCable/Connection/TestCase.html new file mode 100644 index 0000000000..b50c8db698 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestCase.html @@ -0,0 +1,162 @@ +--- +title: ActionCable::Connection::TestCase +layout: default +--- +
+ +
+
+ +
+ +

Unit test Action Cable connections.

+ +

Useful to check whether a connection’s identified_by gets assigned properly and that any improper connection requests are rejected.

+ +

Basic example

+ +

Unit tests are written as follows:

+
  1. +

    Simulate a connection attempt by calling connect.

    +
  2. +

    Assert state, e.g. identifiers, has been assigned.

    +
+ +
class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
+  def test_connects_with_proper_cookie
+    # Simulate the connection request with a cookie.
+    cookies["user_id"] = users(:john).id
+
+    connect
+
+    # Assert the connection identifier matches the fixture.
+    assert_equal users(:john).id, connection.user.id
+  end
+
+  def test_rejects_connection_without_proper_cookie
+    assert_reject_connection { connect }
+  end
+end
+
+ +

connect accepts additional information about the HTTP request with the params, headers, session, and Rack env options.

+ +
def test_connect_with_headers_and_query_string
+  connect params: { user_id: 1 }, headers: { "X-API-TOKEN" => "secret-my" }
+
+  assert_equal "1", connection.user.id
+  assert_equal "secret-my", connection.token
+end
+
+def test_connect_with_params
+  connect params: { user_id: 1 }
+
+  assert_equal "1", connection.user.id
+end
+
+ +

You can also set up the correct cookies before the connection request:

+ +
def test_connect_with_cookies
+  # Plain cookies:
+  cookies["user_id"] = 1
+
+  # Or signed/encrypted:
+  # cookies.signed["user_id"] = 1
+  # cookies.encrypted["user_id"] = 1
+
+  connect
+
+  assert_equal "1", connection.user_id
+end
+
+ +

Connection is automatically inferred

+ +

ActionCable::Connection::TestCase will automatically infer the connection under test from the test class name. If the channel cannot be inferred from the test class name, you can explicitly set it with tests.

+ +
class ConnectionTest < ActionCable::Connection::TestCase
+  tests ApplicationCable::Connection
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestCase/Behavior.html b/src/7.0/classes/ActionCable/Connection/TestCase/Behavior.html new file mode 100644 index 0000000000..ebaf4ef35e --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestCase/Behavior.html @@ -0,0 +1,268 @@ +--- +title: ActionCable::Connection::TestCase::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_PATH="/cable"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + connection
+ + + + + +

Instance Public methods

+ +
+

+ + connect(path = ActionCable.server.config.mount_path, **request_params) + +

+ + +
+

Performs connection attempt to exert connect on the connection under test.

+ +

Accepts request path as the first argument and the following request options:

+
  • +

    params – URL parameters (Hash)

    +
  • +

    headers – request headers (Hash)

    +
  • +

    session – session data (Hash)

    +
  • +

    env – additional Rack env configuration (Hash)

    +
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 183
+def connect(path = ActionCable.server.config.mount_path, **request_params)
+  path ||= DEFAULT_PATH
+
+  connection = self.class.connection_class.allocate
+  connection.singleton_class.include(TestConnection)
+  connection.send(:initialize, build_test_request(path, **request_params))
+  connection.connect if connection.respond_to?(:connect)
+
+  # Only set instance variable if connected successfully
+  @connection = connection
+end
+
+
+ +
+ +
+

+ + cookies() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 203
+def cookies
+  @cookie_jar ||= TestCookieJar.new
+end
+
+
+ +
+ +
+

+ + disconnect() + +

+ + +
+

Exert disconnect on the connection under test.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 196
+def disconnect
+  raise "Must be connected!" if connection.nil?
+
+  connection.disconnect if connection.respond_to?(:disconnect)
+  @connection = nil
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestCase/Behavior/ClassMethods.html b/src/7.0/classes/ActionCable/Connection/TestCase/Behavior/ClassMethods.html new file mode 100644 index 0000000000..8d25752ca5 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestCase/Behavior/ClassMethods.html @@ -0,0 +1,194 @@ +--- +title: ActionCable::Connection::TestCase::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + connection_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 158
+def connection_class
+  if connection = self._connection_class
+    connection
+  else
+    tests determine_default_connection(name)
+  end
+end
+
+
+ +
+ +
+

+ + determine_default_connection(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 166
+def determine_default_connection(name)
+  connection = determine_constant_from_test_name(name) do |constant|
+    Class === constant && constant < ActionCable::Connection::Base
+  end
+  raise NonInferrableConnectionError.new(name) if connection.nil?
+  connection
+end
+
+
+ +
+ +
+

+ + tests(connection) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 147
+def tests(connection)
+  case connection
+  when String, Symbol
+    self._connection_class = connection.to_s.camelize.constantize
+  when Module
+    self._connection_class = connection
+  else
+    raise NonInferrableConnectionError.new(connection)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestConnection.html b/src/7.0/classes/ActionCable/Connection/TestConnection.html new file mode 100644 index 0000000000..cb4a9c2cce --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestConnection.html @@ -0,0 +1,127 @@ +--- +title: ActionCable::Connection::TestConnection +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + logger
+ [R] + request
+ + + + +

Class Public methods

+ +
+

+ + new(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 50
+def initialize(request)
+  inner_logger = ActiveSupport::Logger.new(StringIO.new)
+  tagged_logging = ActiveSupport::TaggedLogging.new(inner_logger)
+  @logger = ActionCable::Connection::TaggedLoggerProxy.new(tagged_logging, tags: [])
+  @request = request
+  @env = request.env
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestCookieJar.html b/src/7.0/classes/ActionCable/Connection/TestCookieJar.html new file mode 100644 index 0000000000..7714ce5ae0 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestCookieJar.html @@ -0,0 +1,152 @@ +--- +title: ActionCable::Connection::TestCookieJar +layout: default +--- +
+ +
+
+ +
+ +

We don’t want to use the whole “encryption stack” for connection unit-tests, but we want to make sure that users test against the correct types of cookies (i.e. signed or encrypted or plain)

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + encrypted() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 38
+def encrypted
+  self[:encrypted] ||= {}.with_indifferent_access
+end
+
+
+ +
+ +
+

+ + signed() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/connection/test_case.rb, line 34
+def signed
+  self[:signed] ||= {}.with_indifferent_access
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Connection/TestRequest.html b/src/7.0/classes/ActionCable/Connection/TestRequest.html new file mode 100644 index 0000000000..40d0028e94 --- /dev/null +++ b/src/7.0/classes/ActionCable/Connection/TestRequest.html @@ -0,0 +1,82 @@ +--- +title: ActionCable::Connection::TestRequest +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + cookie_jar
+ [RW] + session
+ + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Helpers.html b/src/7.0/classes/ActionCable/Helpers.html new file mode 100644 index 0000000000..2b15f6d0e1 --- /dev/null +++ b/src/7.0/classes/ActionCable/Helpers.html @@ -0,0 +1,67 @@ +--- +title: ActionCable::Helpers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Helpers/ActionCableHelper.html b/src/7.0/classes/ActionCable/Helpers/ActionCableHelper.html new file mode 100644 index 0000000000..2e4a02fe20 --- /dev/null +++ b/src/7.0/classes/ActionCable/Helpers/ActionCableHelper.html @@ -0,0 +1,130 @@ +--- +title: ActionCable::Helpers::ActionCableHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + action_cable_meta_tag() + +

+ + +
+

Returns an “action-cable-url” meta tag with the value of the URL specified in your configuration. Ensure this is above your JavaScript tag:

+ +
<head>
+  <%= action_cable_meta_tag %>
+  <%= javascript_include_tag 'application', 'data-turbo-track' => 'reload' %>
+</head>
+
+ +

This is then used by Action Cable to determine the URL of your WebSocket server. Your JavaScript can then connect to the server without needing to specify the URL directly:

+ +
import Cable from "@rails/actioncable"
+window.Cable = Cable
+window.App = {}
+App.cable = Cable.createConsumer()
+
+ +

Make sure to specify the correct server location in each of your environment config files:

+ +
config.action_cable.mount_path = "/cable123"
+<%= action_cable_meta_tag %> would render:
+=> <meta name="action-cable-url" content="/cable123" />
+
+config.action_cable.url = "ws://actioncable.com"
+<%= action_cable_meta_tag %> would render:
+=> <meta name="action-cable-url" content="ws://actioncable.com" />
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/helpers/action_cable_helper.rb, line 34
+def action_cable_meta_tag
+  tag "meta", name: "action-cable-url", content: (
+    ActionCable.server.config.url ||
+    ActionCable.server.config.mount_path ||
+    raise("No Action Cable URL configured -- please configure this at config.action_cable.url")
+  )
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/RemoteConnections.html b/src/7.0/classes/ActionCable/RemoteConnections.html new file mode 100644 index 0000000000..aac7dac720 --- /dev/null +++ b/src/7.0/classes/ActionCable/RemoteConnections.html @@ -0,0 +1,194 @@ +--- +title: ActionCable::RemoteConnections +layout: default +--- +
+ +
+
+ +
+ +

If you need to disconnect a given connection, you can go through the RemoteConnections. You can find the connections you’re looking for by searching for the identifier declared on the connection. For example:

+ +
module ApplicationCable
+  class Connection < ActionCable::Connection::Base
+    identified_by :current_user
+    ....
+  end
+end
+
+ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect
+
+ +

This will disconnect all the connections established for User.find(1), across all servers running on all machines, because it uses the internal channel that all of these servers are subscribed to.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + server
+ + + + +

Class Public methods

+ +
+

+ + new(server) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/remote_connections.rb, line 25
+def initialize(server)
+  @server = server
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + where(identifier) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/remote_connections.rb, line 29
+def where(identifier)
+  RemoteConnection.new(server, identifier)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection.html b/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection.html new file mode 100644 index 0000000000..8608d9f17c --- /dev/null +++ b/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection.html @@ -0,0 +1,183 @@ +--- +title: ActionCable::RemoteConnections::RemoteConnection +layout: default +--- +
+ +
+
+ +
+ +

Represents a single remote connection found via ActionCable.server.remote_connections.where(*). Exists solely for the purpose of calling disconnect on that connection.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + server
+ + + + +

Class Public methods

+ +
+

+ + new(server, ids) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/remote_connections.rb, line 41
+def initialize(server, ids)
+  @server = server
+  set_identifier_instance_vars(ids)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + disconnect() + +

+ + +
+

Uses the internal channel to disconnect the connection.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/remote_connections.rb, line 47
+def disconnect
+  server.broadcast internal_channel, { type: "disconnect" }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection/InvalidIdentifiersError.html b/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection/InvalidIdentifiersError.html new file mode 100644 index 0000000000..c376e34e37 --- /dev/null +++ b/src/7.0/classes/ActionCable/RemoteConnections/RemoteConnection/InvalidIdentifiersError.html @@ -0,0 +1,60 @@ +--- +title: ActionCable::RemoteConnections::RemoteConnection::InvalidIdentifiersError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server.html b/src/7.0/classes/ActionCable/Server.html new file mode 100644 index 0000000000..96d7a8a1f0 --- /dev/null +++ b/src/7.0/classes/ActionCable/Server.html @@ -0,0 +1,90 @@ +--- +title: ActionCable::Server +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Base.html b/src/7.0/classes/ActionCable/Server/Base.html new file mode 100644 index 0000000000..acffc0e365 --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Base.html @@ -0,0 +1,522 @@ +--- +title: ActionCable::Server::Base +layout: default +--- +
+ +
+
+ +
+ +

A singleton ActionCable::Server instance is available via ActionCable.server. It’s used by the Rack process that starts the Action Cable server, but is also used by the user to reach the RemoteConnections object, which is used for finding and disconnecting connections across all servers.

+ +

Also, this is the server instance used for broadcasting. See Broadcasting for more information.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + config
+ [R] + mutex
+ + + + +

Class Public methods

+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 19
+def self.logger; config.logger; end
+
+
+ +
+ +
+

+ + new(config: self.class.config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 24
+def initialize(config: self.class.config)
+  @config = config
+  @mutex = Monitor.new
+  @remote_connections = @event_loop = @worker_pool = @pubsub = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+

Called by Rack to set up the server.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 31
+def call(env)
+  setup_heartbeat_timer
+  config.connection_class.call.new(self, env).process
+end
+
+
+ +
+ +
+

+ + connection_identifiers() + +

+ + +
+

All of the identifiers applied to the connection class associated with this server.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 87
+def connection_identifiers
+  config.connection_class.call.identifiers
+end
+
+
+ +
+ +
+

+ + disconnect(identifiers) + +

+ + +
+

Disconnect all the connections identified by identifiers on this server or any others via RemoteConnections.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 37
+def disconnect(identifiers)
+  remote_connections.where(identifiers).disconnect
+end
+
+
+ +
+ +
+

+ + event_loop() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 62
+def event_loop
+  @event_loop || @mutex.synchronize { @event_loop ||= ActionCable::Connection::StreamEventLoop.new }
+end
+
+
+ +
+ +
+

+ + pubsub() + +

+ + +
+

Adapter used for all streams/broadcasting.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 82
+def pubsub
+  @pubsub || @mutex.synchronize { @pubsub ||= config.pubsub_adapter.new(self) }
+end
+
+
+ +
+ +
+

+ + remote_connections() + +

+ + +
+

Gateway to RemoteConnections. See that class for details.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 58
+def remote_connections
+  @remote_connections || @mutex.synchronize { @remote_connections ||= RemoteConnections.new(self) }
+end
+
+
+ +
+ +
+

+ + restart() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 41
+def restart
+  connections.each do |connection|
+    connection.close(reason: ActionCable::INTERNAL[:disconnect_reasons][:server_restart])
+  end
+
+  @mutex.synchronize do
+    # Shutdown the worker pool
+    @worker_pool.halt if @worker_pool
+    @worker_pool = nil
+
+    # Shutdown the pub/sub adapter
+    @pubsub.shutdown if @pubsub
+    @pubsub = nil
+  end
+end
+
+
+ +
+ +
+

+ + worker_pool() + +

+ + +
+

The worker pool is where we run connection callbacks and channel actions. We do as little as possible on the server’s main thread. The worker pool is an executor service that’s backed by a pool of threads working from a task queue. The thread pool size maxes out at 4 worker threads by default. Tune the size yourself with config.action_cable.worker_pool_size.

+ +

Using Active Record, Redis, etc within your channel actions means you’ll get a separate connection from each thread in the worker pool. Plan your deployment accordingly: 5 servers each running 5 Puma workers each running an 8-thread worker pool means at least 200 database connections.

+ +

Also, ensure that your database connection pool size is as least as large as your worker pool size. Otherwise, workers may oversubscribe the database connection pool and block while they wait for other workers to release their connections. Use a smaller worker pool or a larger database connection pool instead.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/base.rb, line 77
+def worker_pool
+  @worker_pool || @mutex.synchronize { @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Broadcasting.html b/src/7.0/classes/ActionCable/Server/Broadcasting.html new file mode 100644 index 0000000000..83114ebb81 --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Broadcasting.html @@ -0,0 +1,175 @@ +--- +title: ActionCable::Server::Broadcasting +layout: default +--- +
+ +
+
+ +
+ +

Broadcasting is how other parts of your application can send messages to a channel’s subscribers. As explained in Channel, most of the time, these broadcastings are streamed directly to the clients subscribed to the named broadcasting. Let’s explain with a full-stack example:

+ +
class WebNotificationsChannel < ApplicationCable::Channel
+  def subscribed
+    stream_from "web_notifications_#{current_user.id}"
+  end
+end
+
+# Somewhere in your app this is called, perhaps from a NewCommentJob:
+ActionCable.server.broadcast \
+  "web_notifications_1", { title: "New things!", body: "All that's fit for print" }
+
+# Client-side CoffeeScript, which assumes you've already requested the right to send web notifications:
+App.cable.subscriptions.create "WebNotificationsChannel",
+  received: (data) ->
+    new Notification data['title'], body: data['body']
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + broadcast(broadcasting, message, coder: ActiveSupport::JSON) + +

+ + +
+

Broadcast a hash directly to a named broadcasting. This will later be JSON encoded.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/broadcasting.rb, line 24
+def broadcast(broadcasting, message, coder: ActiveSupport::JSON)
+  broadcaster_for(broadcasting, coder: coder).broadcast(message)
+end
+
+
+ +
+ +
+

+ + broadcaster_for(broadcasting, coder: ActiveSupport::JSON) + +

+ + +
+

Returns a broadcaster for a named broadcasting that can be reused. Useful when you have an object that may need multiple spots to transmit to a specific broadcasting over and over.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/broadcasting.rb, line 30
+def broadcaster_for(broadcasting, coder: ActiveSupport::JSON)
+  Broadcaster.new(self, String(broadcasting), coder: coder)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Broadcasting/Broadcaster.html b/src/7.0/classes/ActionCable/Server/Broadcasting/Broadcaster.html new file mode 100644 index 0000000000..64831b9d46 --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Broadcasting/Broadcaster.html @@ -0,0 +1,185 @@ +--- +title: ActionCable::Server::Broadcasting::Broadcaster +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + broadcasting
+ [R] + coder
+ [R] + server
+ + + + +

Class Public methods

+ +
+

+ + new(server, broadcasting, coder:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/broadcasting.rb, line 38
+def initialize(server, broadcasting, coder:)
+  @server, @broadcasting, @coder = server, broadcasting, coder
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + broadcast(message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/broadcasting.rb, line 42
+def broadcast(message)
+  server.logger.debug { "[ActionCable] Broadcasting to #{broadcasting}: #{message.inspect.truncate(300)}" }
+
+  payload = { broadcasting: broadcasting, message: message, coder: coder }
+  ActiveSupport::Notifications.instrument("broadcast.action_cable", payload) do
+    encoded = coder ? coder.encode(message) : message
+    server.pubsub.broadcast broadcasting, encoded
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Configuration.html b/src/7.0/classes/ActionCable/Server/Configuration.html new file mode 100644 index 0000000000..c65ff8e121 --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Configuration.html @@ -0,0 +1,280 @@ +--- +title: ActionCable::Server::Configuration +layout: default +--- +
+ +
+
+ +
+ +

An instance of this configuration object is available via ActionCable.server.config, which allows you to tweak Action Cable configuration in a Rails config initializer.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + allow_same_origin_as_host
+ [RW] + allowed_request_origins
+ [RW] + cable
+ [RW] + connection_class
+ [RW] + disable_request_forgery_protection
+ [RW] + log_tags
+ [RW] + logger
+ [RW] + mount_path
+ [RW] + precompile_assets
+ [RW] + url
+ [RW] + worker_pool_size
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/configuration.rb, line 14
+def initialize
+  @log_tags = []
+
+  @connection_class = -> { ActionCable::Connection::Base }
+  @worker_pool_size = 4
+
+  @disable_request_forgery_protection = false
+  @allow_same_origin_as_host = true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + pubsub_adapter() + +

+ + +
+

Returns constant of subscription adapter specified in config/cable.yml. If the adapter cannot be found, this will default to the Redis adapter. Also makes sure proper dependencies are required.

+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/configuration.rb, line 27
+def pubsub_adapter
+  adapter = (cable.fetch("adapter") { "redis" })
+
+  # Require the adapter itself and give useful feedback about
+  #   1. Missing adapter gems and
+  #   2. Adapter gems' missing dependencies.
+  path_to_adapter = "action_cable/subscription_adapter/#{adapter}"
+  begin
+    require path_to_adapter
+  rescue LoadError => e
+    # We couldn't require the adapter itself. Raise an exception that
+    # points out config typos and missing gems.
+    if e.path == path_to_adapter
+      # We can assume that a non-builtin adapter was specified, so it's
+      # either misspelled or missing from Gemfile.
+      raise e.class, "Could not load the '#{adapter}' Action Cable pubsub adapter. Ensure that the adapter is spelled correctly in config/cable.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
+
+    # Bubbled up from the adapter require. Prefix the exception message
+    # with some guidance about how to address it and reraise.
+    else
+      raise e.class, "Error loading the '#{adapter}' Action Cable pubsub adapter. Missing a gem it depends on? #{e.message}", e.backtrace
+    end
+  end
+
+  adapter = adapter.camelize
+  adapter = "PostgreSQL" if adapter == "Postgresql"
+  "ActionCable::SubscriptionAdapter::#{adapter}".constantize
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Worker.html b/src/7.0/classes/ActionCable/Server/Worker.html new file mode 100644 index 0000000000..eeadb8f04f --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Worker.html @@ -0,0 +1,75 @@ +--- +title: ActionCable::Server::Worker +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/Server/Worker/ActiveRecordConnectionManagement.html b/src/7.0/classes/ActionCable/Server/Worker/ActiveRecordConnectionManagement.html new file mode 100644 index 0000000000..31ea87c95a --- /dev/null +++ b/src/7.0/classes/ActionCable/Server/Worker/ActiveRecordConnectionManagement.html @@ -0,0 +1,101 @@ +--- +title: ActionCable::Server::Worker::ActiveRecordConnectionManagement +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + with_database_connections(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/server/worker/active_record_connection_management.rb, line 15
+def with_database_connections(&block)
+  connection.logger.tag(ActiveRecord::Base.logger, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter.html b/src/7.0/classes/ActionCable/SubscriptionAdapter.html new file mode 100644 index 0000000000..d0402d959b --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter.html @@ -0,0 +1,95 @@ +--- +title: ActionCable::SubscriptionAdapter +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Async.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Async.html new file mode 100644 index 0000000000..64cb909679 --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Async.html @@ -0,0 +1,73 @@ +--- +title: ActionCable::SubscriptionAdapter::Async +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Async/AsyncSubscriberMap.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Async/AsyncSubscriberMap.html new file mode 100644 index 0000000000..4d7e137dfe --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Async/AsyncSubscriberMap.html @@ -0,0 +1,189 @@ +--- +title: ActionCable::SubscriptionAdapter::Async::AsyncSubscriberMap +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(event_loop) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/async.rb, line 14
+def initialize(event_loop)
+  @event_loop = event_loop
+  super()
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_subscriber(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/async.rb, line 19
+def add_subscriber(*)
+  @event_loop.post { super }
+end
+
+
+ +
+ +
+

+ + invoke_callback(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/async.rb, line 23
+def invoke_callback(*)
+  @event_loop.post { super }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Base.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Base.html new file mode 100644 index 0000000000..3d6d62e67f --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Base.html @@ -0,0 +1,328 @@ +--- +title: ActionCable::SubscriptionAdapter::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + logger
+ [R] + server
+ + + + +

Class Public methods

+ +
+

+ + new(server) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 8
+def initialize(server)
+  @server = server
+  @logger = @server.logger
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + broadcast(channel, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 13
+def broadcast(channel, payload)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + identifier() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 29
+def identifier
+  @server.config.cable[:id] ||= "ActionCable-PID-#{$$}"
+end
+
+
+ +
+ +
+

+ + shutdown() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 25
+def shutdown
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + subscribe(channel, message_callback, success_callback = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 17
+def subscribe(channel, message_callback, success_callback = nil)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + unsubscribe(channel, message_callback) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/base.rb, line 21
+def unsubscribe(channel, message_callback)
+  raise NotImplementedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL.html new file mode 100644 index 0000000000..cbbe1deae4 --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL.html @@ -0,0 +1,73 @@ +--- +title: ActionCable::SubscriptionAdapter::PostgreSQL +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL/Listener.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL/Listener.html new file mode 100644 index 0000000000..ac166468c6 --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/PostgreSQL/Listener.html @@ -0,0 +1,337 @@ +--- +title: ActionCable::SubscriptionAdapter::PostgreSQL::Listener +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(adapter, event_loop) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 75
+def initialize(adapter, event_loop)
+  super()
+
+  @adapter = adapter
+  @event_loop = event_loop
+  @queue = Queue.new
+
+  @thread = Thread.new do
+    Thread.current.abort_on_exception = true
+    listen
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_channel(channel, on_success) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 119
+def add_channel(channel, on_success)
+  @queue.push([:listen, channel, on_success])
+end
+
+
+ +
+ +
+

+ + invoke_callback(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 127
+def invoke_callback(*)
+  @event_loop.post { super }
+end
+
+
+ +
+ +
+

+ + listen() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 88
+def listen
+  @adapter.with_subscriptions_connection do |pg_conn|
+    catch :shutdown do
+      loop do
+        until @queue.empty?
+          action, channel, callback = @queue.pop(true)
+
+          case action
+          when :listen
+            pg_conn.exec("LISTEN #{pg_conn.escape_identifier channel}")
+            @event_loop.post(&callback) if callback
+          when :unlisten
+            pg_conn.exec("UNLISTEN #{pg_conn.escape_identifier channel}")
+          when :shutdown
+            throw :shutdown
+          end
+        end
+
+        pg_conn.wait_for_notify(1) do |chan, pid, message|
+          broadcast(chan, message)
+        end
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + remove_channel(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 123
+def remove_channel(channel)
+  @queue.push([:unlisten, channel])
+end
+
+
+ +
+ +
+

+ + shutdown() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/postgresql.rb, line 114
+def shutdown
+  @queue.push([:shutdown])
+  Thread.pass while @thread.alive?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis.html new file mode 100644 index 0000000000..73ca703f7c --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis.html @@ -0,0 +1,73 @@ +--- +title: ActionCable::SubscriptionAdapter::Redis +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener.html new file mode 100644 index 0000000000..e64965e71a --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener.html @@ -0,0 +1,403 @@ +--- +title: ActionCable::SubscriptionAdapter::Redis::Listener +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ConnectionError=::Redis::ConnectionError
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(adapter, config_options, event_loop) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 67
+def initialize(adapter, config_options, event_loop)
+  super()
+
+  @adapter = adapter
+  @event_loop = event_loop
+
+  @subscribe_callbacks = Hash.new { |h, k| h[k] = [] }
+  @subscription_lock = Mutex.new
+
+  @reconnect_attempt = 0
+  # Use the same config as used by Redis conn
+  @reconnect_attempts = config_options.fetch(:reconnect_attempts, 1)
+  @reconnect_attempts = Array.new(@reconnect_attempts, 0) if @reconnect_attempts.is_a?(Integer)
+
+  @subscribed_client = nil
+
+  @when_connected = []
+
+  @thread = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_channel(channel, on_success) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 140
+def add_channel(channel, on_success)
+  @subscription_lock.synchronize do
+    ensure_listener_running
+    @subscribe_callbacks[channel] << on_success
+    when_connected { @subscribed_client.subscribe(channel) }
+  end
+end
+
+
+ +
+ +
+

+ + invoke_callback(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 154
+def invoke_callback(*)
+  @event_loop.post { super }
+end
+
+
+ +
+ +
+

+ + listen(conn) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 88
+def listen(conn)
+  conn.without_reconnect do
+    original_client = extract_subscribed_client(conn)
+
+    conn.subscribe("_action_cable_internal") do |on|
+      on.subscribe do |chan, count|
+        @subscription_lock.synchronize do
+          if count == 1
+            @reconnect_attempt = 0
+            @subscribed_client = original_client
+
+            until @when_connected.empty?
+              @when_connected.shift.call
+            end
+          end
+
+          if callbacks = @subscribe_callbacks[chan]
+            next_callback = callbacks.shift
+            @event_loop.post(&next_callback) if next_callback
+            @subscribe_callbacks.delete(chan) if callbacks.empty?
+          end
+        end
+      end
+
+      on.message do |chan, message|
+        broadcast(chan, message)
+      end
+
+      on.unsubscribe do |chan, count|
+        if count == 0
+          @subscription_lock.synchronize do
+            @subscribed_client = nil
+          end
+        end
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + remove_channel(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 148
+def remove_channel(channel)
+  @subscription_lock.synchronize do
+    when_connected { @subscribed_client.unsubscribe(channel) }
+  end
+end
+
+
+ +
+ +
+

+ + shutdown() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 127
+def shutdown
+  @subscription_lock.synchronize do
+    return if @thread.nil?
+
+    when_connected do
+      @subscribed_client.unsubscribe
+      @subscribed_client = nil
+    end
+  end
+
+  Thread.pass while @thread.alive?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener/SubscribedClient.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener/SubscribedClient.html new file mode 100644 index 0000000000..fdc34a023e --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Redis/Listener/SubscribedClient.html @@ -0,0 +1,188 @@ +--- +title: ActionCable::SubscriptionAdapter::Redis::Listener::SubscribedClient +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(raw_client) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 215
+def initialize(raw_client)
+  @raw_client = raw_client
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + subscribe(*channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 219
+def subscribe(*channel)
+  send_command("subscribe", *channel)
+end
+
+
+ +
+ +
+

+ + unsubscribe(*channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/redis.rb, line 223
+def unsubscribe(*channel)
+  send_command("unsubscribe", *channel)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/SubscriberMap.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/SubscriberMap.html new file mode 100644 index 0000000000..4d2ee00422 --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/SubscriberMap.html @@ -0,0 +1,368 @@ +--- +title: ActionCable::SubscriptionAdapter::SubscriberMap +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 6
+def initialize
+  @subscribers = Hash.new { |h, k| h[k] = [] }
+  @sync = Mutex.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_channel(channel, on_success) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 47
+def add_channel(channel, on_success)
+  on_success.call if on_success
+end
+
+
+ +
+ +
+

+ + add_subscriber(channel, subscriber, on_success) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 11
+def add_subscriber(channel, subscriber, on_success)
+  @sync.synchronize do
+    new_channel = !@subscribers.key?(channel)
+
+    @subscribers[channel] << subscriber
+
+    if new_channel
+      add_channel channel, on_success
+    elsif on_success
+      on_success.call
+    end
+  end
+end
+
+
+ +
+ +
+

+ + broadcast(channel, message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 36
+def broadcast(channel, message)
+  list = @sync.synchronize do
+    return if !@subscribers.key?(channel)
+    @subscribers[channel].dup
+  end
+
+  list.each do |subscriber|
+    invoke_callback(subscriber, message)
+  end
+end
+
+
+ +
+ +
+

+ + invoke_callback(callback, message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 54
+def invoke_callback(callback, message)
+  callback.call message
+end
+
+
+ +
+ +
+

+ + remove_channel(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 51
+def remove_channel(channel)
+end
+
+
+ +
+ +
+

+ + remove_subscriber(channel, subscriber) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/subscriber_map.rb, line 25
+def remove_subscriber(channel, subscriber)
+  @sync.synchronize do
+    @subscribers[channel].delete(subscriber)
+
+    if @subscribers[channel].empty?
+      @subscribers.delete channel
+      remove_channel channel
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/SubscriptionAdapter/Test.html b/src/7.0/classes/ActionCable/SubscriptionAdapter/Test.html new file mode 100644 index 0000000000..c3f216ac08 --- /dev/null +++ b/src/7.0/classes/ActionCable/SubscriptionAdapter/Test.html @@ -0,0 +1,237 @@ +--- +title: ActionCable::SubscriptionAdapter::Test +layout: default +--- +
+ +
+
+ +
+ +

Test adapter for Action Cable

+ +

The test adapter should be used only in testing. Along with ActionCable::TestHelper it makes a great tool to test your Rails application.

+ +

To use the test adapter set adapter value to test in your config/cable.yml file.

+ +

NOTE: Test adapter extends the ActionCable::SubscriptionsAdapter::Async adapter, so it could be used in system tests too.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + broadcast(channel, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/test.rb, line 17
+def broadcast(channel, payload)
+  broadcasts(channel) << payload
+  super
+end
+
+
+ +
+ +
+

+ + broadcasts(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/test.rb, line 22
+def broadcasts(channel)
+  channels_data[channel] ||= []
+end
+
+
+ +
+ +
+

+ + clear() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/test.rb, line 30
+def clear
+  @channels_data = nil
+end
+
+
+ +
+ +
+

+ + clear_messages(channel) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/subscription_adapter/test.rb, line 26
+def clear_messages(channel)
+  channels_data[channel] = []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/TestCase.html b/src/7.0/classes/ActionCable/TestCase.html new file mode 100644 index 0000000000..697f2cc9f7 --- /dev/null +++ b/src/7.0/classes/ActionCable/TestCase.html @@ -0,0 +1,74 @@ +--- +title: ActionCable::TestCase +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/TestHelper.html b/src/7.0/classes/ActionCable/TestHelper.html new file mode 100644 index 0000000000..7636070b3f --- /dev/null +++ b/src/7.0/classes/ActionCable/TestHelper.html @@ -0,0 +1,274 @@ +--- +title: ActionCable::TestHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides helper methods for testing Action Cable broadcasting

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_broadcast_on(stream, data, &block) + +

+ + +
+

Asserts that the specified message has been sent to the stream.

+ +
def test_assert_transmitted_message
+  ActionCable.server.broadcast 'messages', text: 'hello'
+  assert_broadcast_on('messages', text: 'hello')
+end
+
+ +

If a block is passed, that block should cause a message with the specified data to be sent.

+ +
def test_assert_broadcast_on_again
+  assert_broadcast_on('messages', text: 'hello') do
+    ActionCable.server.broadcast 'messages', text: 'hello'
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/test_helper.rb, line 97
+def assert_broadcast_on(stream, data, &block)
+  # Encode to JSON and back–we want to use this value to compare
+  # with decoded JSON.
+  # Comparing JSON strings doesn't work due to the order if the keys.
+  serialized_msg =
+    ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
+
+  new_messages = broadcasts(stream)
+  if block_given?
+    old_messages = new_messages
+    clear_messages(stream)
+
+    _assert_nothing_raised_or_warn("assert_broadcast_on", &block)
+    new_messages = broadcasts(stream)
+    clear_messages(stream)
+
+    # Restore all sent messages
+    (old_messages + new_messages).each { |m| pubsub_adapter.broadcast(stream, m) }
+  end
+
+  message = new_messages.find { |msg| ActiveSupport::JSON.decode(msg) == serialized_msg }
+
+  assert message, "No messages sent with #{data} to #{stream}"
+end
+
+
+ +
+ +
+

+ + assert_broadcasts(stream, number, &block) + +

+ + +
+

Asserts that the number of broadcasted messages to the stream matches the given number.

+ +
def test_broadcasts
+  assert_broadcasts 'messages', 0
+  ActionCable.server.broadcast 'messages', { text: 'hello' }
+  assert_broadcasts 'messages', 1
+  ActionCable.server.broadcast 'messages', { text: 'world' }
+  assert_broadcasts 'messages', 2
+end
+
+ +

If a block is passed, that block should cause the specified number of messages to be broadcasted.

+ +
def test_broadcasts_again
+  assert_broadcasts('messages', 1) do
+    ActionCable.server.broadcast 'messages', { text: 'hello' }
+  end
+
+  assert_broadcasts('messages', 2) do
+    ActionCable.server.broadcast 'messages', { text: 'hi' }
+    ActionCable.server.broadcast 'messages', { text: 'how are you?' }
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/test_helper.rb, line 45
+def assert_broadcasts(stream, number, &block)
+  if block_given?
+    original_count = broadcasts_size(stream)
+    _assert_nothing_raised_or_warn("assert_broadcasts", &block)
+    new_count = broadcasts_size(stream)
+    actual_count = new_count - original_count
+  else
+    actual_count = broadcasts_size(stream)
+  end
+
+  assert_equal number, actual_count, "#{number} broadcasts to #{stream} expected, but #{actual_count} were sent"
+end
+
+
+ +
+ +
+

+ + assert_no_broadcasts(stream, &block) + +

+ + +
+

Asserts that no messages have been sent to the stream.

+ +
def test_no_broadcasts
+  assert_no_broadcasts 'messages'
+  ActionCable.server.broadcast 'messages', { text: 'hi' }
+  assert_broadcasts 'messages', 1
+end
+
+ +

If a block is passed, that block should not cause any message to be sent.

+ +
def test_broadcasts_again
+  assert_no_broadcasts 'messages' do
+    # No job messages should be sent from this block
+  end
+end
+
+ +

Note: This assertion is simply a shortcut for:

+ +
assert_broadcasts 'messages', 0, &block
+
+
+ + + + + + + + +
+ + +
+
# File actioncable/lib/action_cable/test_helper.rb, line 78
+def assert_no_broadcasts(stream, &block)
+  assert_broadcasts stream, 0, &block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionCable/VERSION.html b/src/7.0/classes/ActionCable/VERSION.html new file mode 100644 index 0000000000..9f8ac3667d --- /dev/null +++ b/src/7.0/classes/ActionCable/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActionCable::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController.html b/src/7.0/classes/ActionController.html new file mode 100644 index 0000000000..27a1456afa --- /dev/null +++ b/src/7.0/classes/ActionController.html @@ -0,0 +1,354 @@ +--- +title: ActionController +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + add_renderer(key, &block) + +

+ + +
+

See Renderers.add

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 7
+def self.add_renderer(key, &block)
+  Renderers.add(key, &block)
+end
+
+
+ +
+ +
+

+ + remove_renderer(key) + +

+ + + + + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 12
+def self.remove_renderer(key)
+  Renderers.remove(key)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/API.html b/src/7.0/classes/ActionController/API.html new file mode 100644 index 0000000000..9f6cf2f7a0 --- /dev/null +++ b/src/7.0/classes/ActionController/API.html @@ -0,0 +1,231 @@ +--- +title: ActionController::API +layout: default +--- +
+ +
+
+ +
+ +

API Controller is a lightweight version of ActionController::Base, created for applications that don’t require all functionalities that a complete Rails controller provides, allowing you to create controllers with just the features that you need for API only applications.

+ +

An API Controller is different from a normal controller in the sense that by default it doesn’t include a number of features that are usually required by browser access only: layouts and templates rendering, flash, assets, and so on. This makes the entire controller stack thinner, suitable for API applications. It doesn’t mean you won’t have such features if you need them: they’re all available for you to include in your application, they’re just not part of the default API controller stack.

+ +

Normally, ApplicationController is the only controller that inherits from ActionController::API. All other controllers in turn inherit from ApplicationController.

+ +

A sample controller could look like this:

+ +
class PostsController < ApplicationController
+  def index
+    posts = Post.all
+    render json: posts
+  end
+end
+
+ +

Request, response, and parameters objects all work the exact same way as ActionController::Base.

+ +

Renders

+ +

The default API Controller stack includes all renderers, which means you can use render :json and siblings freely in your controllers. Keep in mind that templates are not going to be rendered, so you need to ensure your controller is calling either render or redirect_to in all actions, otherwise it will return 204 No Content.

+ +
def show
+  post = Post.find(params[:id])
+  render json: post
+end
+
+ +

Redirects

+ +

Redirects are used to move from one action to another. You can use the redirect_to method in your controllers in the same way as in ActionController::Base. For example:

+ +
def create
+  redirect_to root_url and return if not_authorized?
+  # do stuff here
+end
+
+ +

Adding New Behavior

+ +

In some scenarios you may want to add back some functionality provided by ActionController::Base that is not present by default in ActionController::API, for instance MimeResponds. This module gives you the respond_to method. Adding it is quite simple, you just need to include the module in a specific controller or in ApplicationController in case you want it available in your entire application:

+ +
class ApplicationController < ActionController::API
+  include ActionController::MimeResponds
+end
+
+class PostsController < ApplicationController
+  def index
+    posts = Post.all
+
+    respond_to do |format|
+      format.json { render json: posts }
+      format.xml  { render xml: posts }
+    end
+  end
+end
+
+ +

Make sure to check the modules included in ActionController::Base if you want to use any other functionality that is not provided by ActionController::API out of the box.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MODULES=[ +AbstractController::Rendering, + +UrlFor, +Redirecting, +ApiRendering, +Renderers::All, +ConditionalGet, +BasicImplicitRender, +StrongParameters, + +DataStreaming, +DefaultHeaders, +Logging, + +# Before callbacks should also be executed as early as possible, so +# also include them at the bottom. +AbstractController::Callbacks, + +# Append rescue at the bottom to wrap as much as possible. +Rescue, + +# Add instrumentations hooks at the bottom, to ensure they instrument +# all the methods properly. +Instrumentation, + +# Params wrapper should come before instrumentation so they are +# properly showed in logs +ParamsWrapper +]
 
+ + + + + + +

Class Public methods

+ +
+

+ + without_modules(*modules) + +

+ + +
+

Shortcut helper that returns all the ActionController::API modules except the ones passed as arguments:

+ +
class MyAPIBaseController < ActionController::Metal
+  ActionController::API.without_modules(:UrlFor).each do |left|
+    include left
+  end
+end
+
+ +

This gives better control over what you want to exclude and makes it easier to create an API controller class, instead of listing the modules required manually.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/api.rb, line 104
+def self.without_modules(*modules)
+  modules = modules.map do |m|
+    m.is_a?(Symbol) ? ActionController.const_get(m) : m
+  end
+
+  MODULES - modules
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ApiRendering.html b/src/7.0/classes/ActionController/ApiRendering.html new file mode 100644 index 0000000000..061ff4ad37 --- /dev/null +++ b/src/7.0/classes/ActionController/ApiRendering.html @@ -0,0 +1,116 @@ +--- +title: ActionController::ApiRendering +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + render_to_body(options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/api/api_rendering.rb, line 11
+def render_to_body(options = {})
+  _process_options(options)
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Base.html b/src/7.0/classes/ActionController/Base.html new file mode 100644 index 0000000000..679e183c5f --- /dev/null +++ b/src/7.0/classes/ActionController/Base.html @@ -0,0 +1,422 @@ +--- +title: ActionController::Base +layout: default +--- +
+ +
+
+ +
+ +

Action Controllers are the core of a web request in Rails. They are made up of one or more actions that are executed on request and then either it renders a template or redirects to another action. An action is defined as a public method on the controller, which will automatically be made accessible to the web-server through Rails Routes.

+ +

By default, only the ApplicationController in a Rails application inherits from ActionController::Base. All other controllers inherit from ApplicationController. This gives you one class to configure things such as request forgery protection and filtering of sensitive request parameters.

+ +

A sample controller could look like this:

+ +
class PostsController < ApplicationController
+  def index
+    @posts = Post.all
+  end
+
+  def create
+    @post = Post.create params[:post]
+    redirect_to posts_path
+  end
+end
+
+ +

Actions, by default, render a template in the app/views directory corresponding to the name of the controller and action after executing code in the action. For example, the index action of the PostsController would render the template app/views/posts/index.html.erb by default after populating the @posts instance variable.

+ +

Unlike index, the create action will not render a template. After performing its main purpose (creating a new post), it initiates a redirect instead. This redirect works by returning an external 302 Moved HTTP response that takes the user to the index action.

+ +

These two methods represent the two basic action archetypes used in Action Controllers: Get-and-show and do-and-redirect. Most actions are variations on these themes.

+ +

Requests

+ +

For every request, the router determines the value of the controller and action keys. These determine which controller and action are called. The remaining request parameters, the session (if one is available), and the full request with all the HTTP headers are made available to the action through accessor methods. Then the action is performed.

+ +

The full request object is available via the request accessor and is primarily used to query for HTTP headers:

+ +
def server_ip
+  location = request.env["REMOTE_ADDR"]
+  render plain: "This server hosted at #{location}"
+end
+
+ +

Parameters

+ +

All request parameters, whether they come from a query string in the URL or form data submitted through a POST request are available through the params method which returns a hash. For example, an action that was performed through /posts?category=All&limit=5 will include { "category" => "All", "limit" => "5" } in params.

+ +

It’s also possible to construct multi-dimensional parameter hashes by specifying keys using brackets, such as:

+ +
<input type="text" name="post[name]" value="david">
+<input type="text" name="post[address]" value="hyacintvej">
+
+ +

A request coming from a form holding these inputs will include { "post" => { "name" => "david", "address" => "hyacintvej" } }. If the address input had been named post[address][street], the params would have included { "post" => { "address" => { "street" => "hyacintvej" } } }. There’s no limit to the depth of the nesting.

+ +

Sessions

+ +

Sessions allow you to store objects in between requests. This is useful for objects that are not yet ready to be persisted, such as a Signup object constructed in a multi-paged process, or objects that don’t change much and are needed all the time, such as a User object for a system that requires login. The session should not be used, however, as a cache for objects where it’s likely they could be changed unknowingly. It’s usually too much work to keep it all synchronized – something databases already excel at.

+ +

You can place objects in the session by using the session method, which accesses a hash:

+ +
session[:person] = Person.authenticate(user_name, password)
+
+ +

You can retrieve it again through the same hash:

+ +
"Hello #{session[:person]}"
+
+ +

For removing objects from the session, you can either assign a single key to nil:

+ +
# removes :person from session
+session[:person] = nil
+
+ +

or you can remove the entire session with reset_session.

+ +

By default, sessions are stored in an encrypted browser cookie (see ActionDispatch::Session::CookieStore). Thus the user will not be able to read or edit the session data. However, the user can keep a copy of the cookie even after it has expired, so you should avoid storing sensitive information in cookie-based sessions.

+ +

Responses

+ +

Each action results in a response, which holds the headers and document to be sent to the user’s browser. The actual response object is generated automatically through the use of renders and redirects and requires no user intervention.

+ +

Renders

+ +

Action Controller sends content to the user by using one of five rendering methods. The most versatile and common is the rendering of a template. Included in the Action Pack is the Action View, which enables rendering of ERB templates. It’s automatically configured. The controller passes objects to the view by assigning instance variables:

+ +
def show
+  @post = Post.find(params[:id])
+end
+
+ +

Which are then automatically available to the view:

+ +
Title: <%= @post.title %>
+
+ +

You don’t have to rely on the automated rendering. For example, actions that could result in the rendering of different templates will use the manual rendering methods:

+ +
def search
+  @results = Search.find(params[:query])
+  case @results.count
+    when 0 then render action: "no_results"
+    when 1 then render action: "show"
+    when 2..10 then render action: "show_many"
+  end
+end
+
+ +

Read more about writing ERB and Builder templates in ActionView::Base.

+ +

Redirects

+ +

Redirects are used to move from one action to another. For example, after a create action, which stores a blog entry to the database, we might like to show the user the new entry. Because we’re following good DRY principles (Don’t Repeat Yourself), we’re going to reuse (and redirect to) a show action that we’ll assume has already been created. The code might look like this:

+ +
def create
+  @entry = Entry.new(params[:entry])
+  if @entry.save
+    # The entry was saved correctly, redirect to show
+    redirect_to action: 'show', id: @entry.id
+  else
+    # things didn't go so well, do something else
+  end
+end
+
+ +

In this case, after saving our new entry to the database, the user is redirected to the show method, which is then executed. Note that this is an external HTTP-level redirection which will cause the browser to make a second request (a GET to the show action), and not some internal re-routing which calls both “create” and then “show” within one request.

+ +

Learn more about redirect_to and what options you have in ActionController::Redirecting.

+ +

Calling multiple redirects or renders

+ +

An action may contain only a single render or a single redirect. Attempting to try to do either again will result in a DoubleRenderError:

+ +
def do_something
+  redirect_to action: "elsewhere"
+  render action: "overthere" # raises DoubleRenderError
+end
+
+ +

If you need to redirect on the condition of something, then be sure to add “and return” to halt execution.

+ +
def do_something
+  redirect_to(action: "elsewhere") and return if monkeys.nil?
+  render action: "overthere" # won't be called if monkeys is nil
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MODULES=[ +AbstractController::Rendering, +AbstractController::Translation, +AbstractController::AssetPaths, + +Helpers, +UrlFor, +Redirecting, +ActionView::Layouts, +Rendering, +Renderers::All, +ConditionalGet, +EtagWithTemplateDigest, +EtagWithFlash, +Caching, +MimeResponds, +ImplicitRender, +StrongParameters, +ParameterEncoding, +Cookies, +Flash, +FormBuilder, +RequestForgeryProtection, +ContentSecurityPolicy, +PermissionsPolicy, +Streaming, +DataStreaming, +HttpAuthentication::Basic::ControllerMethods, +HttpAuthentication::Digest::ControllerMethods, +HttpAuthentication::Token::ControllerMethods, +DefaultHeaders, +Logging, + +# Before callbacks should also be executed as early as possible, so +# also include them at the bottom. +AbstractController::Callbacks, + +# Append rescue at the bottom to wrap as much as possible. +Rescue, + +# Add instrumentations hooks at the bottom, to ensure they instrument +# all the methods properly. +Instrumentation, + +# Params wrapper should come before instrumentation so they are +# properly showed in logs +ParamsWrapper +]
 
PROTECTED_IVARS=AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + %i( +@_params @_response @_request @_config @_url_options @_action_has_layout @_view_context_class +@_view_renderer @_lookup_context @_routes @_view_runtime @_db_runtime @_helper_proxy +)
 

Define some internal variables that should not be propagated to the view.

+ + + + + + +

Class Public methods

+ +
+

+ + without_modules(*modules) + +

+ + +
+

Shortcut helper that returns all the modules included in ActionController::Base except the ones passed as arguments:

+ +
class MyBaseController < ActionController::Metal
+  ActionController::Base.without_modules(:ParamsWrapper, :Streaming).each do |left|
+    include left
+  end
+end
+
+ +

This gives better control over what you want to exclude and makes it easier to create a bare controller class, instead of listing the modules required manually.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/base.rb, line 198
+def self.without_modules(*modules)
+  modules = modules.map do |m|
+    m.is_a?(Symbol) ? ActionController.const_get(m) : m
+  end
+
+  MODULES - modules
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + request + +

+ + +
+

Returns an ActionDispatch::Request instance that represents the current request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/base.rb, line 175
+    
+
+
+ +
+ +
+

+ + response + +

+ + +
+

Returns an ActionDispatch::Response that represents the current response.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/base.rb, line 181
+    
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Caching.html b/src/7.0/classes/ActionController/Caching.html new file mode 100644 index 0000000000..af439cd51a --- /dev/null +++ b/src/7.0/classes/ActionController/Caching.html @@ -0,0 +1,94 @@ +--- +title: ActionController::Caching +layout: default +--- +
+ +
+
+ +
+ +

Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls around for subsequent requests.

+ +

You can read more about each approach by clicking the modules below.

+ +

Note: To turn off all caching provided by Action Controller, set

+ +
config.action_controller.perform_caching = false
+
+ +

Caching stores

+ +

All the caching stores from ActiveSupport::Cache are available to be used as backends for Action Controller caching.

+ +

Configuration examples (FileStore is the default):

+ +
config.action_controller.cache_store = :memory_store
+config.action_controller.cache_store = :file_store, '/path/to/cache/directory'
+config.action_controller.cache_store = :mem_cache_store, 'localhost'
+config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new('localhost:11211')
+config.action_controller.cache_store = MyOwnStore.new('parameter')
+
+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ConditionalGet.html b/src/7.0/classes/ActionController/ConditionalGet.html new file mode 100644 index 0000000000..8a575daa13 --- /dev/null +++ b/src/7.0/classes/ActionController/ConditionalGet.html @@ -0,0 +1,546 @@ +--- +title: ActionController::ConditionalGet +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + expires_in(seconds, options = {}) + +

+ + +
+

Sets the Cache-Control header, overwriting existing directives. This method will also ensure an HTTP Date header for client compatibility.

+ +

Defaults to issuing the private directive, so that intermediate caches must not cache the response.

+ +

Options

+
:public +
+

If true, replaces the default private directive with the public directive.

+
:must_revalidate +
+

If true, adds the must-revalidate directive.

+
:stale_while_revalidate +
+

Sets the value of the stale-while-revalidate directive.

+
:stale_if_error +
+

Sets the value of the stale-if-error directive.

+
+ +

Any additional key-value pairs are concatenated as directives. For a list of supported Cache-Control directives, see the article on MDN.

+ +

Examples

+ +
expires_in 10.minutes
+# => Cache-Control: max-age=600, private
+
+expires_in 10.minutes, public: true
+# => Cache-Control: max-age=600, public
+
+expires_in 10.minutes, public: true, must_revalidate: true
+# => Cache-Control: max-age=600, public, must-revalidate
+
+expires_in 1.hour, stale_while_revalidate: 60.seconds
+# => Cache-Control: max-age=3600, private, stale-while-revalidate=60
+
+expires_in 1.hour, stale_if_error: 5.minutes
+# => Cache-Control: max-age=3600, private, stale-if-error=300
+
+expires_in 1.hour, public: true, "s-maxage": 3.hours, "no-transform": true
+# => Cache-Control: max-age=3600, public, s-maxage=10800, no-transform=true
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 274
+def expires_in(seconds, options = {})
+  response.cache_control.delete(:no_store)
+  response.cache_control.merge!(
+    max_age: seconds,
+    public: options.delete(:public),
+    must_revalidate: options.delete(:must_revalidate),
+    stale_while_revalidate: options.delete(:stale_while_revalidate),
+    stale_if_error: options.delete(:stale_if_error),
+  )
+  options.delete(:private)
+
+  response.cache_control[:extras] = options.map { |k, v| "#{k}=#{v}" }
+  response.date = Time.now unless response.date?
+end
+
+
+ +
+ +
+

+ + expires_now() + +

+ + +
+

Sets an HTTP 1.1 Cache-Control header of no-cache. This means the resource will be marked as stale, so clients must always revalidate. Intermediate/browser caches may still store the asset.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 292
+def expires_now
+  response.cache_control.replace(no_cache: true)
+end
+
+
+ +
+ +
+

+ + fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil) + +

+ + +
+

Sets the etag, last_modified, or both on the response, and renders a 304 Not Modified response if the request is already fresh.

+ +

Options

+
:etag +
+

Sets a “weak” ETag validator on the response. See the :weak_etag option.

+
:weak_etag +
+

Sets a “weak” ETag validator on the response. Requests that specify an If-None-Match header may receive a 304 Not Modified response if the ETag matches exactly.

+ +

A weak ETag indicates semantic equivalence, not byte-for-byte equality, so they’re good for caching HTML pages in browser caches. They can’t be used for responses that must be byte-identical, like serving Range requests within a PDF file.

+
:strong_etag +
+

Sets a “strong” ETag validator on the response. Requests that specify an If-None-Match header may receive a 304 Not Modified response if the ETag matches exactly.

+ +

A strong ETag implies exact equality – the response must match byte for byte. This is necessary for serving Range requests within a large video or PDF file, for example, or for compatibility with some CDNs that don’t support weak ETags.

+
:last_modified +
+

Sets a “weak” last-update validator on the response. Subsequent requests that specify an If-Modified-Since header may receive a 304 Not Modified response if last_modified <= If-Modified-Since.

+
:public +
+

By default the Cache-Control header is private. Set this option to true if you want your application to be cacheable by other devices, such as proxy caches.

+
:cache_control +
+

When given, will overwrite an existing Cache-Control header. For a list of Cache-Control directives, see the article on MDN.

+
:template +
+

By default, the template digest for the current controller/action is included in ETags. If the action renders a different template, you can include its digest instead. If the action doesn’t render a template at all, you can pass template: false to skip any attempt to check for a template digest.

+
+ +

Examples

+ +
def show
+  @article = Article.find(params[:id])
+  fresh_when(etag: @article, last_modified: @article.updated_at, public: true)
+end
+
+ +

This will send a 304 Not Modified response if the request specifies a matching ETag and If-Modified-Since header. Otherwise, it will render the show template.

+ +

You can also just pass a record:

+ +
def show
+  @article = Article.find(params[:id])
+  fresh_when(@article)
+end
+
+ +

etag will be set to the record, and last_modified will be set to the record’s updated_at.

+ +

You can also pass an object that responds to maximum, such as a collection of records:

+ +
def index
+  @articles = Article.all
+  fresh_when(@articles)
+end
+
+ +

In this case, etag will be set to the collection, and last_modified will be set to maximum(:updated_at) (the timestamp of the most recently updated record).

+ +

When passing a record or a collection, you can still specify other options, such as :public and :cache_control:

+ +
def show
+  @article = Article.find(params[:id])
+  fresh_when(@article, public: true, cache_control: { no_cache: true })
+end
+
+ +

The above will set Cache-Control: public, no-cache in the response.

+ +

When rendering a different template than the controller/action’s default template, you can indicate which digest to include in the ETag:

+ +
before_action { fresh_when @article, template: "widgets/show" }
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 128
+def fresh_when(object = nil, etag: nil, weak_etag: nil, strong_etag: nil, last_modified: nil, public: false, cache_control: {}, template: nil)
+  response.cache_control.delete(:no_store)
+  weak_etag ||= etag || object unless strong_etag
+  last_modified ||= object.try(:updated_at) || object.try(:maximum, :updated_at)
+
+  if strong_etag
+    response.strong_etag = combine_etags strong_etag,
+      last_modified: last_modified, public: public, template: template
+  elsif weak_etag || template
+    response.weak_etag = combine_etags weak_etag,
+      last_modified: last_modified, public: public, template: template
+  end
+
+  response.last_modified = last_modified if last_modified
+  response.cache_control[:public] = true if public
+  response.cache_control.merge!(cache_control)
+
+  head :not_modified if request.fresh?(response)
+end
+
+
+ +
+ +
+

+ + http_cache_forever(public: false) + +

+ + +
+

Cache or yield the block. The cache is supposed to never expire.

+ +

You can use this method when you have an HTTP response that never changes, and the browser and proxies should cache it indefinitely.

+
  • +

    public: By default, HTTP responses are private, cached only on the user’s web browser. To allow proxies to cache the response, set true to indicate that they can serve the cached response to all users.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 304
+def http_cache_forever(public: false)
+  expires_in 100.years, public: public
+
+  yield if stale?(etag: request.fullpath,
+                  last_modified: Time.new(2011, 1, 1).utc,
+                  public: public)
+end
+
+
+ +
+ +
+

+ + no_store() + +

+ + +
+

Sets an HTTP 1.1 Cache-Control header of no-store. This means the resource may not be stored in any cache.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 314
+def no_store
+  response.cache_control.replace(no_store: true)
+end
+
+
+ +
+ +
+

+ + stale?(object = nil, **freshness_kwargs) + +

+ + +
+

Sets the etag and/or last_modified on the response and checks them against the request. If the request doesn’t match the provided options, it is considered stale, and the response should be rendered from scratch. Otherwise, it is fresh, and a 304 Not Modified is sent.

+ +

Options

+ +

See fresh_when for supported options.

+ +

Examples

+ +
def show
+  @article = Article.find(params[:id])
+
+  if stale?(etag: @article, last_modified: @article.updated_at)
+    @statistics = @article.really_expensive_call
+    respond_to do |format|
+      # all the supported formats
+    end
+  end
+end
+
+ +

You can also just pass a record:

+ +
def show
+  @article = Article.find(params[:id])
+
+  if stale?(@article)
+    @statistics = @article.really_expensive_call
+    respond_to do |format|
+      # all the supported formats
+    end
+  end
+end
+
+ +

etag will be set to the record, and last_modified will be set to the record’s updated_at.

+ +

You can also pass an object that responds to maximum, such as a collection of records:

+ +
def index
+  @articles = Article.all
+
+  if stale?(@articles)
+    @statistics = @articles.really_expensive_call
+    respond_to do |format|
+      # all the supported formats
+    end
+  end
+end
+
+ +

In this case, etag will be set to the collection, and last_modified will be set to maximum(:updated_at) (the timestamp of the most recently updated record).

+ +

When passing a record or a collection, you can still specify other options, such as :public and :cache_control:

+ +
def show
+  @article = Article.find(params[:id])
+
+  if stale?(@article, public: true, cache_control: { no_cache: true })
+    @statistics = @articles.really_expensive_call
+    respond_to do |format|
+      # all the supported formats
+    end
+  end
+end
+
+ +

The above will set Cache-Control: public, no-cache in the response.

+ +

When rendering a different template than the controller/action’s default template, you can indicate which digest to include in the ETag:

+ +
def show
+  super if stale?(@article, template: "widgets/show")
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 227
+def stale?(object = nil, **freshness_kwargs)
+  fresh_when(object, **freshness_kwargs)
+  !request.fresh?(response)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ConditionalGet/ClassMethods.html b/src/7.0/classes/ActionController/ConditionalGet/ClassMethods.html new file mode 100644 index 0000000000..29724a0fbd --- /dev/null +++ b/src/7.0/classes/ActionController/ConditionalGet/ClassMethods.html @@ -0,0 +1,112 @@ +--- +title: ActionController::ConditionalGet::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + etag(&etagger) + +

+ + +
+

Allows you to consider additional controller-wide information when generating an ETag. For example, if you serve pages tailored depending on who’s logged in at the moment, you may want to add the current user id to be part of the ETag to prevent unauthorized displaying of cached pages.

+ +
class InvoicesController < ApplicationController
+  etag { current_user&.id }
+
+  def show
+    # Etag will differ even for the same invoice when it's viewed by a different current_user
+    @invoice = Invoice.find(params[:id])
+    fresh_when etag: @invoice
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/conditional_get.rb, line 31
+def etag(&etagger)
+  self.etaggers += [etagger]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ContentSecurityPolicy.html b/src/7.0/classes/ActionController/ContentSecurityPolicy.html new file mode 100644 index 0000000000..7da79bedd4 --- /dev/null +++ b/src/7.0/classes/ActionController/ContentSecurityPolicy.html @@ -0,0 +1,89 @@ +--- +title: ActionController::ContentSecurityPolicy +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ContentSecurityPolicy/ClassMethods.html b/src/7.0/classes/ActionController/ContentSecurityPolicy/ClassMethods.html new file mode 100644 index 0000000000..b5cc535bdd --- /dev/null +++ b/src/7.0/classes/ActionController/ContentSecurityPolicy/ClassMethods.html @@ -0,0 +1,187 @@ +--- +title: ActionController::ContentSecurityPolicy::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + content_security_policy(enabled = true, **options, &block) + +

+ + +
+

Overrides parts of the globally configured Content-Security-Policy header:

+ +
class PostsController < ApplicationController
+  content_security_policy do |policy|
+    policy.base_uri "https://www.example.com"
+  end
+end
+
+ +

Options can be passed similar to before_action. For example, pass only: :index to override the header on the index action only:

+ +
class PostsController < ApplicationController
+  content_security_policy(only: :index) do |policy|
+    policy.default_src :self, :https
+  end
+end
+
+ +

Pass false to remove the Content-Security-Policy header:

+ +
class PostsController < ApplicationController
+  content_security_policy false, only: :index
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/content_security_policy.rb, line 39
+def content_security_policy(enabled = true, **options, &block)
+  before_action(options) do
+    if block_given?
+      policy = current_content_security_policy
+      yield policy
+      request.content_security_policy = policy
+    end
+
+    unless enabled
+      request.content_security_policy = nil
+    end
+  end
+end
+
+
+ +
+ +
+

+ + content_security_policy_report_only(report_only = true, **options) + +

+ + +
+

Overrides the globally configured Content-Security-Policy-Report-Only header:

+ +
class PostsController < ApplicationController
+  content_security_policy_report_only only: :index
+end
+
+ +

Pass false to remove the Content-Security-Policy-Report-Only header:

+ +
class PostsController < ApplicationController
+  content_security_policy_report_only false, only: :index
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/content_security_policy.rb, line 65
+def content_security_policy_report_only(report_only = true, **options)
+  before_action(options) do
+    request.content_security_policy_report_only = report_only
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Cookies.html b/src/7.0/classes/ActionController/Cookies.html new file mode 100644 index 0000000000..63c43438cc --- /dev/null +++ b/src/7.0/classes/ActionController/Cookies.html @@ -0,0 +1,101 @@ +--- +title: ActionController::Cookies +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Private methods

+ +
+

+ + cookies() + +

+ + +
+

The cookies for the current request. See ActionDispatch::Cookies for more information.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/cookies.rb, line 14
+def cookies # :doc:
+  request.cookie_jar
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/DataStreaming.html b/src/7.0/classes/ActionController/DataStreaming.html new file mode 100644 index 0000000000..46fbce013c --- /dev/null +++ b/src/7.0/classes/ActionController/DataStreaming.html @@ -0,0 +1,232 @@ +--- +title: ActionController::DataStreaming +layout: default +--- +
+ +
+
+ +
+ +

Methods for sending arbitrary data and for streaming files to the browser, instead of rendering.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Private methods

+ +
+

+ + send_data(data, options = {}) + +

+ + +
+

Sends the given binary data to the browser. This method is similar to render plain: data, but also allows you to specify whether the browser should display the response as a file attachment (i.e. in a download dialog) or as inline data. You may also set the content type, the file name, and other things.

+ +

Options:

+
  • +

    :filename - suggests a filename for the browser to use.

    +
  • +

    :type - specifies an HTTP content type. Defaults to application/octet-stream. You can specify either a string or a symbol for a registered type with Mime::Type.register, for example :json. If omitted, type will be inferred from the file extension specified in :filename. If no content type is registered for the extension, the default type application/octet-stream will be used.

    +
  • +

    :disposition - specifies whether the file will be shown inline or downloaded. Valid values are "inline" and "attachment" (default).

    +
  • +

    :status - specifies the status code to send with the response. Defaults to 200.

    +
+ +

Generic data download:

+ +
send_data buffer
+
+ +

Download a dynamically-generated tarball:

+ +
send_data generate_tgz('dir'), filename: 'dir.tgz'
+
+ +

Display an image Active Record in the browser:

+ +
send_data image.data, type: image.content_type, disposition: 'inline'
+
+ +

See send_file for more information on HTTP Content-* headers and caching.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/data_streaming.rb, line 109
+def send_data(data, options = {}) # :doc:
+  send_file_headers! options
+  render options.slice(:status, :content_type).merge(body: data)
+end
+
+
+ +
+ +
+

+ + send_file(path, options = {}) + +

+ + +
+

Sends the file. This uses a server-appropriate method (such as X-Sendfile) via the Rack::Sendfile middleware. The header to use is set via config.action_dispatch.x_sendfile_header. Your server can also configure this for you by setting the X-Sendfile-Type header.

+ +

Be careful to sanitize the path parameter if it is coming from a web page. send_file(params[:path]) allows a malicious user to download any file on your server.

+ +

Options:

+
  • +

    :filename - suggests a filename for the browser to use. Defaults to File.basename(path).

    +
  • +

    :type - specifies an HTTP content type. You can specify either a string or a symbol for a registered type with Mime::Type.register, for example :json. If omitted, the type will be inferred from the file extension specified in :filename. If no content type is registered for the extension, the default type application/octet-stream will be used.

    +
  • +

    :disposition - specifies whether the file will be shown inline or downloaded. Valid values are "inline" and "attachment" (default).

    +
  • +

    :status - specifies the status code to send with the response. Defaults to 200.

    +
  • +

    :url_based_filename - set to true if you want the browser to guess the filename from the URL, which is necessary for i18n filenames on certain browsers (setting :filename overrides this option).

    +
+ +

The default Content-Type and Content-Disposition headers are set to download arbitrary binary files in as many browsers as possible. IE versions 4, 5, 5.5, and 6 are all known to have a variety of quirks (especially when downloading over SSL).

+ +

Simple download:

+ +
send_file '/path/to.zip'
+
+ +

Show a JPEG in the browser:

+ +
send_file '/path/to.jpeg', type: 'image/jpeg', disposition: 'inline'
+
+ +

Show a 404 page in the browser:

+ +
send_file '/path/to/404.html', type: 'text/html; charset=utf-8', disposition: 'inline', status: 404
+
+ +

You can use other Content-* HTTP headers to provide additional information to the client. See MDN for a list of HTTP headers.

+ +

Also be aware that the document may be cached by proxies and browsers. The Pragma and Cache-Control headers declare how the file may be cached by intermediaries. They default to require clients to validate with the server before releasing cached responses. See www.mnot.net/cache_docs/ for an overview of web caching and RFC 9111 for the Cache-Control header spec.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/data_streaming.rb, line 69
+def send_file(path, options = {}) # :doc:
+  raise MissingFile, "Cannot read file #{path}" unless File.file?(path) && File.readable?(path)
+
+  options[:filename] ||= File.basename(path) unless options[:url_based_filename]
+  send_file_headers! options
+
+  self.status = options[:status] || 200
+  self.content_type = options[:content_type] if options.key?(:content_type)
+  response.send_file path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/DefaultHeaders.html b/src/7.0/classes/ActionController/DefaultHeaders.html new file mode 100644 index 0000000000..d49924eb47 --- /dev/null +++ b/src/7.0/classes/ActionController/DefaultHeaders.html @@ -0,0 +1,73 @@ +--- +title: ActionController::DefaultHeaders +layout: default +--- +
+ +
+
+ +
+ +

Allows configuring default headers that will be automatically merged into each response.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/DefaultHeaders/ClassMethods.html b/src/7.0/classes/ActionController/DefaultHeaders/ClassMethods.html new file mode 100644 index 0000000000..dcf3d63eca --- /dev/null +++ b/src/7.0/classes/ActionController/DefaultHeaders/ClassMethods.html @@ -0,0 +1,103 @@ +--- +title: ActionController::DefaultHeaders::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + make_response!(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/default_headers.rb, line 10
+def make_response!(request)
+  ActionDispatch::Response.create.tap do |res|
+    res.request = request
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/EtagWithFlash.html b/src/7.0/classes/ActionController/EtagWithFlash.html new file mode 100644 index 0000000000..23d8973b8b --- /dev/null +++ b/src/7.0/classes/ActionController/EtagWithFlash.html @@ -0,0 +1,74 @@ +--- +title: ActionController::EtagWithFlash +layout: default +--- +
+ +
+
+ +
+ +

When you’re using the flash, it’s generally used as a conditional on the view. This means the content of the view depends on the flash. Which in turn means that the ETag for a response should be computed with the content of the flash in mind. This does that by including the content of the flash as a component in the ETag that’s generated for a response.

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/EtagWithTemplateDigest.html b/src/7.0/classes/ActionController/EtagWithTemplateDigest.html new file mode 100644 index 0000000000..de770b98fd --- /dev/null +++ b/src/7.0/classes/ActionController/EtagWithTemplateDigest.html @@ -0,0 +1,88 @@ +--- +title: ActionController::EtagWithTemplateDigest +layout: default +--- +
+ +
+
+ +
+ +

When our views change, they should bubble up into HTTP cache freshness and bust browser caches. So the template digest for the current action is automatically included in the ETag.

+ +

Enabled by default for apps that use Action View. Disable by setting

+ +
config.action_controller.etag_with_template_digest = false
+
+ +

Override the template to digest by passing :template to fresh_when and stale? calls. For example:

+ +
# We're going to render widgets/show, not posts/show
+fresh_when @post, template: 'widgets/show'
+
+# We're not going to render a template, so omit it from the ETag.
+fresh_when @post, template: false
+
+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Flash.html b/src/7.0/classes/ActionController/Flash.html new file mode 100644 index 0000000000..d4a24dc193 --- /dev/null +++ b/src/7.0/classes/ActionController/Flash.html @@ -0,0 +1,124 @@ +--- +title: ActionController::Flash +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Private methods

+ +
+

+ + redirect_to(options = {}, response_options_and_flash = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/flash.rb, line 51
+def redirect_to(options = {}, response_options_and_flash = {}) # :doc:
+  self.class._flash_types.each do |flash_type|
+    if type = response_options_and_flash.delete(flash_type)
+      flash[flash_type] = type
+    end
+  end
+
+  if other_flashes = response_options_and_flash.delete(:flash)
+    flash.update(other_flashes)
+  end
+
+  super(options, response_options_and_flash)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Flash/ClassMethods.html b/src/7.0/classes/ActionController/Flash/ClassMethods.html new file mode 100644 index 0000000000..5f5c1d8e0a --- /dev/null +++ b/src/7.0/classes/ActionController/Flash/ClassMethods.html @@ -0,0 +1,124 @@ +--- +title: ActionController::Flash::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + add_flash_types(*types) + +

+ + +
+

Creates new flash types. You can pass as many types as you want to create flash types other than the default alert and notice in your controllers and views. For instance:

+ +
# in application_controller.rb
+class ApplicationController < ActionController::Base
+  add_flash_types :warning
+end
+
+# in your controller
+redirect_to user_path(@user), warning: "Incomplete profile"
+
+# in your view
+<%= warning %>
+
+ +

This method will automatically define a new method for each of the given names, and it will be available in your views.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/flash.rb, line 32
+def add_flash_types(*types)
+  types.each do |type|
+    next if _flash_types.include?(type)
+
+    define_method(type) do
+      request.flash[type]
+    end
+    helper_method(type) if respond_to?(:helper_method)
+
+    self._flash_types += [type]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/FormBuilder.html b/src/7.0/classes/ActionController/FormBuilder.html new file mode 100644 index 0000000000..55e876ce41 --- /dev/null +++ b/src/7.0/classes/ActionController/FormBuilder.html @@ -0,0 +1,142 @@ +--- +title: ActionController::FormBuilder +layout: default +--- +
+ +
+
+ +
+ +

Override the default form builder for all views rendered by this controller and any of its descendants. Accepts a subclass of ActionView::Helpers::FormBuilder.

+ +

For example, given a form builder:

+ +
class AdminFormBuilder < ActionView::Helpers::FormBuilder
+  def special_field(name)
+  end
+end
+
+ +

The controller specifies a form builder as its default:

+ +
class AdminAreaController < ApplicationController
+  default_form_builder AdminFormBuilder
+end
+
+ +

Then in the view any form using form_for will be an instance of the specified form builder:

+ +
<%= form_for(@instance) do |builder| %>
+  <%= builder.special_field(:name) %>
+<% end %>
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + default_form_builder() + +

+ + +
+

Default form builder for the controller

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/form_builder.rb, line 46
+def default_form_builder
+  self.class._default_form_builder
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/FormBuilder/ClassMethods.html b/src/7.0/classes/ActionController/FormBuilder/ClassMethods.html new file mode 100644 index 0000000000..ddcfbe68c6 --- /dev/null +++ b/src/7.0/classes/ActionController/FormBuilder/ClassMethods.html @@ -0,0 +1,106 @@ +--- +title: ActionController::FormBuilder::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + default_form_builder(builder) + +

+ + +
+

Set the form builder to be used as the default for all forms in the views rendered by this controller and its subclasses.

+ +

Parameters

+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/form_builder.rb, line 40
+def default_form_builder(builder)
+  self._default_form_builder = builder
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Head.html b/src/7.0/classes/ActionController/Head.html new file mode 100644 index 0000000000..614f0bd213 --- /dev/null +++ b/src/7.0/classes/ActionController/Head.html @@ -0,0 +1,141 @@ +--- +title: ActionController::Head +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + head(status, options = {}) + +

+ + +
+

Returns a response that has no content (merely headers). The options argument is interpreted to be a hash of header names and values. This allows you to easily return a response that consists only of significant headers:

+ +
head :created, location: person_path(@person)
+
+head :created, location: @person
+
+ +

It can also be used to return exceptional conditions:

+ +
return head(:method_not_allowed) unless request.post?
+return head(:bad_request) unless valid_request?
+render
+
+ +

See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list of valid status symbols.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/head.rb, line 21
+def head(status, options = {})
+  if status.is_a?(Hash)
+    raise ArgumentError, "#{status.inspect} is not a valid value for `status`."
+  end
+
+  status ||= :ok
+
+  location = options.delete(:location)
+  content_type = options.delete(:content_type)
+
+  options.each do |key, value|
+    headers[key.to_s.split(/[-_]/).each { |v| v[0] = v[0].upcase }.join("-")] = value.to_s
+  end
+
+  self.status = status
+  self.location = url_for(location) if location
+
+  if include_content?(response_code)
+    unless self.media_type
+      self.content_type = content_type || (Mime[formats.first] if formats) || Mime[:html]
+    end
+
+    response.charset = false
+  end
+
+  self.response_body = ""
+
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Helpers.html b/src/7.0/classes/ActionController/Helpers.html new file mode 100644 index 0000000000..f4fe807e4a --- /dev/null +++ b/src/7.0/classes/ActionController/Helpers.html @@ -0,0 +1,194 @@ +--- +title: ActionController::Helpers +layout: default +--- +
+ +
+
+ +
+ +

The Rails framework provides a large number of helpers for working with assets, dates, forms, numbers and model objects, to name a few. These helpers are available to all templates by default.

+ +

In addition to using the standard template helpers provided, creating custom helpers to extract complicated logic or reusable functionality is strongly encouraged. By default, each controller will include all helpers. These helpers are only accessible on the controller through #helpers

+ +

In previous versions of Rails the controller will include a helper which matches the name of the controller, e.g., MyController will automatically include MyHelper. You can revert to the old behavior with the following:

+ +
# config/application.rb
+class Application < Rails::Application
+  config.action_controller.include_all_helpers = false
+end
+
+ +

Additional helpers can be specified using the helper class method in ActionController::Base or any controller which inherits from it.

+ +

The to_s method from the Time class can be wrapped in a helper method to display a custom message if a Time object is blank:

+ +
module FormattedTimeHelper
+  def format_time(time, format=:long, blank_message="&nbsp;")
+    time.blank? ? blank_message : time.to_fs(format)
+  end
+end
+
+ +

FormattedTimeHelper can now be included in a controller, using the helper class method:

+ +
class EventsController < ActionController::Base
+  helper FormattedTimeHelper
+  def index
+    @events = Event.all
+  end
+end
+
+ +

Then, in any view rendered by EventsController, the format_time method can be called:

+ +
<% @events.each do |event| -%>
+  <p>
+    <%= format_time(event.time, :short, "N/A") %> | <%= event.name %>
+  </p>
+<% end -%>
+
+ +

Finally, assuming we have two event instances, one which has a time and one which does not, the output might look like this:

+ +
23 Aug 11:30 | Carolina Railhawks Soccer Match
+N/A | Carolina Railhawks Training Workshop
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + helpers_path
+ + + + + +

Instance Public methods

+ +
+

+ + helpers() + +

+ + +
+

Provides a proxy to access helper methods from outside the view.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/helpers.rb, line 128
+def helpers
+  @_helper_proxy ||= view_context
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Helpers/ClassMethods.html b/src/7.0/classes/ActionController/Helpers/ClassMethods.html new file mode 100644 index 0000000000..dbd8b0ac50 --- /dev/null +++ b/src/7.0/classes/ActionController/Helpers/ClassMethods.html @@ -0,0 +1,253 @@ +--- +title: ActionController::Helpers::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + all_helpers_from_path(path) + +

+ + +
+

Returns a list of helper names in a given path.

+ +
ActionController::Base.all_helpers_from_path 'app/helpers'
+# => ["application", "chart", "rubygems"]
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/helpers.rb, line 111
+def all_helpers_from_path(path)
+  helpers = Array(path).flat_map do |_path|
+    names = Dir["#{_path}/**/*_helper.rb"].map { |file| file[_path.to_s.size + 1..-"_helper.rb".size - 1] }
+    names.sort!
+  end
+  helpers.uniq!
+  helpers
+end
+
+
+ +
+ +
+

+ + helper_attr(*attrs) + +

+ + +
+

Declares helper accessors for controller attributes. For example, the following adds new name and name= instance methods to a controller and makes them available to the view:

+ +
attr_accessor :name
+helper_attr :name
+
+ +

Parameters

+
  • +

    attrs - Names of attributes to be converted into helpers.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/helpers.rb, line 76
+def helper_attr(*attrs)
+  attrs.flatten.each { |attr| helper_method(attr, "#{attr}=") }
+end
+
+
+ +
+ +
+

+ + helpers() + +

+ + +
+

Provides a proxy to access helper methods from outside the view.

+ +

Note that the proxy is rendered under a different view context. This may cause incorrect behaviour with capture methods. Consider using helper instead when using capture.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/helpers.rb, line 86
+def helpers
+  @helper_proxy ||= begin
+    proxy = ActionView::Base.empty
+    proxy.config = config.inheritable_copy
+    proxy.extend(_helpers)
+  end
+end
+
+
+ +
+ +
+

+ + modules_for_helpers(args) + +

+ + +
+

Override modules_for_helpers to accept :all as argument, which loads all helpers in helpers_path.

+ +

Parameters

+
  • +

    args - A list of helpers

    +
+ +

Returns

+
  • +

    array - A normalized list of modules for the list of helpers provided.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/helpers.rb, line 102
+def modules_for_helpers(args)
+  args += all_application_helpers if args.delete(:all)
+  super(args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication.html b/src/7.0/classes/ActionController/HttpAuthentication.html new file mode 100644 index 0000000000..18002ea3b5 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication.html @@ -0,0 +1,77 @@ +--- +title: ActionController::HttpAuthentication +layout: default +--- +
+ +
+
+ +
+ +

HTTP Basic, Digest, and Token authentication.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Basic.html b/src/7.0/classes/ActionController/HttpAuthentication/Basic.html new file mode 100644 index 0000000000..fa54011960 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Basic.html @@ -0,0 +1,455 @@ +--- +title: ActionController::HttpAuthentication::Basic +layout: default +--- +
+ +
+
+ +
+ +

HTTP Basic authentication

+ +

Simple Basic example

+ +
 class PostsController < ApplicationController
+   http_basic_authenticate_with name: "dhh", password: "secret", except: :index
+
+   def index
+     render plain: "Everyone can see me!"
+   end
+
+   def edit
+     render plain: "I'm only accessible if you know the password"
+   end
+end
+
+ +

Advanced Basic example

+ +

Here is a more advanced Basic example where only Atom feeds and the XML API are protected by HTTP authentication. The regular HTML interface is protected by a session approach:

+ +
class ApplicationController < ActionController::Base
+  before_action :set_account, :authenticate
+
+  private
+    def set_account
+      @account = Account.find_by(url_name: request.subdomains.first)
+    end
+
+    def authenticate
+      case request.format
+      when Mime[:xml], Mime[:atom]
+        if user = authenticate_with_http_basic { |u, p| @account.users.authenticate(u, p) }
+          @current_user = user
+        else
+          request_http_basic_authentication
+        end
+      else
+        if session_authenticated?
+          @current_user = @account.users.find(session[:authenticated][:user_id])
+        else
+          redirect_to(login_url) and return false
+        end
+      end
+    end
+end
+
+ +

In your integration tests, you can do something like this:

+ +
def test_access_granted_from_xml
+  authorization = ActionController::HttpAuthentication::Basic.encode_credentials(users(:dhh).name, users(:dhh).password)
+
+  get "/notes/1.xml", headers: { 'HTTP_AUTHORIZATION' => authorization }
+
+  assert_equal 200, status
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + auth_param(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 127
+def auth_param(request)
+  request.authorization.to_s.split(" ", 2).second
+end
+
+
+ +
+ +
+

+ + auth_scheme(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 123
+def auth_scheme(request)
+  request.authorization.to_s.split(" ", 2).first
+end
+
+
+ +
+ +
+

+ + authenticate(request, &login_procedure) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 105
+def authenticate(request, &login_procedure)
+  if has_basic_credentials?(request)
+    login_procedure.call(*user_name_and_password(request))
+  end
+end
+
+
+ +
+ +
+

+ + authentication_request(controller, realm, message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 135
+def authentication_request(controller, realm, message)
+  message ||= "HTTP Basic: Access denied.\n"
+  controller.headers["WWW-Authenticate"] = %(Basic realm="#{realm.tr('"', "")}")
+  controller.status = 401
+  controller.response_body = message
+end
+
+
+ +
+ +
+

+ + decode_credentials(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 119
+def decode_credentials(request)
+  ::Base64.decode64(auth_param(request) || "")
+end
+
+
+ +
+ +
+

+ + encode_credentials(user_name, password) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 131
+def encode_credentials(user_name, password)
+  "Basic #{::Base64.strict_encode64("#{user_name}:#{password}")}"
+end
+
+
+ +
+ +
+

+ + has_basic_credentials?(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 111
+def has_basic_credentials?(request)
+  request.authorization.present? && (auth_scheme(request).downcase == "basic")
+end
+
+
+ +
+ +
+

+ + user_name_and_password(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 115
+def user_name_and_password(request)
+  decode_credentials(request).split(":", 2)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html b/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html new file mode 100644 index 0000000000..72749001ec --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods.html @@ -0,0 +1,236 @@ +--- +title: ActionController::HttpAuthentication::Basic::ControllerMethods +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + authenticate_or_request_with_http_basic(realm = nil, message = nil, &login_procedure) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 92
+def authenticate_or_request_with_http_basic(realm = nil, message = nil, &login_procedure)
+  authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm || "Application", message)
+end
+
+
+ +
+ +
+

+ + authenticate_with_http_basic(&login_procedure) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 96
+def authenticate_with_http_basic(&login_procedure)
+  HttpAuthentication::Basic.authenticate(request, &login_procedure)
+end
+
+
+ +
+ +
+

+ + http_basic_authenticate_or_request_with(name:, password:, realm: nil, message: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 83
+def http_basic_authenticate_or_request_with(name:, password:, realm: nil, message: nil)
+  authenticate_or_request_with_http_basic(realm, message) do |given_name, given_password|
+    # This comparison uses & so that it doesn't short circuit and
+    # uses `secure_compare` so that length information isn't leaked.
+    ActiveSupport::SecurityUtils.secure_compare(given_name.to_s, name) &
+      ActiveSupport::SecurityUtils.secure_compare(given_password.to_s, password)
+  end
+end
+
+
+ +
+ +
+

+ + request_http_basic_authentication(realm = "Application", message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 100
+def request_http_basic_authentication(realm = "Application", message = nil)
+  HttpAuthentication::Basic.authentication_request(self, realm, message)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods/ClassMethods.html b/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods/ClassMethods.html new file mode 100644 index 0000000000..5d9dc7f04b --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Basic/ControllerMethods/ClassMethods.html @@ -0,0 +1,105 @@ +--- +title: ActionController::HttpAuthentication::Basic::ControllerMethods::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + http_basic_authenticate_with(name:, password:, realm: nil, **options) + +

+ + +
+

Enables HTTP Basic authentication.

+ +

See ActionController::HttpAuthentication::Basic for example usage.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 76
+def http_basic_authenticate_with(name:, password:, realm: nil, **options)
+  raise ArgumentError, "Expected name: to be a String, got #{name.class}" unless name.is_a?(String)
+  raise ArgumentError, "Expected password: to be a String, got #{password.class}" unless password.is_a?(String)
+  before_action(options) { http_basic_authenticate_or_request_with name: name, password: password, realm: realm }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Digest.html b/src/7.0/classes/ActionController/HttpAuthentication/Digest.html new file mode 100644 index 0000000000..e8b45a3f57 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Digest.html @@ -0,0 +1,673 @@ +--- +title: ActionController::HttpAuthentication::Digest +layout: default +--- +
+ +
+
+ +
+ +

HTTP Digest authentication

+ +

Simple Digest example

+ +
require "openssl"
+class PostsController < ApplicationController
+  REALM = "SuperSecret"
+  USERS = {"dhh" => "secret", #plain text password
+           "dap" => OpenSSL::Digest::MD5.hexdigest(["dap",REALM,"secret"].join(":"))}  #ha1 digest password
+
+  before_action :authenticate, except: [:index]
+
+  def index
+    render plain: "Everyone can see me!"
+  end
+
+  def edit
+    render plain: "I'm only accessible if you know the password"
+  end
+
+  private
+    def authenticate
+      authenticate_or_request_with_http_digest(REALM) do |username|
+        USERS[username]
+      end
+    end
+end
+
+ +

Notes

+ +

The authenticate_or_request_with_http_digest block must return the user’s password or the ha1 digest hash so the framework can appropriately hash to check the user’s credentials. Returning nil will cause authentication to fail.

+ +

Storing the ha1 hash: MD5(username:realm:password), is better than storing a plain password. If the password file or database is compromised, the attacker would be able to use the ha1 hash to authenticate as the user at this realm, but would not have the user’s password to try using at other sites.

+ +

In rare instances, web servers or front proxies strip authorization headers before they reach your application. You can debug this situation by logging all environment variables, and check for HTTP_AUTHORIZATION, amongst others.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + authenticate(request, realm, &password_procedure) + +

+ + +
+

Returns false on a valid response, true otherwise.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 211
+def authenticate(request, realm, &password_procedure)
+  request.authorization && validate_digest_response(request, realm, &password_procedure)
+end
+
+
+ +
+ +
+

+ + authentication_header(controller, realm) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 269
+def authentication_header(controller, realm)
+  secret_key = secret_token(controller.request)
+  nonce = self.nonce(secret_key)
+  opaque = opaque(secret_key)
+  controller.headers["WWW-Authenticate"] = %(Digest realm="#{realm}", qop="auth", algorithm=MD5, nonce="#{nonce}", opaque="#{opaque}")
+end
+
+
+ +
+ +
+

+ + authentication_request(controller, realm, message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 276
+def authentication_request(controller, realm, message = nil)
+  message ||= "HTTP Digest: Access denied.\n"
+  authentication_header(controller, realm)
+  controller.status = 401
+  controller.response_body = message
+end
+
+
+ +
+ +
+

+ + decode_credentials(header) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 262
+def decode_credentials(header)
+  ActiveSupport::HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/, "").split(",").map do |pair|
+    key, value = pair.split("=", 2)
+    [key.strip, value.to_s.gsub(/^"|"$/, "").delete("'")]
+  end]
+end
+
+
+ +
+ +
+

+ + decode_credentials_header(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 258
+def decode_credentials_header(request)
+  decode_credentials(request.authorization)
+end
+
+
+ +
+ +
+

+ + encode_credentials(http_method, credentials, password, password_is_ha1) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 253
+def encode_credentials(http_method, credentials, password, password_is_ha1)
+  credentials[:response] = expected_response(http_method, credentials[:uri], credentials, password, password_is_ha1)
+  "Digest " + credentials.sort_by { |x| x[0].to_s }.map { |v| "#{v[0]}='#{v[1]}'" }.join(", ")
+end
+
+
+ +
+ +
+

+ + expected_response(http_method, uri, credentials, password, password_is_ha1 = true) + +

+ + +
+

Returns the expected response for a request of http_method to uri with the decoded credentials and the expected password Optional parameter password_is_ha1 is set to true by default, since best practice is to store ha1 digest instead of a plain-text password.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 243
+def expected_response(http_method, uri, credentials, password, password_is_ha1 = true)
+  ha1 = password_is_ha1 ? password : ha1(credentials, password)
+  ha2 = OpenSSL::Digest::MD5.hexdigest([http_method.to_s.upcase, uri].join(":"))
+  OpenSSL::Digest::MD5.hexdigest([ha1, credentials[:nonce], credentials[:nc], credentials[:cnonce], credentials[:qop], ha2].join(":"))
+end
+
+
+ +
+ +
+

+ + ha1(credentials, password) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 249
+def ha1(credentials, password)
+  OpenSSL::Digest::MD5.hexdigest([credentials[:username], credentials[:realm], password].join(":"))
+end
+
+
+ +
+ +
+

+ + nonce(secret_key, time = Time.now) + +

+ + +
+

Uses an MD5 digest based on time to generate a value to be used only once.

+ +

A server-specified data string which should be uniquely generated each time a 401 response is made. It is recommended that this string be base64 or hexadecimal data. Specifically, since the string is passed in the header lines as a quoted string, the double-quote character is not allowed.

+ +

The contents of the nonce are implementation dependent. The quality of the implementation depends on a good choice. A nonce might, for example, be constructed as the base 64 encoding of

+ +
time-stamp H(time-stamp ":" ETag ":" private-key)
+
+ +

where time-stamp is a server-generated time or other non-repeating value, ETag is the value of the HTTP ETag header associated with the requested entity, and private-key is data known only to the server. With a nonce of this form a server would recalculate the hash portion after receiving the client authentication header and reject the request if it did not match the nonce from that header or if the time-stamp value is not recent enough. In this way the server can limit the time of the nonce’s validity. The inclusion of the ETag prevents a replay request for an updated version of the resource. (Note: including the IP address of the client in the nonce would appear to offer the server the ability to limit the reuse of the nonce to the same client that originally got it. However, that would break proxy farms, where requests from a single user often go through different proxies in the farm. Also, IP address spoofing is not that hard.)

+ +

An implementation might choose not to accept a previously used nonce or a previously used digest, in order to protect against a replay attack. Or, an implementation might choose to use one-time nonces or digests for POST, PUT, or PATCH requests, and a time-stamp for GET requests. For more details on the issues involved see Section 4 of this document.

+ +

The nonce is opaque to the client. Composed of Time, and hash of Time with secret key from the Rails session secret generated upon creation of project. Ensures the time cannot be modified by client.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 321
+def nonce(secret_key, time = Time.now)
+  t = time.to_i
+  hashed = [t, secret_key]
+  digest = OpenSSL::Digest::MD5.hexdigest(hashed.join(":"))
+  ::Base64.strict_encode64("#{t}:#{digest}")
+end
+
+
+ +
+ +
+

+ + opaque(secret_key) + +

+ + +
+

Opaque based on digest of secret key

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 340
+def opaque(secret_key)
+  OpenSSL::Digest::MD5.hexdigest(secret_key)
+end
+
+
+ +
+ +
+

+ + secret_token(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 283
+def secret_token(request)
+  key_generator  = request.key_generator
+  http_auth_salt = request.http_auth_salt
+  key_generator.generate_key(http_auth_salt)
+end
+
+
+ +
+ +
+

+ + validate_digest_response(request, realm, &password_procedure) + +

+ + +
+

Returns false unless the request credentials response value matches the expected value. First try the password as a ha1 digest password. If this fails, then try it as a plain text password.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 218
+def validate_digest_response(request, realm, &password_procedure)
+  secret_key  = secret_token(request)
+  credentials = decode_credentials_header(request)
+  valid_nonce = validate_nonce(secret_key, request, credentials[:nonce])
+
+  if valid_nonce && realm == credentials[:realm] && opaque(secret_key) == credentials[:opaque]
+    password = password_procedure.call(credentials[:username])
+    return false unless password
+
+    method = request.get_header("rack.methodoverride.original_method") || request.get_header("REQUEST_METHOD")
+    uri    = credentials[:uri]
+
+    [true, false].any? do |trailing_question_mark|
+      [true, false].any? do |password_is_ha1|
+        _uri = trailing_question_mark ? uri + "?" : uri
+        expected = expected_response(method, _uri, credentials, password, password_is_ha1)
+        expected == credentials[:response]
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + validate_nonce(secret_key, request, value, seconds_to_timeout = 5 * 60) + +

+ + +
+

Might want a shorter timeout depending on whether the request is a PATCH, PUT, or POST, and if the client is a browser or web service. Can be much shorter if the Stale directive is implemented. This would allow a user to use new nonce without prompting the user again for their username and password.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 333
+def validate_nonce(secret_key, request, value, seconds_to_timeout = 5 * 60)
+  return false if value.nil?
+  t = ::Base64.decode64(value).split(":").first.to_i
+  nonce(secret_key, t) == value && (t - Time.now.to_i).abs <= seconds_to_timeout
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Digest/ControllerMethods.html b/src/7.0/classes/ActionController/HttpAuthentication/Digest/ControllerMethods.html new file mode 100644 index 0000000000..b3b26b3fc5 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Digest/ControllerMethods.html @@ -0,0 +1,181 @@ +--- +title: ActionController::HttpAuthentication::Digest::ControllerMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + authenticate_or_request_with_http_digest(realm = "Application", message = nil, &password_procedure) + +

+ + +
+

Authenticate using an HTTP Digest, or otherwise render an HTTP header requesting the client to send a Digest.

+ +

See ActionController::HttpAuthentication::Digest for example usage.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 193
+def authenticate_or_request_with_http_digest(realm = "Application", message = nil, &password_procedure)
+  authenticate_with_http_digest(realm, &password_procedure) || request_http_digest_authentication(realm, message)
+end
+
+
+ +
+ +
+

+ + authenticate_with_http_digest(realm = "Application", &password_procedure) + +

+ + +
+

Authenticate using an HTTP Digest. Returns true if authentication is successful, false otherwise.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 199
+def authenticate_with_http_digest(realm = "Application", &password_procedure)
+  HttpAuthentication::Digest.authenticate(request, realm, &password_procedure)
+end
+
+
+ +
+ +
+

+ + request_http_digest_authentication(realm = "Application", message = nil) + +

+ + +
+

Render an HTTP header requesting the client to send a Digest for authentication.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 205
+def request_http_digest_authentication(realm = "Application", message = nil)
+  HttpAuthentication::Digest.authentication_request(self, realm, message)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Token.html b/src/7.0/classes/ActionController/HttpAuthentication/Token.html new file mode 100644 index 0000000000..ded57bb8a4 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Token.html @@ -0,0 +1,566 @@ +--- +title: ActionController::HttpAuthentication::Token +layout: default +--- +
+ +
+
+ +
+ +

HTTP Token authentication

+ +

Simple Token example

+ +
class PostsController < ApplicationController
+  TOKEN = "secret"
+
+  before_action :authenticate, except: [ :index ]
+
+  def index
+    render plain: "Everyone can see me!"
+  end
+
+  def edit
+    render plain: "I'm only accessible if you know the password"
+  end
+
+  private
+    def authenticate
+      authenticate_or_request_with_http_token do |token, options|
+        # Compare the tokens in a time-constant manner, to mitigate
+        # timing attacks.
+        ActiveSupport::SecurityUtils.secure_compare(token, TOKEN)
+      end
+    end
+end
+
+ +

Here is a more advanced Token example where only Atom feeds and the XML API are protected by HTTP token authentication. The regular HTML interface is protected by a session approach:

+ +
class ApplicationController < ActionController::Base
+  before_action :set_account, :authenticate
+
+  private
+    def set_account
+      @account = Account.find_by(url_name: request.subdomains.first)
+    end
+
+    def authenticate
+      case request.format
+      when Mime[:xml], Mime[:atom]
+        if user = authenticate_with_http_token { |t, o| @account.users.authenticate(t, o) }
+          @current_user = user
+        else
+          request_http_token_authentication
+        end
+      else
+        if session_authenticated?
+          @current_user = @account.users.find(session[:authenticated][:user_id])
+        else
+          redirect_to(login_url) and return false
+        end
+      end
+    end
+end
+
+ +

In your integration tests, you can do something like this:

+ +
def test_access_granted_from_xml
+  authorization = ActionController::HttpAuthentication::Token.encode_credentials(users(:dhh).token)
+
+  get "/notes/1.xml", headers: { 'HTTP_AUTHORIZATION' => authorization }
+
+  assert_equal 200, status
+end
+
+ +

On shared hosts, Apache sometimes doesn’t pass authentication headers to FCGI instances. If your environment matches this description and you cannot authenticate, try this rule in your Apache setup:

+ +
RewriteRule ^(.*)$ dispatch.fcgi [E=X-HTTP_AUTHORIZATION:%{HTTP:Authorization},QSA,L]
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AUTHN_PAIR_DELIMITERS=/(?:,|;|\t)/
 
TOKEN_KEY="token="
 
TOKEN_REGEX=/^(Token|Bearer)\s+/
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + authenticate(controller, &login_procedure) + +

+ + +
+

If token Authorization header is present, call the login procedure with the present token and options.

+ +

Returns the return value of login_procedure if a token is found. Returns nil if no token is found.

+ +

Parameters

+
  • +

    controller - ActionController::Base instance for the current request.

    +
  • +

    login_procedure - Proc to call if a token is present. The Proc should take two arguments:

    + +
    authenticate(controller) { |token, options| ... }
    +
    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 461
+def authenticate(controller, &login_procedure)
+  token, options = token_and_options(controller.request)
+  unless token.blank?
+    login_procedure.call(token, options)
+  end
+end
+
+
+ +
+ +
+

+ + authentication_request(controller, realm, message = nil) + +

+ + +
+

Sets a WWW-Authenticate header to let the client know a token is desired.

+ +

Returns nothing.

+ +

Parameters

+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 541
+def authentication_request(controller, realm, message = nil)
+  message ||= "HTTP Token: Access denied.\n"
+  controller.headers["WWW-Authenticate"] = %(Token realm="#{realm.tr('"', "")}")
+  controller.__send__ :render, plain: message, status: :unauthorized
+end
+
+
+ +
+ +
+

+ + encode_credentials(token, options = {}) + +

+ + +
+

Encodes the given token and options into an Authorization header value.

+ +

Returns String.

+ +

Parameters

+
  • +

    token - String token.

    +
  • +

    options - Optional Hash of the options.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 526
+def encode_credentials(token, options = {})
+  values = ["#{TOKEN_KEY}#{token.to_s.inspect}"] + options.map do |key, value|
+    "#{key}=#{value.to_s.inspect}"
+  end
+  "Token #{values * ", "}"
+end
+
+
+ +
+ +
+

+ + params_array_from(raw_params) + +

+ + +
+

Takes raw_params and turns it into an array of parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 496
+def params_array_from(raw_params)
+  raw_params.map { |param| param.split %r/=(.+)?/ }
+end
+
+
+ +
+ +
+

+ + raw_params(auth) + +

+ + +
+

This method takes an authorization body and splits up the key-value pairs by the standardized :, ;, or \t delimiters defined in AUTHN_PAIR_DELIMITERS.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 508
+def raw_params(auth)
+  _raw_params = auth.sub(TOKEN_REGEX, "").split(/\s*#{AUTHN_PAIR_DELIMITERS}\s*/)
+
+  if !_raw_params.first&.start_with?(TOKEN_KEY)
+    _raw_params[0] = "#{TOKEN_KEY}#{_raw_params.first}"
+  end
+
+  _raw_params
+end
+
+
+ +
+ +
+

+ + rewrite_param_values(array_params) + +

+ + +
+

This removes the " characters wrapping the value.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 501
+def rewrite_param_values(array_params)
+  array_params.each { |param| (param[1] || +"").gsub! %r/^"|"$/, "" }
+end
+
+
+ +
+ +
+

+ + token_and_options(request) + +

+ + +
+

Parses the token and options out of the token Authorization header. The value for the Authorization header is expected to have the prefix "Token" or "Bearer". If the header looks like this:

+ +
Authorization: Token token="abc", nonce="def"
+
+ +

Then the returned token is "abc", and the options are {nonce: "def"}.

+ +

Returns an Array of [String, Hash] if a token is present. Returns nil if no token is found.

+ +

Parameters

+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 483
+def token_and_options(request)
+  authorization_request = request.authorization.to_s
+  if authorization_request[TOKEN_REGEX]
+    params = token_params_from authorization_request
+    [params.shift[1], Hash[params].with_indifferent_access]
+  end
+end
+
+
+ +
+ +
+

+ + token_params_from(auth) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 491
+def token_params_from(auth)
+  rewrite_param_values params_array_from raw_params auth
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html b/src/7.0/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html new file mode 100644 index 0000000000..3665ec2240 --- /dev/null +++ b/src/7.0/classes/ActionController/HttpAuthentication/Token/ControllerMethods.html @@ -0,0 +1,181 @@ +--- +title: ActionController::HttpAuthentication::Token::ControllerMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + authenticate_or_request_with_http_token(realm = "Application", message = nil, &login_procedure) + +

+ + +
+

Authenticate using an HTTP Bearer token, or otherwise render an HTTP header requesting the client to send a Bearer token.

+ +

See ActionController::HttpAuthentication::Token for example usage.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 430
+def authenticate_or_request_with_http_token(realm = "Application", message = nil, &login_procedure)
+  authenticate_with_http_token(&login_procedure) || request_http_token_authentication(realm, message)
+end
+
+
+ +
+ +
+

+ + authenticate_with_http_token(&login_procedure) + +

+ + +
+

Authenticate using an HTTP Bearer token. Returns true if authentication is successful, false otherwise.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 436
+def authenticate_with_http_token(&login_procedure)
+  Token.authenticate(self, &login_procedure)
+end
+
+
+ +
+ +
+

+ + request_http_token_authentication(realm = "Application", message = nil) + +

+ + +
+

Render an HTTP header requesting the client to send a Bearer token for authentication.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/http_authentication.rb, line 442
+def request_http_token_authentication(realm = "Application", message = nil)
+  Token.authentication_request(self, realm, message)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ImplicitRender.html b/src/7.0/classes/ActionController/ImplicitRender.html new file mode 100644 index 0000000000..4b5c7aaca8 --- /dev/null +++ b/src/7.0/classes/ActionController/ImplicitRender.html @@ -0,0 +1,72 @@ +--- +title: ActionController::ImplicitRender +layout: default +--- +
+ +
+
+ +
+ +

Handles implicit rendering for a controller action that does not explicitly respond with render, respond_to, redirect, or head.

+ +

For API controllers, the implicit response is always 204 No Content.

+ +

For all other controllers, we use these heuristics to decide whether to render a template, raise an error for a missing template, or respond with 204 No Content:

+ +

First, if we DO find a template, it’s rendered. Template lookup accounts for the action name, locales, format, variant, template handlers, and more (see render for details).

+ +

Second, if we DON’T find a template but the controller action does have templates for other formats, variants, etc., then we trust that you meant to provide a template for this response, too, and we raise ActionController::UnknownFormat with an explanation.

+ +

Third, if we DON’T find a template AND the request is a page load in a web browser (technically, a non-XHR GET request for an HTML response) where you reasonably expect to have rendered a template, then we raise ActionController::MissingExactTemplate with an explanation.

+ +

Finally, if we DON’T find a template AND the request isn’t a browser page load, then we implicitly respond with 204 No Content.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Instrumentation.html b/src/7.0/classes/ActionController/Instrumentation.html new file mode 100644 index 0000000000..fa0e663821 --- /dev/null +++ b/src/7.0/classes/ActionController/Instrumentation.html @@ -0,0 +1,339 @@ +--- +title: ActionController::Instrumentation +layout: default +--- +
+ +
+
+ +
+ +

Adds instrumentation to several ends in ActionController::Base. It also provides some hooks related with process_action. This allows an ORM like Active Record and/or DataMapper to plug in ActionController and show related information.

+ +

Check ActiveRecord::Railties::ControllerRuntime for an example.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + redirect_to(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 40
+def redirect_to(*)
+  ActiveSupport::Notifications.instrument("redirect_to.action_controller", request: request) do |payload|
+    result = super
+    payload[:status]   = response.status
+    payload[:location] = response.filtered_location
+    result
+  end
+end
+
+
+ +
+ +
+

+ + render(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 19
+def render(*)
+  render_output = nil
+  self.view_runtime = cleanup_view_runtime do
+    Benchmark.ms { render_output = super }
+  end
+  render_output
+end
+
+
+ +
+ +
+

+ + send_data(data, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 34
+def send_data(data, options = {})
+  ActiveSupport::Notifications.instrument("send_data.action_controller", options) do
+    super
+  end
+end
+
+
+ +
+ +
+

+ + send_file(path, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 27
+def send_file(path, options = {})
+  ActiveSupport::Notifications.instrument("send_file.action_controller",
+    options.merge(path: path)) do
+    super
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + append_info_to_payload(payload) + +

+ + +
+

Every time after an action is processed, this method is invoked with the payload, so you can add more information.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 96
+def append_info_to_payload(payload) # :doc:
+  payload[:view_runtime] = view_runtime
+end
+
+
+ +
+ +
+

+ + cleanup_view_runtime() + +

+ + +
+

A hook which allows you to clean up any time, wrongly taken into account in views, like database querying time.

+ +
def cleanup_view_runtime
+  super - time_taken_in_something_expensive
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/instrumentation.rb, line 90
+def cleanup_view_runtime # :doc:
+  yield
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Instrumentation/ClassMethods.html b/src/7.0/classes/ActionController/Instrumentation/ClassMethods.html new file mode 100644 index 0000000000..0d0d61281d --- /dev/null +++ b/src/7.0/classes/ActionController/Instrumentation/ClassMethods.html @@ -0,0 +1,54 @@ +--- +title: ActionController::Instrumentation::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Live.html b/src/7.0/classes/ActionController/Live.html new file mode 100644 index 0000000000..d52f8982c5 --- /dev/null +++ b/src/7.0/classes/ActionController/Live.html @@ -0,0 +1,303 @@ +--- +title: ActionController::Live +layout: default +--- +
+ +
+
+ +
+ +

Mix this module into your controller, and all actions in that controller will be able to stream data to the client as it’s written.

+ +
class MyController < ActionController::Base
+  include ActionController::Live
+
+  def stream
+    response.headers['Content-Type'] = 'text/event-stream'
+    100.times {
+      response.stream.write "hello world\n"
+      sleep 1
+    }
+  ensure
+    response.stream.close
+  end
+end
+
+ +

There are a few caveats with this module. You cannot write headers after the response has been committed (Response#committed? will return truthy). Calling write or close on the response stream will cause the response object to be committed. Make sure all headers are set before calling write or close on your stream.

+ +

You must call close on your stream when you’re finished, otherwise the socket may be left open forever.

+ +

The final caveat is that your actions are executed in a separate thread than the main thread. Make sure your actions are thread safe, and this shouldn’t be a problem (don’t share state across threads, etc).

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + process(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 249
+def process(name)
+  t1 = Thread.current
+  locals = t1.keys.map { |key| [key, t1[key]] }
+
+  error = nil
+  # This processes the action in a child thread. It lets us return the
+  # response code and headers back up the Rack stack, and still process
+  # the body in parallel with sending data to the client.
+  new_controller_thread {
+    ActiveSupport::Dependencies.interlock.running do
+      t2 = Thread.current
+
+      # Since we're processing the view in a different thread, copy the
+      # thread locals from the main thread to the child thread. :'(
+      locals.each { |k, v| t2[k] = v }
+      ActiveSupport::IsolatedExecutionState.share_with(t1)
+
+      begin
+        super(name)
+      rescue => e
+        if @_response.committed?
+          begin
+            @_response.stream.write(ActionView::Base.streaming_completion_on_exception) if request.format == :html
+            @_response.stream.call_on_error
+          rescue => exception
+            log_error(exception)
+          ensure
+            log_error(e)
+            @_response.stream.close
+          end
+        else
+          error = e
+        end
+      ensure
+        @_response.commit!
+      end
+    end
+  }
+
+  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+    @_response.await_commit
+  end
+
+  raise error if error
+end
+
+
+ +
+ +
+

+ + response_body=(body) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 295
+def response_body=(body)
+  super
+  response.close if response
+end
+
+
+ +
+ +
+

+ + send_stream(filename:, disposition: "attachment", type: nil) + +

+ + +
+

Sends a stream to the browser, which is helpful when you’re generating exports or other running data where you don’t want the entire file buffered in memory first. Similar to send_data, but where the data is generated live.

+ +

Options:

+
  • +

    :filename - suggests a filename for the browser to use.

    +
  • +

    :type - specifies an HTTP content type. You can specify either a string or a symbol for a registered type with Mime::Type.register, for example :json. If omitted, type will be inferred from the file extension specified in :filename. If no content type is registered for the extension, the default type ‘application/octet-stream’ will be used.

    +
  • +

    :disposition - specifies whether the file will be shown inline or downloaded. Valid values are ‘inline’ and ‘attachment’ (default).

    +
+ +

Example of generating a csv export:

+ +
send_stream(filename: "subscribers.csv") do |stream|
+  stream.write "email_address,updated_at\n"
+
+  @subscribers.find_each do |subscriber|
+    stream.write "#{subscriber.email_address},#{subscriber.updated_at}\n"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 321
+def send_stream(filename:, disposition: "attachment", type: nil)
+  response.headers["Content-Type"] =
+    (type.is_a?(Symbol) ? Mime[type].to_s : type) ||
+    Mime::Type.lookup_by_extension(File.extname(filename).downcase.delete("."))&.to_s ||
+    "application/octet-stream"
+
+  response.headers["Content-Disposition"] =
+    ActionDispatch::Http::ContentDisposition.format(disposition: disposition, filename: filename)
+
+  yield response.stream
+ensure
+  response.stream.close
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Live/ClassMethods.html b/src/7.0/classes/ActionController/Live/ClassMethods.html new file mode 100644 index 0000000000..41f42d69d4 --- /dev/null +++ b/src/7.0/classes/ActionController/Live/ClassMethods.html @@ -0,0 +1,107 @@ +--- +title: ActionController::Live::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + make_response!(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 41
+def make_response!(request)
+  if request.get_header("HTTP_VERSION") == "HTTP/1.0"
+    super
+  else
+    Live::Response.new.tap do |res|
+      res.request = request
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Live/ClientDisconnected.html b/src/7.0/classes/ActionController/Live/ClientDisconnected.html new file mode 100644 index 0000000000..8c6200ecb4 --- /dev/null +++ b/src/7.0/classes/ActionController/Live/ClientDisconnected.html @@ -0,0 +1,60 @@ +--- +title: ActionController::Live::ClientDisconnected +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Live/SSE.html b/src/7.0/classes/ActionController/Live/SSE.html new file mode 100644 index 0000000000..6b39bc5926 --- /dev/null +++ b/src/7.0/classes/ActionController/Live/SSE.html @@ -0,0 +1,250 @@ +--- +title: ActionController::Live::SSE +layout: default +--- +
+ +
+
+ +
+ +

This class provides the ability to write an SSE (Server Sent Event) to an IO stream. The class is initialized with a stream and can be used to either write a JSON string or an object which can be converted to JSON.

+ +

Writing an object will convert it into standard SSE format with whatever options you have configured. You may choose to set the following options:

+ +
1) Event. If specified, an event with this name will be dispatched on
+the browser.
+2) Retry. The reconnection time in milliseconds used when attempting
+to send the event.
+3) Id. If the connection dies while sending an SSE to the browser, then
+the server will receive a +Last-Event-ID+ header with value equal to +id+.
+
+ +

After setting an option in the constructor of the SSE object, all future SSEs sent across the stream will use those options unless overridden.

+ +

Example Usage:

+ +
class MyController < ActionController::Base
+  include ActionController::Live
+
+  def index
+    response.headers['Content-Type'] = 'text/event-stream'
+    sse = SSE.new(response.stream, retry: 300, event: "event-name")
+    sse.write({ name: 'John'})
+    sse.write({ name: 'John'}, id: 10)
+    sse.write({ name: 'John'}, id: 10, event: "other-event")
+    sse.write({ name: 'John'}, id: 10, event: "other-event", retry: 500)
+  ensure
+    sse.close
+  end
+end
+
+ +

Note: SSEs are not currently supported by IE. However, they are supported by Chrome, Firefox, Opera, and Safari.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PERMITTED_OPTIONS=%w( retry event id )
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(stream, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 91
+def initialize(stream, options = {})
+  @stream = stream
+  @options = options
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + close() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 96
+def close
+  @stream.close
+end
+
+
+ +
+ +
+

+ + write(object, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/live.rb, line 100
+def write(object, options = {})
+  case object
+  when String
+    perform_write(object, options)
+  else
+    perform_write(ActiveSupport::JSON.encode(object), options)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/LiveTestResponse.html b/src/7.0/classes/ActionController/LiveTestResponse.html new file mode 100644 index 0000000000..45f932868c --- /dev/null +++ b/src/7.0/classes/ActionController/LiveTestResponse.html @@ -0,0 +1,60 @@ +--- +title: ActionController::LiveTestResponse +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/LogSubscriber.html b/src/7.0/classes/ActionController/LogSubscriber.html new file mode 100644 index 0000000000..14a77d06ab --- /dev/null +++ b/src/7.0/classes/ActionController/LogSubscriber.html @@ -0,0 +1,428 @@ +--- +title: ActionController::LogSubscriber +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
INTERNAL_PARAMS=%w(controller action format _method only_path)
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + halted_callback(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 40
+def halted_callback(event)
+  info { "Filter chain halted as #{event.payload[:filter].inspect} rendered or redirected" }
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 76
+def logger
+  ActionController::Base.logger
+end
+
+
+ +
+ +
+

+ + process_action(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 20
+def process_action(event)
+  info do
+    payload = event.payload
+    additions = ActionController::Base.log_process_action(payload)
+    status = payload[:status]
+
+    if status.nil? && (exception_class_name = payload[:exception]&.first)
+      status = ActionDispatch::ExceptionWrapper.status_code_for_exception(exception_class_name)
+    end
+
+    additions << "Allocations: #{event.allocations}"
+
+    message = +"Completed #{status} #{Rack::Utils::HTTP_STATUS_CODES[status]} in #{event.duration.round}ms"
+    message << " (#{additions.join(" | ")})"
+    message << "\n\n" if defined?(Rails.env) && Rails.env.development?
+
+    message
+  end
+end
+
+
+ +
+ +
+

+ + redirect_to(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 48
+def redirect_to(event)
+  info { "Redirected to #{event.payload[:location]}" }
+end
+
+
+ +
+ +
+

+ + send_data(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 52
+def send_data(event)
+  info { "Sent data #{event.payload[:filename]} (#{event.duration.round(1)}ms)" }
+end
+
+
+ +
+ +
+

+ + send_file(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 44
+def send_file(event)
+  info { "Sent file #{event.payload[:path]} (#{event.duration.round(1)}ms)" }
+end
+
+
+ +
+ +
+

+ + start_processing(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 7
+def start_processing(event)
+  return unless logger.info?
+
+  payload = event.payload
+  params  = payload[:params].except(*INTERNAL_PARAMS)
+  format  = payload[:format]
+  format  = format.to_s.upcase if format.is_a?(Symbol)
+  format  = "*/*" if format.nil?
+
+  info "Processing by #{payload[:controller]}##{payload[:action]} as #{format}"
+  info "  Parameters: #{params.inspect}" unless params.empty?
+end
+
+
+ +
+ +
+

+ + unpermitted_parameters(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/log_subscriber.rb, line 56
+def unpermitted_parameters(event)
+  debug do
+    unpermitted_keys = event.payload[:keys]
+    display_unpermitted_keys = unpermitted_keys.map { |e| ":#{e}" }.join(", ")
+    context = event.payload[:context].map { |k, v| "#{k}: #{v}" }.join(", ")
+    color("Unpermitted parameter#{'s' if unpermitted_keys.size > 1}: #{display_unpermitted_keys}. Context: { #{context} }", RED)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Logging.html b/src/7.0/classes/ActionController/Logging.html new file mode 100644 index 0000000000..15d4d312ff --- /dev/null +++ b/src/7.0/classes/ActionController/Logging.html @@ -0,0 +1,67 @@ +--- +title: ActionController::Logging +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Logging/ClassMethods.html b/src/7.0/classes/ActionController/Logging/ClassMethods.html new file mode 100644 index 0000000000..dfa989c3a8 --- /dev/null +++ b/src/7.0/classes/ActionController/Logging/ClassMethods.html @@ -0,0 +1,107 @@ +--- +title: ActionController::Logging::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + log_at(level, **options) + +

+ + +
+

Set a different log level per request.

+ +
# Use the debug log level if a particular cookie is set.
+class ApplicationController < ActionController::Base
+  log_at :debug, if: -> { cookies[:debug] }
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/logging.rb, line 15
+def log_at(level, **options)
+  around_action ->(_, action) { logger.log_at(level, &action) }, **options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Metal.html b/src/7.0/classes/ActionController/Metal.html new file mode 100644 index 0000000000..ce32b85768 --- /dev/null +++ b/src/7.0/classes/ActionController/Metal.html @@ -0,0 +1,702 @@ +--- +title: ActionController::Metal +layout: default +--- +
+ +
+
+ +
+ +

ActionController::Metal is the simplest possible controller, providing a valid Rack interface without the additional niceties provided by ActionController::Base.

+ +

A sample metal controller might look like this:

+ +
class HelloController < ActionController::Metal
+  def index
+    self.response_body = "Hello World!"
+  end
+end
+
+ +

And then to route requests to your metal controller, you would add something like this to config/routes.rb:

+ +
get 'hello', to: HelloController.action(:index)
+
+ +

The action method returns a valid Rack application for the Rails router to dispatch to.

+ +

Rendering Helpers

+ +

ActionController::Metal by default provides no utilities for rendering views, partials, or other responses aside from explicitly calling of response_body=, content_type=, and status=. To add the render helpers you’re used to having in a normal controller, you can do the following:

+ +
class HelloController < ActionController::Metal
+  include AbstractController::Rendering
+  include ActionView::Layouts
+  append_view_path "#{Rails.root}/app/views"
+
+  def index
+    render "hello/index"
+  end
+end
+
+ +

Redirection Helpers

+ +

To add redirection helpers to your metal controller, do the following:

+ +
class HelloController < ActionController::Metal
+  include ActionController::Redirecting
+  include Rails.application.routes.url_helpers
+
+  def index
+    redirect_to root_url
+  end
+end
+
+ +

Other Helpers

+ +

You can refer to the modules included in ActionController::Base to see other features you can bring into your metal controller.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + action(name) + +

+ + +
+

Returns a Rack endpoint for the given action name.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 231
+def self.action(name)
+  app = lambda { |env|
+    req = ActionDispatch::Request.new(env)
+    res = make_response! req
+    new.dispatch(name, req, res)
+  }
+
+  if middleware_stack.any?
+    middleware_stack.build(name, app)
+  else
+    app
+  end
+end
+
+
+ +
+ +
+

+ + controller_name() + +

+ + +
+

Returns the last part of the controller’s name, underscored, without the ending Controller. For instance, PostsController returns posts. Namespaces are left out, so Admin::PostsController returns posts as well.

+ +

Returns

+
  • +

    string

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 126
+def self.controller_name
+  @controller_name ||= (name.demodulize.delete_suffix("Controller").underscore unless anonymous?)
+end
+
+
+ +
+ +
+

+ + dispatch(name, req, res) + +

+ + +
+

Direct dispatch to the controller. Instantiates the controller, then executes the action named name.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 247
+def self.dispatch(name, req, res)
+  if middleware_stack.any?
+    middleware_stack.build(name) { |env| new.dispatch(name, req, res) }.call req.env
+  else
+    new.dispatch(name, req, res)
+  end
+end
+
+
+ +
+ +
+

+ + make_response!(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 130
+def self.make_response!(request)
+  ActionDispatch::Response.new.tap do |res|
+    res.request = request
+  end
+end
+
+
+ +
+ +
+

+ + middleware() + +

+ + +
+

Alias for middleware_stack.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 226
+def self.middleware
+  middleware_stack
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 150
+def initialize
+  @_request = nil
+  @_response = nil
+  @_routes = nil
+  super
+end
+
+
+ +
+ +
+

+ + use(...) + +

+ + +
+

Pushes the given Rack middleware and its arguments to the bottom of the middleware stack.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 220
+def use(...)
+  middleware_stack.use(...)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + controller_name() + +

+ + +
+

Delegates to the class’s ::controller_name.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 141
+def controller_name
+  self.class.controller_name
+end
+
+
+ +
+ +
+

+ + params() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 157
+def params
+  @_params ||= request.parameters
+end
+
+
+ +
+ +
+

+ + params=(val) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 161
+def params=(val)
+  @_params = val
+end
+
+
+ +
+ +
+

+ + performed?() + +

+ + +
+

Tests if render or redirect has already happened.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 181
+def performed?
+  response_body || response.committed?
+end
+
+
+ +
+ +
+

+ + reset_session() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 206
+def reset_session
+  @_request.reset_session
+end
+
+
+ +
+ +
+

+ + response_body=(body) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 172
+def response_body=(body)
+  body = [body] unless body.nil? || body.respond_to?(:each)
+  response.reset_body!
+  return unless body
+  response.body = body
+  super
+end
+
+
+ +
+ +
+

+ + url_for(string) + +

+ + +
+

Basic url_for that can be overridden for more robust functionality.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal.rb, line 168
+def url_for(string)
+  string
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/MimeResponds.html b/src/7.0/classes/ActionController/MimeResponds.html new file mode 100644 index 0000000000..df0ba53a7a --- /dev/null +++ b/src/7.0/classes/ActionController/MimeResponds.html @@ -0,0 +1,326 @@ +--- +title: ActionController::MimeResponds +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + respond_to(*mimes) + +

+ + +
+

Without web-service support, an action which collects the data for displaying a list of people might look something like this:

+ +
def index
+  @people = Person.all
+end
+
+ +

That action implicitly responds to all formats, but formats can also be explicitly enumerated:

+ +
def index
+  @people = Person.all
+  respond_to :html, :js
+end
+
+ +

Here’s the same action, with web-service support baked in:

+ +
def index
+  @people = Person.all
+
+  respond_to do |format|
+    format.html
+    format.js
+    format.xml { render xml: @people }
+  end
+end
+
+ +

What that says is, “if the client wants HTML or JS in response to this action, just respond as we would have before, but if the client wants XML, return them the list of people in XML format.” (Rails determines the desired response format from the HTTP Accept header submitted by the client.)

+ +

Supposing you have an action that adds a new person, optionally creating their company (by name) if it does not already exist, without web-services, it might look like this:

+ +
def create
+  @company = Company.find_or_create_by(name: params[:company][:name])
+  @person  = @company.people.create(params[:person])
+
+  redirect_to(person_list_url)
+end
+
+ +

Here’s the same action, with web-service support baked in:

+ +
def create
+  company  = params[:person].delete(:company)
+  @company = Company.find_or_create_by(name: company[:name])
+  @person  = @company.people.create(params[:person])
+
+  respond_to do |format|
+    format.html { redirect_to(person_list_url) }
+    format.js
+    format.xml  { render xml: @person.to_xml(include: @company) }
+  end
+end
+
+ +

If the client wants HTML, we just redirect them back to the person list. If they want JavaScript, then it is an Ajax request and we render the JavaScript template associated with this action. Lastly, if the client wants XML, we render the created person as XML, but with a twist: we also include the person’s company in the rendered XML, so you get something like this:

+ +
<person>
+  <id>...</id>
+  ...
+  <company>
+    <id>...</id>
+    <name>...</name>
+    ...
+  </company>
+</person>
+
+ +

Note, however, the extra bit at the top of that action:

+ +
company  = params[:person].delete(:company)
+@company = Company.find_or_create_by(name: company[:name])
+
+ +

This is because the incoming XML document (if a web-service request is in process) can only contain a single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):

+ +
person[name]=...&person[company][name]=...&...
+
+ +

And, like this (xml-encoded):

+ +
<person>
+  <name>...</name>
+  <company>
+    <name>...</name>
+  </company>
+</person>
+
+ +

In other words, we make the request so that it operates on a single entity’s person. Then, in the action, we extract the company data from the request, find or create the company, and then create the new person with the remaining data.

+ +

Note that you can define your own XML parameter parser which would allow you to describe multiple entities in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow and accept Rails’ defaults, life will be much easier.

+ +

If you need to use a MIME type which isn’t supported by default, you can register your own handlers in config/initializers/mime_types.rb as follows.

+ +
Mime::Type.register "image/jpeg", :jpg
+
+ +

respond_to also allows you to specify a common block for different formats by using any:

+ +
def index
+  @people = Person.all
+
+  respond_to do |format|
+    format.html
+    format.any(:xml, :json) { render request.format.to_sym => @people }
+  end
+end
+
+ +

In the example above, if the format is xml, it will render:

+ +
render xml: @people
+
+ +

Or if the format is json:

+ +
render json: @people
+
+ +

any can also be used with no arguments, in which case it will be used for any format requested by the user:

+ +
respond_to do |format|
+  format.html
+  format.any { redirect_to support_path }
+end
+
+ +

Formats can have different variants.

+ +

The request variant is a specialization of the request format, like :tablet, :phone, or :desktop.

+ +

We often want to render different html/json/xml templates for phones, tablets, and desktop browsers. Variants make it easy.

+ +

You can set the variant in a before_action:

+ +
request.variant = :tablet if /iPad/.match?(request.user_agent)
+
+ +

Respond to variants in the action just like you respond to formats:

+ +
respond_to do |format|
+  format.html do |variant|
+    variant.tablet # renders app/views/projects/show.html+tablet.erb
+    variant.phone { extra_setup; render ... }
+    variant.none  { special_setup } # executed only if there is no variant set
+  end
+end
+
+ +

Provide separate templates for each format and variant:

+ +
app/views/projects/show.html.erb
+app/views/projects/show.html+tablet.erb
+app/views/projects/show.html+phone.erb
+
+ +

When you’re not sharing any code within the format, you can simplify defining variants using the inline syntax:

+ +
respond_to do |format|
+  format.js         { render "trash" }
+  format.html.phone { redirect_to progress_path }
+  format.html.none  { render "trash" }
+end
+
+ +

Variants also support common any/all block that formats have.

+ +

It works for both inline:

+ +
respond_to do |format|
+  format.html.any   { render html: "any"   }
+  format.html.phone { render html: "phone" }
+end
+
+ +

and block syntax:

+ +
respond_to do |format|
+  format.html do |variant|
+    variant.any(:tablet, :phablet){ render html: "any" }
+    variant.phone { render html: "phone" }
+  end
+end
+
+ +

You can also set an array of variants:

+ +
request.variant = [:tablet, :phone]
+
+ +

This will work similarly to formats and MIME types negotiation. If there is no :tablet variant declared, the :phone variant will be used:

+ +
respond_to do |format|
+  format.html.none
+  format.html.phone # this gets rendered
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 201
+def respond_to(*mimes)
+  raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
+
+  collector = Collector.new(mimes, request.variant)
+  yield collector if block_given?
+
+  if format = collector.negotiate_format(request)
+    if media_type && media_type != format
+      raise ActionController::RespondToMismatchError
+    end
+    _process_format(format)
+    _set_rendered_content_type(format) unless collector.any_response?
+    response = collector.response
+    response.call if response
+  else
+    raise ActionController::UnknownFormat
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/MimeResponds/Collector.html b/src/7.0/classes/ActionController/MimeResponds/Collector.html new file mode 100644 index 0000000000..1efa783feb --- /dev/null +++ b/src/7.0/classes/ActionController/MimeResponds/Collector.html @@ -0,0 +1,404 @@ +--- +title: ActionController::MimeResponds::Collector +layout: default +--- +
+ +
+
+ +
+ +

A container for responses available from the current controller for requests for different mime-types sent to a particular action.

+ +

The public controller methods respond_to may be called with a block that is used to define responses to different mime-types, e.g. for respond_to :

+ +
respond_to do |format|
+  format.html
+  format.xml { render xml: @people }
+end
+
+ +

In this usage, the argument passed to the block (format above) is an instance of the ActionController::MimeResponds::Collector class. This object serves as a container in which available responses can be stored by calling any of the dynamically generated, mime-type-specific methods such as html, xml etc on the Collector. Each response is represented by a corresponding block if present.

+ +

A subsequent call to negotiate_format(request) will enable the Collector to determine which specific mime-type it should respond with for the current request, with this response then being accessible by calling response.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + format
+ + + + +

Class Public methods

+ +
+

+ + new(mimes, variant = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 246
+def initialize(mimes, variant = nil)
+  @responses = {}
+  @variant = variant
+
+  mimes.each { |mime| @responses[Mime[mime]] = nil }
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + all(*args, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: any +
+ + + +
+ +
+

+ + any(*args, &block) + +

+ + +
+ +
+ + + +
+ Also aliased as: all +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 253
+def any(*args, &block)
+  if args.any?
+    args.each { |type| send(type, &block) }
+  else
+    custom(Mime::ALL, &block)
+  end
+end
+
+
+ +
+ +
+

+ + any_response?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 271
+def any_response?
+  !@responses.fetch(format, false) && @responses[Mime::ALL]
+end
+
+
+ +
+ +
+

+ + custom(mime_type, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 262
+def custom(mime_type, &block)
+  mime_type = Mime::Type.lookup(mime_type.to_s) unless mime_type.is_a?(Mime::Type)
+  @responses[mime_type] ||= if block_given?
+    block
+  else
+    VariantCollector.new(@variant)
+  end
+end
+
+
+ +
+ +
+

+ + negotiate_format(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 288
+def negotiate_format(request)
+  @format = request.negotiate_mime(@responses.keys)
+end
+
+
+ +
+ +
+

+ + response() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/mime_responds.rb, line 275
+def response
+  response = @responses.fetch(format, @responses[Mime::ALL])
+  if response.is_a?(VariantCollector) # `format.html.phone` - variant inline syntax
+    response.variant
+  elsif response.nil? || response.arity == 0 # `format.html` - just a format, call its block
+    response
+  else # `format.html{ |variant| variant.phone }` - variant block syntax
+    variant_collector = VariantCollector.new(@variant)
+    response.call(variant_collector) # call format block with variants collector
+    variant_collector.variant
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/MissingRenderer.html b/src/7.0/classes/ActionController/MissingRenderer.html new file mode 100644 index 0000000000..2279fdc364 --- /dev/null +++ b/src/7.0/classes/ActionController/MissingRenderer.html @@ -0,0 +1,113 @@ +--- +title: ActionController::MissingRenderer +layout: default +--- +
+ +
+
+ +
+ +

See Responder#api_behavior

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(format) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 18
+def initialize(format)
+  super "No renderer defined for format: #{format}"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParameterEncoding.html b/src/7.0/classes/ActionController/ParameterEncoding.html new file mode 100644 index 0000000000..aaaa6560cd --- /dev/null +++ b/src/7.0/classes/ActionController/ParameterEncoding.html @@ -0,0 +1,73 @@ +--- +title: ActionController::ParameterEncoding +layout: default +--- +
+ +
+
+ +
+ +

Specify binary encoding for parameters for a given action.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParameterEncoding/ClassMethods.html b/src/7.0/classes/ActionController/ParameterEncoding/ClassMethods.html new file mode 100644 index 0000000000..04aff924ea --- /dev/null +++ b/src/7.0/classes/ActionController/ParameterEncoding/ClassMethods.html @@ -0,0 +1,182 @@ +--- +title: ActionController::ParameterEncoding::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + param_encoding(action, param, encoding) + +

+ + +
+

Specify the encoding for a parameter on an action. If not specified the default is UTF-8.

+ +

You can specify a binary (ASCII_8BIT) parameter with:

+ +
class RepositoryController < ActionController::Base
+  # This specifies that file_path is not UTF-8 and is instead ASCII_8BIT
+  param_encoding :show, :file_path, Encoding::ASCII_8BIT
+
+  def show
+    @repo = Repository.find_by_filesystem_path params[:file_path]
+
+    # params[:repo_name] remains UTF-8 encoded
+    @repo_name = params[:repo_name]
+  end
+
+  def index
+    @repositories = Repository.all
+  end
+end
+
+ +

The file_path parameter on the show action would be encoded as ASCII-8BIT, but all other arguments will remain UTF-8 encoded. This is useful in the case where an application must handle data but encoding of the data is unknown, like file system data.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/parameter_encoding.rb, line 77
+def param_encoding(action, param, encoding)
+  @_parameter_encodings[action.to_s][param.to_s] = encoding
+end
+
+
+ +
+ +
+

+ + skip_parameter_encoding(action) + +

+ + +
+

Specify that a given action’s parameters should all be encoded as ASCII-8BIT (it “skips” the encoding default of UTF-8).

+ +

For example, a controller would use it like this:

+ +
class RepositoryController < ActionController::Base
+  skip_parameter_encoding :show
+
+  def show
+    @repo = Repository.find_by_filesystem_path params[:file_path]
+
+    # `repo_name` is guaranteed to be UTF-8, but was ASCII-8BIT, so
+    # tag it as such
+    @repo_name = params[:repo_name].force_encoding 'UTF-8'
+  end
+
+  def index
+    @repositories = Repository.all
+  end
+end
+
+ +

The show action in the above controller would have all parameter values encoded as ASCII-8BIT. This is useful in the case where an application must handle data but encoding of the data is unknown, like file system data.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/parameter_encoding.rb, line 48
+def skip_parameter_encoding(action)
+  @_parameter_encodings[action.to_s] = Hash.new { Encoding::ASCII_8BIT }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParameterMissing.html b/src/7.0/classes/ActionController/ParameterMissing.html new file mode 100644 index 0000000000..d4e4c2fdd8 --- /dev/null +++ b/src/7.0/classes/ActionController/ParameterMissing.html @@ -0,0 +1,73 @@ +--- +title: ActionController::ParameterMissing +layout: default +--- +
+ +
+
+ +
+ +

Raised when a required parameter is missing.

+ +
params = ActionController::Parameters.new(a: {})
+params.fetch(:b)
+# => ActionController::ParameterMissing: param is missing or the value is empty: b
+params.require(:a)
+# => ActionController::ParameterMissing: param is missing or the value is empty: a
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Parameters.html b/src/7.0/classes/ActionController/Parameters.html new file mode 100644 index 0000000000..cdc1435f86 --- /dev/null +++ b/src/7.0/classes/ActionController/Parameters.html @@ -0,0 +1,3094 @@ +--- +title: ActionController::Parameters +layout: default +--- +
+ +
+
+ +
+ +

Action Controller Parameters

+ +

Allows you to choose which attributes should be permitted for mass updating and thus prevent accidentally exposing that which shouldn’t be exposed. Provides two methods for this purpose: require and permit. The former is used to mark parameters as required. The latter is used to set the parameter as permitted and limit which attributes should be allowed for mass updating.

+ +
params = ActionController::Parameters.new({
+  person: {
+    name: "Francesco",
+    age:  22,
+    role: "admin"
+  }
+})
+
+permitted = params.require(:person).permit(:name, :age)
+permitted            # => #<ActionController::Parameters {"name"=>"Francesco", "age"=>22} permitted: true>
+permitted.permitted? # => true
+
+Person.first.update!(permitted)
+# => #<Person id: 1, name: "Francesco", age: 22, role: "user">
+
+ +

It provides two options that controls the top-level behavior of new instances:

+
  • +

    permit_all_parameters - If it’s true, all the parameters will be permitted by default. The default is false.

    +
  • +

    action_on_unpermitted_parameters - Controls behavior when parameters that are not explicitly

    + +
    permitted are found. The default value is <tt>:log</tt> in test and development environments,
    ++false+ otherwise. The values can be:
    +
    +
    • +

      false to take no action.

      +
    • +

      :log to emit an ActiveSupport::Notifications.instrument event on the unpermitted_parameters.action_controller topic and log at the DEBUG level.

      +
    • +

      :raise to raise an ActionController::UnpermittedParameters exception.

      +
    +
+ +

Examples:

+ +
params = ActionController::Parameters.new
+params.permitted? # => false
+
+ActionController::Parameters.permit_all_parameters = true
+
+params = ActionController::Parameters.new
+params.permitted? # => true
+
+params = ActionController::Parameters.new(a: "123", b: "456")
+params.permit(:c)
+# => #<ActionController::Parameters {} permitted: true>
+
+ActionController::Parameters.action_on_unpermitted_parameters = :raise
+
+params = ActionController::Parameters.new(a: "123", b: "456")
+params.permit(:c)
+# => ActionController::UnpermittedParameters: found unpermitted keys: a, b
+
+ +

Please note that these options *are not thread-safe*. In a multi-threaded environment they should only be set once at boot-time and never mutated at runtime.

+ +

You can fetch values of ActionController::Parameters using either :key or "key".

+ +
params = ActionController::Parameters.new(key: "value")
+params[:key]  # => "value"
+params["key"] # => "value"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PERMITTED_SCALAR_TYPES=[ +String, +Symbol, +NilClass, +Numeric, +TrueClass, +FalseClass, +Date, +Time, +# DateTimes are Dates, we document the type but avoid the redundant check. +StringIO, +IO, +ActionDispatch::Http::UploadedFile, +Rack::Test::UploadedFile, +]
 

This is a list of permitted scalar types that includes the ones supported in XML and JSON requests.

+ +

This list is in particular used to filter ordinary requests, String goes as first element to quickly short-circuit the common case.

+ +

If you modify this collection please update the one in the permit doc as well.

+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + parameters
+ [W] + permitted
+ + + + +

Class Public methods

+ +
+

+ + new(parameters = {}, logging_context = {}) + +

+ + +
+

Returns a new ActionController::Parameters instance. Also, sets the permitted attribute to the default value of ActionController::Parameters.permit_all_parameters.

+ +
class Person < ActiveRecord::Base
+end
+
+params = ActionController::Parameters.new(name: "Francesco")
+params.permitted?  # => false
+Person.new(params) # => ActiveModel::ForbiddenAttributesError
+
+ActionController::Parameters.permit_all_parameters = true
+
+params = ActionController::Parameters.new(name: "Francesco")
+params.permitted?  # => true
+Person.new(params) # => #<Person id: nil, name: "Francesco">
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 247
+def initialize(parameters = {}, logging_context = {})
+  @parameters = parameters.with_indifferent_access
+  @logging_context = logging_context
+  @permitted = self.class.permit_all_parameters
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other) + +

+ + +
+

Returns true if another Parameters object contains the same content and permitted flag.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 255
+def ==(other)
+  if other.respond_to?(:permitted?)
+    permitted? == other.permitted? && parameters == other.parameters
+  else
+    @parameters == other
+  end
+end
+
+
+ +
+ +
+

+ + [](key) + +

+ + +
+

Returns a parameter for the given key. If not found, returns nil.

+ +
params = ActionController::Parameters.new(person: { name: "Francesco" })
+params[:person] # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
+params[:none]   # => nil
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 619
+def [](key)
+  convert_hashes_to_parameters(key, @parameters[key])
+end
+
+
+ +
+ +
+

+ + []=(key, value) + +

+ + +
+

Assigns a value to a given key. The given key may still get filtered out when permit is called.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 625
+def []=(key, value)
+  @parameters[key] = value
+end
+
+
+ +
+ +
+

+ + as_json(options=nil) + + +

+ + +
+

Returns a hash that can be used as the JSON representation for the parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 138
+    
+
+
+ +
+ +
+

+ + compact() + +

+ + +
+

Returns a new ActionController::Parameters instance with nil values removed.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 795
+def compact
+  new_instance_with_inherited_permitted_status(@parameters.compact)
+end
+
+
+ +
+ +
+

+ + compact!() + +

+ + +
+

Removes all nil values in place and returns self, or nil if no changes were made.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 800
+def compact!
+  self if @parameters.compact!
+end
+
+
+ +
+ +
+

+ + compact_blank() + +

+ + +
+

Returns a new ActionController::Parameters instance without the blank values. Uses Object#blank? for determining if a value is blank.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 806
+def compact_blank
+  reject { |_k, v| v.blank? }
+end
+
+
+ +
+ +
+

+ + compact_blank!() + +

+ + +
+

Removes all blank values in place and returns self. Uses Object#blank? for determining if a value is blank.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 812
+def compact_blank!
+  reject! { |_k, v| v.blank? }
+end
+
+
+ +
+ +
+

+ + converted_arrays() + +

+ + +
+

Attribute that keeps track of converted arrays, if any, to avoid double looping in the common use case permit + mass-assignment. Defined in a method to instantiate it only if needed.

+ +

Testing membership still loops, but it’s going to be faster than our own loop that converts values. Also, we are not going to build a new array object per fetch.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 384
+def converted_arrays
+  @converted_arrays ||= Set.new
+end
+
+
+ +
+ +
+

+ + deep_dup() + +

+ + +
+

Returns a duplicate ActionController::Parameters instance with the same permitted parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 897
+def deep_dup
+  self.class.new(@parameters.deep_dup, @logging_context).tap do |duplicate|
+    duplicate.permitted = @permitted
+  end
+end
+
+
+ +
+ +
+

+ + deep_transform_keys(&block) + +

+ + +
+

Returns a new ActionController::Parameters instance with the results of running block once for every key. This includes the keys from the root hash and from all nested hashes and arrays. The values are unchanged.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 746
+def deep_transform_keys(&block)
+  new_instance_with_inherited_permitted_status(
+    @parameters.deep_transform_keys(&block)
+  )
+end
+
+
+ +
+ +
+

+ + deep_transform_keys!(&block) + +

+ + +
+

Returns the same ActionController::Parameters instance with changed keys. This includes the keys from the root hash and from all nested hashes and arrays. The values are unchanged.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 755
+def deep_transform_keys!(&block)
+  @parameters.deep_transform_keys!(&block)
+  self
+end
+
+
+ +
+ +
+

+ + delete(key, &block) + +

+ + +
+

Deletes a key-value pair from Parameters and returns the value. If key is not found, returns nil (or, with optional code block, yields key and returns the result). This method is similar to extract!, which returns the corresponding ActionController::Parameters object.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 764
+def delete(key, &block)
+  convert_value_to_parameters(@parameters.delete(key, &block))
+end
+
+
+ +
+ +
+

+ + delete_if(&block) + +

+ + +
+ +
+ + + + + +
+ Alias for: reject! +
+ + + +
+ +
+

+ + dig(*keys) + +

+ + +
+

Extracts the nested parameter from the given keys by calling dig at each step. Returns nil if any intermediate step is nil.

+ +
params = ActionController::Parameters.new(foo: { bar: { baz: 1 } })
+params.dig(:foo, :bar, :baz) # => 1
+params.dig(:foo, :zot, :xyz) # => nil
+
+params2 = ActionController::Parameters.new(foo: [10, 11, 12])
+params2.dig(:foo, 1) # => 11
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 663
+def dig(*keys)
+  convert_hashes_to_parameters(keys.first, @parameters[keys.first])
+  @parameters.dig(*keys)
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + +
+ Alias for: each_pair +
+ + + +
+ +
+

+ + each_key(&block) + + +

+ + +
+

Calls block once for each key in the parameters, passing the key. If no block is given, an enumerator is returned instead.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 146
+    
+
+
+ +
+ +
+

+ + each_pair(&block) + +

+ + +
+

Convert all hashes in values into parameters, then yield each pair in the same way as Hash#each_pair.

+
+ + + +
+ Also aliased as: each +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 356
+def each_pair(&block)
+  return to_enum(__callee__) unless block_given?
+  @parameters.each_pair do |key, value|
+    yield [key, convert_hashes_to_parameters(key, value)]
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + each_value(&block) + +

+ + +
+

Convert all hashes in values into parameters, then yield each value in the same way as Hash#each_value.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 368
+def each_value(&block)
+  return to_enum(:each_value) unless block_given?
+  @parameters.each_pair do |key, value|
+    yield convert_hashes_to_parameters(key, value)
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + empty?() + + +

+ + +
+

Returns true if the parameters have no key/value pairs.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 155
+    
+
+
+ +
+ +
+

+ + eql?(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 263
+def eql?(other)
+  self.class == other.class &&
+    permitted? == other.permitted? &&
+    parameters.eql?(other.parameters)
+end
+
+
+ +
+ +
+

+ + except(*keys) + +

+ + +
+

Returns a new ActionController::Parameters instance that filters out the given keys.

+ +
params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+params.except(:a, :b) # => #<ActionController::Parameters {"c"=>3} permitted: false>
+params.except(:d)     # => #<ActionController::Parameters {"a"=>1, "b"=>2, "c"=>3} permitted: false>
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 692
+def except(*keys)
+  new_instance_with_inherited_permitted_status(@parameters.except(*keys))
+end
+
+
+ +
+ +
+

+ + extract!(*keys) + +

+ + +
+

Removes and returns the key/value pairs matching the given keys.

+ +
params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+params.extract!(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+params                  # => #<ActionController::Parameters {"c"=>3} permitted: false>
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 701
+def extract!(*keys)
+  new_instance_with_inherited_permitted_status(@parameters.extract!(*keys))
+end
+
+
+ +
+ +
+

+ + fetch(key, *args) + +

+ + +
+

Returns a parameter for the given key. If the key can’t be found, there are several options: With no other arguments, it will raise an ActionController::ParameterMissing error; if a second argument is given, then that is returned (converted to an instance of ActionController::Parameters if possible); if a block is given, then that will be run and its result returned.

+ +
params = ActionController::Parameters.new(person: { name: "Francesco" })
+params.fetch(:person)               # => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
+params.fetch(:none)                 # => ActionController::ParameterMissing: param is missing or the value is empty: none
+params.fetch(:none, {})             # => #<ActionController::Parameters {} permitted: false>
+params.fetch(:none, "Francesco")    # => "Francesco"
+params.fetch(:none) { "Francesco" } # => "Francesco"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 642
+def fetch(key, *args)
+  convert_value_to_parameters(
+    @parameters.fetch(key) {
+      if block_given?
+        yield
+      else
+        args.fetch(0) { raise ActionController::ParameterMissing.new(key, @parameters.keys) }
+      end
+    }
+  )
+end
+
+
+ +
+ +
+

+ + has_key? + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + has_value?(value) + + +

+ + +
+

Returns true if the given value is present for some key in the parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 163
+    
+
+
+ +
+ +
+

+ + hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 269
+def hash
+  [self.class, @parameters, @permitted].hash
+end
+
+
+ +
+ +
+

+ + include?(key) + +

+ + +
+

Returns true if the given key is present in the parameters.

+
+ + + +
+ Also aliased as: has_key?, key?, member? +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 171
+    
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 861
+def inspect
+  "#<#{self.class} #{@parameters} permitted: #{@permitted}>"
+end
+
+
+ +
+ +
+

+ + keep_if(&block) + +

+ + +
+ +
+ + + + + +
+ Alias for: select! +
+ + + +
+ +
+

+ + key? + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + keys() + + +

+ + +
+

Returns a new array of the keys of the parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 179
+    
+
+
+ +
+ +
+

+ + member? + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + merge(other_hash) + +

+ + +
+

Returns a new ActionController::Parameters instance with all keys from other_hash merged into current hash.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 824
+def merge(other_hash)
+  new_instance_with_inherited_permitted_status(
+    @parameters.merge(other_hash.to_h)
+  )
+end
+
+
+ +
+ +
+

+ + merge!(other_hash) + +

+ + +
+

Returns the current ActionController::Parameters instance with other_hash merged into current hash.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 832
+def merge!(other_hash)
+  @parameters.merge!(other_hash.to_h)
+  self
+end
+
+
+ +
+ +
+

+ + permit(*filters) + +

+ + +
+

Returns a new ActionController::Parameters instance that includes only the given filters and sets the permitted attribute for the object to true. This is useful for limiting which attributes should be allowed for mass updating.

+ +
params = ActionController::Parameters.new(user: { name: "Francesco", age: 22, role: "admin" })
+permitted = params.require(:user).permit(:name, :age)
+permitted.permitted?      # => true
+permitted.has_key?(:name) # => true
+permitted.has_key?(:age)  # => true
+permitted.has_key?(:role) # => false
+
+ +

Only permitted scalars pass the filter. For example, given

+ +
params.permit(:name)
+
+ +

:name passes if it is a key of params whose associated value is of type String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile or Rack::Test::UploadedFile. Otherwise, the key :name is filtered out.

+ +

You may declare that the parameter should be an array of permitted scalars by mapping it to an empty array:

+ +
params = ActionController::Parameters.new(tags: ["rails", "parameters"])
+params.permit(tags: [])
+
+ +

Sometimes it is not possible or convenient to declare the valid keys of a hash parameter or its internal structure. Just map to an empty hash:

+ +
params.permit(preferences: {})
+
+ +

Be careful because this opens the door to arbitrary input. In this case, permit ensures values in the returned structure are permitted scalars and filters out anything else.

+ +

You can also use permit on nested parameters, like:

+ +
params = ActionController::Parameters.new({
+  person: {
+    name: "Francesco",
+    age:  22,
+    pets: [{
+      name: "Purplish",
+      category: "dogs"
+    }]
+  }
+})
+
+permitted = params.permit(person: [ :name, { pets: :name } ])
+permitted.permitted?                    # => true
+permitted[:person][:name]               # => "Francesco"
+permitted[:person][:age]                # => nil
+permitted[:person][:pets][0][:name]     # => "Purplish"
+permitted[:person][:pets][0][:category] # => nil
+
+ +

Note that if you use permit in a key that points to a hash, it won’t allow all the hash. You also need to specify which attributes inside the hash should be permitted.

+ +
params = ActionController::Parameters.new({
+  person: {
+    contact: {
+      email: "none@test.com",
+      phone: "555-1234"
+    }
+  }
+})
+
+params.require(:person).permit(:contact)
+# => #<ActionController::Parameters {} permitted: true>
+
+params.require(:person).permit(contact: :phone)
+# => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"phone"=>"555-1234"} permitted: true>} permitted: true>
+
+params.require(:person).permit(contact: [ :email, :phone ])
+# => #<ActionController::Parameters {"contact"=>#<ActionController::Parameters {"email"=>"none@test.com", "phone"=>"555-1234"} permitted: true>} permitted: true>
+
+ +

If your parameters specify multiple parameters indexed by a number, you can permit each set of parameters under the numeric key to be the same using the same syntax as permitting a single item.

+ +
params = ActionController::Parameters.new({
+  person: {
+    '0': {
+      email: "none@test.com",
+      phone: "555-1234"
+    },
+    '1': {
+      email: "nothing@test.com",
+      phone: "555-6789"
+    },
+  }
+})
+params.permit(person: [:email]).to_h
+# => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"email"=>"nothing@test.com"}}}
+
+ +

If you want to specify what keys you want from each numeric key, you can instead specify each one individually

+ +
params = ActionController::Parameters.new({
+  person: {
+    '0': {
+      email: "none@test.com",
+      phone: "555-1234"
+    },
+    '1': {
+      email: "nothing@test.com",
+      phone: "555-6789"
+    },
+  }
+})
+params.permit(person: { '0': [:email], '1': [:phone]}).to_h
+# => {"person"=>{"0"=>{"email"=>"none@test.com"}, "1"=>{"phone"=>"555-6789"}}}
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 596
+def permit(*filters)
+  params = self.class.new
+
+  filters.flatten.each do |filter|
+    case filter
+    when Symbol, String
+      permitted_scalar_filter(params, filter)
+    when Hash
+      hash_filter(params, filter)
+    end
+  end
+
+  unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters
+
+  params.permit!
+end
+
+
+ +
+ +
+

+ + permit!() + +

+ + +
+

Sets the permitted attribute to true. This can be used to pass mass assignment. Returns self.

+ +
class Person < ActiveRecord::Base
+end
+
+params = ActionController::Parameters.new(name: "Francesco")
+params.permitted?  # => false
+Person.new(params) # => ActiveModel::ForbiddenAttributesError
+params.permit!
+params.permitted?  # => true
+Person.new(params) # => #<Person id: nil, name: "Francesco">
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 410
+def permit!
+  each_pair do |key, value|
+    Array.wrap(value).flatten.each do |v|
+      v.permit! if v.respond_to? :permit!
+    end
+  end
+
+  @permitted = true
+  self
+end
+
+
+ +
+ +
+

+ + permitted?() + +

+ + +
+

Returns true if the parameter is permitted, false otherwise.

+ +
params = ActionController::Parameters.new
+params.permitted? # => false
+params.permit!
+params.permitted? # => true
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 394
+def permitted?
+  @permitted
+end
+
+
+ +
+ +
+

+ + reject(&block) + +

+ + +
+

Returns a new ActionController::Parameters instance with items that the block evaluates to true removed.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 783
+def reject(&block)
+  new_instance_with_inherited_permitted_status(@parameters.reject(&block))
+end
+
+
+ +
+ +
+

+ + reject!(&block) + +

+ + +
+

Removes items that the block evaluates to true and returns self.

+
+ + + +
+ Also aliased as: delete_if +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 788
+def reject!(&block)
+  @parameters.reject!(&block)
+  self
+end
+
+
+ +
+ +
+

+ + require(key) + +

+ + +
+

This method accepts both a single key and an array of keys.

+ +

When passed a single key, if it exists and its associated value is either present or the singleton false, returns said value:

+ +
ActionController::Parameters.new(person: { name: "Francesco" }).require(:person)
+# => #<ActionController::Parameters {"name"=>"Francesco"} permitted: false>
+
+ +

Otherwise raises ActionController::ParameterMissing:

+ +
ActionController::Parameters.new.require(:person)
+# ActionController::ParameterMissing: param is missing or the value is empty: person
+
+ActionController::Parameters.new(person: nil).require(:person)
+# ActionController::ParameterMissing: param is missing or the value is empty: person
+
+ActionController::Parameters.new(person: "\t").require(:person)
+# ActionController::ParameterMissing: param is missing or the value is empty: person
+
+ActionController::Parameters.new(person: {}).require(:person)
+# ActionController::ParameterMissing: param is missing or the value is empty: person
+
+ +

When given an array of keys, the method tries to require each one of them in order. If it succeeds, an array with the respective return values is returned:

+ +
params = ActionController::Parameters.new(user: { ... }, profile: { ... })
+user_params, profile_params = params.require([:user, :profile])
+
+ +

Otherwise, the method re-raises the first exception found:

+ +
params = ActionController::Parameters.new(user: {}, profile: {})
+user_params, profile_params = params.require([:user, :profile])
+# ActionController::ParameterMissing: param is missing or the value is empty: user
+
+ +

Technically this method can be used to fetch terminal values:

+ +
# CAREFUL
+params = ActionController::Parameters.new(person: { name: "Finn" })
+name = params.require(:person).require(:name) # CAREFUL
+
+ +

but take into account that at some point those ones have to be permitted:

+ +
def person_params
+  params.require(:person).permit(:name).tap do |person_params|
+    person_params.require(:name) # SAFER
+  end
+end
+
+ +

for example.

+
+ + + +
+ Also aliased as: required +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 471
+def require(key)
+  return key.map { |k| require(k) } if key.is_a?(Array)
+  value = self[key]
+  if value.present? || value == false
+    value
+  else
+    raise ParameterMissing.new(key, @parameters.keys)
+  end
+end
+
+
+ +
+ +
+

+ + required(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: require +
+ + + +
+ +
+

+ + reverse_merge(other_hash) + +

+ + +
+

Returns a new ActionController::Parameters instance with all keys from current hash merged into other_hash.

+
+ + + +
+ Also aliased as: with_defaults +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 839
+def reverse_merge(other_hash)
+  new_instance_with_inherited_permitted_status(
+    other_hash.to_h.merge(@parameters)
+  )
+end
+
+
+ +
+ +
+

+ + reverse_merge!(other_hash) + +

+ + +
+

Returns the current ActionController::Parameters instance with current hash merged into other_hash.

+
+ + + +
+ Also aliased as: with_defaults! +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 848
+def reverse_merge!(other_hash)
+  @parameters.merge!(other_hash.to_h) { |key, left, right| left }
+  self
+end
+
+
+ +
+ +
+

+ + select(&block) + +

+ + +
+

Returns a new ActionController::Parameters instance with only items that the block evaluates to true.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 770
+def select(&block)
+  new_instance_with_inherited_permitted_status(@parameters.select(&block))
+end
+
+
+ +
+ +
+

+ + select!(&block) + +

+ + +
+

Equivalent to Hash#keep_if, but returns nil if no changes were made.

+
+ + + +
+ Also aliased as: keep_if +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 775
+def select!(&block)
+  @parameters.select!(&block)
+  self
+end
+
+
+ +
+ +
+

+ + slice(*keys) + +

+ + +
+

Returns a new ActionController::Parameters instance that includes only the given keys. If the given keys don’t exist, returns an empty hash.

+ +
params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+params.slice(:a, :b) # => #<ActionController::Parameters {"a"=>1, "b"=>2} permitted: false>
+params.slice(:d)     # => #<ActionController::Parameters {} permitted: false>
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 675
+def slice(*keys)
+  new_instance_with_inherited_permitted_status(@parameters.slice(*keys))
+end
+
+
+ +
+ +
+

+ + slice!(*keys) + +

+ + +
+

Returns the current ActionController::Parameters instance which contains only the given keys.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 681
+def slice!(*keys)
+  @parameters.slice!(*keys)
+  self
+end
+
+
+ +
+ +
+

+ + to_h() + +

+ + +
+

Returns a safe ActiveSupport::HashWithIndifferentAccess representation of the parameters with all unpermitted keys removed.

+ +
params = ActionController::Parameters.new({
+  name: "Senjougahara Hitagi",
+  oddity: "Heavy stone crab"
+})
+params.to_h
+# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+
+safe_params = params.permit(:name)
+safe_params.to_h # => {"name"=>"Senjougahara Hitagi"}
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 285
+def to_h
+  if permitted?
+    convert_parameters_to_hashes(@parameters, :to_h)
+  else
+    raise UnfilteredParameters
+  end
+end
+
+
+ +
+ +
+

+ + to_hash() + +

+ + +
+

Returns a safe Hash representation of the parameters with all unpermitted keys removed.

+ +
params = ActionController::Parameters.new({
+  name: "Senjougahara Hitagi",
+  oddity: "Heavy stone crab"
+})
+params.to_hash
+# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+
+safe_params = params.permit(:name)
+safe_params.to_hash # => {"name"=>"Senjougahara Hitagi"}
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 305
+def to_hash
+  to_h.to_hash
+end
+
+
+ +
+ +
+

+ + to_param(*args) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_query +
+ + + +
+ +
+

+ + to_query(*args) + +

+ + +
+

Returns a string representation of the receiver suitable for use as a URL query string:

+ +
params = ActionController::Parameters.new({
+  name: "David",
+  nationality: "Danish"
+})
+params.to_query
+# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+
+safe_params = params.permit(:name, :nationality)
+safe_params.to_query
+# => "name=David&nationality=Danish"
+
+ +

An optional namespace can be passed to enclose key names:

+ +
params = ActionController::Parameters.new({
+  name: "David",
+  nationality: "Danish"
+})
+safe_params = params.permit(:name, :nationality)
+safe_params.to_query("user")
+# => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
+
+ +

The string pairs "key=value" that conform the query string are sorted lexicographically in ascending order.

+
+ + + +
+ Also aliased as: to_param +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 335
+def to_query(*args)
+  to_h.to_query(*args)
+end
+
+
+ +
+ +
+

+ + to_s() + + +

+ + +
+

Returns the content of the parameters as a string.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 187
+    
+
+
+ +
+ +
+

+ + to_unsafe_h() + +

+ + +
+

Returns an unsafe, unfiltered ActiveSupport::HashWithIndifferentAccess representation of the parameters.

+ +
params = ActionController::Parameters.new({
+  name: "Senjougahara Hitagi",
+  oddity: "Heavy stone crab"
+})
+params.to_unsafe_h
+# => {"name"=>"Senjougahara Hitagi", "oddity" => "Heavy stone crab"}
+
+
+ + + +
+ Also aliased as: to_unsafe_hash +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 349
+def to_unsafe_h
+  convert_parameters_to_hashes(@parameters, :to_unsafe_h)
+end
+
+
+ +
+ +
+

+ + to_unsafe_hash() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_unsafe_h +
+ + + +
+ +
+

+ + transform_keys(&block) + +

+ + +
+

Returns a new ActionController::Parameters instance with the results of running block once for every key. The values are unchanged.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 728
+def transform_keys(&block)
+  return to_enum(:transform_keys) unless block_given?
+  new_instance_with_inherited_permitted_status(
+    @parameters.transform_keys(&block)
+  )
+end
+
+
+ +
+ +
+

+ + transform_keys!(&block) + +

+ + +
+

Performs keys transformation and returns the altered ActionController::Parameters instance.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 737
+def transform_keys!(&block)
+  return to_enum(:transform_keys!) unless block_given?
+  @parameters.transform_keys!(&block)
+  self
+end
+
+
+ +
+ +
+

+ + transform_values() + +

+ + +
+

Returns a new ActionController::Parameters instance with the results of running block once for every value. The keys are unchanged.

+ +
params = ActionController::Parameters.new(a: 1, b: 2, c: 3)
+params.transform_values { |x| x * 2 }
+# => #<ActionController::Parameters {"a"=>2, "b"=>4, "c"=>6} permitted: false>
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 711
+def transform_values
+  return to_enum(:transform_values) unless block_given?
+  new_instance_with_inherited_permitted_status(
+    @parameters.transform_values { |v| yield convert_value_to_parameters(v) }
+  )
+end
+
+
+ +
+ +
+

+ + transform_values!() + +

+ + +
+

Performs values transformation and returns the altered ActionController::Parameters instance.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 720
+def transform_values!
+  return to_enum(:transform_values!) unless block_given?
+  @parameters.transform_values! { |v| yield convert_value_to_parameters(v) }
+  self
+end
+
+
+ +
+ +
+

+ + value?(value) + + +

+ + +
+

Returns true if the given value is present for some key in the parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 195
+    
+
+
+ +
+ +
+

+ + values() + + +

+ + +
+

Returns a new array of the values of the parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 209
+delegate :keys, :values, :has_value?, :value?, :empty?, :include?,
+  :as_json, :to_s, :each_key, to: :@parameters
+
+
+
+ +
+ +
+

+ + values_at(*keys) + +

+ + +
+

Returns values that were assigned to the given keys. Note that all the Hash objects will be converted to ActionController::Parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 818
+def values_at(*keys)
+  convert_value_to_parameters(@parameters.values_at(*keys))
+end
+
+
+ +
+ +
+

+ + with_defaults(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge +
+ + + +
+ +
+

+ + with_defaults!(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge! +
+ + + +
+ + +

Instance Protected methods

+ +
+

+ + each_nested_attribute() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 912
+def each_nested_attribute
+  hash = self.class.new
+  self.each { |k, v| hash[k] = yield v if Parameters.nested_attribute?(k, v) }
+  hash
+end
+
+
+ +
+ +
+

+ + nested_attributes?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 908
+def nested_attributes?
+  @parameters.any? { |k, v| Parameters.nested_attribute?(k, v) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParamsWrapper.html b/src/7.0/classes/ActionController/ParamsWrapper.html new file mode 100644 index 0000000000..33fc23087a --- /dev/null +++ b/src/7.0/classes/ActionController/ParamsWrapper.html @@ -0,0 +1,153 @@ +--- +title: ActionController::ParamsWrapper +layout: default +--- +
+ +
+
+ +
+ +

Wraps the parameters hash into a nested hash. This will allow clients to submit requests without having to specify any root elements.

+ +

This functionality is enabled by default for JSON, and can be customized by setting the format array:

+ +
class ApplicationController < ActionController::Base
+  wrap_parameters format: [:json, :xml]
+end
+
+ +

You could also turn it on per controller:

+ +
class UsersController < ApplicationController
+  wrap_parameters format: [:json, :xml, :url_encoded_form, :multipart_form]
+end
+
+ +

If you enable ParamsWrapper for :json format, instead of having to send JSON parameters like this:

+ +
{"user": {"name": "Konata"}}
+
+ +

You can send parameters like this:

+ +
{"name": "Konata"}
+
+ +

And it will be wrapped into a nested hash with the key name matching the controller’s name. For example, if you’re posting to UsersController, your new params hash will look like this:

+ +
{"name" => "Konata", "user" => {"name" => "Konata"}}
+
+ +

You can also specify the key in which the parameters should be wrapped to, and also the list of attributes it should wrap by using either :include or :exclude options like this:

+ +
class UsersController < ApplicationController
+  wrap_parameters :person, include: [:username, :password]
+end
+
+ +

On Active Record models with no :include or :exclude option set, it will only wrap the parameters returned by the class method attribute_names.

+ +

If you’re going to pass the parameters to an ActiveModel object (such as User.new(params[:user])), you might consider passing the model class to the method instead. The ParamsWrapper will actually try to determine the list of attribute names from the model and only wrap those attributes:

+ +
class UsersController < ApplicationController
+  wrap_parameters Person
+end
+
+ +

You still could pass :include and :exclude to set the list of attributes you want to wrap.

+ +

By default, if you don’t specify the key in which the parameters would be wrapped to, ParamsWrapper will actually try to determine if there’s a model related to it or not. This controller, for example:

+ +
class Admin::UsersController < ApplicationController
+end
+
+ +

will try to check if Admin::User or User model exists, and use it to determine the wrapper key respectively. If both models don’t exist, it will then fallback to use user as the key.

+ +

To disable this functionality for a controller:

+ +
class UsersController < ApplicationController
+  wrap_parameters false
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
EXCLUDE_PARAMETERS=%w(authenticity_token _method utf8)
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParamsWrapper/Options.html b/src/7.0/classes/ActionController/ParamsWrapper/Options.html new file mode 100644 index 0000000000..2f164c7721 --- /dev/null +++ b/src/7.0/classes/ActionController/ParamsWrapper/Options.html @@ -0,0 +1,73 @@ +--- +title: ActionController::ParamsWrapper::Options +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/ParamsWrapper/Options/ClassMethods.html b/src/7.0/classes/ActionController/ParamsWrapper/Options/ClassMethods.html new file mode 100644 index 0000000000..4f7969b292 --- /dev/null +++ b/src/7.0/classes/ActionController/ParamsWrapper/Options/ClassMethods.html @@ -0,0 +1,229 @@ +--- +title: ActionController::ParamsWrapper::Options::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _set_wrapper_options(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/params_wrapper.rb, line 189
+def _set_wrapper_options(options)
+  self._wrapper_options = Options.from_hash(options)
+end
+
+
+ +
+ +
+

+ + inherited(klass) + +

+ + +
+

Sets the default wrapper key or model which will be used to determine wrapper key and attribute names. Called automatically when the module is inherited.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/params_wrapper.rb, line 244
+def inherited(klass)
+  if klass._wrapper_options.format.any?
+    params = klass._wrapper_options.dup
+    params.klass = klass
+    klass._wrapper_options = params
+  end
+  super
+end
+
+
+ +
+ +
+

+ + wrap_parameters(name_or_model_or_options, options = {}) + +

+ + +
+

Sets the name of the wrapper key, or the model which ParamsWrapper would use to determine the attribute names from.

+ +

Examples

+ +
wrap_parameters format: :xml
+  # enables the parameter wrapper for XML format
+
+wrap_parameters :person
+  # wraps parameters into +params[:person]+ hash
+
+wrap_parameters Person
+  # wraps parameters by determining the wrapper key from Person class
+  # (+person+, in this case) and the list of attribute names
+
+wrap_parameters include: [:username, :title]
+  # wraps only +:username+ and +:title+ attributes from parameters.
+
+wrap_parameters false
+  # disables parameters wrapping for this controller altogether.
+
+ +

Options

+
  • +

    :format - The list of formats in which the parameters wrapper will be enabled.

    +
  • +

    :include - The list of attribute names which parameters wrapper will wrap into a nested hash.

    +
  • +

    :exclude - The list of attribute names which parameters wrapper will exclude from a nested hash.

    +
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/params_wrapper.rb, line 220
+def wrap_parameters(name_or_model_or_options, options = {})
+  model = nil
+
+  case name_or_model_or_options
+  when Hash
+    options = name_or_model_or_options
+  when false
+    options = options.merge(format: [])
+  when Symbol, String
+    options = options.merge(name: name_or_model_or_options)
+  else
+    model = name_or_model_or_options
+  end
+
+  opts = Options.from_hash _wrapper_options.to_h.slice(:format).merge(options)
+  opts.model = model
+  opts.klass = self
+
+  self._wrapper_options = opts
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/PermissionsPolicy.html b/src/7.0/classes/ActionController/PermissionsPolicy.html new file mode 100644 index 0000000000..905ddc3c22 --- /dev/null +++ b/src/7.0/classes/ActionController/PermissionsPolicy.html @@ -0,0 +1,67 @@ +--- +title: ActionController::PermissionsPolicy +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/PermissionsPolicy/ClassMethods.html b/src/7.0/classes/ActionController/PermissionsPolicy/ClassMethods.html new file mode 100644 index 0000000000..11450fc07b --- /dev/null +++ b/src/7.0/classes/ActionController/PermissionsPolicy/ClassMethods.html @@ -0,0 +1,123 @@ +--- +title: ActionController::PermissionsPolicy::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + permissions_policy(**options, &block) + +

+ + +
+

Overrides parts of the globally configured Feature-Policy header:

+ +
class PagesController < ApplicationController
+  permissions_policy do |policy|
+    policy.geolocation "https://example.com"
+  end
+end
+
+ +

Options can be passed similar to before_action. For example, pass only: :index to override the header on the index action only:

+ +
class PagesController < ApplicationController
+  permissions_policy(only: :index) do |policy|
+    policy.camera :self
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/permissions_policy.rb, line 26
+def permissions_policy(**options, &block)
+  before_action(options) do
+    if block_given?
+      policy = request.permissions_policy.clone
+      yield policy
+      request.permissions_policy = policy
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Railties.html b/src/7.0/classes/ActionController/Railties.html new file mode 100644 index 0000000000..c6226a573c --- /dev/null +++ b/src/7.0/classes/ActionController/Railties.html @@ -0,0 +1,67 @@ +--- +title: ActionController::Railties +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Railties/Helpers.html b/src/7.0/classes/ActionController/Railties/Helpers.html new file mode 100644 index 0000000000..42bfad124c --- /dev/null +++ b/src/7.0/classes/ActionController/Railties/Helpers.html @@ -0,0 +1,114 @@ +--- +title: ActionController::Railties::Helpers +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + inherited(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/railties/helpers.rb, line 6
+def inherited(klass)
+  super
+  return unless klass.respond_to?(:helpers_path=)
+
+  if namespace = klass.module_parents.detect { |m| m.respond_to?(:railtie_helpers_paths) }
+    paths = namespace.railtie_helpers_paths
+  else
+    paths = ActionController::Helpers.helpers_path
+  end
+
+  klass.helpers_path = paths
+
+  if klass.superclass == ActionController::Base && ActionController::Base.include_all_helpers
+    klass.helper :all
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Redirecting.html b/src/7.0/classes/ActionController/Redirecting.html new file mode 100644 index 0000000000..c59d308df8 --- /dev/null +++ b/src/7.0/classes/ActionController/Redirecting.html @@ -0,0 +1,385 @@ +--- +title: ActionController::Redirecting +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ILLEGAL_HEADER_VALUE_REGEX=/[\x00-\x08\x0A-\x1F]/.freeze
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args) + +

+ + +
+

Soft deprecated alias for redirect_back_or_to where the fallback_location location is supplied as a keyword argument instead of the first positional argument.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/redirecting.rb, line 101
+def redirect_back(fallback_location:, allow_other_host: _allow_other_host, **args)
+  redirect_back_or_to fallback_location, allow_other_host: allow_other_host, **args
+end
+
+
+ +
+ +
+

+ + redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options) + +

+ + +
+

Redirects the browser to the page that issued the request (the referrer) if possible, otherwise redirects to the provided default fallback location.

+ +

The referrer information is pulled from the HTTP Referer (sic) header on the request. This is an optional header and its presence on the request is subject to browser security settings and user preferences. If the request is missing this header, the fallback_location will be used.

+ +
redirect_back_or_to({ action: "show", id: 5 })
+redirect_back_or_to @post
+redirect_back_or_to "http://www.rubyonrails.org"
+redirect_back_or_to "/images/screenshot.jpg"
+redirect_back_or_to posts_url
+redirect_back_or_to proc { edit_post_url(@post) }
+redirect_back_or_to '/', allow_other_host: false
+
+ +

Options

+
  • +

    :allow_other_host - Allow or disallow redirection to the host that is different to the current host, defaults to true.

    +
+ +

All other options that can be passed to redirect_to are accepted as options, and the behavior is identical.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/redirecting.rb, line 127
+def redirect_back_or_to(fallback_location, allow_other_host: _allow_other_host, **options)
+  if request.referer && (allow_other_host || _url_host_allowed?(request.referer))
+    redirect_to request.referer, allow_other_host: allow_other_host, **options
+  else
+    # The method level `allow_other_host` doesn't apply in the fallback case, omit and let the `redirect_to` handling take over.
+    redirect_to fallback_location, **options
+  end
+end
+
+
+ +
+ +
+

+ + redirect_to(options = {}, response_options = {}) + +

+ + +
+

Redirects the browser to the target specified in options. This parameter can be any one of:

+
  • +

    Hash - The URL will be generated by calling url_for with the options.

    +
  • +

    Record - The URL will be generated by calling url_for with the options, which will reference a named URL for that record.

    +
  • +

    String starting with protocol:// (like http://) or a protocol relative reference (like //) - Is passed straight through as the target for redirection.

    +
  • +

    String not containing a protocol - The current protocol and host is prepended to the string.

    +
  • +

    Proc - A block that will be executed in the controller’s context. Should return any option accepted by redirect_to.

    +
+ +

Examples:

+ +
redirect_to action: "show", id: 5
+redirect_to @post
+redirect_to "http://www.rubyonrails.org"
+redirect_to "/images/screenshot.jpg"
+redirect_to posts_url
+redirect_to proc { edit_post_url(@post) }
+
+ +

The redirection happens as a 302 Found header unless otherwise specified using the :status option:

+ +
redirect_to post_url(@post), status: :found
+redirect_to action: 'atom', status: :moved_permanently
+redirect_to post_url(@post), status: 301
+redirect_to action: 'atom', status: 302
+
+ +

The status code can either be a standard HTTP Status code as an integer, or a symbol representing the downcased, underscored and symbolized description. Note that the status code must be a 3xx HTTP code, or redirection will not occur.

+ +

If you are using XHR requests other than GET or POST and redirecting after the request then some browsers will follow the redirect using the original request method. This may lead to undesirable behavior such as a double DELETE. To work around this you can return a 303 See Other status code which will be followed using a GET request.

+ +
redirect_to posts_url, status: :see_other
+redirect_to action: 'index', status: 303
+
+ +

It is also possible to assign a flash message as part of the redirection. There are two special accessors for the commonly used flash names alert and notice as well as a general purpose flash bucket.

+ +
redirect_to post_url(@post), alert: "Watch it, mister!"
+redirect_to post_url(@post), status: :found, notice: "Pay attention to the road"
+redirect_to post_url(@post), status: 301, flash: { updated_post_id: @post.id }
+redirect_to({ action: 'atom' }, alert: "Something serious happened")
+
+ +

Statements after redirect_to in our controller get executed, so redirect_to doesn’t stop the execution of the function. To terminate the execution of the function immediately after the redirect_to, use return.

+ +
redirect_to post_url(@post) and return
+
+ +

Open Redirect protection

+ +

By default, Rails protects against redirecting to external hosts for your app’s safety, so called open redirects. Note: this was a new default in Rails 7.0, after upgrading opt-in by uncommenting the line with raise_on_open_redirects in config/initializers/new_framework_defaults_7_0.rb

+ +

Here redirect_to automatically validates the potentially-unsafe URL:

+ +
redirect_to params[:redirect_url]
+
+ +

Raises UnsafeRedirectError in the case of an unsafe redirect.

+ +

To allow any external redirects pass allow_other_host: true, though using a user-provided param in that case is unsafe.

+ +
redirect_to "https://rubyonrails.org", allow_other_host: true
+
+ +

See url_from for more information on what an internal and safe URL is, or how to fall back to an alternate redirect URL in the unsafe case.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/redirecting.rb, line 84
+def redirect_to(options = {}, response_options = {})
+  raise ActionControllerError.new("Cannot redirect to nil!") unless options
+  raise AbstractController::DoubleRenderError if response_body
+
+  allow_other_host = response_options.delete(:allow_other_host) { _allow_other_host }
+
+  self.status = _extract_redirect_to_status(options, response_options)
+
+  redirect_to_location = _compute_redirect_to_location(request, options)
+  _ensure_url_is_http_header_safe(redirect_to_location)
+
+  self.location      = _enforce_open_redirect_protection(redirect_to_location, allow_other_host: allow_other_host)
+  self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
+end
+
+
+ +
+ +
+

+ + url_from(location) + +

+ + +
+

Verifies the passed location is an internal URL that’s safe to redirect to and returns it, or nil if not. Useful to wrap a params provided redirect URL and fallback to an alternate URL to redirect to:

+ +
redirect_to url_from(params[:redirect_url]) || root_url
+
+ +

The location is considered internal, and safe, if it’s on the same host as request.host:

+ +
# If request.host is example.com:
+url_from("https://example.com/profile") # => "https://example.com/profile"
+url_from("http://example.com/profile")  # => "http://example.com/profile"
+url_from("http://evil.com/profile")     # => nil
+
+ +

Subdomains are considered part of the host:

+ +
# If request.host is on https://example.com or https://app.example.com, you'd get:
+url_from("https://dev.example.com/profile") # => nil
+
+ +

NOTE: there’s a similarity with url_for, which generates an internal URL from various options from within the app, e.g. url_for(@post). However, url_from is meant to take an external parameter to verify as in url_from(params[:redirect_url]).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/redirecting.rb, line 175
+def url_from(location)
+  location = location.presence
+  location if location && _url_host_allowed?(location)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Redirecting/UnsafeRedirectError.html b/src/7.0/classes/ActionController/Redirecting/UnsafeRedirectError.html new file mode 100644 index 0000000000..b2aa85fca2 --- /dev/null +++ b/src/7.0/classes/ActionController/Redirecting/UnsafeRedirectError.html @@ -0,0 +1,60 @@ +--- +title: ActionController::Redirecting::UnsafeRedirectError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Renderer.html b/src/7.0/classes/ActionController/Renderer.html new file mode 100644 index 0000000000..a086314c9b --- /dev/null +++ b/src/7.0/classes/ActionController/Renderer.html @@ -0,0 +1,411 @@ +--- +title: ActionController::Renderer +layout: default +--- +
+ +
+
+ +
+ +

ActionController::Renderer allows you to render arbitrary templates without requirement of being in controller actions.

+ +

You get a concrete renderer class by invoking ActionController::Base#renderer. For example:

+ +
ApplicationController.renderer
+
+ +

It allows you to call method render directly.

+ +
ApplicationController.renderer.render template: '...'
+
+ +

You can use this shortcut in a controller, instead of the previous example:

+ +
ApplicationController.render template: '...'
+
+ +

render allows you to use the same options that you can use when rendering in a controller. For example:

+ +
FooController.render :action, locals: { ... }, assigns: { ... }
+
+ +

The template will be rendered in a Rack environment which is accessible through ActionController::Renderer#env. You can set it up in two ways:

+
  • +

    by changing renderer defaults, like

    + +
    ApplicationController.renderer.defaults # => hash with default Rack environment
    +
    +
  • +

    by initializing an instance of renderer by passing it a custom environment.

    + +
    ApplicationController.renderer.new(method: 'post', https: true)
    +
    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULTS={ +http_host: "example.org", +https: false, +method: "get", +script_name: "", +input: "" +}.freeze
 
RACK_KEY_TRANSLATION={ +http_host: "HTTP_HOST", +https: "HTTPS", +method: "REQUEST_METHOD", +script_name: "SCRIPT_NAME", +input: "rack.input" +}
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + controller
+ [R] + defaults
+ + + + +

Class Public methods

+ +
+

+ + for(controller, env = {}, defaults = DEFAULTS.dup) + +

+ + +
+

Create a new renderer instance for a specific controller class.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/renderer.rb, line 48
+def self.for(controller, env = {}, defaults = DEFAULTS.dup)
+  new(controller, env, defaults)
+end
+
+
+ +
+ +
+

+ + new(controller, env, defaults) + +

+ + +
+

Accepts a custom Rack environment to render templates in. It will be merged with the default Rack environment defined by ActionController::Renderer::DEFAULTS.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/renderer.rb, line 65
+def initialize(controller, env, defaults)
+  @controller = controller
+  @defaults = defaults
+  @env = normalize_keys defaults, env
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + new(env = {}) + +

+ + +
+

Create a new renderer for the same controller but with a new env.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/renderer.rb, line 53
+def new(env = {})
+  self.class.new controller, env, defaults
+end
+
+
+ +
+ +
+

+ + render(*args) + +

+ + +
+

Renders a template to a string, just like ActionController::Rendering#render_to_string.

+
+ + + +
+ Also aliased as: render_to_string +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/renderer.rb, line 72
+def render(*args)
+  raise "missing controller" unless controller
+
+  request = ActionDispatch::Request.new @env
+  request.routes = controller._routes
+
+  instance = controller.new
+  instance.set_request! request
+  instance.set_response! controller.make_response!(request)
+  instance.render_to_string(*args)
+end
+
+
+ +
+ +
+

+ + render_to_string(*args) + +

+ + +
+ +
+ + + + + +
+ Alias for: render +
+ + + +
+ +
+

+ + with_defaults(defaults) + +

+ + +
+

Create a new renderer for the same controller but with new defaults.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/renderer.rb, line 58
+def with_defaults(defaults)
+  self.class.new controller, @env, self.defaults.merge(defaults)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Renderers.html b/src/7.0/classes/ActionController/Renderers.html new file mode 100644 index 0000000000..3083506d8b --- /dev/null +++ b/src/7.0/classes/ActionController/Renderers.html @@ -0,0 +1,333 @@ +--- +title: ActionController::Renderers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RENDERERS=Set.new
 

A Set containing renderer names that correspond to available renderer procs. Default values are :json, :js, :xml.

+ + + + + + +

Class Public methods

+ +
+

+ + _render_with_renderer_method_name(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 90
+def self._render_with_renderer_method_name(key)
+  "_render_with_renderer_#{key}"
+end
+
+
+ +
+ +
+

+ + add(key, &block) + +

+ + +
+

Adds a new renderer to call within controller actions. A renderer is invoked by passing its name as an option to AbstractController::Rendering#render. To create a renderer pass it a name and a block. The block takes two arguments, the first is the value paired with its key and the second is the remaining hash of options passed to render.

+ +

Create a csv renderer:

+ +
ActionController::Renderers.add :csv do |obj, options|
+  filename = options[:filename] || 'data'
+  str = obj.respond_to?(:to_csv) ? obj.to_csv : obj.to_s
+  send_data str, type: Mime[:csv],
+    disposition: "attachment; filename=#{filename}.csv"
+end
+
+ +

Note that we used Mime for the csv mime type as it comes with Rails. For a custom renderer, you’ll need to register a mime type with Mime::Type.register.

+ +

To use the csv renderer in a controller action:

+ +
def show
+  @csvable = Csvable.find(params[:id])
+  respond_to do |format|
+    format.html
+    format.csv { render csv: @csvable, filename: @csvable.name }
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 74
+def self.add(key, &block)
+  define_method(_render_with_renderer_method_name(key), &block)
+  RENDERERS << key.to_sym
+end
+
+
+ +
+ +
+

+ + remove(key) + +

+ + +
+

This method is the opposite of add method.

+ +

To remove a csv renderer:

+ +
ActionController::Renderers.remove(:csv)
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 84
+def self.remove(key)
+  RENDERERS.delete(key.to_sym)
+  method_name = _render_with_renderer_method_name(key)
+  remove_possible_method(method_name)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + _render_to_body_with_renderer(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 144
+def _render_to_body_with_renderer(options)
+  _renderers.each do |name|
+    if options.key?(name)
+      _process_options(options)
+      method_name = Renderers._render_with_renderer_method_name(name)
+      return send(method_name, options.delete(name), options)
+    end
+  end
+  nil
+end
+
+
+ +
+ +
+

+ + render_to_body(options) + +

+ + +
+

Called by render in AbstractController::Rendering which sets the return value as the response_body.

+ +

If no renderer is found, super returns control to ActionView::Rendering.render_to_body, if present.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 140
+def render_to_body(options)
+  _render_to_body_with_renderer(options) || super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Renderers/All.html b/src/7.0/classes/ActionController/Renderers/All.html new file mode 100644 index 0000000000..eed9fbf5e8 --- /dev/null +++ b/src/7.0/classes/ActionController/Renderers/All.html @@ -0,0 +1,74 @@ +--- +title: ActionController::Renderers::All +layout: default +--- +
+ +
+
+ +
+ +

Used in ActionController::Base and ActionController::API to include all renderers by default.

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Renderers/ClassMethods.html b/src/7.0/classes/ActionController/Renderers/ClassMethods.html new file mode 100644 index 0000000000..8b752d1fd5 --- /dev/null +++ b/src/7.0/classes/ActionController/Renderers/ClassMethods.html @@ -0,0 +1,157 @@ +--- +title: ActionController::Renderers::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + use_renderer(*args) + +

+ + +
+ +
+ + + + + +
+ Alias for: use_renderers +
+ + + +
+ +
+

+ + use_renderers(*args) + +

+ + +
+

Adds, by name, a renderer or renderers to the _renderers available to call within controller actions.

+ +

It is useful when rendering from an ActionController::Metal controller or otherwise to add an available renderer proc to a specific controller.

+ +

Both ActionController::Base and ActionController::API include ActionController::Renderers::All, making all renderers available in the controller. See Renderers::RENDERERS and Renderers.add.

+ +

Since ActionController::Metal controllers cannot render, the controller must include AbstractController::Rendering, ActionController::Rendering, and ActionController::Renderers, and have at least one renderer.

+ +

Rather than including ActionController::Renderers::All and including all renderers, you may specify which renderers to include by passing the renderer name or names to use_renderers. For example, a controller that includes only the :json renderer (_render_with_renderer_json) might look like:

+ +
class MetalRenderingController < ActionController::Metal
+  include AbstractController::Rendering
+  include ActionController::Rendering
+  include ActionController::Renderers
+
+  use_renderers :json
+
+  def show
+    render json: record
+  end
+end
+
+ +

You must specify a use_renderer, else the controller.renderer and controller._renderers will be nil, and the action will fail.

+
+ + + +
+ Also aliased as: use_renderer +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/renderers.rb, line 128
+def use_renderers(*args)
+  renderers = _renderers + args
+  self._renderers = renderers.freeze
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Rendering.html b/src/7.0/classes/ActionController/Rendering.html new file mode 100644 index 0000000000..b9934deb65 --- /dev/null +++ b/src/7.0/classes/ActionController/Rendering.html @@ -0,0 +1,289 @@ +--- +title: ActionController::Rendering +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RENDER_FORMATS_IN_PRIORITY=[:body, :plain, :html]
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + render(*args) + +

+ + +
+

Renders a template and assigns the result to self.response_body.

+ +

If no rendering mode option is specified, the template will be derived from the first argument.

+ +
render "posts/show"
+# => renders app/views/posts/show.html.erb
+
+# In a PostsController action...
+render :show
+# => renders app/views/posts/show.html.erb
+
+ +

If the first argument responds to render_in, the template will be rendered by calling render_in with the current view context.

+ +

Rendering Mode

+
:partial +
+

See ActionView::PartialRenderer for details.

+ +
render partial: "posts/form", locals: { post: Post.new }
+# => renders app/views/posts/_form.html.erb
+
+
:file +
+

Renders the contents of a file. This option should not be used with unsanitized user input.

+ +
render file: "/path/to/some/file"
+# => renders /path/to/some/file
+
+
:inline +
+

Renders an ERB template string.

+ +
@name = "World"
+render inline: "<h1>Hello, <%= @name %>!</h1>"
+# => renders "<h1>Hello, World!</h1>"
+
+
:body +
+

Renders the provided text, and sets the content type as text/plain.

+ +
render body: "Hello, World!"
+# => renders "Hello, World!"
+
+
:plain +
+

Renders the provided text, and sets the content type as text/plain.

+ +
render plain: "Hello, World!"
+# => renders "Hello, World!"
+
+
:html +
+

Renders the provided HTML string, and sets the content type as text/html. If the string is not html_safe?, performs HTML escaping on the string before rendering.

+ +
render html: "<h1>Hello, World!</h1>".html_safe
+# => renders "<h1>Hello, World!</h1>"
+
+render html: "<h1>Hello, World!</h1>"
+# => renders "&lt;h1&gt;Hello, World!&lt;/h1&gt;"
+
+
:json +
+

Renders the provided object as JSON, and sets the content type as application/json. If the object is not a string, it will be converted to JSON by calling to_json.

+ +
render json: { hello: "world" }
+# => renders "{\"hello\":\"world\"}"
+
+
+ +

By default, when a rendering mode is specified, no layout template is rendered.

+ +

Options

+
:assigns +
+

Hash of instance variable assignments for the template.

+ +
render inline: "<h1>Hello, <%= @name %>!</h1>", assigns: { name: "World" }
+# => renders "<h1>Hello, World!</h1>"
+
+
:locals +
+

Hash of local variable assignments for the template.

+ +
render inline: "<h1>Hello, <%= name %>!</h1>", locals: { name: "World" }
+# => renders "<h1>Hello, World!</h1>"
+
+
:layout +
+

The layout template to render. Can also be false or true to disable or (re)enable the default layout template.

+ +
render "posts/show", layout: "holiday"
+# => renders app/views/posts/show.html.erb with the app/views/layouts/holiday.html.erb layout
+
+render "posts/show", layout: false
+# => renders app/views/posts/show.html.erb with no layout
+
+render inline: "<h1>Hello, World!</h1>", layout: true
+# => renders "<h1>Hello, World!</h1>" with the default layout
+
+
:status +
+

The HTTP status code to send with the response. Can be specified as a number or as the status name in Symbol form. Defaults to 200.

+ +
render "posts/new", status: 422
+# => renders app/views/posts/new.html.erb with HTTP status code 422
+
+render "posts/new", status: :unprocessable_entity
+# => renders app/views/posts/new.html.erb with HTTP status code 422
+
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/rendering.rb, line 137
+def render(*args)
+  raise ::AbstractController::DoubleRenderError if response_body
+  super
+end
+
+
+ +
+ +
+

+ + render_to_string(*) + +

+ + +
+

Similar to render, but only returns the rendered template as a string, instead of setting self.response_body.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/rendering.rb, line 146
+def render_to_string(*)
+  result = super
+  if result.respond_to?(:each)
+    string = +""
+    result.each { |r| string << r }
+    string
+  else
+    result
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Rendering/ClassMethods.html b/src/7.0/classes/ActionController/Rendering/ClassMethods.html new file mode 100644 index 0000000000..0c3df2f145 --- /dev/null +++ b/src/7.0/classes/ActionController/Rendering/ClassMethods.html @@ -0,0 +1,116 @@ +--- +title: ActionController::Rendering::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + renderer

Returns a renderer instance (inherited from ActionController::Renderer) for the controller.

+ + + + + +

Instance Public methods

+ +
+

+ + inherited(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/rendering.rb, line 21
+def inherited(klass)
+  klass.setup_renderer!
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection.html b/src/7.0/classes/ActionController/RequestForgeryProtection.html new file mode 100644 index 0000000000..88f7286ef7 --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection.html @@ -0,0 +1,1222 @@ +--- +title: ActionController::RequestForgeryProtection +layout: default +--- +
+ +
+
+ +
+ +

Controller actions are protected from Cross-Site Request Forgery (CSRF) attacks by including a token in the rendered HTML for your application. This token is stored as a random string in the session, to which an attacker does not have access. When a request reaches your application, Rails verifies the received token with the token in the session. All requests are checked except GET requests as these should be idempotent. Keep in mind that all session-oriented requests are CSRF protected by default, including JavaScript and HTML requests.

+ +

Since HTML and JavaScript requests are typically made from the browser, we need to ensure to verify request authenticity for the web browser. We can use session-oriented authentication for these types of requests, by using the protect_from_forgery method in our controllers.

+ +

GET requests are not protected since they don’t have side effects like writing to the database and don’t leak sensitive information. JavaScript requests are an exception: a third-party site can use a <script> tag to reference a JavaScript URL on your site. When your JavaScript response loads on their site, it executes. With carefully crafted JavaScript on their end, sensitive data in your JavaScript response may be extracted. To prevent this, only XmlHttpRequest (known as XHR or Ajax) requests are allowed to make requests for JavaScript responses.

+ +

Subclasses of ActionController::Base are protected by default with the :exception strategy, which raises an ActionController::InvalidAuthenticityToken error on unverified requests.

+ +

APIs may want to disable this behavior since they are typically designed to be state-less: that is, the request API client handles the session instead of Rails. One way to achieve this is to use the :null_session strategy instead, which allows unverified requests to be handled, but with an empty session:

+ +
class ApplicationController < ActionController::Base
+  protect_from_forgery with: :null_session
+end
+
+ +

Note that API only applications don’t include this module or a session middleware by default, and so don’t require CSRF protection to be configured.

+ +

The token parameter is named authenticity_token by default. The name and value of this token must be added to every layout that renders forms by including csrf_meta_tags in the HTML head.

+ +

Learn more about CSRF attacks and securing your application in the Ruby on Rails Security Guide.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
AUTHENTICITY_TOKEN_LENGTH=32
 
NULL_ORIGIN_MESSAGE=<<~MSG
 
+ + + + + + + +

Instance Private methods

+ +
+

+ + any_authenticity_token_valid?() + +

+ + +
+

Checks if any of the authenticity tokens from the request are valid.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 346
+def any_authenticity_token_valid? # :doc:
+  request_authenticity_tokens.any? do |token|
+    valid_authenticity_token?(session, token)
+  end
+end
+
+
+ +
+ +
+

+ + compare_with_global_token(token, session) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 432
+def compare_with_global_token(token, session) # :doc:
+  ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, global_csrf_token(session))
+end
+
+
+ +
+ +
+

+ + compare_with_real_token(token, session) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 428
+def compare_with_real_token(token, session) # :doc:
+  ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, real_csrf_token(session))
+end
+
+
+ +
+ +
+

+ + csrf_token_hmac(session, identifier) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 466
+def csrf_token_hmac(session, identifier) # :doc:
+  OpenSSL::HMAC.digest(
+    OpenSSL::Digest::SHA256.new,
+    real_csrf_token(session),
+    identifier
+  )
+end
+
+
+ +
+ +
+

+ + form_authenticity_param() + +

+ + +
+

The form’s authenticity parameter. Override to provide your own.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 486
+def form_authenticity_param # :doc:
+  params[request_forgery_protection_token]
+end
+
+
+ +
+ +
+

+ + form_authenticity_token(form_options: {}) + +

+ + +
+

Creates the authenticity token for the current request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 358
+def form_authenticity_token(form_options: {}) # :doc:
+  masked_authenticity_token(session, form_options: form_options)
+end
+
+
+ +
+ +
+

+ + global_csrf_token(session) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 462
+def global_csrf_token(session) # :doc:
+  csrf_token_hmac(session, GLOBAL_CSRF_TOKEN_IDENTIFIER)
+end
+
+
+ +
+ +
+

+ + handle_unverified_request() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 279
+def handle_unverified_request # :doc:
+  protection_strategy = forgery_protection_strategy.new(self)
+
+  if protection_strategy.respond_to?(:warning_message)
+    protection_strategy.warning_message = unverified_request_warning_message
+  end
+
+  protection_strategy.handle_unverified_request
+end
+
+
+ +
+ +
+

+ + mark_for_same_origin_verification!() + +

+ + +
+

GET requests are checked for cross-origin JavaScript after rendering.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 318
+def mark_for_same_origin_verification! # :doc:
+  @marked_for_same_origin_verification = request.get?
+end
+
+
+ +
+ +
+

+ + marked_for_same_origin_verification?() + +

+ + +
+

If the verify_authenticity_token before_action ran, verify that JavaScript responses are only served to same-origin GET requests.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 324
+def marked_for_same_origin_verification? # :doc:
+  @marked_for_same_origin_verification ||= false
+end
+
+
+ +
+ +
+

+ + mask_token(raw_token) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 421
+def mask_token(raw_token) # :doc:
+  one_time_pad = SecureRandom.random_bytes(AUTHENTICITY_TOKEN_LENGTH)
+  encrypted_csrf_token = xor_byte_strings(one_time_pad, raw_token)
+  masked_token = one_time_pad + encrypted_csrf_token
+  encode_csrf_token(masked_token)
+end
+
+
+ +
+ +
+

+ + non_xhr_javascript_response?() + +

+ + +
+

Check for cross-origin JavaScript responses.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 329
+def non_xhr_javascript_response? # :doc:
+  %r(\A(?:text|application)/javascript).match?(media_type) && !request.xhr?
+end
+
+
+ +
+ +
+

+ + normalize_action_path(action_path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 516
+def normalize_action_path(action_path) # :doc:
+  uri = URI.parse(action_path)
+  uri.path.chomp("/")
+end
+
+
+ +
+ +
+

+ + per_form_csrf_token(session, action_path, method) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 455
+def per_form_csrf_token(session, action_path, method) # :doc:
+  csrf_token_hmac(session, [action_path, method.downcase].join("#"))
+end
+
+
+ +
+ +
+

+ + protect_against_forgery?() + +

+ + +
+

Checks if the controller allows forgery protection.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 491
+def protect_against_forgery? # :doc:
+  allow_forgery_protection && (!session.respond_to?(:enabled?) || session.enabled?)
+end
+
+
+ +
+ +
+

+ + real_csrf_token(session) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 450
+def real_csrf_token(session) # :doc:
+  session[:_csrf_token] ||= generate_csrf_token
+  decode_csrf_token(session[:_csrf_token])
+end
+
+
+ +
+ +
+

+ + request_authenticity_tokens() + +

+ + +
+

Possible authenticity tokens sent in the request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 353
+def request_authenticity_tokens # :doc:
+  [form_authenticity_param, request.x_csrf_token]
+end
+
+
+ +
+ +
+

+ + unmask_token(masked_token) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 413
+def unmask_token(masked_token) # :doc:
+  # Split the token into the one-time pad and the encrypted
+  # value and decrypt it.
+  one_time_pad = masked_token[0...AUTHENTICITY_TOKEN_LENGTH]
+  encrypted_csrf_token = masked_token[AUTHENTICITY_TOKEN_LENGTH..-1]
+  xor_byte_strings(one_time_pad, encrypted_csrf_token)
+end
+
+
+ +
+ +
+

+ + valid_authenticity_token?(session, encoded_masked_token) + +

+ + +
+

Checks the client’s masked token to see if it matches the session token. Essentially the inverse of masked_authenticity_token.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 381
+def valid_authenticity_token?(session, encoded_masked_token) # :doc:
+  if encoded_masked_token.nil? || encoded_masked_token.empty? || !encoded_masked_token.is_a?(String)
+    return false
+  end
+
+  begin
+    masked_token = decode_csrf_token(encoded_masked_token)
+  rescue ArgumentError # encoded_masked_token is invalid Base64
+    return false
+  end
+
+  # See if it's actually a masked token or not. In order to
+  # deploy this code, we should be able to handle any unmasked
+  # tokens that we've issued without error.
+
+  if masked_token.length == AUTHENTICITY_TOKEN_LENGTH
+    # This is actually an unmasked token. This is expected if
+    # you have just upgraded to masked tokens, but should stop
+    # happening shortly after installing this gem.
+    compare_with_real_token masked_token, session
+
+  elsif masked_token.length == AUTHENTICITY_TOKEN_LENGTH * 2
+    csrf_token = unmask_token(masked_token)
+
+    compare_with_global_token(csrf_token, session) ||
+      compare_with_real_token(csrf_token, session) ||
+      valid_per_form_csrf_token?(csrf_token, session)
+  else
+    false # Token is malformed.
+  end
+end
+
+
+ +
+ +
+

+ + valid_per_form_csrf_token?(token, session) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 436
+def valid_per_form_csrf_token?(token, session) # :doc:
+  if per_form_csrf_tokens
+    correct_token = per_form_csrf_token(
+      session,
+      request.path.chomp("/"),
+      request.request_method
+    )
+
+    ActiveSupport::SecurityUtils.fixed_length_secure_compare(token, correct_token)
+  else
+    false
+  end
+end
+
+
+ +
+ +
+

+ + valid_request_origin?() + +

+ + +
+

Checks if the request originated from the same origin by looking at the Origin header.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 506
+def valid_request_origin? # :doc:
+  if forgery_protection_origin_check
+    # We accept blank origin headers because some user agents don't send it.
+    raise InvalidAuthenticityToken, NULL_ORIGIN_MESSAGE if request.origin == "null"
+    request.origin.nil? || request.origin == request.base_url
+  else
+    true
+  end
+end
+
+
+ +
+ +
+

+ + verified_request?() + +

+ + +
+

Returns true or false if a request is verified. Checks:

+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 340
+def verified_request? # :doc:
+  !protect_against_forgery? || request.get? || request.head? ||
+    (valid_request_origin? && any_authenticity_token_valid?)
+end
+
+
+ +
+ +
+

+ + verify_authenticity_token() + +

+ + +
+

The actual before_action that is used to verify the CSRF token. Don’t override this directly. Provide your own forgery protection strategy instead. If you override, you’ll disable same-origin <script> verification.

+ +

Lean on the protect_from_forgery declaration to mark which actions are due for same-origin request verification. If protect_from_forgery is enabled on an action, this before_action flags its after_action to verify that JavaScript responses are for XHR requests, ensuring they follow the browser’s same-origin policy.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 269
+def verify_authenticity_token # :doc:
+  mark_for_same_origin_verification!
+
+  if !verified_request?
+    logger.warn unverified_request_warning_message if logger && log_warning_on_csrf_failure
+
+    handle_unverified_request
+  end
+end
+
+
+ +
+ +
+

+ + verify_same_origin_request() + +

+ + +
+

If verify_authenticity_token was run (indicating that we have forgery protection enabled for this request) then also verify that we aren’t serving an unauthorized cross-origin response.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 308
+def verify_same_origin_request # :doc:
+  if marked_for_same_origin_verification? && non_xhr_javascript_response?
+    if logger && log_warning_on_csrf_failure
+      logger.warn CROSS_ORIGIN_JAVASCRIPT_WARNING
+    end
+    raise ActionController::InvalidCrossOriginRequest, CROSS_ORIGIN_JAVASCRIPT_WARNING
+  end
+end
+
+
+ +
+ +
+

+ + xor_byte_strings(s1, s2) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 474
+def xor_byte_strings(s1, s2) # :doc:
+  s2 = s2.dup
+  size = s1.bytesize
+  i = 0
+  while i < size
+    s2.setbyte(i, s1.getbyte(i) ^ s2.getbyte(i))
+    i += 1
+  end
+  s2
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection/ClassMethods.html b/src/7.0/classes/ActionController/RequestForgeryProtection/ClassMethods.html new file mode 100644 index 0000000000..7f1fab02cc --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection/ClassMethods.html @@ -0,0 +1,205 @@ +--- +title: ActionController::RequestForgeryProtection::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + protect_from_forgery(options = {}) + +

+ + +
+

Turn on request forgery protection. Bear in mind that GET and HEAD requests are not checked.

+ +
class ApplicationController < ActionController::Base
+  protect_from_forgery
+end
+
+class FooController < ApplicationController
+  protect_from_forgery except: :index
+end
+
+ +

You can disable forgery protection on a controller using skip_forgery_protection:

+ +
class BarController < ApplicationController
+  skip_forgery_protection
+end
+
+ +

Valid Options:

+
  • +

    :only / :except - Only apply forgery protection to a subset of actions. For example only: [ :create, :create_all ].

    +
  • +

    :if / :unless - Turn off the forgery protection entirely depending on the passed Proc or method reference.

    +
  • +

    :prepend - By default, the verification of the authentication token will be added at the position of the protect_from_forgery call in your application. This means any callbacks added before are run first. This is useful when you want your forgery protection to depend on other callbacks, like authentication methods (Oauth vs Cookie auth).

    + +

    If you need to add verification to the beginning of the callback chain, use prepend: true.

    +
  • +

    :with - Set the method to handle unverified request.

    +
+ +

Built-in unverified request handling methods are:

+
  • +

    :exception - Raises ActionController::InvalidAuthenticityToken exception.

    +
  • +

    :reset_session - Resets the session.

    +
  • +

    :null_session - Provides an empty session during request but doesn’t reset it completely. Used as default if :with option is not specified.

    +
+ +

You can also implement custom strategy classes for unverified request handling:

+ +
class CustomStrategy
+  def initialize(controller)
+    @controller = controller
+  end
+
+  def handle_unverified_request
+    # Custom behaviour for unverfied request
+  end
+end
+
+class ApplicationController < ActionController:x:Base
+  protect_from_forgery with: CustomStrategy
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 158
+def protect_from_forgery(options = {})
+  options = options.reverse_merge(prepend: false)
+
+  self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
+  self.request_forgery_protection_token ||= :authenticity_token
+  before_action :verify_authenticity_token, options
+  append_after_action :verify_same_origin_request
+end
+
+
+ +
+ +
+

+ + skip_forgery_protection(options = {}) + +

+ + +
+

Turn off request forgery protection. This is a wrapper for:

+ +
skip_before_action :verify_authenticity_token
+
+ +

See skip_before_action for allowed options.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 172
+def skip_forgery_protection(options = {})
+  skip_before_action :verify_authenticity_token, options.reverse_merge(raise: false)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods.html b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods.html new file mode 100644 index 0000000000..b458e9d7d0 --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods.html @@ -0,0 +1,71 @@ +--- +title: ActionController::RequestForgeryProtection::ProtectionMethods +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/Exception.html b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/Exception.html new file mode 100644 index 0000000000..38ef9f6cc2 --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/Exception.html @@ -0,0 +1,163 @@ +--- +title: ActionController::RequestForgeryProtection::ProtectionMethods::Exception +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + warning_message
+ + + + +

Class Public methods

+ +
+

+ + new(controller) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 248
+def initialize(controller)
+  @controller = controller
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + handle_unverified_request() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 252
+def handle_unverified_request
+  raise ActionController::InvalidAuthenticityToken, warning_message
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/NullSession.html b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/NullSession.html new file mode 100644 index 0000000000..f2672cbc4e --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/NullSession.html @@ -0,0 +1,153 @@ +--- +title: ActionController::RequestForgeryProtection::ProtectionMethods::NullSession +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(controller) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 195
+def initialize(controller)
+  @controller = controller
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + handle_unverified_request() + +

+ + +
+

This is the method that defines the application behavior when a request is found to be unverified.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 200
+def handle_unverified_request
+  request = @controller.request
+  request.session = NullSessionHash.new(request)
+  request.flash = nil
+  request.session_options = { skip: true }
+  request.cookie_jar = NullCookieJar.build(request, {})
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/ResetSession.html b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/ResetSession.html new file mode 100644 index 0000000000..ca0454db8b --- /dev/null +++ b/src/7.0/classes/ActionController/RequestForgeryProtection/ProtectionMethods/ResetSession.html @@ -0,0 +1,149 @@ +--- +title: ActionController::RequestForgeryProtection::ProtectionMethods::ResetSession +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(controller) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 236
+def initialize(controller)
+  @controller = controller
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + handle_unverified_request() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/request_forgery_protection.rb, line 240
+def handle_unverified_request
+  @controller.reset_session
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Rescue.html b/src/7.0/classes/ActionController/Rescue.html new file mode 100644 index 0000000000..71185f248a --- /dev/null +++ b/src/7.0/classes/ActionController/Rescue.html @@ -0,0 +1,121 @@ +--- +title: ActionController::Rescue +layout: default +--- +
+ +
+
+ +
+ +

This module is responsible for providing rescue_from to controllers, wrapping actions to handle configured errors, and configuring when detailed exceptions must be shown.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show_detailed_exceptions?() + +

+ + +
+

Override this method if you want to customize when detailed exceptions must be shown. This method is only called when consider_all_requests_local is false. By default, it returns false, but someone may set it to request.local? so local requests in production still show the detailed exception pages.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/rescue.rb, line 17
+def show_detailed_exceptions?
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/RespondToMismatchError.html b/src/7.0/classes/ActionController/RespondToMismatchError.html new file mode 100644 index 0000000000..34ac5daeac --- /dev/null +++ b/src/7.0/classes/ActionController/RespondToMismatchError.html @@ -0,0 +1,140 @@ +--- +title: ActionController::RespondToMismatchError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a nested respond_to is triggered and the content types of each are incompatible. For example:

+ +
respond_to do |outer_type|
+  outer_type.js do
+    respond_to do |inner_type|
+      inner_type.html { render body: "HTML" }
+    end
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_MESSAGE="respond_to was called multiple times and matched with conflicting formats in this action. Please note that you may only call respond_to and match on a single format per action."
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/exceptions.rb, line 89
+def initialize(message = nil)
+  super(message || DEFAULT_MESSAGE)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Streaming.html b/src/7.0/classes/ActionController/Streaming.html new file mode 100644 index 0000000000..a5ade37a40 --- /dev/null +++ b/src/7.0/classes/ActionController/Streaming.html @@ -0,0 +1,212 @@ +--- +title: ActionController::Streaming +layout: default +--- +
+ +
+
+ +
+ +

Allows views to be streamed back to the client as they are rendered.

+ +

By default, Rails renders views by first rendering the template and then the layout. The response is sent to the client after the whole template is rendered, all queries are made, and the layout is processed.

+ +

Streaming inverts the rendering flow by rendering the layout first and streaming each part of the layout as they are processed. This allows the header of the HTML (which is usually in the layout) to be streamed back to client very quickly, allowing JavaScripts and stylesheets to be loaded earlier than usual.

+ +

This approach was introduced in Rails 3.1 and is still improving. Several Rack middlewares may not work and you need to be careful when streaming. Those points are going to be addressed soon.

+ +

In order to use streaming, you will need to use a Ruby version that supports fibers (fibers are supported since version 1.9.2 of the main Ruby implementation).

+ +

Streaming can be added to a given template easily, all you need to do is to pass the :stream option.

+ +
class PostsController
+  def index
+    @posts = Post.all
+    render stream: true
+  end
+end
+
+ +

When to use streaming

+ +

Streaming may be considered to be overkill for lightweight actions like new or edit. The real benefit of streaming is on expensive actions that, for example, do a lot of queries on the database.

+ +

In such actions, you want to delay queries execution as much as you can. For example, imagine the following dashboard action:

+ +
def dashboard
+  @posts = Post.all
+  @pages = Page.all
+  @articles = Article.all
+end
+
+ +

Most of the queries here are happening in the controller. In order to benefit from streaming you would want to rewrite it as:

+ +
def dashboard
+  # Allow lazy execution of the queries
+  @posts = Post.all
+  @pages = Page.all
+  @articles = Article.all
+  render stream: true
+end
+
+ +

Notice that :stream only works with templates. Rendering :json or :xml with :stream won’t work.

+ +

Communication between layout and template

+ +

When streaming, rendering happens top-down instead of inside-out. Rails starts with the layout, and the template is rendered later, when its yield is reached.

+ +

This means that, if your application currently relies on instance variables set in the template to be used in the layout, they won’t work once you move to streaming. The proper way to communicate between layout and template, regardless of whether you use streaming or not, is by using content_for, provide, and yield.

+ +

Take a simple example where the layout expects the template to tell which title to use:

+ +
<html>
+  <head><title><%= yield :title %></title></head>
+  <body><%= yield %></body>
+</html>
+
+ +

You would use content_for in your template to specify the title:

+ +
<%= content_for :title, "Main" %>
+Hello
+
+ +

And the final result would be:

+ +
<html>
+  <head><title>Main</title></head>
+  <body>Hello</body>
+</html>
+
+ +

However, if content_for is called several times, the final result would have all calls concatenated. For instance, if we have the following template:

+ +
<%= content_for :title, "Main" %>
+Hello
+<%= content_for :title, " page" %>
+
+ +

The final result would be:

+ +
<html>
+  <head><title>Main page</title></head>
+  <body>Hello</body>
+</html>
+
+ +

This means that, if you have yield :title in your layout and you want to use streaming, you would have to render the whole template (and eventually trigger all queries) before streaming the title and all assets, which kills the purpose of streaming. For this purpose, you can use a helper called provide that does the same as content_for but tells the layout to stop searching for other entries and continue rendering.

+ +

For instance, the template above using provide would be:

+ +
<%= provide :title, "Main" %>
+Hello
+<%= content_for :title, " page" %>
+
+ +

Giving:

+ +
<html>
+  <head><title>Main</title></head>
+  <body>Hello</body>
+</html>
+
+ +

That said, when streaming, you need to properly check your templates and choose when to use provide and content_for.

+ +

Headers, cookies, session, and flash

+ +

When streaming, the HTTP headers are sent to the client right before it renders the first line. This means that, modifying headers, cookies, session or flash after the template starts rendering will not propagate to the client.

+ +

Middlewares

+ +

Middlewares that need to manipulate the body won’t work with streaming. You should disable those middlewares whenever streaming in development or production. For instance, Rack::Bug won’t work when streaming as it needs to inject contents in the HTML body.

+ +

Also Rack::Cache won’t work with streaming as it does not support streaming bodies yet. Whenever streaming Cache-Control is automatically set to “no-cache”.

+ +

Errors

+ +

When it comes to streaming, exceptions get a bit more complicated. This happens because part of the template was already rendered and streamed to the client, making it impossible to render a whole exception page.

+ +

Currently, when an exception happens in development or production, Rails will automatically stream to the client:

+ +
"><script>window.location = "/500.html"</script></html>
+
+ +

The first two characters (“>) are required in case the exception happens while rendering attributes for a given tag. You can check the real cause for the exception in your logger.

+ +

Web server support

+ +

Not all web servers support streaming out-of-the-box. You need to check the instructions for each of them.

+ +

Unicorn

+ +

Unicorn supports streaming but it needs to be configured. For this, you need to create a config file as follow:

+ +
# unicorn.config.rb
+listen 3000, tcp_nopush: false
+
+ +

And use it on initialization:

+ +
unicorn_rails --config-file unicorn.config.rb
+
+ +

You may also want to configure other parameters like :tcp_nodelay. Please check its documentation for more information: bogomips.org/unicorn/Unicorn/Configurator.html#method-i-listen

+ +

If you are using Unicorn with NGINX, you may need to tweak NGINX. Streaming should work out of the box on Rainbows.

+ +

Passenger

+ +

To be described.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/StrongParameters.html b/src/7.0/classes/ActionController/StrongParameters.html new file mode 100644 index 0000000000..b96cd33345 --- /dev/null +++ b/src/7.0/classes/ActionController/StrongParameters.html @@ -0,0 +1,215 @@ +--- +title: ActionController::StrongParameters +layout: default +--- +
+ +
+
+ +
+ +

Strong Parameters

+ +

It provides an interface for protecting attributes from end-user assignment. This makes Action Controller parameters forbidden to be used in Active Model mass assignment until they have been explicitly enumerated.

+ +

In addition, parameters can be marked as required and flow through a predefined raise/rescue flow to end up as a 400 Bad Request with no effort.

+ +
class PeopleController < ActionController::Base
+  # Using "Person.create(params[:person])" would raise an
+  # ActiveModel::ForbiddenAttributesError exception because it'd
+  # be using mass assignment without an explicit permit step.
+  # This is the recommended form:
+  def create
+    Person.create(person_params)
+  end
+
+  # This will pass with flying colors as long as there's a person key in the
+  # parameters, otherwise it'll raise an ActionController::ParameterMissing
+  # exception, which will get caught by ActionController::Base and turned
+  # into a 400 Bad Request reply.
+  def update
+    redirect_to current_account.people.find(params[:id]).tap { |person|
+      person.update!(person_params)
+    }
+  end
+
+  private
+    # Using a private method to encapsulate the permissible parameters is
+    # a good pattern since you'll be able to reuse the same permit
+    # list between create and update. Also, you can specialize this method
+    # with per-user checking of permissible attributes.
+    def person_params
+      params.require(:person).permit(:name, :age)
+    end
+end
+
+ +

In order to use accepts_nested_attributes_for with Strong Parameters, you will need to specify which nested attributes should be permitted. You might want to allow :id and :_destroy, see ActiveRecord::NestedAttributes for more information.

+ +
class Person
+  has_many :pets
+  accepts_nested_attributes_for :pets
+end
+
+class PeopleController < ActionController::Base
+  def create
+    Person.create(person_params)
+  end
+
+  ...
+
+  private
+
+    def person_params
+      # It's mandatory to specify the nested attributes that should be permitted.
+      # If you use `permit` with just the key that points to the nested attributes hash,
+      # it will return an empty hash.
+      params.require(:person).permit(:name, :age, pets_attributes: [ :id, :name, :category ])
+    end
+end
+
+ +

See ActionController::Parameters.require and ActionController::Parameters.permit for more information.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + params() + +

+ + +
+

Returns a new ActionController::Parameters object that has been instantiated with the request.parameters.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1201
+def params
+  @_params ||= begin
+    context = {
+      controller: self.class.name,
+      action: action_name,
+      request: request,
+      params: request.filtered_parameters
+    }
+    Parameters.new(request.parameters, context)
+  end
+end
+
+
+ +
+ +
+

+ + params=(value) + +

+ + +
+

Assigns the given value to the params hash. If value is a Hash, this will create an ActionController::Parameters object that has been instantiated with the given value hash.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/strong_parameters.rb, line 1216
+def params=(value)
+  @_params = value.is_a?(Hash) ? Parameters.new(value) : value
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/TestCase.html b/src/7.0/classes/ActionController/TestCase.html new file mode 100644 index 0000000000..a2312b91b0 --- /dev/null +++ b/src/7.0/classes/ActionController/TestCase.html @@ -0,0 +1,211 @@ +--- +title: ActionController::TestCase +layout: default +--- +
+ +
+
+ +
+ +

Superclass for ActionController functional tests. Functional tests allow you to test a single controller action per test method.

+ +

Use integration style controller tests over functional style controller tests.

+ +

Rails discourages the use of functional tests in favor of integration tests (use ActionDispatch::IntegrationTest).

+ +

New Rails applications no longer generate functional style controller tests and they should only be used for backward compatibility. Integration style controller tests perform actual requests, whereas functional style controller tests merely simulate a request. Besides, integration tests are as fast as functional tests and provide lot of helpers such as as, parsed_body for effective testing of controller actions including even API endpoints.

+ +

Basic example

+ +

Functional tests are written as follows:

+
  1. +

    First, one uses the get, post, patch, put, delete, or head method to simulate an HTTP request.

    +
  2. +

    Then, one asserts whether the current state is as expected. “State” can be anything: the controller’s HTTP response, the database contents, etc.

    +
+ +

For example:

+ +
class BooksControllerTest < ActionController::TestCase
+  def test_create
+    # Simulate a POST response with the given HTTP parameters.
+    post(:create, params: { book: { title: "Love Hina" }})
+
+    # Asserts that the controller tried to redirect us to
+    # the created book's URI.
+    assert_response :found
+
+    # Asserts that the controller really put the book in the database.
+    assert_not_nil Book.find_by(title: "Love Hina")
+  end
+end
+
+ +

You can also send a real document in the simulated HTTP request.

+ +
def test_create
+  json = {book: { title: "Love Hina" }}.to_json
+  post :create, body: json
+end
+
+ +

Special instance variables

+ +

ActionController::TestCase will also automatically provide the following instance variables for use in the tests:

+
@controller +
+

The controller instance that will be tested.

+
@request +
+

An ActionController::TestRequest, representing the current HTTP request. You can modify this object before sending the HTTP request. For example, you might want to set some session properties before sending a GET request.

+
@response +
+

An ActionDispatch::TestResponse object, representing the response of the last HTTP response. In the above example, @response becomes valid after calling post. If the various assert methods are not sufficient, then you may use this object to inspect the HTTP response in detail.

+
+ +

Controller is automatically inferred

+ +

ActionController::TestCase will automatically infer the controller under test from the test class name. If the controller cannot be inferred from the test class name, you can explicitly set it with tests.

+ +
class SpecialEdgeCaseWidgetsControllerTest < ActionController::TestCase
+  tests WidgetController
+end
+
+ +

Testing controller internals

+ +

In addition to these specific assertions, you also have easy access to various collections that the regular test/unit assertions can be used against. These collections are:

+
  • +

    session: Objects being saved in the session.

    +
  • +

    flash: The flash objects currently in the session.

    +
  • +

    cookies: Cookies being sent to the user on this request.

    +
+ +

These collections can be used just like any other hash:

+ +
assert_equal "Dave", cookies[:name] # makes sure that a cookie called :name was set as "Dave"
+assert flash.empty? # makes sure that there's nothing in the flash
+
+ +

On top of the collections, you have the complete URL that a given action redirected to available in redirect_to_url.

+ +

For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another action call which can then be asserted against.

+ +

Manipulating session and cookie variables

+ +

Sometimes you need to set up the session and cookie variables for a test. To do this just assign a value to the session or cookie collection:

+ +
session[:key] = "value"
+cookies[:key] = "value"
+
+ +

To clear the cookies for a test just clear the cookie collection:

+ +
cookies.clear
+
+ +

Testing named routes

+ +

If you’re using named routes, they can be easily tested using the original named routes’ methods straight in the test case.

+ +
assert_redirected_to page_url(title: 'foo')
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + executor_around_each_request
+ + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/TestCase/Behavior.html b/src/7.0/classes/ActionController/TestCase/Behavior.html new file mode 100644 index 0000000000..b2aa091428 --- /dev/null +++ b/src/7.0/classes/ActionController/TestCase/Behavior.html @@ -0,0 +1,718 @@ +--- +title: ActionController::TestCase::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + request
+ [R] + response
+ + + + + +

Instance Public methods

+ +
+

+ + build_response(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 554
+def build_response(klass)
+  klass.create
+end
+
+
+ +
+ +
+

+ + controller_class_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 514
+def controller_class_name
+  @controller.class.anonymous? ? "anonymous" : @controller.class.controller_path
+end
+
+
+ +
+ +
+

+ + delete(action, **args) + +

+ + +
+

Simulate a DELETE request with the given parameters and set/volley the response. See get for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 429
+def delete(action, **args)
+  process(action, method: "DELETE", **args)
+end
+
+
+ +
+ +
+

+ + generated_path(generated_extras) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 518
+def generated_path(generated_extras)
+  generated_extras[0]
+end
+
+
+ +
+ +
+

+ + get(action, **args) + +

+ + +
+

Simulate a GET request with the given parameters.

+
  • +

    action: The controller action to call.

    +
  • +

    params: The hash with HTTP parameters that you want to pass. This may be nil.

    +
  • +

    body: The request body with a string that is appropriately encoded (application/x-www-form-urlencoded or multipart/form-data).

    +
  • +

    session: A hash of parameters to store in the session. This may be nil.

    +
  • +

    flash: A hash of parameters to store in the flash. This may be nil.

    +
+ +

You can also simulate POST, PATCH, PUT, DELETE, and HEAD requests with post, patch, put, delete, and head. Example sending parameters, session, and setting a flash message:

+ +
get :show,
+  params: { id: 7 },
+  session: { user_id: 1 },
+  flash: { notice: 'This is flash message' }
+
+ +

Note that the request method is not verified. The different methods are available to make the tests more expressive.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 403
+def get(action, **args)
+  res = process(action, method: "GET", **args)
+  cookies.update res.cookies
+  res
+end
+
+
+ +
+ +
+

+ + head(action, **args) + +

+ + +
+

Simulate a HEAD request with the given parameters and set/volley the response. See get for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 435
+def head(action, **args)
+  process(action, method: "HEAD", **args)
+end
+
+
+ +
+ +
+

+ + patch(action, **args) + +

+ + +
+

Simulate a PATCH request with the given parameters and set/volley the response. See get for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 417
+def patch(action, **args)
+  process(action, method: "PATCH", **args)
+end
+
+
+ +
+ +
+

+ + post(action, **args) + +

+ + +
+

Simulate a POST request with the given parameters and set/volley the response. See get for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 411
+def post(action, **args)
+  process(action, method: "POST", **args)
+end
+
+
+ +
+ +
+

+ + process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil) + +

+ + +
+

Simulate an HTTP request to action by specifying request method, parameters and set/volley the response.

+
  • +

    action: The controller action to call.

    +
  • +

    method: Request method used to send the HTTP request. Possible values are GET, POST, PATCH, PUT, DELETE, HEAD. Defaults to GET. Can be a symbol.

    +
  • +

    params: The hash with HTTP parameters that you want to pass. This may be nil.

    +
  • +

    body: The request body with a string that is appropriately encoded (application/x-www-form-urlencoded or multipart/form-data).

    +
  • +

    session: A hash of parameters to store in the session. This may be nil.

    +
  • +

    flash: A hash of parameters to store in the flash. This may be nil.

    +
  • +

    format: Request format. Defaults to nil. Can be string or symbol.

    +
  • +

    as: Content type. Defaults to nil. Must be a symbol that corresponds to a mime type.

    +
+ +

Example calling create action and sending two params:

+ +
process :create,
+  method: 'POST',
+  params: {
+    user: { name: 'Gaurish Sharma', email: 'user@example.com' }
+  },
+  session: { user_id: 1 },
+  flash: { notice: 'This is flash message' }
+
+ +

To simulate GET, POST, PATCH, PUT, DELETE, and HEAD requests prefer using get, post, patch, put, delete and head methods respectively which will make tests more expressive.

+ +

It’s not recommended to make more than one request in the same test. Instance variables that are set in one request will not persist to the next request, but it’s not guaranteed that all Rails internal state will be reset. Prefer ActionDispatch::IntegrationTest for making multiple requests in the same test.

+ +

Note that the request method is not verified.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 474
+def process(action, method: "GET", params: nil, session: nil, body: nil, flash: {}, format: nil, xhr: false, as: nil)
+  check_required_ivars
+  @controller.clear_instance_variables_between_requests
+
+  action = +action.to_s
+  http_method = method.to_s.upcase
+
+  @html_document = nil
+
+  cookies.update(@request.cookies)
+  cookies.update_cookies_from_jar
+  @request.set_header "HTTP_COOKIE", cookies.to_header
+  @request.delete_header "action_dispatch.cookies"
+
+  @request          = TestRequest.new scrub_env!(@request.env), @request.session, @controller.class
+  @response         = build_response @response_klass
+  @response.request = @request
+  @controller.recycle!
+
+  if body
+    @request.set_header "RAW_POST_DATA", body
+  end
+
+  @request.set_header "REQUEST_METHOD", http_method
+
+  if as
+    @request.content_type = Mime[as].to_s
+    format ||= as
+  end
+
+  parameters = (params || {}).symbolize_keys
+
+  if format
+    parameters[:format] = format
+  end
+
+  setup_request(controller_class_name, action, parameters, session, flash, xhr)
+  process_controller_response(action, cookies, xhr)
+end
+
+
+ +
+ +
+

+ + put(action, **args) + +

+ + +
+

Simulate a PUT request with the given parameters and set/volley the response. See get for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 423
+def put(action, **args)
+  process(action, method: "PUT", **args)
+end
+
+
+ +
+ +
+

+ + query_parameter_names(generated_extras) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 522
+def query_parameter_names(generated_extras)
+  generated_extras[1] + [:controller, :action]
+end
+
+
+ +
+ +
+

+ + setup_controller_request_and_response() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 526
+def setup_controller_request_and_response
+  @controller = nil unless defined? @controller
+
+  @response_klass = ActionDispatch::TestResponse
+
+  if klass = self.class.controller_class
+    if klass < ActionController::Live
+      @response_klass = LiveTestResponse
+    end
+    unless @controller
+      begin
+        @controller = klass.new
+      rescue
+        warn "could not construct controller #{klass}" if $VERBOSE
+      end
+    end
+  end
+
+  @request          = TestRequest.create(@controller.class)
+  @response         = build_response @response_klass
+  @response.request = @request
+
+  if @controller
+    @controller.request = @request
+    @controller.params = {}
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/TestCase/Behavior/ClassMethods.html b/src/7.0/classes/ActionController/TestCase/Behavior/ClassMethods.html new file mode 100644 index 0000000000..39d941860f --- /dev/null +++ b/src/7.0/classes/ActionController/TestCase/Behavior/ClassMethods.html @@ -0,0 +1,236 @@ +--- +title: ActionController::TestCase::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + controller_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 368
+def controller_class
+  if current_controller_class = _controller_class
+    current_controller_class
+  else
+    self.controller_class = determine_default_controller_class(name)
+  end
+end
+
+
+ +
+ +
+

+ + controller_class=(new_class) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 364
+def controller_class=(new_class)
+  self._controller_class = new_class
+end
+
+
+ +
+ +
+

+ + determine_default_controller_class(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 376
+def determine_default_controller_class(name)
+  determine_constant_from_test_name(name) do |constant|
+    Class === constant && constant < ActionController::Metal
+  end
+end
+
+
+ +
+ +
+

+ + tests(controller_class) + +

+ + +
+

Sets the controller class name. Useful if the name can’t be inferred from test class. Normalizes controller_class before using.

+ +
tests WidgetController
+tests :widget
+tests 'widget'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/test_case.rb, line 353
+def tests(controller_class)
+  case controller_class
+  when String, Symbol
+    self.controller_class = "#{controller_class.to_s.camelize}Controller".constantize
+  when Class
+    self.controller_class = controller_class
+  else
+    raise ArgumentError, "controller class must be a String, Symbol, or Class"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/Testing.html b/src/7.0/classes/ActionController/Testing.html new file mode 100644 index 0000000000..d1a0445860 --- /dev/null +++ b/src/7.0/classes/ActionController/Testing.html @@ -0,0 +1,54 @@ +--- +title: ActionController::Testing +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/UnfilteredParameters.html b/src/7.0/classes/ActionController/UnfilteredParameters.html new file mode 100644 index 0000000000..40d9ab3208 --- /dev/null +++ b/src/7.0/classes/ActionController/UnfilteredParameters.html @@ -0,0 +1,71 @@ +--- +title: ActionController::UnfilteredParameters +layout: default +--- +
+ +
+
+ +
+ +

Raised when a Parameters instance is not marked as permitted and an operation to transform it to hash is called.

+ +
params = ActionController::Parameters.new(a: "123", b: "456")
+params.to_h
+# => ActionController::UnfilteredParameters: unable to convert unpermitted parameters to hash
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/UnpermittedParameters.html b/src/7.0/classes/ActionController/UnpermittedParameters.html new file mode 100644 index 0000000000..a804ee4664 --- /dev/null +++ b/src/7.0/classes/ActionController/UnpermittedParameters.html @@ -0,0 +1,71 @@ +--- +title: ActionController::UnpermittedParameters +layout: default +--- +
+ +
+
+ +
+ +

Raised when a supplied parameter is not expected and ActionController::Parameters.action_on_unpermitted_parameters is set to :raise.

+ +
params = ActionController::Parameters.new(a: "123", b: "456")
+params.permit(:c)
+# => ActionController::UnpermittedParameters: found unpermitted parameters: :a, :b
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionController/UrlFor.html b/src/7.0/classes/ActionController/UrlFor.html new file mode 100644 index 0000000000..c3eb65767e --- /dev/null +++ b/src/7.0/classes/ActionController/UrlFor.html @@ -0,0 +1,160 @@ +--- +title: ActionController::UrlFor +layout: default +--- +
+ +
+
+ +
+ +

Includes url_for into the host class. The class has to provide a RouteSet by implementing the _routes method. Otherwise, an exception will be raised.

+ +

In addition to AbstractController::UrlFor, this module accesses the HTTP layer to define URL options like the host. In order to do so, this module requires the host class to implement env which needs to be Rack-compatible, and request which returns an ActionDispatch::Request instance.

+ +
class RootUrl
+  include ActionController::UrlFor
+  include Rails.application.routes.url_helpers
+
+  delegate :env, :request, to: :controller
+
+  def initialize(controller)
+    @controller = controller
+    @url        = root_path # named route from the application.
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + url_options() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_controller/metal/url_for.rb, line 28
+def url_options
+  @_url_options ||= {
+    host: request.host,
+    port: request.optional_port,
+    protocol: request.protocol,
+    _recall: request.path_parameters
+  }.merge!(super).freeze
+
+  if (same_origin = _routes.equal?(request.routes)) ||
+     (script_name = request.engine_script_name(_routes)) ||
+     (original_script_name = request.original_script_name)
+
+    options = @_url_options.dup
+    if original_script_name
+      options[:original_script_name] = original_script_name
+    else
+      if same_origin
+        options[:script_name] = request.script_name.empty? ? "" : request.script_name.dup
+      else
+        options[:script_name] = script_name
+      end
+    end
+    options.freeze
+  else
+    @_url_options
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch.html b/src/7.0/classes/ActionDispatch.html new file mode 100644 index 0000000000..1229793d7c --- /dev/null +++ b/src/7.0/classes/ActionDispatch.html @@ -0,0 +1,348 @@ +--- +title: ActionDispatch +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionDispatch/AssertionResponse.html b/src/7.0/classes/ActionDispatch/AssertionResponse.html new file mode 100644 index 0000000000..46fbef3075 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/AssertionResponse.html @@ -0,0 +1,186 @@ +--- +title: ActionDispatch::AssertionResponse +layout: default +--- +
+ +
+
+ +
+ +

This is a class that abstracts away an asserted response. It purposely does not inherit from Response because it doesn’t need it. That means it does not have headers or a body.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + code
+ [R] + name
+ + + + +

Class Public methods

+ +
+

+ + new(code_or_name) + +

+ + +
+

Accepts a specific response status code as an Integer (404) or String (‘404’) or a response status range as a Symbol pseudo-code (:success, indicating any 200-299 status code).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertion_response.rb, line 20
+def initialize(code_or_name)
+  if code_or_name.is_a?(Symbol)
+    @name = code_or_name
+    @code = code_from_name(code_or_name)
+  else
+    @name = name_from_code(code_or_name)
+    @code = code_or_name
+  end
+
+  raise ArgumentError, "Invalid response name: #{name}" if @code.nil?
+  raise ArgumentError, "Invalid response code: #{code}" if @name.nil?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + code_and_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertion_response.rb, line 33
+def code_and_name
+  "#{code}: #{name}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Assertions.html b/src/7.0/classes/ActionDispatch/Assertions.html new file mode 100644 index 0000000000..4d517481e4 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Assertions.html @@ -0,0 +1,152 @@ +--- +title: ActionDispatch::Assertions +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + html_document() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions.rb, line 13
+def html_document
+  @html_document ||= if @response.media_type&.end_with?("xml")
+    Nokogiri::XML::Document.parse(@response.body)
+  else
+    Nokogiri::HTML::Document.parse(@response.body)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Assertions/ResponseAssertions.html b/src/7.0/classes/ActionDispatch/Assertions/ResponseAssertions.html new file mode 100644 index 0000000000..84570f9417 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Assertions/ResponseAssertions.html @@ -0,0 +1,190 @@ +--- +title: ActionDispatch::Assertions::ResponseAssertions +layout: default +--- +
+ +
+
+ +
+ +

A small suite of assertions that test responses from Rails applications.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_redirected_to(options = {}, message = nil) + +

+ + +
+

Asserts that the response is a redirect to a URL matching the given options.

+ +
# Asserts that the redirection was to the "index" action on the WeblogController
+assert_redirected_to controller: "weblog", action: "index"
+
+# Asserts that the redirection was to the named route login_url
+assert_redirected_to login_url
+
+# Asserts that the redirection was to the URL for @customer
+assert_redirected_to @customer
+
+# Asserts that the redirection matches the regular expression
+assert_redirected_to %r(\Ahttp://example.org)
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/response.rb, line 53
+def assert_redirected_to(options = {}, message = nil)
+  assert_response(:redirect, message)
+  return true if options === @response.location
+
+  redirect_is       = normalize_argument_to_redirection(@response.location)
+  redirect_expected = normalize_argument_to_redirection(options)
+
+  message ||= "Expected response to be a redirect to <#{redirect_expected}> but was a redirect to <#{redirect_is}>"
+  assert_operator redirect_expected, :===, redirect_is, message
+end
+
+
+ +
+ +
+

+ + assert_response(type, message = nil) + +

+ + +
+

Asserts that the response is one of the following types:

+
  • +

    :success - Status code was in the 200-299 range

    +
  • +

    :redirect - Status code was in the 300-399 range

    +
  • +

    :missing - Status code was 404

    +
  • +

    :error - Status code was in the 500-599 range

    +
+ +

You can also pass an explicit status number like assert_response(501) or its symbolic equivalent assert_response(:not_implemented). See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list.

+ +
# Asserts that the response was a redirection
+assert_response :redirect
+
+# Asserts that the response code was status code 401 (unauthorized)
+assert_response 401
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/response.rb, line 30
+def assert_response(type, message = nil)
+  message ||= generate_response_message(type)
+
+  if RESPONSE_PREDICATES.keys.include?(type)
+    assert @response.public_send(RESPONSE_PREDICATES[type]), message
+  else
+    assert_equal AssertionResponse.new(type).code, @response.response_code, message
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Assertions/RoutingAssertions.html b/src/7.0/classes/ActionDispatch/Assertions/RoutingAssertions.html new file mode 100644 index 0000000000..4eb205229c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Assertions/RoutingAssertions.html @@ -0,0 +1,405 @@ +--- +title: ActionDispatch::Assertions::RoutingAssertions +layout: default +--- +
+ +
+
+ +
+ +

Suite of assertions to test routes generated by Rails and the handling of requests made to them.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil) + +

+ + +
+

Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.

+ +

The defaults parameter is unused.

+ +
# Asserts that the default action is generated for a route with no action
+assert_generates "/items", controller: "items", action: "index"
+
+# Tests that the list action is properly routed
+assert_generates "/items/list", controller: "items", action: "list"
+
+# Tests the generation of a route with a parameter
+assert_generates "/items/list/1", { controller: "items", action: "list", id: "1" }
+
+# Asserts that the generated route gives us our custom route
+assert_generates "changesets/12", { controller: 'scm', action: 'show_diff', revision: "12" }
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/routing.rb, line 85
+def assert_generates(expected_path, options, defaults = {}, extras = {}, message = nil)
+  if %r{://}.match?(expected_path)
+    fail_on(URI::InvalidURIError, message) do
+      uri = URI.parse(expected_path)
+      expected_path = uri.path.to_s.empty? ? "/" : uri.path
+    end
+  else
+    expected_path = "/#{expected_path}" unless expected_path.start_with?("/")
+  end
+
+  options = options.clone
+  generated_path, query_string_keys = @routes.generate_extras(options, defaults)
+  found_extras = options.reject { |k, _| ! query_string_keys.include? k }
+
+  msg = message || sprintf("found extras <%s>, not <%s>", found_extras, extras)
+  assert_equal(extras, found_extras, msg)
+
+  msg = message || sprintf("The generated path <%s> did not match <%s>", generated_path,
+      expected_path)
+  assert_equal(expected_path, generated_path, msg)
+end
+
+
+ +
+ +
+

+ + assert_recognizes(expected_options, path, extras = {}, msg = nil) + +

+ + +
+

Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.

+ +

Pass a hash in the second argument (path) to specify the request method. This is useful for routes requiring a specific HTTP method. The hash should contain a :path with the incoming request path and a :method containing the required HTTP verb.

+ +
# Asserts that POSTing to /items will call the create action on ItemsController
+assert_recognizes({controller: 'items', action: 'create'}, {path: 'items', method: :post})
+
+ +

You can also pass in extras with a hash containing URL parameters that would normally be in the query string. This can be used to assert that values in the query string will end up in the params hash correctly. To test query strings you must use the extras argument because appending the query string on the path directly will not work. For example:

+ +
# Asserts that a path of '/items/list/1?view=print' returns the correct options
+assert_recognizes({controller: 'items', action: 'list', id: '1', view: 'print'}, 'items/list/1', { view: "print" })
+
+ +

The message parameter allows you to pass in an error message that is displayed upon failure.

+ +
# Check the default route (i.e., the index action)
+assert_recognizes({controller: 'items', action: 'index'}, 'items')
+
+# Test a specific action
+assert_recognizes({controller: 'items', action: 'list'}, 'items/list')
+
+# Test an action with a parameter
+assert_recognizes({controller: 'items', action: 'destroy', id: '1'}, 'items/destroy/1')
+
+# Test a custom route
+assert_recognizes({controller: 'items', action: 'show', id: '1'}, 'view/item1')
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/routing.rb, line 47
+def assert_recognizes(expected_options, path, extras = {}, msg = nil)
+  if path.is_a?(Hash) && path[:method].to_s == "all"
+    [:get, :post, :put, :delete].each do |method|
+      assert_recognizes(expected_options, path.merge(method: method), extras, msg)
+    end
+  else
+    request = recognized_request_for(path, extras, msg)
+
+    expected_options = expected_options.clone
+
+    expected_options.stringify_keys!
+
+    msg = message(msg, "") {
+      sprintf("The recognized options <%s> did not match <%s>, difference:",
+              request.path_parameters, expected_options)
+    }
+
+    assert_equal(expected_options, request.path_parameters, msg)
+  end
+end
+
+
+ +
+ +
+

+ + assert_routing(path, options, defaults = {}, extras = {}, message = nil) + +

+ + +
+

Asserts that path and options match both ways; in other words, it verifies that path generates options and then that options generates path. This essentially combines assert_recognizes and assert_generates into one step.

+ +

The extras hash allows you to specify options that would normally be provided as a query string to the action. The message parameter allows you to specify a custom error message to display upon failure.

+ +
# Asserts a basic route: a controller with the default action (index)
+assert_routing '/home', controller: 'home', action: 'index'
+
+# Test a route generated with a specific controller, action, and parameter (id)
+assert_routing '/entries/show/23', controller: 'entries', action: 'show', id: 23
+
+# Asserts a basic route (controller + default action), with an error message if it fails
+assert_routing '/store', { controller: 'store', action: 'index' }, {}, {}, 'Route for store index not generated properly'
+
+# Tests a route, providing a defaults hash
+assert_routing 'controller/action/9', {id: "9", item: "square"}, {controller: "controller", action: "action"}, {}, {item: "square"}
+
+# Tests a route with an HTTP method
+assert_routing({ method: 'put', path: '/product/321' }, { controller: "product", action: "update", id: "321" })
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/routing.rb, line 128
+def assert_routing(path, options, defaults = {}, extras = {}, message = nil)
+  assert_recognizes(options, path, extras, message)
+
+  controller, default_controller = options[:controller], defaults[:controller]
+  if controller && controller.include?(?/) && default_controller && default_controller.include?(?/)
+    options[:controller] = "/#{controller}"
+  end
+
+  generate_options = options.dup.delete_if { |k, _| defaults.key?(k) }
+  assert_generates(path.is_a?(Hash) ? path[:path] : path, generate_options, defaults, extras, message)
+end
+
+
+ +
+ +
+

+ + method_missing(selector, *args, &block) + +

+ + +
+

ROUTES TODO: These assertions should really work in an integration context

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/routing.rb, line 183
+def method_missing(selector, *args, &block)
+  if defined?(@controller) && @controller && defined?(@routes) && @routes && @routes.named_routes.route_defined?(selector)
+    @controller.public_send(selector, *args, &block)
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + with_routing() + +

+ + +
+

A helper to make it easier to test different route configurations. This method temporarily replaces @routes with a new RouteSet instance.

+ +

The new instance is yielded to the passed block. Typically the block will create some routes using set.draw { match ... }:

+ +
with_routing do |set|
+  set.draw do
+    resources :users
+  end
+  assert_equal "/users", users_path
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/assertions/routing.rb, line 153
+def with_routing
+  old_routes, @routes = @routes, ActionDispatch::Routing::RouteSet.new
+  if defined?(@controller) && @controller
+    old_controller, @controller = @controller, @controller.clone
+    _routes = @routes
+
+    @controller.singleton_class.include(_routes.url_helpers)
+
+    if @controller.respond_to? :view_context_class
+      view_context_class = Class.new(@controller.view_context_class) do
+        include _routes.url_helpers
+      end
+
+      custom_view_context = Module.new {
+        define_method(:view_context_class) do
+          view_context_class
+        end
+      }
+      @controller.extend(custom_view_context)
+    end
+  end
+  yield @routes
+ensure
+  @routes = old_routes
+  if defined?(@controller) && @controller
+    @controller = old_controller
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Callbacks.html b/src/7.0/classes/ActionDispatch/Callbacks.html new file mode 100644 index 0000000000..8fa21f81ec --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Callbacks.html @@ -0,0 +1,253 @@ +--- +title: ActionDispatch::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Provides callbacks to be executed before and after dispatching the request.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + after(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/callbacks.rb, line 15
+def after(*args, &block)
+  set_callback(:call, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + before(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/callbacks.rb, line 11
+def before(*args, &block)
+  set_callback(:call, :before, *args, &block)
+end
+
+
+ +
+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/callbacks.rb, line 20
+def initialize(app)
+  @app = app
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/callbacks.rb, line 24
+def call(env)
+  error = nil
+  result = run_callbacks :call do
+    @app.call(env)
+  rescue => error
+  end
+  raise error if error
+  result
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ContentSecurityPolicy.html b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy.html new file mode 100644 index 0000000000..24981cf51e --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy.html @@ -0,0 +1,551 @@ +--- +title: ActionDispatch::ContentSecurityPolicy +layout: default +--- +
+ +
+
+ +
+ +

Configures the HTTP Content-Security-Policy response header to help protect against XSS and injection attacks.

+ +

Example global policy:

+ +
Rails.application.config.content_security_policy do |policy|
+  policy.default_src :self, :https
+  policy.font_src    :self, :https, :data
+  policy.img_src     :self, :https, :data
+  policy.object_src  :none
+  policy.script_src  :self, :https
+  policy.style_src   :self, :https
+
+  # Specify URI for violation reports
+  policy.report_uri "/csp-violation-report-endpoint"
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + directives
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 173
+def initialize
+  @directives = {}
+  yield self if block_given?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + block_all_mixed_content(enabled = true) + +

+ + +
+

Specify whether to prevent the user agent from loading any assets over HTTP when the page uses HTTPS:

+ +
policy.block_all_mixed_content
+
+ +

Pass false to allow it again:

+ +
policy.block_all_mixed_content false
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 201
+def block_all_mixed_content(enabled = true)
+  if enabled
+    @directives["block-all-mixed-content"] = true
+  else
+    @directives.delete("block-all-mixed-content")
+  end
+end
+
+
+ +
+ +
+

+ + build(context = nil, nonce = nil, nonce_directives = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 290
+def build(context = nil, nonce = nil, nonce_directives = nil)
+  nonce_directives = DEFAULT_NONCE_DIRECTIVES if nonce_directives.nil?
+  build_directives(context, nonce, nonce_directives).compact.join("; ")
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 178
+def initialize_copy(other)
+  @directives = other.directives.deep_dup
+end
+
+
+ +
+ +
+

+ + plugin_types(*types) + +

+ + +
+

Restricts the set of plugins that can be embedded:

+ +
policy.plugin_types "application/x-shockwave-flash"
+
+ +

Leave empty to allow all plugins:

+ +
policy.plugin_types
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 217
+def plugin_types(*types)
+  if types.first
+    @directives["plugin-types"] = types
+  else
+    @directives.delete("plugin-types")
+  end
+end
+
+
+ +
+ +
+

+ + report_uri(uri) + +

+ + +
+

Enable the report-uri directive. Violation reports will be sent to the specified URI:

+ +
policy.report_uri "/csp-violation-report-endpoint"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 230
+def report_uri(uri)
+  @directives["report-uri"] = [uri]
+end
+
+
+ +
+ +
+

+ + require_sri_for(*types) + +

+ + +
+

Specify asset types for which Subresource Integrity is required:

+ +
policy.require_sri_for :script, :style
+
+ +

Leave empty to not require Subresource Integrity:

+ +
policy.require_sri_for
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 243
+def require_sri_for(*types)
+  if types.first
+    @directives["require-sri-for"] = types
+  else
+    @directives.delete("require-sri-for")
+  end
+end
+
+
+ +
+ +
+

+ + sandbox(*values) + +

+ + +
+

Specify whether a sandbox should be enabled for the requested resource:

+ +
policy.sandbox
+
+ +

Values can be passed as arguments:

+ +
policy.sandbox "allow-scripts", "allow-modals"
+
+ +

Pass false to disable the sandbox:

+ +
policy.sandbox false
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 264
+def sandbox(*values)
+  if values.empty?
+    @directives["sandbox"] = true
+  elsif values.first
+    @directives["sandbox"] = values
+  else
+    @directives.delete("sandbox")
+  end
+end
+
+
+ +
+ +
+

+ + upgrade_insecure_requests(enabled = true) + +

+ + +
+

Specify whether user agents should treat any assets over HTTP as HTTPS:

+ +
policy.upgrade_insecure_requests
+
+ +

Pass false to disable it:

+ +
policy.upgrade_insecure_requests false
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 282
+def upgrade_insecure_requests(enabled = true)
+  if enabled
+    @directives["upgrade-insecure-requests"] = true
+  else
+    @directives.delete("upgrade-insecure-requests")
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Middleware.html b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Middleware.html new file mode 100644 index 0000000000..b77f06596a --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Middleware.html @@ -0,0 +1,207 @@ +--- +title: ActionDispatch::ContentSecurityPolicy::Middleware +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_TYPE="Content-Type"
 
POLICY="Content-Security-Policy"
 
POLICY_REPORT_ONLY="Content-Security-Policy-Report-Only"
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 30
+def initialize(app)
+  @app = app
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 34
+def call(env)
+  request = ActionDispatch::Request.new env
+  status, headers, _ = response = @app.call(env)
+
+  # Returning CSP headers with a 304 Not Modified is harmful, since nonces in the new
+  # CSP headers might not match nonces in the cached HTML.
+  return response if status == 304
+
+  return response if policy_present?(headers)
+
+  if policy = request.content_security_policy
+    nonce = request.content_security_policy_nonce
+    nonce_directives = request.content_security_policy_nonce_directives
+    context = request.controller_instance || request
+    headers[header_name(request)] = policy.build(context, nonce, nonce_directives)
+  end
+
+  response
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Request.html b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Request.html new file mode 100644 index 0000000000..b8f3e89034 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ContentSecurityPolicy/Request.html @@ -0,0 +1,485 @@ +--- +title: ActionDispatch::ContentSecurityPolicy::Request +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NONCE="action_dispatch.content_security_policy_nonce"
 
NONCE_DIRECTIVES="action_dispatch.content_security_policy_nonce_directives"
 
NONCE_GENERATOR="action_dispatch.content_security_policy_nonce_generator"
 
POLICY="action_dispatch.content_security_policy"
 
POLICY_REPORT_ONLY="action_dispatch.content_security_policy_report_only"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + content_security_policy() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 75
+def content_security_policy
+  get_header(POLICY)
+end
+
+
+ +
+ +
+

+ + content_security_policy=(policy) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 79
+def content_security_policy=(policy)
+  set_header(POLICY, policy)
+end
+
+
+ +
+ +
+

+ + content_security_policy_nonce() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 107
+def content_security_policy_nonce
+  if content_security_policy_nonce_generator
+    if nonce = get_header(NONCE)
+      nonce
+    else
+      set_header(NONCE, generate_content_security_policy_nonce)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + content_security_policy_nonce_directives() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 99
+def content_security_policy_nonce_directives
+  get_header(NONCE_DIRECTIVES)
+end
+
+
+ +
+ +
+

+ + content_security_policy_nonce_directives=(generator) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 103
+def content_security_policy_nonce_directives=(generator)
+  set_header(NONCE_DIRECTIVES, generator)
+end
+
+
+ +
+ +
+

+ + content_security_policy_nonce_generator() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 91
+def content_security_policy_nonce_generator
+  get_header(NONCE_GENERATOR)
+end
+
+
+ +
+ +
+

+ + content_security_policy_nonce_generator=(generator) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 95
+def content_security_policy_nonce_generator=(generator)
+  set_header(NONCE_GENERATOR, generator)
+end
+
+
+ +
+ +
+

+ + content_security_policy_report_only() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 83
+def content_security_policy_report_only
+  get_header(POLICY_REPORT_ONLY)
+end
+
+
+ +
+ +
+

+ + content_security_policy_report_only=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/content_security_policy.rb, line 87
+def content_security_policy_report_only=(value)
+  set_header(POLICY_REPORT_ONLY, value)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Cookies.html b/src/7.0/classes/ActionDispatch/Cookies.html new file mode 100644 index 0000000000..886d9e84f9 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Cookies.html @@ -0,0 +1,480 @@ +--- +title: ActionDispatch::Cookies +layout: default +--- +
+ +
+
+ +
+ +

Read and write data to cookies through ActionController::Base#cookies.

+ +

When reading cookie data, the data is read from the HTTP request header, Cookie. When writing cookie data, the data is sent out in the HTTP response header, Set-Cookie.

+ +

Examples of writing:

+ +
# Sets a simple session cookie.
+# This cookie will be deleted when the user's browser is closed.
+cookies[:user_name] = "david"
+
+# Cookie values are String-based. Other data types need to be serialized.
+cookies[:lat_lon] = JSON.generate([47.68, -122.37])
+
+# Sets a cookie that expires in 1 hour.
+cookies[:login] = { value: "XJ-122", expires: 1.hour }
+
+# Sets a cookie that expires at a specific time.
+cookies[:login] = { value: "XJ-122", expires: Time.utc(2020, 10, 15, 5) }
+
+# Sets a signed cookie, which prevents users from tampering with its value.
+# It can be read using the signed method `cookies.signed[:name]`
+cookies.signed[:user_id] = current_user.id
+
+# Sets an encrypted cookie value before sending it to the client which
+# prevent users from reading and tampering with its value.
+# It can be read using the encrypted method `cookies.encrypted[:name]`
+cookies.encrypted[:discount] = 45
+
+# Sets a "permanent" cookie (which expires in 20 years from now).
+cookies.permanent[:login] = "XJ-122"
+
+# You can also chain these methods:
+cookies.signed.permanent[:login] = "XJ-122"
+
+ +

Examples of reading:

+ +
cookies[:user_name]           # => "david"
+cookies.size                  # => 2
+JSON.parse(cookies[:lat_lon]) # => [47.68, -122.37]
+cookies.signed[:login]        # => "XJ-122"
+cookies.encrypted[:discount]  # => 45
+
+ +

Example for deleting:

+ +
cookies.delete :user_name
+
+ +

Please note that if you specify a :domain when setting a cookie, you must also specify the domain when deleting the cookie:

+ +
cookies[:name] = {
+  value: 'a yummy cookie',
+  expires: 1.year,
+  domain: 'domain.com'
+}
+
+cookies.delete(:name, domain: 'domain.com')
+
+ +

The option symbols for setting cookies are:

+
  • +

    :value - The cookie’s value.

    +
  • +

    :path - The path for which this cookie applies. Defaults to the root of the application.

    +
  • +

    :domain - The domain for which this cookie applies so you can restrict to the domain level. If you use a schema like www.example.com and want to share session with user.example.com set :domain to :all. To support multiple domains, provide an array, and the first domain matching request.host will be used. Make sure to specify the :domain option with :all or Array again when deleting cookies.

    + +
    domain: nil  # Does not set cookie domain. (default)
    +domain: :all # Allow the cookie for the top most level
    +             # domain and subdomains.
    +domain: %w(.example.com .example.org) # Allow the cookie
    +                                      # for concrete domain names.
    +
    +
  • +

    :tld_length - When using :domain => :all, this option can be used to explicitly set the TLD length when using a short (<= 3 character) domain that is being interpreted as part of a TLD. For example, to share cookies between user1.lvh.me and user2.lvh.me, set :tld_length to 2.

    +
  • +

    :expires - The time at which this cookie expires, as a Time or ActiveSupport::Duration object.

    +
  • +

    :secure - Whether this cookie is only transmitted to HTTPS servers. Default is false.

    +
  • +

    :httponly - Whether this cookie is accessible via scripting or only HTTP. Defaults to false.

    +
  • +

    :same_site - The value of the SameSite cookie attribute, which determines how this cookie should be restricted in cross-site contexts. Possible values are :none, :lax, and :strict. Defaults to :lax.

    +
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AUTHENTICATED_ENCRYPTED_COOKIE_SALT="action_dispatch.authenticated_encrypted_cookie_salt"
 
COOKIES_DIGEST="action_dispatch.cookies_digest"
 
COOKIES_ROTATIONS="action_dispatch.cookies_rotations"
 
COOKIES_SAME_SITE_PROTECTION="action_dispatch.cookies_same_site_protection"
 
COOKIES_SERIALIZER="action_dispatch.cookies_serializer"
 
CookieOverflow=Class.new StandardError
 

Raised when storing more than 4K of session data.

ENCRYPTED_COOKIE_CIPHER="action_dispatch.encrypted_cookie_cipher"
 
ENCRYPTED_COOKIE_SALT="action_dispatch.encrypted_cookie_salt"
 
ENCRYPTED_SIGNED_COOKIE_SALT="action_dispatch.encrypted_signed_cookie_salt"
 
GENERATOR_KEY="action_dispatch.key_generator"
 
HTTP_HEADER="Set-Cookie"
 
MAX_COOKIE_SIZE=4096
 

Cookies can typically store 4096 bytes.

SECRET_KEY_BASE="action_dispatch.secret_key_base"
 
SIGNED_COOKIE_DIGEST="action_dispatch.signed_cookie_digest"
 
SIGNED_COOKIE_SALT="action_dispatch.signed_cookie_salt"
 
USE_AUTHENTICATED_COOKIE_ENCRYPTION="action_dispatch.use_authenticated_cookie_encryption"
 
USE_COOKIES_WITH_METADATA="action_dispatch.use_cookies_with_metadata"
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 697
+def initialize(app)
+  @app = app
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 701
+def call(env)
+  request = ActionDispatch::Request.new env
+
+  status, headers, body = @app.call(env)
+
+  if request.have_cookie_jar?
+    cookie_jar = request.cookie_jar
+    unless cookie_jar.committed?
+      cookie_jar.write(headers)
+      if headers[HTTP_HEADER].respond_to?(:join)
+        headers[HTTP_HEADER] = headers[HTTP_HEADER].join("\n")
+      end
+    end
+  end
+
+  [status, headers, body]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Cookies/ChainedCookieJars.html b/src/7.0/classes/ActionDispatch/Cookies/ChainedCookieJars.html new file mode 100644 index 0000000000..a216733d9d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Cookies/ChainedCookieJars.html @@ -0,0 +1,263 @@ +--- +title: ActionDispatch::Cookies::ChainedCookieJars +layout: default +--- +
+ +
+
+ +
+ +

Include in a cookie jar to allow chaining, e.g. cookies.permanent.signed.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + encrypted() + +

+ + +
+

Returns a jar that’ll automatically encrypt cookie values before sending them to the client and will decrypt them for read. If the cookie was tampered with by the user (or a 3rd party), nil will be returned.

+ +

If config.action_dispatch.encrypted_cookie_salt and config.action_dispatch.encrypted_signed_cookie_salt are both set, legacy cookies encrypted with HMAC AES-256-CBC will be transparently upgraded.

+ +

This jar requires that you set a suitable secret for the verification on your app’s secret_key_base.

+ +

Example:

+ +
cookies.encrypted[:discount] = 45
+# => Set-Cookie: discount=DIQ7fw==--K3n//8vvnSbGq9dA--7Xh91HfLpwzbj1czhBiwOg==; path=/
+
+cookies.encrypted[:discount] # => 45
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 252
+def encrypted
+  @encrypted ||= EncryptedKeyRotatingCookieJar.new(self)
+end
+
+
+ +
+ +
+

+ + permanent() + +

+ + +
+

Returns a jar that’ll automatically set the assigned cookies to have an expiration date 20 years from now. Example:

+ +
cookies.permanent[:prefers_open_id] = true
+# => Set-Cookie: prefers_open_id=true; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
+
+ +

This jar is only meant for writing. You’ll read permanent cookies through the regular accessor.

+ +

This jar allows chaining with the signed jar as well, so you can set permanent, signed cookies. Examples:

+ +
cookies.permanent.signed[:remember_me] = current_user.id
+# => Set-Cookie: remember_me=BAhU--848956038e692d7046deab32b7131856ab20e14e; path=/; expires=Sun, 16-Dec-2029 03:24:16 GMT
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 218
+def permanent
+  @permanent ||= PermanentCookieJar.new(self)
+end
+
+
+ +
+ +
+

+ + signed() + +

+ + +
+

Returns a jar that’ll automatically generate a signed representation of cookie value and verify it when reading from the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed cookie was tampered with by the user (or a 3rd party), nil will be returned.

+ +

This jar requires that you set a suitable secret for the verification on your app’s secret_key_base.

+ +

Example:

+ +
cookies.signed[:discount] = 45
+# => Set-Cookie: discount=BAhpMg==--2c1c6906c90a3bc4fd54a51ffb41dffa4bf6b5f7; path=/
+
+cookies.signed[:discount] # => 45
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 234
+def signed
+  @signed ||= SignedKeyRotatingCookieJar.new(self)
+end
+
+
+ +
+ +
+

+ + signed_or_encrypted() + +

+ + +
+

Returns the signed or encrypted jar, preferring encrypted if secret_key_base is set. Used by ActionDispatch::Session::CookieStore to avoid the need to introduce new cookie stores.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/cookies.rb, line 258
+def signed_or_encrypted
+  @signed_or_encrypted ||=
+    if request.secret_key_base.present?
+      encrypted
+    else
+      signed
+    end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/DebugExceptions.html b/src/7.0/classes/ActionDispatch/DebugExceptions.html new file mode 100644 index 0000000000..0ad165785b --- /dev/null +++ b/src/7.0/classes/ActionDispatch/DebugExceptions.html @@ -0,0 +1,210 @@ +--- +title: ActionDispatch::DebugExceptions +layout: default +--- +
+ +
+
+ +
+ +

This middleware is responsible for logging exceptions and showing a debugging page in case the request is local.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/debug_exceptions.rb, line 19
+def initialize(app, routes_app = nil, response_format = :default, interceptors = self.class.interceptors)
+  @app             = app
+  @routes_app      = routes_app
+  @response_format = response_format
+  @interceptors    = interceptors
+end
+
+
+ +
+ +
+

+ + register_interceptor(object = nil, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/debug_exceptions.rb, line 14
+def self.register_interceptor(object = nil, &block)
+  interceptor = object || block
+  interceptors << interceptor
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/debug_exceptions.rb, line 26
+def call(env)
+  request = ActionDispatch::Request.new env
+  _, headers, body = response = @app.call(env)
+
+  if headers["X-Cascade"] == "pass"
+    body.close if body.respond_to?(:close)
+    raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
+  end
+
+  response
+rescue Exception => exception
+  invoke_interceptors(request, exception)
+  raise exception unless request.show_exceptions?
+  render_exception(request, exception)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/DebugLocks.html b/src/7.0/classes/ActionDispatch/DebugLocks.html new file mode 100644 index 0000000000..ec559daa82 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/DebugLocks.html @@ -0,0 +1,178 @@ +--- +title: ActionDispatch::DebugLocks +layout: default +--- +
+ +
+
+ +
+ +

This middleware can be used to diagnose deadlocks in the autoload interlock.

+ +

To use it, insert it near the top of the middleware stack, using config/application.rb:

+ +
config.middleware.insert_before Rack::Sendfile, ActionDispatch::DebugLocks
+
+ +

After restarting the application and re-triggering the deadlock condition, the route /rails/locks will show a summary of all threads currently known to the interlock, which lock level they are holding or awaiting, and their current backtrace.

+ +

Generally a deadlock will be caused by the interlock conflicting with some other external lock or blocking I/O call. These cannot be automatically identified, but should be visible in the displayed backtraces.

+ +

NOTE: The formatting and content of this middleware’s output is intended for human consumption, and should be expected to change between releases.

+ +

This middleware exposes operational details of the server, with no access control. It should only be enabled when in use, and removed thereafter.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, path = "/rails/locks") + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/debug_locks.rb, line 26
+def initialize(app, path = "/rails/locks")
+  @app = app
+  @path = path
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/debug_locks.rb, line 31
+def call(env)
+  req = ActionDispatch::Request.new env
+
+  if req.get?
+    path = req.path_info.chomp("/")
+    if path == @path
+      return render_details(req)
+    end
+  end
+
+  @app.call(env)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ExceptionWrapper.html b/src/7.0/classes/ActionDispatch/ExceptionWrapper.html new file mode 100644 index 0000000000..e5490d7ffe --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ExceptionWrapper.html @@ -0,0 +1,709 @@ +--- +title: ActionDispatch::ExceptionWrapper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + backtrace_cleaner
+ [R] + exception
+ [R] + file
+ [R] + line_number
+ [R] + wrapped_causes
+ + + + +

Class Public methods

+ +
+

+ + new(backtrace_cleaner, exception) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 46
+def initialize(backtrace_cleaner, exception)
+  @backtrace_cleaner = backtrace_cleaner
+  @exception = exception
+  @exception_class_name = @exception.class.name
+  @wrapped_causes = wrapped_causes_for(exception, backtrace_cleaner)
+
+  expand_backtrace if exception.is_a?(SyntaxError) || exception.cause.is_a?(SyntaxError)
+end
+
+
+ +
+ +
+

+ + status_code_for_exception(class_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 117
+def self.status_code_for_exception(class_name)
+  Rack::Utils.status_code(@@rescue_responses[class_name])
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + application_trace() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 77
+def application_trace
+  clean_backtrace(:silent)
+end
+
+
+ +
+ +
+

+ + exception_trace() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 71
+def exception_trace
+  trace = application_trace
+  trace = framework_trace if trace.empty? && !silent_exceptions.include?(@exception_class_name)
+  trace
+end
+
+
+ +
+ +
+

+ + framework_trace() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 81
+def framework_trace
+  clean_backtrace(:noise)
+end
+
+
+ +
+ +
+

+ + full_trace() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 85
+def full_trace
+  clean_backtrace(:all)
+end
+
+
+ +
+ +
+

+ + rescue_response?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 121
+def rescue_response?
+  @@rescue_responses.key?(exception.class.name)
+end
+
+
+ +
+ +
+

+ + rescue_template() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 63
+def rescue_template
+  @@rescue_templates[@exception_class_name]
+end
+
+
+ +
+ +
+

+ + source_extracts() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 125
+def source_extracts
+  backtrace.map do |trace|
+    file, line_number = extract_file_and_line_number(trace)
+
+    {
+      code: source_fragment(file, line_number),
+      line_number: line_number
+    }
+  end
+end
+
+
+ +
+ +
+

+ + source_to_show_id() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 144
+def source_to_show_id
+  (traces[trace_to_show].first || {})[:id]
+end
+
+
+ +
+ +
+

+ + status_code() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 67
+def status_code
+  self.class.status_code_for_exception(unwrapped_exception.class.name)
+end
+
+
+ +
+ +
+

+ + trace_to_show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 136
+def trace_to_show
+  if traces["Application Trace"].empty? && rescue_template != "routing_error"
+    "Full Trace"
+  else
+    "Application Trace"
+  end
+end
+
+
+ +
+ +
+

+ + traces() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 89
+def traces
+  application_trace_with_ids = []
+  framework_trace_with_ids = []
+  full_trace_with_ids = []
+
+  full_trace.each_with_index do |trace, idx|
+    trace_with_id = {
+      exception_object_id: @exception.object_id,
+      id: idx,
+      trace: trace
+    }
+
+    if application_trace.include?(trace)
+      application_trace_with_ids << trace_with_id
+    else
+      framework_trace_with_ids << trace_with_id
+    end
+
+    full_trace_with_ids << trace_with_id
+  end
+
+  {
+    "Application Trace" => application_trace_with_ids,
+    "Framework Trace" => framework_trace_with_ids,
+    "Full Trace" => full_trace_with_ids
+  }
+end
+
+
+ +
+ +
+

+ + unwrapped_exception() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/exception_wrapper.rb, line 55
+def unwrapped_exception
+  if wrapper_exceptions.include?(@exception_class_name)
+    exception.cause
+  else
+    exception
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Executor.html b/src/7.0/classes/ActionDispatch/Executor.html new file mode 100644 index 0000000000..249ad0d4dd --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Executor.html @@ -0,0 +1,158 @@ +--- +title: ActionDispatch::Executor +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, executor) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/executor.rb, line 7
+def initialize(app, executor)
+  @app, @executor = app, executor
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/executor.rb, line 11
+def call(env)
+  state = @executor.run!(reset: true)
+  begin
+    response = @app.call(env)
+    returned = response << ::Rack::BodyProxy.new(response.pop) { state.complete! }
+  rescue => error
+    @executor.error_reporter.report(error, handled: false)
+    raise
+  ensure
+    state.complete! unless returned
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/FileHandler.html b/src/7.0/classes/ActionDispatch/FileHandler.html new file mode 100644 index 0000000000..f9434cae21 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/FileHandler.html @@ -0,0 +1,236 @@ +--- +title: ActionDispatch::FileHandler +layout: default +--- +
+ +
+
+ +
+ +

This endpoint serves static files from disk using Rack::File.

+ +

URL paths are matched with static files according to expected conventions: path, path.html, path/index.html.

+ +

Precompressed versions of these files are checked first. Brotli (.br) and gzip (.gz) files are supported. If path.br exists, this endpoint returns that file with a Content-Encoding: br header.

+ +

If no matching file is found, this endpoint responds 404 Not Found.

+ +

Pass the root directory to search for matching files, an optional index: "index" to change the default path/index.html, and optional additional response headers.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PRECOMPRESSED={ +"br" => ".br", +"gzip" => ".gz", +"identity" => nil +}
 

Accept-Encoding value -> file extension

+ + + + + + +

Class Public methods

+ +
+

+ + new(root, index: "index", headers: {}, precompressed: %i[ br gzip ], compressible_content_types: /\A(?:text\/|application\/javascript)/) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/static.rb, line 49
+def initialize(root, index: "index", headers: {}, precompressed: %i[ br gzip ], compressible_content_types: /\A(?:text\/|application\/javascript)/)
+  @root = root.chomp("/").b
+  @index = index
+
+  @precompressed = Array(precompressed).map(&:to_s) | %w[ identity ]
+  @compressible_content_types = compressible_content_types
+
+  @file_server = ::Rack::File.new(@root, headers)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attempt(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/static.rb, line 63
+def attempt(env)
+  request = Rack::Request.new env
+
+  if request.get? || request.head?
+    if found = find_file(request.path_info, accept_encoding: request.accept_encoding)
+      serve request, *found
+    end
+  end
+end
+
+
+ +
+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/static.rb, line 59
+def call(env)
+  attempt(env) || @file_server.call(env)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Flash.html b/src/7.0/classes/ActionDispatch/Flash.html new file mode 100644 index 0000000000..08fab138f6 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Flash.html @@ -0,0 +1,181 @@ +--- +title: ActionDispatch::Flash +layout: default +--- +
+ +
+
+ +
+ +

The flash provides a way to pass temporary primitive-types (String, Array, Hash) between actions. Anything you place in the flash will be exposed to the very next action and then cleared out. This is a great way of doing notices and alerts, such as a create action that sets flash[:notice] = "Post successfully created" before redirecting to a display action that can then expose the flash to its template. Actually, that exposure is automatically done.

+ +
class PostsController < ActionController::Base
+  def create
+    # save post
+    flash[:notice] = "Post successfully created"
+    redirect_to @post
+  end
+
+  def show
+    # doesn't need to assign the flash notice to the template, that's done automatically
+  end
+end
+
+ +

Then in show.html.erb:

+ +
<% if flash[:notice] %>
+  <div class="notice"><%= flash[:notice] %></div>
+<% end %>
+
+ +

Since the notice and alert keys are a common idiom, convenience accessors are available:

+ +
flash.alert = "You must be logged in"
+flash.notice = "Post successfully created"
+
+ +

This example places a string in the flash. And of course, you can put as many as you like at a time too. If you want to pass non-primitive types, you will have to handle that in your application. Example: To show messages with links, you will have to use sanitize helper.

+ +

Just remember: They’ll be gone by the time the next action has been performed.

+ +

See docs on the FlashHash class for more details about the flash.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
KEY="action_dispatch.request.flash_hash"
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 293
+def self.new(app) app; end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Flash/FlashHash.html b/src/7.0/classes/ActionDispatch/Flash/FlashHash.html new file mode 100644 index 0000000000..a7a5e73844 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Flash/FlashHash.html @@ -0,0 +1,869 @@ +--- +title: ActionDispatch::Flash::FlashHash +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + [](k) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 160
+def [](k)
+  @flashes[k.to_s]
+end
+
+
+ +
+ +
+

+ + []=(k, v) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 154
+def []=(k, v)
+  k = k.to_s
+  @discard.delete k
+  @flashes[k] = v
+end
+
+
+ +
+ +
+

+ + alert() + +

+ + +
+

Convenience accessor for flash[:alert].

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 261
+def alert
+  self[:alert]
+end
+
+
+ +
+ +
+

+ + alert=(message) + +

+ + +
+

Convenience accessor for flash[:alert]=.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 266
+def alert=(message)
+  self[:alert] = message
+end
+
+
+ +
+ +
+

+ + clear() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 193
+def clear
+  @discard.clear
+  @flashes.clear
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 178
+def delete(key)
+  key = key.to_s
+  @discard.delete key
+  @flashes.delete key
+  self
+end
+
+
+ +
+ +
+

+ + discard(k = nil) + +

+ + +
+

Marks the entire flash or a single flash entry to be discarded by the end of the current action:

+ +
flash.discard              # discard the entire flash at the end of the current action
+flash.discard(:warning)    # discard only the "warning" entry at the end of the current action
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 246
+def discard(k = nil)
+  k = k.to_s if k
+  @discard.merge Array(k || keys)
+  k ? self[k] : self
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 198
+def each(&block)
+  @flashes.each(&block)
+end
+
+
+ +
+ +
+

+ + empty?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 189
+def empty?
+  @flashes.empty?
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 146
+def initialize_copy(other)
+  if other.now_is_loaded?
+    @now = other.now.dup
+    @now.flash = self
+  end
+  super
+end
+
+
+ +
+ +
+

+ + keep(k = nil) + +

+ + +
+

Keeps either the entire current flash or a specific flash entry available for the next action:

+ +
flash.keep            # keeps the entire flash
+flash.keep(:notice)   # keeps only the "notice" entry, the rest of the flash is discarded
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 236
+def keep(k = nil)
+  k = k.to_s if k
+  @discard.subtract Array(k || keys)
+  k ? self[k] : self
+end
+
+
+ +
+ +
+

+ + key?(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 174
+def key?(name)
+  @flashes.key? name.to_s
+end
+
+
+ +
+ +
+

+ + keys() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 170
+def keys
+  @flashes.keys
+end
+
+
+ +
+ +
+

+ + notice() + +

+ + +
+

Convenience accessor for flash[:notice].

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 271
+def notice
+  self[:notice]
+end
+
+
+ +
+ +
+

+ + notice=(message) + +

+ + +
+

Convenience accessor for flash[:notice]=.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 276
+def notice=(message)
+  self[:notice] = message
+end
+
+
+ +
+ +
+

+ + now() + +

+ + +
+

Sets a flash that will not be available to the next action, only to the current.

+ +
flash.now[:message] = "Hello current action"
+
+ +

This method enables you to use the flash as a central messaging system in your app. When you need to pass an object to the next action, you use the standard flash assign ([]=). When you need to pass an object to the current action, you use now, and your object will vanish when the current action is done.

+ +

Entries set via now are accessed the same way as standard entries: flash['my-key'].

+ +

Also, brings two convenience accessors:

+ +
flash.now.alert = "Beware now!"
+# Equivalent to flash.now[:alert] = "Beware now!"
+
+flash.now.notice = "Good luck now!"
+# Equivalent to flash.now[:notice] = "Good luck now!"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 228
+def now
+  @now ||= FlashNow.new(self)
+end
+
+
+ +
+ +
+

+ + to_hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 185
+def to_hash
+  @flashes.dup
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + now_is_loaded?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 281
+def now_is_loaded?
+  @now
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + stringify_array(array) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 286
+def stringify_array(array) # :doc:
+  array.map do |item|
+    item.kind_of?(Symbol) ? item.to_s : item
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Flash/RequestMethods.html b/src/7.0/classes/ActionDispatch/Flash/RequestMethods.html new file mode 100644 index 0000000000..195509a502 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Flash/RequestMethods.html @@ -0,0 +1,144 @@ +--- +title: ActionDispatch::Flash::RequestMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + flash() + +

+ + +
+

Access the contents of the flash. Returns a ActionDispatch::Flash::FlashHash.

+ +

See ActionDispatch::Flash for example usage.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 48
+def flash
+  flash = flash_hash
+  return flash if flash
+  self.flash = Flash::FlashHash.from_session_value(session["flash"])
+end
+
+
+ +
+ +
+

+ + flash=(flash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/flash.rb, line 54
+def flash=(flash)
+  set_header Flash::KEY, flash
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/HostAuthorization.html b/src/7.0/classes/ActionDispatch/HostAuthorization.html new file mode 100644 index 0000000000..952f824172 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/HostAuthorization.html @@ -0,0 +1,197 @@ +--- +title: ActionDispatch::HostAuthorization +layout: default +--- +
+ +
+
+ +
+ +

This middleware guards from DNS rebinding attacks by explicitly permitting the hosts a request can be sent to, and is passed the options set in config.host_authorization.

+ +

Requests can opt-out of Host Authorization with exclude:

+ +
config.host_authorization = { exclude: ->(request) { request.path =~ /healthcheck/ } }
+
+ +

When a request comes to an unauthorized host, the response_app application will be executed and rendered. If no response_app is given, a default one will run. The default response app logs blocked host info with level ‘error’ and responds with 403 Forbidden. The body of the response contains debug info if config.consider_all_requests_local is set to true, otherwise the body is empty.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ALLOWED_HOSTS_IN_DEVELOPMENT=[".localhost", IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")]
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(app, hosts, exclude: nil, response_app: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/host_authorization.rb, line 122
+def initialize(app, hosts, exclude: nil, response_app: nil)
+  @app = app
+  @permissions = Permissions.new(hosts)
+  @exclude = exclude
+
+  @response_app = response_app || DefaultResponseApp.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/host_authorization.rb, line 130
+def call(env)
+  return @app.call(env) if @permissions.empty?
+
+  request = Request.new(env)
+  hosts = blocked_hosts(request)
+
+  if hosts.empty? || excluded?(request)
+    mark_as_authorized(request)
+    @app.call(env)
+  else
+    env["action_dispatch.blocked_hosts"] = hosts
+    @response_app.call(env)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http.html b/src/7.0/classes/ActionDispatch/Http.html new file mode 100644 index 0000000000..da0bef438a --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http.html @@ -0,0 +1,116 @@ +--- +title: ActionDispatch::Http +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Cache.html b/src/7.0/classes/ActionDispatch/Http/Cache.html new file mode 100644 index 0000000000..db7b7298de --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Cache.html @@ -0,0 +1,69 @@ +--- +title: ActionDispatch::Http::Cache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Cache/Request.html b/src/7.0/classes/ActionDispatch/Http/Cache/Request.html new file mode 100644 index 0000000000..77d6d8c09c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Cache/Request.html @@ -0,0 +1,339 @@ +--- +title: ActionDispatch::Http::Cache::Request +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
HTTP_IF_MODIFIED_SINCE="HTTP_IF_MODIFIED_SINCE"
 
HTTP_IF_NONE_MATCH="HTTP_IF_NONE_MATCH"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + etag_matches?(etag) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 28
+def etag_matches?(etag)
+  if etag
+    validators = if_none_match_etags
+    validators.include?(etag) || validators.include?("*")
+  end
+end
+
+
+ +
+ +
+

+ + fresh?(response) + +

+ + +
+

Check response freshness (Last-Modified and ETag) against request If-Modified-Since and If-None-Match conditions. If both headers are supplied, both must match, or the request is not considered fresh.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 38
+def fresh?(response)
+  last_modified = if_modified_since
+  etag          = if_none_match
+
+  return false unless last_modified || etag
+
+  success = true
+  success &&= not_modified?(response.last_modified) if last_modified
+  success &&= etag_matches?(response.etag) if etag
+  success
+end
+
+
+ +
+ +
+

+ + if_modified_since() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 10
+def if_modified_since
+  if since = get_header(HTTP_IF_MODIFIED_SINCE)
+    Time.rfc2822(since) rescue nil
+  end
+end
+
+
+ +
+ +
+

+ + if_none_match() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 16
+def if_none_match
+  get_header HTTP_IF_NONE_MATCH
+end
+
+
+ +
+ +
+

+ + if_none_match_etags() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 20
+def if_none_match_etags
+  if_none_match ? if_none_match.split(",").each(&:strip!) : []
+end
+
+
+ +
+ +
+

+ + not_modified?(modified_at) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 24
+def not_modified?(modified_at)
+  if_modified_since && modified_at && if_modified_since >= modified_at
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Cache/Response.html b/src/7.0/classes/ActionDispatch/Http/Cache/Response.html new file mode 100644 index 0000000000..a2f87635a9 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Cache/Response.html @@ -0,0 +1,666 @@ +--- +title: ActionDispatch::Http::Cache::Response +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DATE="Date"
 
DEFAULT_CACHE_CONTROL="max-age=0, private, must-revalidate"
 
LAST_MODIFIED="Last-Modified"
 
MUST_REVALIDATE="must-revalidate"
 
NO_CACHE="no-cache"
 
NO_STORE="no-store"
 
PRIVATE="private"
 
PUBLIC="public"
 
SPECIAL_KEYS=Set.new(%w[extras no-store no-cache max-age public private must-revalidate])
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + cache_control
+ + + + + +

Instance Public methods

+ +
+

+ + date() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 68
+def date
+  if date_header = get_header(DATE)
+    Time.httpdate(date_header)
+  end
+end
+
+
+ +
+ +
+

+ + date=(utc_time) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 78
+def date=(utc_time)
+  set_header DATE, utc_time.httpdate
+end
+
+
+ +
+ +
+

+ + date?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 74
+def date?
+  has_header? DATE
+end
+
+
+ +
+ +
+

+ + etag=(weak_validators) + +

+ + +
+

This method sets a weak ETag validator on the response so browsers and proxies may cache the response, keyed on the ETag. On subsequent requests, the If-None-Match header is set to the cached ETag. If it matches the current ETag, we can return a 304 Not Modified response with no body, letting the browser or proxy know that their cache is current. Big savings in request time and network bandwidth.

+ +

Weak ETags are considered to be semantically equivalent but not byte-for-byte identical. This is perfect for browser caching of HTML pages where we don’t care about exact equality, just what the user is viewing.

+ +

Strong ETags are considered byte-for-byte identical. They allow a browser or proxy cache to support Range requests, useful for paging through a PDF file or scrubbing through a video. Some CDNs only support strong ETags and will ignore weak ETags entirely.

+ +

Weak ETags are what we almost always need, so they’re the default. Check out strong_etag= to provide a strong ETag validator.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 101
+def etag=(weak_validators)
+  self.weak_etag = weak_validators
+end
+
+
+ +
+ +
+

+ + etag?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 113
+def etag?; etag; end
+
+
+ +
+ +
+

+ + last_modified() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 54
+def last_modified
+  if last = get_header(LAST_MODIFIED)
+    Time.httpdate(last)
+  end
+end
+
+
+ +
+ +
+

+ + last_modified=(utc_time) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 64
+def last_modified=(utc_time)
+  set_header LAST_MODIFIED, utc_time.httpdate
+end
+
+
+ +
+ +
+

+ + last_modified?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 60
+def last_modified?
+  has_header? LAST_MODIFIED
+end
+
+
+ +
+ +
+

+ + strong_etag=(strong_validators) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 109
+def strong_etag=(strong_validators)
+  set_header "ETag", generate_strong_etag(strong_validators)
+end
+
+
+ +
+ +
+

+ + strong_etag?() + +

+ + +
+

True if an ETag is set, and it isn’t a weak validator (not preceded with W/).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 121
+def strong_etag?
+  etag? && !weak_etag?
+end
+
+
+ +
+ +
+

+ + weak_etag=(weak_validators) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 105
+def weak_etag=(weak_validators)
+  set_header "ETag", generate_weak_etag(weak_validators)
+end
+
+
+ +
+ +
+

+ + weak_etag?() + +

+ + +
+

True if an ETag is set, and it’s a weak validator (preceded with W/).

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/cache.rb, line 116
+def weak_etag?
+  etag? && etag.start_with?('W/"')
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/FilterParameters.html b/src/7.0/classes/ActionDispatch/Http/FilterParameters.html new file mode 100644 index 0000000000..0a3e8fd687 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/FilterParameters.html @@ -0,0 +1,434 @@ +--- +title: ActionDispatch::Http::FilterParameters +layout: default +--- +
+ +
+
+ +
+ +

Allows you to specify sensitive query string and POST parameters to filter from the request log.

+ +
# Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
+env["action_dispatch.parameter_filter"] = [:foo, "bar"]
+
+ +

For more information about filter behavior, see ActiveSupport::ParameterFilter.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
KV_RE="[^&;=]+"
 
PAIR_RE=%r{(#{KV_RE})=(#{KV_RE})}
 
+ + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 19
+def initialize
+  super
+  @filtered_parameters = nil
+  @filtered_env        = nil
+  @filtered_path       = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + filtered_env() + +

+ + +
+

Returns a hash of request.env with all sensitive data replaced.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 34
+def filtered_env
+  @filtered_env ||= env_filter.filter(@env)
+end
+
+
+ +
+ +
+

+ + filtered_parameters() + +

+ + +
+

Returns a hash of parameters with all sensitive data replaced.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 27
+def filtered_parameters
+  @filtered_parameters ||= parameter_filter.filter(parameters)
+rescue ActionDispatch::Http::Parameters::ParseError
+  @filtered_parameters = {}
+end
+
+
+ +
+ +
+

+ + filtered_path() + +

+ + +
+

Reconstructs a path with all sensitive GET parameters replaced.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 39
+def filtered_path
+  @filtered_path ||= query_string.empty? ? path : "#{path}?#{filtered_query_string}"
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + env_filter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 50
+def env_filter # :doc:
+  user_key = fetch_header("action_dispatch.parameter_filter") {
+    return NULL_ENV_FILTER
+  }
+  parameter_filter_for(Array(user_key) + ENV_MATCH)
+end
+
+
+ +
+ +
+

+ + filtered_query_string() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 63
+def filtered_query_string # :doc:
+  query_string.gsub(PAIR_RE) do |_|
+    parameter_filter.filter($1 => $2).first.join("=")
+  end
+end
+
+
+ +
+ +
+

+ + parameter_filter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 44
+def parameter_filter # :doc:
+  parameter_filter_for fetch_header("action_dispatch.parameter_filter") {
+    return NULL_PARAM_FILTER
+  }
+end
+
+
+ +
+ +
+

+ + parameter_filter_for(filters) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/filter_parameters.rb, line 57
+def parameter_filter_for(filters) # :doc:
+  ActiveSupport::ParameterFilter.new(filters)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/FilterRedirect.html b/src/7.0/classes/ActionDispatch/Http/FilterRedirect.html new file mode 100644 index 0000000000..7472adc287 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/FilterRedirect.html @@ -0,0 +1,54 @@ +--- +title: ActionDispatch::Http::FilterRedirect +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Headers.html b/src/7.0/classes/ActionDispatch/Http/Headers.html new file mode 100644 index 0000000000..634a9f4900 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Headers.html @@ -0,0 +1,589 @@ +--- +title: ActionDispatch::Http::Headers +layout: default +--- +
+ +
+
+ +
+ +

Provides access to the request’s HTTP headers from the environment.

+ +
env     = { "CONTENT_TYPE" => "text/plain", "HTTP_USER_AGENT" => "curl/7.43.0" }
+headers = ActionDispatch::Http::Headers.from_hash(env)
+headers["Content-Type"] # => "text/plain"
+headers["User-Agent"] # => "curl/7.43.0"
+
+ +

Also note that when headers are mapped to CGI-like variables by the Rack server, both dashes and underscores are converted to underscores. This ambiguity cannot be resolved at this stage anymore. Both underscores and dashes have to be interpreted as if they were originally sent as dashes.

+ +
# GET / HTTP/1.1
+# ...
+# User-Agent: curl/7.43.0
+# X_Custom_Header: token
+
+headers["X_Custom_Header"] # => nil
+headers["X-Custom-Header"] # => "token"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CGI_VARIABLES=Set.new(%W[ +AUTH_TYPE +CONTENT_LENGTH +CONTENT_TYPE +GATEWAY_INTERFACE +HTTPS +PATH_INFO +PATH_TRANSLATED +QUERY_STRING +REMOTE_ADDR +REMOTE_HOST +REMOTE_IDENT +REMOTE_USER +REQUEST_METHOD +SCRIPT_NAME +SERVER_NAME +SERVER_PORT +SERVER_PROTOCOL +SERVER_SOFTWARE +]).freeze
 
HTTP_HEADER=/\A[A-Za-z0-9-]+\z/
 
+ + + + + + +

Class Public methods

+ +
+

+ + from_hash(hash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 50
+def self.from_hash(hash)
+  new ActionDispatch::Request.new hash
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](key) + +

+ + +
+

Returns the value for the given key mapped to @env.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 59
+def [](key)
+  @req.get_header env_name(key)
+end
+
+
+ +
+ +
+

+ + []=(key, value) + +

+ + +
+

Sets the given value for the key mapped to @env.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 64
+def []=(key, value)
+  @req.set_header env_name(key), value
+end
+
+
+ +
+ +
+

+ + add(key, value) + +

+ + +
+

Add a value to a multivalued header like Vary or Accept-Encoding.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 69
+def add(key, value)
+  @req.add_header env_name(key), value
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 95
+def each(&block)
+  @req.each_header(&block)
+end
+
+
+ +
+ +
+

+ + env() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 116
+def env; @req.env.dup; end
+
+
+ +
+ +
+

+ + fetch(key, default = DEFAULT) + +

+ + +
+

Returns the value for the given key mapped to @env.

+ +

If the key is not found and an optional code block is not provided, raises a KeyError exception.

+ +

If the code block is provided, then it will be run and its result returned.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 87
+def fetch(key, default = DEFAULT)
+  @req.fetch_header(env_name(key)) do
+    return default unless default == DEFAULT
+    return yield if block_given?
+    raise KeyError, key
+  end
+end
+
+
+ +
+ +
+

+ + include?(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: key? +
+ + + +
+ +
+

+ + key?(key) + +

+ + +
+ +
+ + + +
+ Also aliased as: include? +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 73
+def key?(key)
+  @req.has_header? env_name(key)
+end
+
+
+ +
+ +
+

+ + merge(headers_or_env) + +

+ + +
+

Returns a new Http::Headers instance containing the contents of headers_or_env and the original instance.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 101
+def merge(headers_or_env)
+  headers = @req.dup.headers
+  headers.merge!(headers_or_env)
+  headers
+end
+
+
+ +
+ +
+

+ + merge!(headers_or_env) + +

+ + +
+

Adds the contents of headers_or_env to original instance entries; duplicate keys are overwritten with the values from headers_or_env.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/headers.rb, line 110
+def merge!(headers_or_env)
+  headers_or_env.each do |key, value|
+    @req.set_header env_name(key), value
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/MimeNegotiation.html b/src/7.0/classes/ActionDispatch/Http/MimeNegotiation.html new file mode 100644 index 0000000000..2a7c946d8f --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/MimeNegotiation.html @@ -0,0 +1,794 @@ +--- +title: ActionDispatch::Http::MimeNegotiation +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
BROWSER_LIKE_ACCEPTS=/,\s*\*\/\*|\*\/\*\s*,/
 

We use normal content negotiation unless you include / in your list, in which case we assume you’re a browser and send HTML.

RESCUABLE_MIME_FORMAT_ERRORS=[ +ActionController::BadRequest, +ActionDispatch::Http::Parameters::ParseError, +]
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + accepts() + +

+ + +
+

Returns the accepted MIME type for the request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 54
+def accepts
+  fetch_header("action_dispatch.request.accepts") do |k|
+    header = get_header("HTTP_ACCEPT").to_s.strip
+
+    v = if header.empty?
+      [content_mime_type]
+    else
+      Mime::Type.parse(header)
+    end
+    set_header k, v
+  rescue ::Mime::Type::InvalidMimeType => e
+    raise InvalidType, e.message
+  end
+end
+
+
+ +
+ +
+

+ + content_mime_type() + +

+ + +
+

The MIME type of the HTTP request, such as Mime.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 23
+def content_mime_type
+  fetch_header("action_dispatch.request.content_type") do |k|
+    v = if get_header("CONTENT_TYPE") =~ /^([^,;]*)/
+      Mime::Type.lookup($1.strip.downcase)
+    else
+      nil
+    end
+    set_header k, v
+  rescue ::Mime::Type::InvalidMimeType => e
+    raise InvalidType, e.message
+  end
+end
+
+
+ +
+ +
+

+ + content_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 36
+def content_type
+  if self.class.return_only_media_type_on_content_type
+    ActiveSupport::Deprecation.warn(
+      "Rails 7.1 will return Content-Type header without modification." \
+      " If you want just the MIME type, please use `#media_type` instead."
+    )
+
+    content_mime_type&.to_s
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + format(view_path = []) + +

+ + +
+

Returns the MIME type for the format used in the request.

+ +
GET /posts/5.xml   | request.format => Mime[:xml]
+GET /posts/5.xhtml | request.format => Mime[:html]
+GET /posts/5       | request.format => Mime[:html] or Mime[:js], or request.accepts.first
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 75
+def format(view_path = [])
+  formats.first || Mime::NullType.instance
+end
+
+
+ +
+ +
+

+ + format=(extension) + +

+ + +
+

Sets the format by string extension, which can be used to force custom formats that are not controlled by the extension.

+ +
class ApplicationController < ActionController::Base
+  before_action :adjust_format_for_iphone
+
+  private
+    def adjust_format_for_iphone
+      request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
+    end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 127
+def format=(extension)
+  parameters[:format] = extension.to_s
+  set_header "action_dispatch.request.formats", [Mime::Type.lookup_by_extension(parameters[:format])]
+end
+
+
+ +
+ +
+

+ + formats() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 79
+def formats
+  fetch_header("action_dispatch.request.formats") do |k|
+    v = if params_readable?
+      Array(Mime[parameters[:format]])
+    elsif use_accept_header && valid_accept_header
+      accepts
+    elsif extension_format = format_from_path_extension
+      [extension_format]
+    elsif xhr?
+      [Mime[:js]]
+    else
+      [Mime[:html]]
+    end
+
+    v = v.select do |format|
+      format.symbol || format.ref == "*/*"
+    end
+
+    set_header k, v
+  end
+end
+
+
+ +
+ +
+

+ + formats=(extensions) + +

+ + +
+

Sets the formats by string extensions. This differs from format= by allowing you to set multiple, ordered formats, which is useful when you want to have a fallback.

+ +

In this example, the :iphone format will be used if it’s available, otherwise it’ll fallback to the :html format.

+ +
class ApplicationController < ActionController::Base
+  before_action :adjust_format_for_iphone_with_html_fallback
+
+  private
+    def adjust_format_for_iphone_with_html_fallback
+      request.formats = [ :iphone, :html ] if request.env["HTTP_USER_AGENT"][/iPhone/]
+    end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 146
+def formats=(extensions)
+  parameters[:format] = extensions.first.to_s
+  set_header "action_dispatch.request.formats", extensions.collect { |extension|
+    Mime::Type.lookup_by_extension(extension)
+  }
+end
+
+
+ +
+ +
+

+ + negotiate_mime(order) + +

+ + +
+

Returns the first MIME type that matches the provided array of MIME types.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 154
+def negotiate_mime(order)
+  formats.each do |priority|
+    if priority == Mime::ALL
+      return order.first
+    elsif order.include?(priority)
+      return priority
+    end
+  end
+
+  order.include?(Mime::ALL) ? format : nil
+end
+
+
+ +
+ +
+

+ + should_apply_vary_header?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 166
+def should_apply_vary_header?
+  !params_readable? && use_accept_header && valid_accept_header
+end
+
+
+ +
+ +
+

+ + variant() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 112
+def variant
+  @variant ||= ActiveSupport::ArrayInquirer.new
+end
+
+
+ +
+ +
+

+ + variant=(variant) + +

+ + +
+

Sets the variant for template.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 102
+def variant=(variant)
+  variant = Array(variant)
+
+  if variant.all?(Symbol)
+    @variant = ActiveSupport::ArrayInquirer.new(variant)
+  else
+    raise ArgumentError, "request.variant must be set to a Symbol or an Array of Symbols."
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + format_from_path_extension() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 190
+def format_from_path_extension # :doc:
+  path = get_header("action_dispatch.original_path") || get_header("PATH_INFO")
+  if match = path && path.match(/\.(\w+)\z/)
+    Mime[match.captures.first]
+  end
+end
+
+
+ +
+ +
+

+ + params_readable?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 175
+def params_readable? # :doc:
+  parameters[:format]
+rescue *RESCUABLE_MIME_FORMAT_ERRORS
+  false
+end
+
+
+ +
+ +
+

+ + use_accept_header() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 186
+def use_accept_header # :doc:
+  !self.class.ignore_accept_header
+end
+
+
+ +
+ +
+

+ + valid_accept_header() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_negotiation.rb, line 181
+def valid_accept_header # :doc:
+  (xhr? && (accept.present? || content_mime_type)) ||
+    (accept.present? && !accept.match?(BROWSER_LIKE_ACCEPTS))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/MimeNegotiation/InvalidType.html b/src/7.0/classes/ActionDispatch/Http/MimeNegotiation/InvalidType.html new file mode 100644 index 0000000000..1099d25c0d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/MimeNegotiation/InvalidType.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Http::MimeNegotiation::InvalidType +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Parameters.html b/src/7.0/classes/ActionDispatch/Http/Parameters.html new file mode 100644 index 0000000000..d50295c65f --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Parameters.html @@ -0,0 +1,254 @@ +--- +title: ActionDispatch::Http::Parameters +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_PARSERS={ +Mime[:json].symbol => -> (raw_post) { +data = ActiveSupport::JSON.decode(raw_post) +data.is_a?(Hash) ? data : { _json: data } +} +}
 
PARAMETERS_KEY="action_dispatch.request.path_parameters"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + parameter_parsers

Returns the parameter parsers.

+ + + + + +

Instance Public methods

+ +
+

+ + parameters() + +

+ + +
+

Returns both GET and POST parameters in a single hash.

+
+ + + +
+ Also aliased as: params +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/parameters.rb, line 50
+def parameters
+  params = get_header("action_dispatch.request.parameters")
+  return params if params
+
+  params = begin
+             request_parameters.merge(query_parameters)
+           rescue EOFError
+             query_parameters.dup
+           end
+  params.merge!(path_parameters)
+  set_header("action_dispatch.request.parameters", params)
+  params
+end
+
+
+ +
+ +
+

+ + params() + +

+ + +
+ +
+ + + + + +
+ Alias for: parameters +
+ + + +
+ +
+

+ + path_parameters() + +

+ + +
+

Returns a hash with the parameters used to form the path of the request. Returned hash keys are strings:

+ +
{ action: "my_action", controller: "my_controller" }
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/parameters.rb, line 82
+def path_parameters
+  get_header(PARAMETERS_KEY) || set_header(PARAMETERS_KEY, {})
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Parameters/ClassMethods.html b/src/7.0/classes/ActionDispatch/Http/Parameters/ClassMethods.html new file mode 100644 index 0000000000..8378316878 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Parameters/ClassMethods.html @@ -0,0 +1,109 @@ +--- +title: ActionDispatch::Http::Parameters::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + parameter_parsers=(parsers) + +

+ + +
+

Configure the parameter parser for a given MIME type.

+ +

It accepts a hash where the key is the symbol of the MIME type and the value is a proc.

+ +
original_parsers = ActionDispatch::Request.parameter_parsers
+xml_parser = -> (raw_post) { Hash.from_xml(raw_post) || {} }
+new_parsers = original_parsers.merge(xml: xml_parser)
+ActionDispatch::Request.parameter_parsers = new_parsers
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/parameters.rb, line 44
+def parameter_parsers=(parsers)
+  @parameter_parsers = parsers.transform_keys { |key| key.respond_to?(:symbol) ? key.symbol : key }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/Parameters/ParseError.html b/src/7.0/classes/ActionDispatch/Http/Parameters/ParseError.html new file mode 100644 index 0000000000..016b9e459c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/Parameters/ParseError.html @@ -0,0 +1,113 @@ +--- +title: ActionDispatch::Http::Parameters::ParseError +layout: default +--- +
+ +
+
+ +
+ +

Raised when raw data from the request cannot be parsed by the parser defined for request’s content MIME type.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(message = $!.message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/parameters.rb, line 20
+def initialize(message = $!.message)
+  super(message)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/URL.html b/src/7.0/classes/ActionDispatch/Http/URL.html new file mode 100644 index 0000000000..978cdc123b --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/URL.html @@ -0,0 +1,1056 @@ +--- +title: ActionDispatch::Http::URL +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HOST_REGEXP=/(^[^:]+:\/\/)?(\[[^\]]+\]|[^:]+)(?::(\d+$))?/
 
IP_HOST_REGEXP=/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
 
PROTOCOL_REGEXP=/^([^:]+)(:)?(\/\/)?$/
 
+ + + + + + +

Class Public methods

+ +
+

+ + extract_domain(host, tld_length) + +

+ + +
+

Returns the domain part of a host given the domain level.

+ +
# Top-level domain example
+extract_domain('www.example.com', 1) # => "example.com"
+# Second-level domain example
+extract_domain('dev.www.example.co.uk', 2) # => "example.co.uk"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 22
+def extract_domain(host, tld_length)
+  extract_domain_from(host, tld_length) if named_host?(host)
+end
+
+
+ +
+ +
+

+ + extract_subdomain(host, tld_length) + +

+ + +
+

Returns the subdomains of a host as a String given the domain level.

+ +
# Top-level domain example
+extract_subdomain('www.example.com', 1) # => "www"
+# Second-level domain example
+extract_subdomain('dev.www.example.co.uk', 2) # => "dev.www"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 46
+def extract_subdomain(host, tld_length)
+  extract_subdomains(host, tld_length).join(".")
+end
+
+
+ +
+ +
+

+ + extract_subdomains(host, tld_length) + +

+ + +
+

Returns the subdomains of a host as an Array given the domain level.

+ +
# Top-level domain example
+extract_subdomains('www.example.com', 1) # => ["www"]
+# Second-level domain example
+extract_subdomains('dev.www.example.co.uk', 2) # => ["dev", "www"]
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 32
+def extract_subdomains(host, tld_length)
+  if named_host?(host)
+    extract_subdomains_from(host, tld_length)
+  else
+    []
+  end
+end
+
+
+ +
+ +
+

+ + full_url_for(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 58
+def full_url_for(options)
+  host     = options[:host]
+  protocol = options[:protocol]
+  port     = options[:port]
+
+  unless host
+    raise ArgumentError, "Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true"
+  end
+
+  build_host_url(host, port, protocol, options, path_for(options))
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 179
+def initialize
+  super
+  @protocol = nil
+  @port     = nil
+end
+
+
+ +
+ +
+

+ + path_for(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 70
+def path_for(options)
+  path = options[:script_name].to_s.chomp("/")
+  path << options[:path] if options.key?(:path)
+
+  path = "/" if options[:trailing_slash] && path.blank?
+
+  add_params(path, options[:params]) if options.key?(:params)
+  add_anchor(path, options[:anchor]) if options.key?(:anchor)
+
+  path
+end
+
+
+ +
+ +
+

+ + url_for(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 50
+def url_for(options)
+  if options[:only_path]
+    path_for options
+  else
+    full_url_for options
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + domain(tld_length = @@tld_length) + +

+ + +
+

Returns the domain part of a host, such as “rubyonrails.org” in “www.rubyonrails.org”. You can specify a different tld_length, such as 2 to catch rubyonrails.co.uk in “www.rubyonrails.co.uk”.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 321
+def domain(tld_length = @@tld_length)
+  ActionDispatch::Http::URL.extract_domain(host, tld_length)
+end
+
+
+ +
+ +
+

+ + host() + +

+ + +
+

Returns the host for this request, such as “example.com”.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.host # => "example.com"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 226
+def host
+  raw_host_with_port.sub(/:\d+$/, "")
+end
+
+
+ +
+ +
+

+ + host_with_port() + +

+ + +
+

Returns a host:port string for this request, such as “example.com” or “example.com:8080”. Port is only included if it is not a default port (80 or 443)

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
+req.host_with_port # => "example.com"
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
+req.host_with_port # => "example.com"
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.host_with_port # => "example.com:8080"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 242
+def host_with_port
+  "#{host}#{port_string}"
+end
+
+
+ +
+ +
+

+ + optional_port() + +

+ + +
+

Returns a number port suffix like 8080 if the port number of this request is not the default HTTP port 80 or HTTPS port 443.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
+req.optional_port # => nil
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.optional_port # => 8080
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 292
+def optional_port
+  standard_port? ? nil : port
+end
+
+
+ +
+ +
+

+ + port() + +

+ + +
+

Returns the port number of this request as an integer.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
+req.port # => 80
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.port # => 8080
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 253
+def port
+  @port ||= if raw_host_with_port =~ /:(\d+)$/
+    $1.to_i
+  else
+    standard_port
+  end
+end
+
+
+ +
+ +
+

+ + port_string() + +

+ + +
+

Returns a string port suffix, including colon, like “:8080” if the port number of this request is not the default HTTP port 80 or HTTPS port 443.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
+req.port_string # => ""
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.port_string # => ":8080"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 304
+def port_string
+  standard_port? ? "" : ":#{port}"
+end
+
+
+ +
+ +
+

+ + protocol() + +

+ + +
+

Returns ‘https://’ if this is an SSL request and ‘http://’ otherwise.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
+req.protocol # => "http://"
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on'
+req.protocol # => "https://"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 200
+def protocol
+  @protocol ||= ssl? ? "https://" : "http://"
+end
+
+
+ +
+ +
+

+ + raw_host_with_port() + +

+ + +
+

Returns the host and port for this request, such as “example.com:8080”.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
+req.raw_host_with_port # => "example.com"
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
+req.raw_host_with_port # => "example.com:80"
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.raw_host_with_port # => "example.com:8080"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 214
+def raw_host_with_port
+  if forwarded = x_forwarded_host.presence
+    forwarded.split(/,\s?/).last
+  else
+    get_header("HTTP_HOST") || "#{server_name}:#{get_header('SERVER_PORT')}"
+  end
+end
+
+
+ +
+ +
+

+ + server_port() + +

+ + +
+

Returns the requested port, such as 8080, based on SERVER_PORT

+ +
req = ActionDispatch::Request.new 'SERVER_PORT' => '80'
+req.server_port # => 80
+
+req = ActionDispatch::Request.new 'SERVER_PORT' => '8080'
+req.server_port # => 8080
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 315
+def server_port
+  get_header("SERVER_PORT").to_i
+end
+
+
+ +
+ +
+

+ + standard_port() + +

+ + +
+

Returns the standard port number for this request’s protocol.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.standard_port # => 80
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 265
+def standard_port
+  if "https://" == protocol
+    443
+  else
+    80
+  end
+end
+
+
+ +
+ +
+

+ + standard_port?() + +

+ + +
+

Returns whether this request is using the standard port

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80'
+req.standard_port? # => true
+
+req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
+req.standard_port? # => false
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 280
+def standard_port?
+  port == standard_port
+end
+
+
+ +
+ +
+

+ + subdomain(tld_length = @@tld_length) + +

+ + +
+

Returns all the subdomains as a string, so "dev.www" would be returned for “dev.www.rubyonrails.org”. You can specify a different tld_length, such as 2 to catch "www" instead of "www.rubyonrails" in “www.rubyonrails.co.uk”.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 337
+def subdomain(tld_length = @@tld_length)
+  ActionDispatch::Http::URL.extract_subdomain(host, tld_length)
+end
+
+
+ +
+ +
+

+ + subdomains(tld_length = @@tld_length) + +

+ + +
+

Returns all the subdomains as an array, so ["dev", "www"] would be returned for “dev.www.rubyonrails.org”. You can specify a different tld_length, such as 2 to catch ["www"] instead of ["www", "rubyonrails"] in “www.rubyonrails.co.uk”.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 329
+def subdomains(tld_length = @@tld_length)
+  ActionDispatch::Http::URL.extract_subdomains(host, tld_length)
+end
+
+
+ +
+ +
+

+ + url() + +

+ + +
+

Returns the complete URL used for this request.

+ +
req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com'
+req.url # => "http://example.com"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/url.rb, line 189
+def url
+  protocol + host_with_port + fullpath
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Http/UploadedFile.html b/src/7.0/classes/ActionDispatch/Http/UploadedFile.html new file mode 100644 index 0000000000..37f2f5109e --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Http/UploadedFile.html @@ -0,0 +1,467 @@ +--- +title: ActionDispatch::Http::UploadedFile +layout: default +--- +
+ +
+
+ +
+ +

Models uploaded files.

+ +

The actual file is accessible via the tempfile accessor, though some of its interface is available directly for convenience.

+ +

Uploaded files are temporary files whose lifespan is one request. When the object is finalized Ruby unlinks the file, so there is no need to clean them with a separate maintenance task.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + content_type

A string with the MIME type of the file.

+ [RW] + headers

A string with the headers of the multipart request.

+ [RW] + original_filename

The basename of the file in the client.

+ [RW] + tempfile

A Tempfile object with the actual uploaded file. Note that some of its interface is available directly.

+ + + + + +

Instance Public methods

+ +
+

+ + close(unlink_now = false) + +

+ + +
+

Shortcut for tempfile.close.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 69
+def close(unlink_now = false)
+  @tempfile.close(unlink_now)
+end
+
+
+ +
+ +
+

+ + eof?() + +

+ + +
+

Shortcut for tempfile.eof?.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 94
+def eof?
+  @tempfile.eof?
+end
+
+
+ +
+ +
+

+ + open() + +

+ + +
+

Shortcut for tempfile.open.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 64
+def open
+  @tempfile.open
+end
+
+
+ +
+ +
+

+ + path() + +

+ + +
+

Shortcut for tempfile.path.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 74
+def path
+  @tempfile.path
+end
+
+
+ +
+ +
+

+ + read(length = nil, buffer = nil) + +

+ + +
+

Shortcut for tempfile.read.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 59
+def read(length = nil, buffer = nil)
+  @tempfile.read(length, buffer)
+end
+
+
+ +
+ +
+

+ + rewind() + +

+ + +
+

Shortcut for tempfile.rewind.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 84
+def rewind
+  @tempfile.rewind
+end
+
+
+ +
+ +
+

+ + size() + +

+ + +
+

Shortcut for tempfile.size.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 89
+def size
+  @tempfile.size
+end
+
+
+ +
+ +
+

+ + to_io() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 98
+def to_io
+  @tempfile.to_io
+end
+
+
+ +
+ +
+

+ + to_path() + +

+ + +
+

Shortcut for tempfile.to_path.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/upload.rb, line 79
+def to_path
+  @tempfile.to_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Integration.html b/src/7.0/classes/ActionDispatch/Integration.html new file mode 100644 index 0000000000..c29959f829 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Integration.html @@ -0,0 +1,78 @@ +--- +title: ActionDispatch::Integration +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Integration/RequestHelpers.html b/src/7.0/classes/ActionDispatch/Integration/RequestHelpers.html new file mode 100644 index 0000000000..e36a8d9666 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Integration/RequestHelpers.html @@ -0,0 +1,384 @@ +--- +title: ActionDispatch::Integration::RequestHelpers +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + delete(path, **args) + +

+ + +
+

Performs a DELETE request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 39
+def delete(path, **args)
+  process(:delete, path, **args)
+end
+
+
+ +
+ +
+

+ + follow_redirect!(**args) + +

+ + +
+

Follow a single redirect response. If the last response was not a redirect, an exception will be raised. Otherwise, the redirect is performed on the location header. If the redirection is a 307 or 308 redirect, the same HTTP verb will be used when redirecting, otherwise a GET request will be performed. Any arguments are passed to the underlying request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 61
+def follow_redirect!(**args)
+  raise "not a redirect! #{status} #{status_message}" unless redirect?
+
+  method =
+    if [307, 308].include?(response.status)
+      request.method.downcase
+    else
+      :get
+    end
+
+  public_send(method, response.location, **args)
+  status
+end
+
+
+ +
+ +
+

+ + get(path, **args) + +

+ + +
+

Performs a GET request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 15
+def get(path, **args)
+  process(:get, path, **args)
+end
+
+
+ +
+ +
+

+ + head(path, **args) + +

+ + +
+

Performs a HEAD request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 45
+def head(path, **args)
+  process(:head, path, **args)
+end
+
+
+ +
+ +
+

+ + options(path, **args) + +

+ + +
+

Performs an OPTIONS request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 51
+def options(path, **args)
+  process(:options, path, **args)
+end
+
+
+ +
+ +
+

+ + patch(path, **args) + +

+ + +
+

Performs a PATCH request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 27
+def patch(path, **args)
+  process(:patch, path, **args)
+end
+
+
+ +
+ +
+

+ + post(path, **args) + +

+ + +
+

Performs a POST request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 21
+def post(path, **args)
+  process(:post, path, **args)
+end
+
+
+ +
+ +
+

+ + put(path, **args) + +

+ + +
+

Performs a PUT request with the given parameters. See ActionDispatch::Integration::Session#process for more details.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 33
+def put(path, **args)
+  process(:put, path, **args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Integration/Runner.html b/src/7.0/classes/ActionDispatch/Integration/Runner.html new file mode 100644 index 0000000000..231f3cd18c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Integration/Runner.html @@ -0,0 +1,404 @@ +--- +title: ActionDispatch::Integration::Runner +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
APP_SESSIONS={}
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + app
+ + + + +

Class Public methods

+ +
+

+ + new(*args, &blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 324
+def initialize(*args, &blk)
+  super(*args, &blk)
+  @integration_session = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + create_session(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 344
+def create_session(app)
+  klass = APP_SESSIONS[app] ||= Class.new(Integration::Session) {
+    # If the app is a Rails app, make url_helpers available on the session.
+    # This makes app.url_for and app.foo_path available in the console.
+    if app.respond_to?(:routes) && app.routes.is_a?(ActionDispatch::Routing::RouteSet)
+      include app.routes.url_helpers
+      include app.routes.mounted_helpers
+    end
+  }
+  klass.new(app)
+end
+
+
+ +
+ +
+

+ + default_url_options() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 411
+def default_url_options
+  integration_session.default_url_options
+end
+
+
+ +
+ +
+

+ + default_url_options=(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 415
+def default_url_options=(options)
+  integration_session.default_url_options = options
+end
+
+
+ +
+ +
+

+ + integration_session() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 334
+def integration_session
+  @integration_session ||= create_session(app)
+end
+
+
+ +
+ +
+

+ + open_session() + +

+ + +
+

Open a new session instance. If a block is given, the new session is yielded to the block before being returned.

+ +
session = open_session do |sess|
+  sess.extend(CustomAssertions)
+end
+
+ +

By default, a single session is automatically created for you, but you can use this method to open multiple sessions that ought to be tested simultaneously.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 387
+def open_session
+  dup.tap do |session|
+    session.reset!
+    session.root_session = self.root_session || self
+    yield session if block_given?
+  end
+end
+
+
+ +
+ +
+

+ + reset!() + +

+ + +
+

Reset the current session. This is useful for testing multiple sessions in a single test case.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 340
+def reset!
+  @integration_session = create_session(app)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Integration/Session.html b/src/7.0/classes/ActionDispatch/Integration/Session.html new file mode 100644 index 0000000000..42f9c374e1 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Integration/Session.html @@ -0,0 +1,632 @@ +--- +title: ActionDispatch::Integration::Session +layout: default +--- +
+ +
+
+ +
+ +

An instance of this class represents a set of requests and responses performed sequentially by a test process. Because you can instantiate multiple sessions and run them side-by-side, you can also mimic (to some limited extent) multiple simultaneous users interacting with your system.

+ +

Typically, you will instantiate a new session using IntegrationTest#open_session, rather than instantiating Integration::Session directly.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_HOST="www.example.com"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + accept

The Accept header to send.

+ [R] + controller

A reference to the controller instance used by the last request.

+ [W] + host
+ [W] + host!
+ [RW] + remote_addr

The remote_addr used in the last request.

+ [R] + request

A reference to the request instance used by the last request.

+ [RW] + request_count

A running counter of the number of requests processed.

+ [R] + response

A reference to the response instance used by the last request.

+ + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+

Create and initialize a new Session instance.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 126
+def initialize(app)
+  super()
+  @app = app
+
+  reset!
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cookies() + +

+ + +
+

A map of the cookies returned by the last response, and which will be sent with the next request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 107
+def cookies
+  _mock_session.cookie_jar
+end
+
+
+ +
+ +
+

+ + host() + +

+ + +
+

The hostname used in the last request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 94
+def host
+  @host || DEFAULT_HOST
+end
+
+
+ +
+ +
+

+ + https!(flag = true) + +

+ + +
+

Specify whether or not the session should mimic a secure HTTPS request.

+ +
session.https!
+session.https!(false)
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 174
+def https!(flag = true)
+  @https = flag
+end
+
+
+ +
+ +
+

+ + https?() + +

+ + +
+

Returns true if the session is mimicking a secure HTTPS request.

+ +
if session.https?
+  ...
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 183
+def https?
+  @https
+end
+
+
+ +
+ +
+

+ + process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil) + +

+ + +
+

Performs the actual request.

+
  • +

    method: The HTTP method (GET, POST, PATCH, PUT, DELETE, HEAD, OPTIONS) as a symbol.

    +
  • +

    path: The URI (as a String) on which you want to perform the request.

    +
  • +

    params: The HTTP parameters that you want to pass. This may be nil, a Hash, or a String that is appropriately encoded (application/x-www-form-urlencoded or multipart/form-data).

    +
  • +

    headers: Additional headers to pass, as a Hash. The headers will be merged into the Rack env hash.

    +
  • +

    env: Additional env to pass, as a Hash. The headers will be merged into the Rack env hash.

    +
  • +

    xhr: Set to true if you want to make an Ajax request. Adds request headers characteristic of XMLHttpRequest e.g. HTTP_X_REQUESTED_WITH. The headers will be merged into the Rack env hash.

    +
  • +

    as: Used for encoding the request with different content type. Supports :json by default and will set the appropriate request headers. The headers will be merged into the Rack env hash.

    +
+ +

This method is rarely used directly. Use #get, #post, or other standard HTTP methods in integration tests. #process is only required when using a request method that doesn’t have a method defined in the integration tests.

+ +

This method returns the response status, after performing the request. Furthermore, if this method was called from an ActionDispatch::IntegrationTest object, then that object’s @response instance variable will point to a Response object which one can use to inspect the details of the response.

+ +

Example:

+ +
process :get, '/author', params: { since: 201501011400 }
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 220
+def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
+  request_encoder = RequestEncoder.encoder(as)
+  headers ||= {}
+
+  if method == :get && as == :json && params
+    headers["X-Http-Method-Override"] = "GET"
+    method = :post
+  end
+
+  if %r{://}.match?(path)
+    path = build_expanded_path(path) do |location|
+      https! URI::HTTPS === location if location.scheme
+
+      if url_host = location.host
+        default = Rack::Request::DEFAULT_PORTS[location.scheme]
+        url_host += ":#{location.port}" if default != location.port
+        host! url_host
+      end
+    end
+  end
+
+  hostname, port = host.split(":")
+
+  request_env = {
+    :method => method,
+    :params => request_encoder.encode_params(params),
+
+    "SERVER_NAME"     => hostname,
+    "SERVER_PORT"     => port || (https? ? "443" : "80"),
+    "HTTPS"           => https? ? "on" : "off",
+    "rack.url_scheme" => https? ? "https" : "http",
+
+    "REQUEST_URI"    => path,
+    "HTTP_HOST"      => host,
+    "REMOTE_ADDR"    => remote_addr,
+    "CONTENT_TYPE"   => request_encoder.content_type,
+    "HTTP_ACCEPT"    => request_encoder.accept_header || accept
+  }
+
+  wrapped_headers = Http::Headers.from_hash({})
+  wrapped_headers.merge!(headers) if headers
+
+  if xhr
+    wrapped_headers["HTTP_X_REQUESTED_WITH"] = "XMLHttpRequest"
+    wrapped_headers["HTTP_ACCEPT"] ||= [Mime[:js], Mime[:html], Mime[:xml], "text/xml", "*/*"].join(", ")
+  end
+
+  # This modifies the passed request_env directly.
+  if wrapped_headers.present?
+    Http::Headers.from_hash(request_env).merge!(wrapped_headers)
+  end
+  if env.present?
+    Http::Headers.from_hash(request_env).merge!(env)
+  end
+
+  session = Rack::Test::Session.new(_mock_session)
+
+  # NOTE: rack-test v0.5 doesn't build a default uri correctly
+  # Make sure requested path is always a full URI.
+  session.request(build_full_uri(path, request_env), request_env)
+
+  @request_count += 1
+  @request = ActionDispatch::Request.new(session.last_request.env)
+  response = _mock_session.last_response
+  @response = ActionDispatch::TestResponse.from_response(response)
+  @response.request = @request
+  @html_document = nil
+  @url_options = nil
+
+  @controller = @request.controller_instance
+
+  response.status
+end
+
+
+ +
+ +
+

+ + reset!() + +

+ + +
+

Resets the instance. This can be used to reset the state information in an existing session instance, so it can be used from a clean-slate condition.

+ +
session.reset!
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 150
+def reset!
+  @https = false
+  @controller = @request = @response = nil
+  @_mock_session = nil
+  @request_count = 0
+  @url_options = nil
+
+  self.host        = DEFAULT_HOST
+  self.remote_addr = "127.0.0.1"
+  self.accept      = "text/xml,application/xml,application/xhtml+xml," \
+                     "text/html;q=0.9,text/plain;q=0.8,image/png," \
+                     "*/*;q=0.5"
+
+  unless defined? @named_routes_configured
+    # the helpers are made protected by default--we make them public for
+    # easier access during testing and troubleshooting.
+    @named_routes_configured = true
+  end
+end
+
+
+ +
+ +
+

+ + url_options() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 133
+def url_options
+  @url_options ||= default_url_options.dup.tap do |url_options|
+    url_options.reverse_merge!(controller.url_options) if controller.respond_to?(:url_options)
+
+    if @app.respond_to?(:routes)
+      url_options.reverse_merge!(@app.routes.default_url_options)
+    end
+
+    url_options.reverse_merge!(host: host, protocol: https? ? "https" : "http")
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/IntegrationTest.html b/src/7.0/classes/ActionDispatch/IntegrationTest.html new file mode 100644 index 0000000000..b9add3ec4d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/IntegrationTest.html @@ -0,0 +1,281 @@ +--- +title: ActionDispatch::IntegrationTest +layout: default +--- +
+ +
+
+ +
+ +

An integration test spans multiple controllers and actions, tying them all together to ensure they work together as expected. It tests more completely than either unit or functional tests do, exercising the entire stack, from the dispatcher to the database.

+ +

At its simplest, you simply extend IntegrationTest and write your tests using the get/post methods:

+ +
require "test_helper"
+
+class ExampleTest < ActionDispatch::IntegrationTest
+  fixtures :people
+
+  def test_login
+    # get the login page
+    get "/login"
+    assert_equal 200, status
+
+    # post the login and follow through to the home page
+    post "/login", params: { username: people(:jamis).username,
+      password: people(:jamis).password }
+    follow_redirect!
+    assert_equal 200, status
+    assert_equal "/home", path
+  end
+end
+
+ +

However, you can also have multiple session instances open per test, and even extend those instances with assertions and methods to create a very powerful testing DSL that is specific for your application. You can even reference any named routes you happen to have defined.

+ +
require "test_helper"
+
+class AdvancedTest < ActionDispatch::IntegrationTest
+  fixtures :people, :rooms
+
+  def test_login_and_speak
+    jamis, david = login(:jamis), login(:david)
+    room = rooms(:office)
+
+    jamis.enter(room)
+    jamis.speak(room, "anybody home?")
+
+    david.enter(room)
+    david.speak(room, "hello!")
+  end
+
+  private
+
+    module CustomAssertions
+      def enter(room)
+        # reference a named route, for maximum internal consistency!
+        get(room_url(id: room.id))
+        assert(...)
+        ...
+      end
+
+      def speak(room, message)
+        post "/say/#{room.id}", xhr: true, params: { message: message }
+        assert(...)
+        ...
+      end
+    end
+
+    def login(who)
+      open_session do |sess|
+        sess.extend(CustomAssertions)
+        who = people(who)
+        sess.post "/login", params: { username: who.username,
+          password: who.password }
+        assert(...)
+      end
+    end
+end
+
+ +

Another longer example would be:

+ +

A simple integration test that exercises multiple controllers:

+ +
require "test_helper"
+
+class UserFlowsTest < ActionDispatch::IntegrationTest
+  test "login and browse site" do
+    # login via https
+    https!
+    get "/login"
+    assert_response :success
+
+    post "/login", params: { username: users(:david).username, password: users(:david).password }
+    follow_redirect!
+    assert_equal '/welcome', path
+    assert_equal 'Welcome david!', flash[:notice]
+
+    https!(false)
+    get "/articles/all"
+    assert_response :success
+    assert_select 'h1', 'Articles'
+  end
+end
+
+ +

As you can see the integration test involves multiple controllers and exercises the entire stack from database to dispatcher. In addition you can have multiple session instances open simultaneously in a test and extend those instances with assertion methods to create a very powerful testing DSL (domain-specific language) just for your application.

+ +

Here’s an example of multiple sessions and custom DSL in an integration test

+ +
require "test_helper"
+
+class UserFlowsTest < ActionDispatch::IntegrationTest
+  test "login and browse site" do
+    # User david logs in
+    david = login(:david)
+    # User guest logs in
+    guest = login(:guest)
+
+    # Both are now available in different sessions
+    assert_equal 'Welcome david!', david.flash[:notice]
+    assert_equal 'Welcome guest!', guest.flash[:notice]
+
+    # User david can browse site
+    david.browses_site
+    # User guest can browse site as well
+    guest.browses_site
+
+    # Continue with other assertions
+  end
+
+  private
+
+    module CustomDsl
+      def browses_site
+        get "/products/all"
+        assert_response :success
+        assert_select 'h1', 'Products'
+      end
+    end
+
+    def login(user)
+      open_session do |sess|
+        sess.extend(CustomDsl)
+        u = users(user)
+        sess.https!
+        sess.post "/login", params: { username: u.username, password: u.password }
+        assert_equal '/welcome', sess.path
+        sess.https!(false)
+      end
+    end
+end
+
+ +

See the request helpers documentation for help on how to use get, etc.

+ +

Changing the request encoding

+ +

You can also test your JSON API easily by setting what the request should be encoded as:

+ +
require "test_helper"
+
+class ApiTest < ActionDispatch::IntegrationTest
+  test "creates articles" do
+    assert_difference -> { Article.count } do
+      post articles_path, params: { article: { title: "Ahoy!" } }, as: :json
+    end
+
+    assert_response :success
+    assert_equal({ id: Article.last.id, title: "Ahoy!" }, response.parsed_body)
+  end
+end
+
+ +

The as option passes an “application/json” Accept header (thereby setting the request format to JSON unless overridden), sets the content type to “application/json” and encodes the parameters as JSON.

+ +

Calling parsed_body on the response parses the response body based on the last response MIME type.

+ +

Out of the box, only :json is supported. But for any custom MIME types you’ve registered, you can add your own encoders with:

+ +
ActionDispatch::IntegrationTest.register_encoder :wibble,
+  param_encoder: -> params { params.to_wibble },
+  response_parser: -> body { body }
+
+ +

Where param_encoder defines how the params should be encoded and response_parser defines how the response body should be parsed through parsed_body.

+ +

Consult the Rails Testing Guide for more.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior.html b/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior.html new file mode 100644 index 0000000000..9b5250d3d6 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior.html @@ -0,0 +1,175 @@ +--- +title: ActionDispatch::IntegrationTest::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + app() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 672
+def app
+  super || self.class.app
+end
+
+
+ +
+ +
+

+ + document_root_element() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 676
+def document_root_element
+  html_document.root
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior/ClassMethods.html b/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior/ClassMethods.html new file mode 100644 index 0000000000..c926bc32d7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/IntegrationTest/Behavior/ClassMethods.html @@ -0,0 +1,183 @@ +--- +title: ActionDispatch::IntegrationTest::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + app() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 655
+def app
+  if defined?(@@app) && @@app
+    @@app
+  else
+    ActionDispatch.test_app
+  end
+end
+
+
+ +
+ +
+

+ + app=(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 663
+def app=(app)
+  @@app = app
+end
+
+
+ +
+ +
+

+ + register_encoder(*args, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 667
+def register_encoder(*args, **options)
+  RequestEncoder.register_encoder(*args, **options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/IntegrationTest/UrlOptions.html b/src/7.0/classes/ActionDispatch/IntegrationTest/UrlOptions.html new file mode 100644 index 0000000000..4752e66de0 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/IntegrationTest/UrlOptions.html @@ -0,0 +1,101 @@ +--- +title: ActionDispatch::IntegrationTest::UrlOptions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + url_options() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/integration.rb, line 636
+def url_options
+  integration_session.url_options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey.html b/src/7.0/classes/ActionDispatch/Journey.html new file mode 100644 index 0000000000..82c2678b3c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey.html @@ -0,0 +1,107 @@ +--- +title: ActionDispatch::Journey +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Format.html b/src/7.0/classes/ActionDispatch/Journey/Format.html new file mode 100644 index 0000000000..699cd835c3 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Format.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Journey::Format +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Formatter.html b/src/7.0/classes/ActionDispatch/Journey/Formatter.html new file mode 100644 index 0000000000..0c84219107 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Formatter.html @@ -0,0 +1,75 @@ +--- +title: ActionDispatch::Journey::Formatter +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Formatter/MissingRoute.html b/src/7.0/classes/ActionDispatch/Journey/Formatter/MissingRoute.html new file mode 100644 index 0000000000..8410309576 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Formatter/MissingRoute.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Journey::Formatter::MissingRoute +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Formatter/RouteWithParams.html b/src/7.0/classes/ActionDispatch/Journey/Formatter/RouteWithParams.html new file mode 100644 index 0000000000..7dd518a201 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Formatter/RouteWithParams.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Journey::Formatter::RouteWithParams +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Parser.html b/src/7.0/classes/ActionDispatch/Journey/Parser.html new file mode 100644 index 0000000000..0004098fb9 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Parser.html @@ -0,0 +1,62 @@ +--- +title: ActionDispatch::Journey::Parser +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Route.html b/src/7.0/classes/ActionDispatch/Journey/Route.html new file mode 100644 index 0000000000..49d700d432 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Route.html @@ -0,0 +1,73 @@ +--- +title: ActionDispatch::Journey::Route +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers.html b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers.html new file mode 100644 index 0000000000..be0ae376d5 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers.html @@ -0,0 +1,69 @@ +--- +title: ActionDispatch::Journey::Route::VerbMatchers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/All.html b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/All.html new file mode 100644 index 0000000000..c7d804c4d6 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/All.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Journey::Route::VerbMatchers::All +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/Unknown.html b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/Unknown.html new file mode 100644 index 0000000000..4fcfa5033c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Journey/Route/VerbMatchers/Unknown.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Journey::Route::VerbMatchers::Unknown +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/MiddlewareStack.html b/src/7.0/classes/ActionDispatch/MiddlewareStack.html new file mode 100644 index 0000000000..2d8e2e5ed7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/MiddlewareStack.html @@ -0,0 +1,826 @@ +--- +title: ActionDispatch::MiddlewareStack +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + middlewares
+ + + + +

Class Public methods

+ +
+

+ + new(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 70
+def initialize(*args)
+  @middlewares = []
+  yield(self) if block_given?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](i) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 87
+def [](i)
+  middlewares[i]
+end
+
+
+ +
+ +
+

+ + build(app = nil, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 160
+def build(app = nil, &block)
+  instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME)
+  middlewares.freeze.reverse.inject(app || block) do |a, e|
+    if instrumenting
+      e.build_instrumented(a)
+    else
+      e.build(a)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + delete(target) + +

+ + +
+

Deletes a middleware from the middleware stack.

+ +

Returns the array of middlewares not including the deleted item, or returns nil if the target is not found.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 125
+def delete(target)
+  middlewares.reject! { |m| m.name == target.name }
+end
+
+
+ +
+ +
+

+ + delete!(target) + +

+ + +
+

Deletes a middleware from the middleware stack.

+ +

Returns the array of middlewares not including the deleted item, or raises RuntimeError if the target is not found.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 133
+def delete!(target)
+  delete(target) || (raise "No such middleware to remove: #{target.inspect}")
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 75
+def each(&block)
+  @middlewares.each(&block)
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 96
+def initialize_copy(other)
+  self.middlewares = other.middlewares.dup
+end
+
+
+ +
+ +
+

+ + insert(index, klass, *args, &block) + +

+ + +
+ +
+ + + +
+ Also aliased as: insert_before +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 100
+def insert(index, klass, *args, &block)
+  index = assert_index(index, :before)
+  middlewares.insert(index, build_middleware(klass, args, block))
+end
+
+
+ +
+ +
+

+ + insert_after(index, *args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 108
+def insert_after(index, *args, &block)
+  index = assert_index(index, :after)
+  insert(index + 1, *args, &block)
+end
+
+
+ +
+ +
+

+ + insert_before(index, klass, *args, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: insert +
+ + + +
+ +
+

+ + last() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 83
+def last
+  middlewares.last
+end
+
+
+ +
+ +
+

+ + move(target, source) + +

+ + +
+ +
+ + + +
+ Also aliased as: move_before +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 137
+def move(target, source)
+  source_index = assert_index(source, :before)
+  source_middleware = middlewares.delete_at(source_index)
+
+  target_index = assert_index(target, :before)
+  middlewares.insert(target_index, source_middleware)
+end
+
+
+ +
+ +
+

+ + move_after(target, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 147
+def move_after(target, source)
+  source_index = assert_index(source, :after)
+  source_middleware = middlewares.delete_at(source_index)
+
+  target_index = assert_index(target, :after)
+  middlewares.insert(target_index + 1, source_middleware)
+end
+
+
+ +
+ +
+

+ + move_before(target, source) + +

+ + +
+ +
+ + + + + +
+ Alias for: move +
+ + + +
+ +
+

+ + size() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 79
+def size
+  middlewares.size
+end
+
+
+ +
+ +
+

+ + swap(target, *args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 114
+def swap(target, *args, &block)
+  index = assert_index(target, :before)
+  insert(index, *args, &block)
+  middlewares.delete_at(index + 1)
+end
+
+
+ +
+ +
+

+ + unshift(klass, *args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 91
+def unshift(klass, *args, &block)
+  middlewares.unshift(build_middleware(klass, args, block))
+end
+
+
+ +
+ +
+

+ + use(klass, *args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 155
+def use(klass, *args, &block)
+  middlewares.push(build_middleware(klass, args, block))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/MiddlewareStack/InstrumentationProxy.html b/src/7.0/classes/ActionDispatch/MiddlewareStack/InstrumentationProxy.html new file mode 100644 index 0000000000..834b50c108 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/MiddlewareStack/InstrumentationProxy.html @@ -0,0 +1,179 @@ +--- +title: ActionDispatch::MiddlewareStack::InstrumentationProxy +layout: default +--- +
+ +
+
+ +
+ +

This class is used to instrument the execution of a single middleware. It proxies the call method transparently and instruments the method call.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
EVENT_NAME="process_middleware.action_dispatch"
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(middleware, class_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 51
+def initialize(middleware, class_name)
+  @middleware = middleware
+
+  @payload = {
+    middleware: class_name,
+  }
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 59
+def call(env)
+  ActiveSupport::Notifications.instrument(EVENT_NAME, @payload) do
+    @middleware.call(env)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/MiddlewareStack/Middleware.html b/src/7.0/classes/ActionDispatch/MiddlewareStack/Middleware.html new file mode 100644 index 0000000000..3cb2927e88 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/MiddlewareStack/Middleware.html @@ -0,0 +1,344 @@ +--- +title: ActionDispatch::MiddlewareStack::Middleware +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + args
+ [R] + block
+ [R] + klass
+ + + + +

Class Public methods

+ +
+

+ + new(klass, args, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 11
+def initialize(klass, args, block)
+  @klass = klass
+  @args  = args
+  @block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(middleware) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 19
+def ==(middleware)
+  case middleware
+  when Middleware
+    klass == middleware.klass
+  when Class
+    klass == middleware
+  end
+end
+
+
+ +
+ +
+

+ + build(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 36
+def build(app)
+  klass.new(app, *args, &block)
+end
+
+
+ +
+ +
+

+ + build_instrumented(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 40
+def build_instrumented(app)
+  InstrumentationProxy.new(build(app), inspect)
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 28
+def inspect
+  if klass.is_a?(Class)
+    klass.to_s
+  else
+    klass.class.to_s
+  end
+end
+
+
+ +
+ +
+

+ + name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/stack.rb, line 17
+def name; klass.name; end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/PermissionsPolicy.html b/src/7.0/classes/ActionDispatch/PermissionsPolicy.html new file mode 100644 index 0000000000..8f7f4c36a8 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/PermissionsPolicy.html @@ -0,0 +1,243 @@ +--- +title: ActionDispatch::PermissionsPolicy +layout: default +--- +
+ +
+
+ +
+ +

Configures the HTTP Feature-Policy response header to specify which browser features the current document and its iframes can use.

+ +

Example global policy:

+ +
Rails.application.config.permissions_policy do |policy|
+  policy.camera      :none
+  policy.gyroscope   :none
+  policy.microphone  :none
+  policy.usb         :none
+  policy.fullscreen  :self
+  policy.payment     :self, "https://secure.example.com"
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + directives
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 113
+def initialize
+  @directives = {}
+  yield self if block_given?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + build(context = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 132
+def build(context = nil)
+  build_directives(context).compact.join("; ")
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 118
+def initialize_copy(other)
+  @directives = other.directives.deep_dup
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/PermissionsPolicy/Middleware.html b/src/7.0/classes/ActionDispatch/PermissionsPolicy/Middleware.html new file mode 100644 index 0000000000..d6f874085e --- /dev/null +++ b/src/7.0/classes/ActionDispatch/PermissionsPolicy/Middleware.html @@ -0,0 +1,193 @@ +--- +title: ActionDispatch::PermissionsPolicy::Middleware +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_TYPE="Content-Type"
 
POLICY="Feature-Policy"
 

The Feature-Policy header has been renamed to Permissions-Policy. The Permissions-Policy requires a different implementation and isn’t yet supported by all browsers. To avoid having to rename this middleware in the future we use the new name for the middleware but keep the old header name and implementation for now.

+ + + + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 32
+def initialize(app)
+  @app = app
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 36
+def call(env)
+  request = ActionDispatch::Request.new(env)
+  _, headers, _ = response = @app.call(env)
+
+  return response unless html_response?(headers)
+  return response if policy_present?(headers)
+
+  if policy = request.permissions_policy
+    headers[POLICY] = policy.build(request.controller_instance)
+  end
+
+  if policy_empty?(policy)
+    headers.delete(POLICY)
+  end
+
+  response
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/PermissionsPolicy/Request.html b/src/7.0/classes/ActionDispatch/PermissionsPolicy/Request.html new file mode 100644 index 0000000000..e403084a72 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/PermissionsPolicy/Request.html @@ -0,0 +1,158 @@ +--- +title: ActionDispatch::PermissionsPolicy::Request +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
POLICY="action_dispatch.permissions_policy"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + permissions_policy() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 73
+def permissions_policy
+  get_header(POLICY)
+end
+
+
+ +
+ +
+

+ + permissions_policy=(policy) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/permissions_policy.rb, line 77
+def permissions_policy=(policy)
+  set_header(POLICY, policy)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/PublicExceptions.html b/src/7.0/classes/ActionDispatch/PublicExceptions.html new file mode 100644 index 0000000000..4d01fc58c2 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/PublicExceptions.html @@ -0,0 +1,180 @@ +--- +title: ActionDispatch::PublicExceptions +layout: default +--- +
+ +
+
+ +
+ +

When called, this middleware renders an error page. By default if an HTML response is expected it will render static error pages from the /public directory. For example when this middleware receives a 500 response it will render the template found in /public/500.html. If an internationalized locale is set, this middleware will attempt to render the template in /public/500.<locale>.html. If an internationalized template is not found it will fall back on /public/500.html.

+ +

When a request with a content type other than HTML is made, this middleware will attempt to convert error information into the appropriate response type.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + public_path
+ + + + +

Class Public methods

+ +
+

+ + new(public_path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/public_exceptions.rb, line 17
+def initialize(public_path)
+  @public_path = public_path
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/public_exceptions.rb, line 21
+def call(env)
+  request      = ActionDispatch::Request.new(env)
+  status       = request.path_info[1..-1].to_i
+  begin
+    content_type = request.formats.first
+  rescue ActionDispatch::Http::MimeNegotiation::InvalidType
+    content_type = Mime[:text]
+  end
+  body = { status: status, error: Rack::Utils::HTTP_STATUS_CODES.fetch(status, Rack::Utils::HTTP_STATUS_CODES[500]) }
+
+  render(status, content_type, body)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsEntityStore.html b/src/7.0/classes/ActionDispatch/RailsEntityStore.html new file mode 100644 index 0000000000..fc41058323 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsEntityStore.html @@ -0,0 +1,322 @@ +--- +title: ActionDispatch::RailsEntityStore +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(store = Rails.cache) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 37
+def initialize(store = Rails.cache)
+  @store = store
+end
+
+
+ +
+ +
+

+ + resolve(uri) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 33
+def self.resolve(uri)
+  new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + exist?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 41
+def exist?(key)
+  @store.exist?(key)
+end
+
+
+ +
+ +
+

+ + open(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 45
+def open(key)
+  @store.read(key)
+end
+
+
+ +
+ +
+

+ + read(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 49
+def read(key)
+  body = open(key)
+  body.join if body
+end
+
+
+ +
+ +
+

+ + write(body) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 54
+def write(body)
+  buf = []
+  key, size = slurp(body) { |part| buf << part }
+  @store.write(key, buf)
+  [key, size]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack.html b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack.html new file mode 100644 index 0000000000..87a76bcc6d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack.html @@ -0,0 +1,67 @@ +--- +title: ActionDispatch::RailsEntityStore::Rack +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache.html b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache.html new file mode 100644 index 0000000000..64defef17e --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache.html @@ -0,0 +1,67 @@ +--- +title: ActionDispatch::RailsEntityStore::Rack::Cache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache/EntityStore.html b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache/EntityStore.html new file mode 100644 index 0000000000..69f91d9277 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsEntityStore/Rack/Cache/EntityStore.html @@ -0,0 +1,72 @@ +--- +title: ActionDispatch::RailsEntityStore::Rack::Cache::EntityStore +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RAILS=self
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsMetaStore.html b/src/7.0/classes/ActionDispatch/RailsMetaStore.html new file mode 100644 index 0000000000..febcec84ec --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsMetaStore.html @@ -0,0 +1,244 @@ +--- +title: ActionDispatch::RailsMetaStore +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(store = Rails.cache) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 13
+def initialize(store = Rails.cache)
+  @store = store
+end
+
+
+ +
+ +
+

+ + resolve(uri) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 9
+def self.resolve(uri)
+  new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + read(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 17
+def read(key)
+  if data = @store.read(key)
+    Marshal.load(data)
+  else
+    []
+  end
+end
+
+
+ +
+ +
+

+ + write(key, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/rack_cache.rb, line 25
+def write(key, value)
+  @store.write(key, Marshal.dump(value))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack.html b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack.html new file mode 100644 index 0000000000..11236e06d1 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack.html @@ -0,0 +1,67 @@ +--- +title: ActionDispatch::RailsMetaStore::Rack +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache.html b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache.html new file mode 100644 index 0000000000..efe5ee07b5 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache.html @@ -0,0 +1,67 @@ +--- +title: ActionDispatch::RailsMetaStore::Rack::Cache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache/MetaStore.html b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache/MetaStore.html new file mode 100644 index 0000000000..472df70d74 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RailsMetaStore/Rack/Cache/MetaStore.html @@ -0,0 +1,72 @@ +--- +title: ActionDispatch::RailsMetaStore::Rack::Cache::MetaStore +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RAILS=self
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Reloader.html b/src/7.0/classes/ActionDispatch/Reloader.html new file mode 100644 index 0000000000..19ec48d9f7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Reloader.html @@ -0,0 +1,68 @@ +--- +title: ActionDispatch::Reloader +layout: default +--- +
+ +
+
+ +
+ +

ActionDispatch::Reloader wraps the request with callbacks provided by ActiveSupport::Reloader callbacks, intended to assist with code reloading during development.

+ +

By default, ActionDispatch::Reloader is included in the middleware stack only in the development environment; specifically, when config.cache_classes is false.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RemoteIp.html b/src/7.0/classes/ActionDispatch/RemoteIp.html new file mode 100644 index 0000000000..86c4125223 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RemoteIp.html @@ -0,0 +1,249 @@ +--- +title: ActionDispatch::RemoteIp +layout: default +--- +
+ +
+
+ +
+ +

This middleware calculates the IP address of the remote client that is making the request. It does this by checking various headers that could contain the address, and then picking the last-set address that is not on the list of trusted IPs. This follows the precedent set by e.g. the Tomcat server, with reasoning explained at length by @gingerlime. A more detailed explanation of the algorithm is given at GetIp#calculate_ip.

+ +

Some Rack servers concatenate repeated headers, like HTTP RFC 2616 requires. Some Rack servers simply drop preceding headers, and only report the value that was given in the last header. If you are behind multiple proxy servers (like NGINX to HAProxy to Unicorn) then you should test your Rack server to make sure your data is good.

+ +

IF YOU DON’T USE A PROXY, THIS MAKES YOU VULNERABLE TO IP SPOOFING. This middleware assumes that there is at least one proxy sitting around and setting headers with the client’s remote IP address. If you don’t use a proxy, because you are hosted on e.g. Heroku without SSL, any client can claim to have any IP address by setting the X-Forwarded-For header. If you care about that, then you need to explicitly drop or ignore those headers sometime before this middleware runs.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
TRUSTED_PROXIES=[ +"127.0.0.0/8", # localhost IPv4 range, per RFC-3330 +"::1", # localhost IPv6 +"fc00::/7", # private IPv6 range fc00::/7 +"10.0.0.0/8", # private IPv4 range 10.x.x.x +"172.16.0.0/12", # private IPv4 range 172.16.0.0 .. 172.31.255.255 +"192.168.0.0/16", # private IPv4 range 192.168.x.x +].map { |proxy| IPAddr.new(proxy) }
 

The default trusted IPs list simply includes IP addresses that are guaranteed by the IP specification to be private addresses. Those will not be the ultimate client IP in production, and so are discarded. See en.wikipedia.org/wiki/Private_network for details.

+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + check_ip
+ [R] + proxies
+ + + + +

Class Public methods

+ +
+

+ + new(app, ip_spoofing_check = true, custom_proxies = nil) + +

+ + +
+

Create a new RemoteIp middleware instance.

+ +

The ip_spoofing_check option is on by default. When on, an exception is raised if it looks like the client is trying to lie about its own IP address. It makes sense to turn off this check on sites aimed at non-IP clients (like WAP devices), or behind proxies that set headers in an incorrect or confusing way (like AWS ELB).

+ +

The custom_proxies argument can take an enumerable which will be used instead of TRUSTED_PROXIES. Any proxy setup will put the value you want in the middle (or at the beginning) of the X-Forwarded-For list, with your proxy servers after it. If your proxies aren’t removed, pass them in via the custom_proxies parameter. That way, the middleware will ignore those IP addresses, and return the one that you want.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 60
+    def initialize(app, ip_spoofing_check = true, custom_proxies = nil)
+      @app = app
+      @check_ip = ip_spoofing_check
+      @proxies = if custom_proxies.blank?
+        TRUSTED_PROXIES
+      elsif custom_proxies.respond_to?(:any?)
+        custom_proxies
+      else
+        ActiveSupport::Deprecation.warn(<<~EOM)
+          Setting config.action_dispatch.trusted_proxies to a single value has
+          been deprecated. Please set this to an enumerable instead. For
+          example, instead of:
+
+          config.action_dispatch.trusted_proxies = IPAddr.new("10.0.0.0/8")
+
+          Wrap the value in an Array:
+
+          config.action_dispatch.trusted_proxies = [IPAddr.new("10.0.0.0/8")]
+
+          Note that unlike passing a single argument, passing an enumerable
+          will *replace* the default set of trusted proxies.
+        EOM
+        Array(custom_proxies) + TRUSTED_PROXIES
+      end
+    end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+

Since the IP address may not be needed, we store the object here without calculating the IP to keep from slowing down the majority of requests. For those requests that do need to know the IP, the GetIp#calculate_ip method will calculate the memoized client IP address.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 90
+def call(env)
+  req = ActionDispatch::Request.new env
+  req.remote_ip = GetIp.new(req, check_ip, proxies)
+  @app.call(req.env)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RemoteIp/GetIp.html b/src/7.0/classes/ActionDispatch/RemoteIp/GetIp.html new file mode 100644 index 0000000000..583c2e1225 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RemoteIp/GetIp.html @@ -0,0 +1,332 @@ +--- +title: ActionDispatch::RemoteIp::GetIp +layout: default +--- +
+ +
+
+ +
+ +

The GetIp class exists as a way to defer processing of the request data into an actual IP address. If the ActionDispatch::Request#remote_ip method is called, this class will calculate the value and then memoize it.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(req, check_ip, proxies) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 100
+def initialize(req, check_ip, proxies)
+  @req      = req
+  @check_ip = check_ip
+  @proxies  = proxies
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + calculate_ip() + +

+ + +
+

Sort through the various IP address headers, looking for the IP most likely to be the address of the actual remote client making this request.

+ +

REMOTE_ADDR will be correct if the request is made directly against the Ruby process, on e.g. Heroku. When the request is proxied by another server like HAProxy or NGINX, the IP address that made the original request will be put in an X-Forwarded-For header. If there are multiple proxies, that header may contain a list of IPs. Other proxy services set the Client-Ip header instead, so we check that too.

+ +

As discussed in this post about Rails IP Spoofing, while the first IP in the list is likely to be the “originating” IP, it could also have been set by the client maliciously.

+ +

In order to find the first address that is (probably) accurate, we take the list of IPs, remove known and trusted proxies, and then take the last address left, which was presumably set by one of those proxies.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 124
+def calculate_ip
+  # Set by the Rack web server, this is a single value.
+  remote_addr = ips_from(@req.remote_addr).last
+
+  # Could be a CSV list and/or repeated headers that were concatenated.
+  client_ips    = ips_from(@req.client_ip).reverse
+  forwarded_ips = ips_from(@req.x_forwarded_for).reverse
+
+  # +Client-Ip+ and +X-Forwarded-For+ should not, generally, both be set.
+  # If they are both set, it means that either:
+  #
+  # 1) This request passed through two proxies with incompatible IP header
+  #    conventions.
+  # 2) The client passed one of +Client-Ip+ or +X-Forwarded-For+
+  #    (whichever the proxy servers weren't using) themselves.
+  #
+  # Either way, there is no way for us to determine which header is the
+  # right one after the fact. Since we have no idea, if we are concerned
+  # about IP spoofing we need to give up and explode. (If you're not
+  # concerned about IP spoofing you can turn the +ip_spoofing_check+
+  # option off.)
+  should_check_ip = @check_ip && client_ips.last && forwarded_ips.last
+  if should_check_ip && !forwarded_ips.include?(client_ips.last)
+    # We don't know which came from the proxy, and which from the user
+    raise IpSpoofAttackError, "IP spoofing attack?! " \
+      "HTTP_CLIENT_IP=#{@req.client_ip.inspect} " \
+      "HTTP_X_FORWARDED_FOR=#{@req.x_forwarded_for.inspect}"
+  end
+
+  # We assume these things about the IP headers:
+  #
+  #   - X-Forwarded-For will be a list of IPs, one per proxy, or blank
+  #   - Client-Ip is propagated from the outermost proxy, or is blank
+  #   - REMOTE_ADDR will be the IP that made the request to Rack
+  ips = [forwarded_ips, client_ips].flatten.compact
+
+  # If every single IP option is in the trusted list, return the IP
+  # that's furthest away
+  filter_proxies(ips + [remote_addr]).first || ips.last || remote_addr
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+

Memoizes the value returned by calculate_ip and returns it for ActionDispatch::Request to use.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 167
+def to_s
+  @ip ||= calculate_ip
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + filter_proxies(ips) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 186
+def filter_proxies(ips) # :doc:
+  ips.reject do |ip|
+    @proxies.any? { |proxy| proxy === ip }
+  end
+end
+
+
+ +
+ +
+

+ + ips_from(header) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/remote_ip.rb, line 172
+def ips_from(header) # :doc:
+  return [] unless header
+  # Split the comma-separated list into an array of strings.
+  ips = header.strip.split(/[,\s]+/)
+  ips.select do |ip|
+    # Only return IPs that are valid according to the IPAddr#new method.
+    range = IPAddr.new(ip).to_range
+    # We want to make sure nobody is sneaking a netmask in.
+    range.begin == range.end
+  rescue ArgumentError
+    nil
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RemoteIp/IpSpoofAttackError.html b/src/7.0/classes/ActionDispatch/RemoteIp/IpSpoofAttackError.html new file mode 100644 index 0000000000..ce1dd93148 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RemoteIp/IpSpoofAttackError.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::RemoteIp::IpSpoofAttackError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Request.html b/src/7.0/classes/ActionDispatch/Request.html new file mode 100644 index 0000000000..51649af847 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Request.html @@ -0,0 +1,1939 @@ +--- +title: ActionDispatch::Request +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ENV_METHODS=%w[ AUTH_TYPE GATEWAY_INTERFACE +PATH_TRANSLATED REMOTE_HOST +REMOTE_IDENT REMOTE_USER REMOTE_ADDR +SERVER_NAME SERVER_PROTOCOL +ORIGINAL_SCRIPT_NAME + +HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING +HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM +HTTP_NEGOTIATE HTTP_PRAGMA HTTP_CLIENT_IP +HTTP_X_FORWARDED_FOR HTTP_ORIGIN HTTP_VERSION +HTTP_X_CSRF_TOKEN HTTP_X_REQUEST_ID HTTP_X_FORWARDED_HOST +].freeze
 
HTTP_METHODS=RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789
 
HTTP_METHOD_LOOKUP={}
 
LOCALHOST=Regexp.union [/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/]
 
RFC2518=%w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
 

HTTP methods from RFC 2518: HTTP Extensions for Distributed Authoring – WEBDAV

RFC2616=%w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
 

HTTP methods from RFC 2616: Hypertext Transfer Protocol – HTTP/1.1

RFC3253=%w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
 

HTTP methods from RFC 3253: Versioning Extensions to WebDAV

RFC3648=%w(ORDERPATCH)
 

HTTP methods from RFC 3648: WebDAV Ordered Collections Protocol

RFC3744=%w(ACL)
 

HTTP methods from RFC 3744: WebDAV Access Control Protocol

RFC4791=%w(MKCALENDAR)
 

HTTP methods from RFC 4791: Calendaring Extensions to WebDAV

RFC5323=%w(SEARCH)
 

HTTP methods from RFC 5323: WebDAV SEARCH

RFC5789=%w(PATCH)
 

HTTP methods from RFC 5789: PATCH Method for HTTP

+ + + + + + +

Class Public methods

+ +
+

+ + empty() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 56
+def self.empty
+  new({})
+end
+
+
+ +
+ +
+

+ + new(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 60
+def initialize(env)
+  super
+  @method            = nil
+  @request_method    = nil
+  @remote_ip         = nil
+  @original_fullpath = nil
+  @fullpath          = nil
+  @ip                = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + GET() + +

+ + +
+

Override Rack’s GET method to support indifferent access.

+
+ + + +
+ Also aliased as: query_parameters +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 371
+def GET
+  fetch_header("action_dispatch.request.query_parameters") do |k|
+    rack_query_params = super || {}
+    controller = path_parameters[:controller]
+    action = path_parameters[:action]
+    rack_query_params = Request::Utils.set_binary_encoding(self, rack_query_params, controller, action)
+    # Check for non UTF-8 parameter values, which would cause errors later
+    Request::Utils.check_param_encoding(rack_query_params)
+    set_header k, Request::Utils.normalize_encode_params(rack_query_params)
+  end
+rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError => e
+  raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
+end
+
+
+ +
+ +
+

+ + POST() + +

+ + +
+

Override Rack’s POST method to support indifferent access.

+
+ + + +
+ Also aliased as: request_parameters +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 387
+def POST
+  fetch_header("action_dispatch.request.request_parameters") do
+    pr = parse_formatted_parameters(params_parsers) do |params|
+      super || {}
+    end
+    pr = Request::Utils.set_binary_encoding(self, pr, path_parameters[:controller], path_parameters[:action])
+    Request::Utils.check_param_encoding(pr)
+    self.request_parameters = Request::Utils.normalize_encode_params(pr)
+  end
+rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError, EOFError => e
+  raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
+end
+
+
+ +
+ +
+

+ + authorization() + +

+ + +
+

Returns the authorization header regardless of whether it was specified directly or through one of the proxy alternatives.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 403
+def authorization
+  get_header("HTTP_AUTHORIZATION")   ||
+  get_header("X-HTTP_AUTHORIZATION") ||
+  get_header("X_HTTP_AUTHORIZATION") ||
+  get_header("REDIRECT_X_HTTP_AUTHORIZATION")
+end
+
+
+ +
+ +
+

+ + body() + +

+ + +
+

The request body is an IO input stream. If the RAW_POST_DATA environment variable is already set, wrap it in a StringIO.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 333
+def body
+  if raw_post = get_header("RAW_POST_DATA")
+    raw_post = (+raw_post).force_encoding(Encoding::BINARY)
+    StringIO.new(raw_post)
+  else
+    body_stream
+  end
+end
+
+
+ +
+ +
+

+ + commit_flash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 424
+def commit_flash
+end
+
+
+ +
+ +
+

+ + content_length() + +

+ + +
+

Returns the content length of the request as an integer.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 269
+def content_length
+  super.to_i
+end
+
+
+ +
+ +
+

+ + controller_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 79
+def controller_class
+  params = path_parameters
+  params[:action] ||= "index"
+  controller_class_for(params[:controller])
+end
+
+
+ +
+ +
+

+ + controller_class_for(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 85
+def controller_class_for(name)
+  if name
+    controller_param = name.underscore
+    const_name = controller_param.camelize << "Controller"
+    begin
+      const_name.constantize
+    rescue NameError => error
+      if error.missing_name == const_name || const_name.start_with?("#{error.missing_name}::")
+        raise MissingController.new(error.message, error.name)
+      else
+        raise
+      end
+    end
+  else
+    PASS_NOT_FOUND
+  end
+end
+
+
+ +
+ +
+

+ + form_data?() + +

+ + +
+

Determine whether the request body contains form-data by checking the request Content-Type for one of the media-types: application/x-www-form-urlencoded or multipart/form-data. The list of form-data media types can be modified through the FORM_DATA_MEDIA_TYPES array.

+ +

A request body is not assumed to contain form-data when no Content-Type header is provided and the request_method is POST.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 350
+def form_data?
+  FORM_DATA_MEDIA_TYPES.include?(media_type)
+end
+
+
+ +
+ +
+

+ + fullpath() + +

+ + +
+

Returns the String full path including params of the last URL requested.

+ +
# get "/articles"
+request.fullpath # => "/articles"
+
+# get "/articles?page=2"
+request.fullpath # => "/articles?page=2"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 248
+def fullpath
+  @fullpath ||= super
+end
+
+
+ +
+ +
+

+ + headers() + +

+ + +
+

Provides access to the request’s HTTP headers, for example:

+ +
request.headers["Content-Type"] # => "text/plain"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 209
+def headers
+  @headers ||= Http::Headers.new(self)
+end
+
+
+ +
+ +
+

+ + http_auth_salt() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 178
+def http_auth_salt
+  get_header "action_dispatch.http_auth_salt"
+end
+
+
+ +
+ +
+

+ + ip() + +

+ + +
+

Returns the IP address of client as a String.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 282
+def ip
+  @ip ||= super
+end
+
+
+ +
+ +
+

+ + key?(key) + +

+ + +
+

Returns true if the request has a header matching the given key parameter.

+ +
request.key? :ip_spoofing_check # => true
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 106
+def key?(key)
+  has_header? key
+end
+
+
+ +
+ +
+

+ + local?() + +

+ + +
+

True if the request came from localhost, 127.0.0.1, or ::1.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 411
+def local?
+  LOCALHOST.match?(remote_addr) && LOCALHOST.match?(remote_ip)
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 420
+def logger
+  get_header("action_dispatch.logger")
+end
+
+
+ +
+ +
+

+ + media_type() + +

+ + +
+

The String MIME type of the request.

+ +
# get "/articles"
+request.media_type # => "application/x-www-form-urlencoded"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 264
+def media_type
+  content_mime_type&.to_s
+end
+
+
+ +
+ +
+

+ + method() + +

+ + +
+

Returns the original value of the environment’s REQUEST_METHOD, even if it was overridden by middleware. See request_method for more information.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 197
+def method
+  @method ||= check_method(get_header("rack.methodoverride.original_method") || get_header("REQUEST_METHOD"))
+end
+
+
+ +
+ +
+

+ + method_symbol() + +

+ + +
+

Returns a symbol form of the method.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 202
+def method_symbol
+  HTTP_METHOD_LOOKUP[method]
+end
+
+
+ +
+ +
+

+ + original_fullpath() + +

+ + +
+

Returns a String with the last requested path including their params.

+ +
# get '/foo'
+request.original_fullpath # => '/foo'
+
+# get '/foo?bar'
+request.original_fullpath # => '/foo?bar'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 237
+def original_fullpath
+  @original_fullpath ||= (get_header("ORIGINAL_FULLPATH") || fullpath)
+end
+
+
+ +
+ +
+

+ + original_url() + +

+ + +
+

Returns the original request URL as a String.

+ +
# get "/articles?page=2"
+request.original_url # => "http://www.example.com/articles?page=2"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 256
+def original_url
+  base_url + original_fullpath
+end
+
+
+ +
+ +
+

+ + query_parameters() + +

+ + +
+ +
+ + + + + +
+ Alias for: GET +
+ + + +
+ +
+

+ + raw_post() + +

+ + +
+

Read the request body. This is useful for web services that need to work with raw requests directly.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 322
+def raw_post
+  unless has_header? "RAW_POST_DATA"
+    raw_post_body = body
+    set_header("RAW_POST_DATA", raw_post_body.read(content_length))
+    raw_post_body.rewind if raw_post_body.respond_to?(:rewind)
+  end
+  get_header "RAW_POST_DATA"
+end
+
+
+ +
+ +
+

+ + raw_request_method() + +

+ + +
+ +
+ + + + + +
+ Alias for: request_method +
+ + + +
+ +
+

+ + remote_ip() + +

+ + +
+

Returns the IP address of client as a String, usually set by the RemoteIp middleware.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 288
+def remote_ip
+  @remote_ip ||= (get_header("action_dispatch.remote_ip") || ip).to_s
+end
+
+
+ +
+ +
+

+ + remote_ip=(remote_ip) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 292
+def remote_ip=(remote_ip)
+  @remote_ip = nil
+  set_header "action_dispatch.remote_ip", remote_ip
+end
+
+
+ +
+ +
+

+ + request_id() + +

+ + +
+

Returns the unique request id, which is based on either the X-Request-Id header that can be generated by a firewall, load balancer, or web server, or by the RequestId middleware (which sets the action_dispatch.request_id environment variable).

+ +

This unique ID is useful for tracing a request from end-to-end as part of logging or debugging. This relies on the Rack variable set by the ActionDispatch::RequestId middleware.

+
+ + + +
+ Also aliased as: uuid +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 305
+def request_id
+  get_header ACTION_DISPATCH_REQUEST_ID
+end
+
+
+ +
+ +
+

+ + request_method() + +

+ + +
+

Returns the HTTP method that the application should see. In the case where the method was overridden by a middleware (for instance, if a HEAD request was converted to a GET, or if a _method parameter was used to determine the method the application should use), this method returns the overridden value, not the original.

+
+ + + +
+ Also aliased as: raw_request_method +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 144
+def request_method
+  @request_method ||= check_method(super)
+end
+
+
+ +
+ +
+

+ + request_method_symbol() + +

+ + +
+

Returns a symbol form of the request_method.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 190
+def request_method_symbol
+  HTTP_METHOD_LOOKUP[request_method]
+end
+
+
+ +
+ +
+

+ + request_parameters() + +

+ + +
+ +
+ + + + + +
+ Alias for: POST +
+ + + +
+ +
+

+ + request_parameters=(params) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 415
+def request_parameters=(params)
+  raise if params.nil?
+  set_header("action_dispatch.request.request_parameters", params)
+end
+
+
+ +
+ +
+

+ + reset_session() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 358
+def reset_session
+  session.destroy
+end
+
+
+ +
+ +
+

+ + send_early_hints(links) + +

+ + +
+

Early Hints is an HTTP/2 status code that indicates hints to help a client start making preparations for processing the final response.

+ +

If the env contains rack.early_hints then the server accepts HTTP2 push for Link headers.

+ +

The send_early_hints method accepts a hash of links as follows:

+ +
send_early_hints("Link" => "</style.css>; rel=preload; as=style\n</script.js>; rel=preload")
+
+ +

If you are using javascript_include_tag or stylesheet_link_tag the Early Hints headers are included by default if supported.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 224
+def send_early_hints(links)
+  return unless env["rack.early_hints"]
+
+  env["rack.early_hints"].call(links)
+end
+
+
+ +
+ +
+

+ + server_software() + +

+ + +
+

Returns the lowercase name of the HTTP server software.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 316
+def server_software
+  (get_header("SERVER_SOFTWARE") && /^([a-zA-Z]+)/ =~ get_header("SERVER_SOFTWARE")) ? $1.downcase : nil
+end
+
+
+ +
+ +
+

+ + session_options=(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 366
+def session_options=(options)
+  Session::Options.set self, options
+end
+
+
+ +
+ +
+

+ + uuid() + +

+ + +
+ +
+ + + + + +
+ Alias for: request_id +
+ + + +
+ +
+

+ + xhr?() + +

+ + +
+ +
+ + + + + +
+ Alias for: xml_http_request? +
+ + + +
+ +
+

+ + xml_http_request?() + +

+ + +
+

Returns true if the X-Requested-With header contains “XMLHttpRequest” (case-insensitive), which may need to be manually added depending on the choice of JavaScript libraries and frameworks.

+
+ + + +
+ Also aliased as: xhr? +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/request.rb, line 276
+def xml_http_request?
+  /XMLHttpRequest/i.match?(get_header("HTTP_X_REQUESTED_WITH"))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RequestCookieMethods.html b/src/7.0/classes/ActionDispatch/RequestCookieMethods.html new file mode 100644 index 0000000000..7d54bd2ef1 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RequestCookieMethods.html @@ -0,0 +1,103 @@ +--- +title: ActionDispatch::RequestCookieMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+ + + +
+ +
+ + + + + + + + +
+ + + +
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RequestEncoder.html b/src/7.0/classes/ActionDispatch/RequestEncoder.html new file mode 100644 index 0000000000..58a88e7eda --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RequestEncoder.html @@ -0,0 +1,73 @@ +--- +title: ActionDispatch::RequestEncoder +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RequestEncoder/IdentityEncoder.html b/src/7.0/classes/ActionDispatch/RequestEncoder/IdentityEncoder.html new file mode 100644 index 0000000000..b75431a057 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RequestEncoder/IdentityEncoder.html @@ -0,0 +1,216 @@ +--- +title: ActionDispatch::RequestEncoder::IdentityEncoder +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + accept_header() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/request_encoder.rb, line 7
+def accept_header; end
+
+
+ +
+ +
+

+ + content_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/request_encoder.rb, line 6
+def content_type; end
+
+
+ +
+ +
+

+ + encode_params(params) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/request_encoder.rb, line 8
+def encode_params(params); params; end
+
+
+ +
+ +
+

+ + response_parser() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/request_encoder.rb, line 9
+def response_parser; -> body { body }; end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/RequestId.html b/src/7.0/classes/ActionDispatch/RequestId.html new file mode 100644 index 0000000000..45fe45fae9 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/RequestId.html @@ -0,0 +1,162 @@ +--- +title: ActionDispatch::RequestId +layout: default +--- +
+ +
+
+ +
+ +

Makes a unique request id available to the action_dispatch.request_id env variable (which is then accessible through ActionDispatch::Request#request_id or the alias ActionDispatch::Request#uuid) and sends the same id to the client via the X-Request-Id header.

+ +

The unique request id is either based on the X-Request-Id header in the request, which would typically be generated by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the header is accepted from the outside world, we sanitize it to a max of 255 chars and alphanumeric and dashes only.

+ +

The unique request id can be used to trace a request end-to-end and would typically end up being part of log files from multiple pieces of the stack.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, header:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/request_id.rb, line 18
+def initialize(app, header:)
+  @app = app
+  @header = header
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/request_id.rb, line 23
+def call(env)
+  req = ActionDispatch::Request.new env
+  req.request_id = make_request_id(req.headers[@header])
+  @app.call(env).tap { |_status, headers, _body| headers[@header] = req.request_id }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Response.html b/src/7.0/classes/ActionDispatch/Response.html new file mode 100644 index 0000000000..456ab9e9fa --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Response.html @@ -0,0 +1,1808 @@ +--- +title: ActionDispatch::Response +layout: default +--- +
+ +
+
+ +
+ +

Represents an HTTP response generated by a controller action. Use it to retrieve the current state of the response, or customize the response. It can either represent a real HTTP response (i.e. one that is meant to be sent back to the web browser) or a TestResponse (i.e. one that is generated from integration tests).

+ +

Response is mostly a Ruby on Rails framework implementation detail, and should never be used directly in controllers. Controllers should use the methods defined in ActionController::Base instead. For example, if you want to set the HTTP response’s content MIME type, then use ActionControllerBase#headers instead of Response#headers.

+ +

Nevertheless, integration tests may want to inspect controller responses in more detail, and that’s when Response can be useful for application developers. Integration test methods such as Integration::RequestHelpers#get and Integration::RequestHelpers#post return objects of type TestResponse (which are of course also of type Response).

+ +

For example, the following demo integration test prints the body of the controller response to the console:

+ +
class DemoControllerTest < ActionDispatch::IntegrationTest
+  def test_print_root_path_to_console
+    get('/')
+    puts response.body
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_TYPE="Content-Type"
 
ContentTypeHeader=Struct.new :mime_type, :charset
 
LOCATION="Location"
 
NO_CONTENT_CODES=[100, 101, 102, 103, 204, 205, 304]
 
NullContentTypeHeader=ContentTypeHeader.new nil, nil
 
SET_COOKIE="Set-Cookie"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + header

Get headers for this response.

+ [R] + headers

Get headers for this response.

+ [RW] + request

The request that the response is responding to.

+ [R] + status

The HTTP status code.

+ [R] + stream

The underlying body, as a streamable object.

+ + + + +

Class Public methods

+ +
+

+ + create(status = 200, header = {}, body = [], default_headers: self.default_headers) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 149
+def self.create(status = 200, header = {}, body = [], default_headers: self.default_headers)
+  header = merge_default_headers(header, default_headers)
+  new status, header, body
+end
+
+
+ +
+ +
+

+ + merge_default_headers(original, default) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 154
+def self.merge_default_headers(original, default)
+  default.respond_to?(:merge) ? default.merge(original) : original
+end
+
+
+ +
+ +
+

+ + new(status = 200, header = {}, body = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 161
+def initialize(status = 200, header = {}, body = [])
+  super()
+
+  @header = Header.new(self, header)
+
+  self.body, self.status = body, status
+
+  @cv           = new_cond
+  @committed    = false
+  @sending      = false
+  @sent         = false
+
+  prepare_cache_control!
+
+  yield self if block_given?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + abort() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 370
+def abort
+  if stream.respond_to?(:abort)
+    stream.abort
+  elsif stream.respond_to?(:close)
+    # `stream.close` should really be reserved for a close from the
+    # other direction, but we must fall back to it for
+    # compatibility.
+    stream.close
+  end
+end
+
+
+ +
+ +
+

+ + await_commit() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 183
+def await_commit
+  synchronize do
+    @cv.wait_until { @committed }
+  end
+end
+
+
+ +
+ +
+

+ + await_sent() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 189
+def await_sent
+  synchronize { @cv.wait_until { @sent } }
+end
+
+
+ +
+ +
+

+ + body() + +

+ + +
+

Returns the content of the response as a string. This contains the contents of any calls to render.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 304
+def body
+  @stream.body
+end
+
+
+ +
+ +
+

+ + body=(body) + +

+ + +
+

Allows you to manually set or override the response body.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 313
+def body=(body)
+  if body.respond_to?(:to_path)
+    @stream = body
+  else
+    synchronize do
+      @stream = build_buffer self, munge_body_object(body)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + body_parts() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 357
+def body_parts
+  parts = []
+  @stream.each { |x| parts << x }
+  parts
+end
+
+
+ +
+ +
+

+ + charset() + +

+ + +
+

The charset of the response. HTML wants to know the encoding of the content you’re giving them, so we need to send that along.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 274
+def charset
+  header_info = parsed_content_type_header
+  header_info.charset || self.class.default_charset
+end
+
+
+ +
+ +
+

+ + charset=(charset) + +

+ + +
+

Sets the HTTP character set. In case of nil parameter it sets the charset to default_charset.

+ +
response.charset = 'utf-16' # => 'utf-16'
+response.charset = nil      # => 'utf-8'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 263
+def charset=(charset)
+  content_type = parsed_content_type_header.mime_type
+  if false == charset
+    set_content_type content_type, nil
+  else
+    set_content_type content_type, charset || self.class.default_charset
+  end
+end
+
+
+ +
+ +
+

+ + close() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 366
+def close
+  stream.close if stream.respond_to?(:close)
+end
+
+
+ +
+ +
+

+ + code() + +

+ + +
+

Returns a string to ensure compatibility with Net::HTTPResponse.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 285
+def code
+  @status.to_s
+end
+
+
+ +
+ +
+

+ + commit!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 193
+def commit!
+  synchronize do
+    before_committed
+    @committed = true
+    @cv.broadcast
+  end
+end
+
+
+ +
+ +
+

+ + committed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 217
+def committed?; synchronize { @committed }; end
+
+
+ +
+ +
+

+ + content_type() + +

+ + +
+

Content type of response.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 243
+def content_type
+  super.presence
+end
+
+
+ +
+ +
+

+ + content_type=(content_type) + +

+ + +
+

Sets the HTTP response’s content MIME type. For example, in the controller you could write this:

+ +
response.content_type = "text/plain"
+
+ +

If a character set has been defined for this response (see charset=) then the character set information will also be included in the content type information.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 233
+def content_type=(content_type)
+  return unless content_type
+  new_header_info = parse_content_type(content_type.to_s)
+  prev_header_info = parsed_content_type_header
+  charset = new_header_info.charset || prev_header_info.charset
+  charset ||= self.class.default_charset unless prev_header_info.mime_type
+  set_content_type new_header_info.mime_type, charset
+end
+
+
+ +
+ +
+

+ + cookies() + +

+ + +
+

Returns the response cookies, converted to a Hash of (name => value) pairs

+ +
assert_equal 'AuthorOfNewPage', r.cookies['author']
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 394
+def cookies
+  cookies = {}
+  if header = get_header(SET_COOKIE)
+    header = header.split("\n") if header.respond_to?(:to_str)
+    header.each do |cookie|
+      if pair = cookie.split(";").first
+        key, value = pair.split("=").map { |v| Rack::Utils.unescape(v) }
+        cookies[key] = value
+      end
+    end
+  end
+  cookies
+end
+
+
+ +
+ +
+

+ + delete_header(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 181
+def delete_header(key); headers.delete key; end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 73
+def each(&block)
+  sending!
+  x = @stream.each(&block)
+  sent!
+  x
+end
+
+
+ +
+ +
+

+ + get_header(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 179
+def get_header(key);    headers[key];       end
+
+
+ +
+ +
+

+ + has_header?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 178
+def has_header?(key);   headers.key? key;   end
+
+
+ +
+ +
+

+ + media_type() + +

+ + +
+

Media type of response.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 248
+def media_type
+  parsed_content_type_header.mime_type
+end
+
+
+ +
+ +
+

+ + message() + +

+ + +
+

Returns the corresponding message for the current HTTP status code:

+ +
response.status = 200
+response.message # => "OK"
+
+response.status = 404
+response.message # => "Not Found"
+
+
+ + + +
+ Also aliased as: status_message +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 297
+def message
+  Rack::Utils::HTTP_STATUS_CODES[@status]
+end
+
+
+ +
+ +
+

+ + prepare!() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_a +
+ + + +
+ +
+

+ + reset_body!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 353
+def reset_body!
+  @stream = build_buffer(self, [])
+end
+
+
+ +
+ +
+

+ + response_code() + +

+ + +
+

The response code of the request.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 280
+def response_code
+  @status
+end
+
+
+ +
+ +
+

+ + send_file(path) + +

+ + +
+

Send the file stored at path as the response body.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 348
+def send_file(path)
+  commit!
+  @stream = FileBody.new(path)
+end
+
+
+ +
+ +
+

+ + sending!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 201
+def sending!
+  synchronize do
+    before_sending
+    @sending = true
+    @cv.broadcast
+  end
+end
+
+
+ +
+ +
+

+ + sending?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 216
+def sending?;   synchronize { @sending };   end
+
+
+ +
+ +
+

+ + sending_file=(v) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 252
+def sending_file=(v)
+  if true == v
+    self.charset = false
+  end
+end
+
+
+ +
+ +
+

+ + sent!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 209
+def sent!
+  synchronize do
+    @sent = true
+    @cv.broadcast
+  end
+end
+
+
+ +
+ +
+

+ + sent?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 218
+def sent?;      synchronize { @sent };      end
+
+
+ +
+ +
+

+ + set_header(key, v) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 180
+def set_header(key, v); headers[key] = v;   end
+
+
+ +
+ +
+

+ + status=(status) + +

+ + +
+

Sets the HTTP status code.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 221
+def status=(status)
+  @status = Rack::Utils.status_code(status)
+end
+
+
+ +
+ +
+

+ + status_message() + +

+ + +
+ +
+ + + + + +
+ Alias for: message +
+ + + +
+ +
+

+ + to_a() + +

+ + +
+

Turns the Response into a Rack-compatible array of the status, headers, and body. Allows explicit splatting:

+ +
status, headers, body = *response
+
+
+ + + +
+ Also aliased as: prepare! +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 385
+def to_a
+  commit!
+  rack_response @status, @header.to_hash
+end
+
+
+ +
+ +
+

+ + write(string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 308
+def write(string)
+  @stream.write string
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Response/RackBody.html b/src/7.0/classes/ActionDispatch/Response/RackBody.html new file mode 100644 index 0000000000..5cb22763d1 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Response/RackBody.html @@ -0,0 +1,311 @@ +--- +title: ActionDispatch::Response::RackBody +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(response) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 475
+def initialize(response)
+  @response = response
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + body() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 489
+def body
+  @response.body
+end
+
+
+ +
+ +
+

+ + close() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 483
+def close
+  # Rack "close" maps to Response#abort, and *not* Response#close
+  # (which is used when the controller's finished writing)
+  @response.abort
+end
+
+
+ +
+ +
+

+ + each(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 479
+def each(*args, &block)
+  @response.each(*args, &block)
+end
+
+
+ +
+ +
+

+ + respond_to?(method, include_private = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 493
+def respond_to?(method, include_private = false)
+  if method.to_sym == :to_path
+    @response.stream.respond_to?(method)
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + to_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/response.rb, line 501
+def to_path
+  @response.stream.to_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing.html b/src/7.0/classes/ActionDispatch/Routing.html new file mode 100644 index 0000000000..ed288d3eef --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing.html @@ -0,0 +1,352 @@ +--- +title: ActionDispatch::Routing +layout: default +--- +
+ +
+
+ +
+ +

The routing module provides URL rewriting in native Ruby. It’s a way to redirect incoming requests to controllers and actions. This replaces mod_rewrite rules. Best of all, Rails’ Routing works with any web server. Routes are defined in config/routes.rb.

+ +

Think of creating routes as drawing a map for your requests. The map tells them where to go based on some predefined pattern:

+ +
Rails.application.routes.draw do
+  Pattern 1 tells some request to go to one place
+  Pattern 2 tell them to go to another
+  ...
+end
+
+ +

The following symbols are special:

+ +
:controller maps to your controller name
+:action     maps to an action with your controllers
+
+ +

Other names simply map to a parameter as in the case of :id.

+ +

Resources

+ +

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update, and destroy actions, a resourceful route declares them in a single line of code:

+ +
resources :photos
+
+ +

Sometimes, you have a resource that clients always look up without referencing an ID. A common example, /profile always shows the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action.

+ +
resource :profile
+
+ +

It’s common to have resources that are logically children of other resources:

+ +
resources :magazines do
+  resources :ads
+end
+
+ +

You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an admin namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:

+ +
namespace "admin" do
+  resources :posts, :comments
+end
+
+ +

Alternatively, you can add prefixes to your path without using a separate directory by using scope. scope takes additional options which apply to all enclosed routes.

+ +
scope path: "/cpanel", as: 'admin' do
+  resources :posts, :comments
+end
+
+ +

For more, see Routing::Mapper::Resources#resources, Routing::Mapper::Scoping#namespace, and Routing::Mapper::Scoping#scope.

+ +

Non-resourceful routes

+ +

For routes that don’t fit the resources mold, you can use the HTTP helper methods get, post, patch, put and delete.

+ +
get 'post/:id', to: 'posts#show'
+post 'post/:id', to: 'posts#create_comment'
+
+ +

Now, if you POST to /posts/:id, it will route to the create_comment action. A GET on the same URL will route to the show action.

+ +

If your route needs to respond to more than one HTTP method (or all methods) then using the :via option on match is preferable.

+ +
match 'post/:id', to: 'posts#show', via: [:get, :post]
+
+ +

Named routes

+ +

Routes can be named by passing an :as option, allowing for easy reference within your source as name_of_route_url for the full URL and name_of_route_path for the URI path.

+ +

Example:

+ +
# In config/routes.rb
+get '/login', to: 'accounts#login', as: 'login'
+
+# With render, redirect_to, tests, etc.
+redirect_to login_url
+
+ +

Arguments can be passed as well.

+ +
redirect_to show_item_path(id: 25)
+
+ +

Use root as a shorthand to name a route for the root path “/”.

+ +
# In config/routes.rb
+root to: 'blogs#index'
+
+# would recognize http://www.example.com/ as
+params = { controller: 'blogs', action: 'index' }
+
+# and provide these named routes
+root_url   # => 'http://www.example.com/'
+root_path  # => '/'
+
+ +

Note: when using controller, the route is simply named after the method you call on the block parameter rather than map.

+ +
# In config/routes.rb
+controller :blog do
+  get 'blog/show',    to: :list
+  get 'blog/delete',  to: :delete
+  get 'blog/edit',    to: :edit
+end
+
+# provides named routes for show, delete, and edit
+link_to @article.title, blog_show_path(id: @article.id)
+
+ +

Pretty URLs

+ +

Routes can generate pretty URLs. For example:

+ +
get '/articles/:year/:month/:day', to: 'articles#find_by_id', constraints: {
+  year:       /\d{4}/,
+  month:      /\d{1,2}/,
+  day:        /\d{1,2}/
+}
+
+ +

Using the route above, the URL “localhost:3000/articles/2005/11/06” maps to

+ +
params = {year: '2005', month: '11', day: '06'}
+
+ +

Regular Expressions and parameters

+ +

You can specify a regular expression to define a format for a parameter.

+ +
controller 'geocode' do
+  get 'geocode/:postalcode', to: :show, constraints: {
+    postalcode: /\d{5}(-\d{4})?/
+  }
+end
+
+ +

Constraints can include the ‘ignorecase’ and ‘extended syntax’ regular expression modifiers:

+ +
controller 'geocode' do
+  get 'geocode/:postalcode', to: :show, constraints: {
+    postalcode: /hx\d\d\s\d[a-z]{2}/i
+  }
+end
+
+controller 'geocode' do
+  get 'geocode/:postalcode', to: :show, constraints: {
+    postalcode: /# Postalcode format
+       \d{5} #Prefix
+       (-\d{4})? #Suffix
+       /x
+  }
+end
+
+ +

Using the multiline modifier will raise an ArgumentError. Encoding regular expression modifiers are silently ignored. The match will always use the default encoding or ASCII.

+ +

External redirects

+ +

You can redirect any path to another path using the redirect helper in your router:

+ +
get "/stories", to: redirect("/posts")
+
+ +

Unicode character routes

+ +

You can specify unicode character routes in your router:

+ +
get "こんにちは", to: "welcome#index"
+
+ +

Routing to Rack Applications

+ +

Instead of a String, like posts#index, which corresponds to the index action in the PostsController, you can specify any Rack application as the endpoint for a matcher:

+ +
get "/application.js", to: Sprockets
+
+ +

Reloading routes

+ +

You can reload routes if you feel you must:

+ +
Rails.application.reload_routes!
+
+ +

This will clear all named routes and reload config/routes.rb if the file has been modified from last load. To absolutely force reloading, use reload!.

+ +

Testing Routes

+ +

The two main methods for testing your routes:

+ +

assert_routing

+ +
def test_movie_route_properly_splits
+  opts = {controller: "plugin", action: "checkout", id: "2"}
+  assert_routing "plugin/checkout/2", opts
+end
+
+ +

assert_routing lets you test whether or not the route properly resolves into options.

+ +

assert_recognizes

+ +
def test_route_has_options
+  opts = {controller: "plugin", action: "show", id: "12"}
+  assert_recognizes opts, "/plugins/show/12"
+end
+
+ +

Note the subtle difference between the two: assert_routing tests that a URL fits options while assert_recognizes tests that a URL breaks into parameters properly.

+ +

In tests you can simply pass the URL or named route to get or post.

+ +
def send_to_jail
+  get '/jail'
+  assert_response :success
+end
+
+def goes_to_login
+  get login_url
+  #...
+end
+
+ +

View a list of all your routes

+ +
rails routes
+
+ +

Target a specific controller with -c, or grep routes using -g. Useful in conjunction with --expanded which displays routes vertically.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter.html b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter.html new file mode 100644 index 0000000000..2270d37336 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter.html @@ -0,0 +1,73 @@ +--- +title: ActionDispatch::Routing::ConsoleFormatter +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Base.html b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Base.html new file mode 100644 index 0000000000..ea94bfa493 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Base.html @@ -0,0 +1,315 @@ +--- +title: ActionDispatch::Routing::ConsoleFormatter::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 131
+def initialize
+  @buffer = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + header(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 145
+def header(routes)
+end
+
+
+ +
+ +
+

+ + no_routes(routes, filter) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 148
+        def no_routes(routes, filter)
+          @buffer <<
+            if routes.none?
+              <<~MESSAGE
+                You don't have any routes defined!
+
+                Please add some routes in config/routes.rb.
+              MESSAGE
+            elsif filter.key?(:controller)
+              "No routes were found for this controller."
+            elsif filter.key?(:grep)
+              "No routes were found for this grep pattern."
+            end
+
+          @buffer << "For more information about routes, see the Rails guide: https://guides.rubyonrails.org/routing.html."
+        end
+
+
+ +
+ +
+

+ + result() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 135
+def result
+  @buffer.join("\n")
+end
+
+
+ +
+ +
+

+ + section(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 142
+def section(routes)
+end
+
+
+ +
+ +
+

+ + section_title(title) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 139
+def section_title(title)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Expanded.html b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Expanded.html new file mode 100644 index 0000000000..1e17292fe4 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Expanded.html @@ -0,0 +1,189 @@ +--- +title: ActionDispatch::Routing::ConsoleFormatter::Expanded +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(width: IO.console_size[1]) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 203
+def initialize(width: IO.console_size[1])
+  @width = width
+  super()
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + section(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 212
+def section(routes)
+  @buffer << draw_expanded_section(routes)
+end
+
+
+ +
+ +
+

+ + section_title(title) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 208
+def section_title(title)
+  @buffer << "\n#{"[ #{title} ]"}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Sheet.html b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Sheet.html new file mode 100644 index 0000000000..850d62f5bf --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/ConsoleFormatter/Sheet.html @@ -0,0 +1,185 @@ +--- +title: ActionDispatch::Routing::ConsoleFormatter::Sheet +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + header(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 175
+def header(routes)
+  @buffer << draw_header(routes)
+end
+
+
+ +
+ +
+

+ + section(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 171
+def section(routes)
+  @buffer << draw_section(routes)
+end
+
+
+ +
+ +
+

+ + section_title(title) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 167
+def section_title(title)
+  @buffer << "\n#{title}:"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/HtmlTableFormatter.html b/src/7.0/classes/ActionDispatch/Routing/HtmlTableFormatter.html new file mode 100644 index 0000000000..d494e6edf7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/HtmlTableFormatter.html @@ -0,0 +1,316 @@ +--- +title: ActionDispatch::Routing::HtmlTableFormatter +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(view) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 236
+def initialize(view)
+  @view = view
+  @buffer = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + header(routes) + +

+ + +
+

The header is part of the HTML page, so we don’t construct it here.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 250
+def header(routes)
+end
+
+
+ +
+ +
+

+ + no_routes(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 253
+      def no_routes(*)
+        @buffer << <<~MESSAGE
+          <p>You don't have any routes defined!</p>
+          <ul>
+            <li>Please add some routes in <tt>config/routes.rb</tt>.</li>
+            <li>
+              For more information about routes, please see the Rails guide
+              <a href="https://guides.rubyonrails.org/routing.html">Rails Routing from the Outside In</a>.
+            </li>
+          </ul>
+        MESSAGE
+      end
+
+
+ +
+ +
+

+ + result() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 266
+def result
+  @view.raw @view.render(layout: "routes/table") {
+    @view.raw @buffer.join("\n")
+  }
+end
+
+
+ +
+ +
+

+ + section(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 245
+def section(routes)
+  @buffer << @view.render(partial: "routes/route", collection: routes)
+end
+
+
+ +
+ +
+

+ + section_title(title) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/inspector.rb, line 241
+def section_title(title)
+  @buffer << %(<tr><th colspan="4">#{title}</th></tr>)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper.html b/src/7.0/classes/ActionDispatch/Routing/Mapper.html new file mode 100644 index 0000000000..0997d5cd24 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper.html @@ -0,0 +1,262 @@ +--- +title: ActionDispatch::Routing::Mapper +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
URL_OPTIONS=[:protocol, :subdomain, :domain, :host, :port]
 
+ + + + + + +

Class Public methods

+ +
+

+ + normalize_name(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 381
+def self.normalize_name(name)
+  normalize_path(name)[1..-1].tr("/", "_")
+end
+
+
+ +
+ +
+

+ + normalize_path(path) + +

+ + +
+

Invokes Journey::Router::Utils.normalize_path, then ensures that /(:locale) becomes (/:locale). Except for root cases, where the former is the correct one.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 364
+def self.normalize_path(path)
+  path = Journey::Router::Utils.normalize_path(path)
+
+  # the path for a root URL at this point can be something like
+  # "/(/:locale)(/:platform)/(:browser)", and we would want
+  # "/(:locale)(/:platform)(/:browser)"
+
+  # reverse "/(", "/((" etc to "(/", "((/" etc
+  path.gsub!(%r{/(\(+)/?}, '\1/')
+  # if a path is all optional segments, change the leading "(/" back to
+  # "/(" so it evaluates to "/" when interpreted with no options.
+  # Unless, however, at least one secondary segment consists of a static
+  # part, ex. "(/:locale)(/pages/:page)"
+  path.sub!(%r{^(\(+)/}, '/\1') if %r{^(\(+[^)]+\))(\(+/:[^)]+\))*$}.match?(path)
+  path
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/Base.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/Base.html new file mode 100644 index 0000000000..d60be85363 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/Base.html @@ -0,0 +1,505 @@ +--- +title: ActionDispatch::Routing::Mapper::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + default_url_options(options) + +

+ + +
+ +
+ + + + + +
+ Alias for: default_url_options= +
+ + + +
+ +
+

+ + default_url_options=(options) + +

+ + +
+ +
+ + + +
+ Also aliased as: default_url_options +
+ + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 618
+def default_url_options=(options)
+  @set.default_url_options = options
+end
+
+
+ +
+ +
+

+ + has_named_route?(name) + +

+ + +
+

Query if the following named route was already defined.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 630
+def has_named_route?(name)
+  @set.named_routes.key?(name)
+end
+
+
+ +
+ +
+

+ + match(path, options = nil) + +

+ + +
+

Matches a URL pattern to one or more routes.

+ +

You should not use the match method in your router without specifying an HTTP method.

+ +

If you want to expose your action to both GET and POST, use:

+ +
# sets :controller, :action, and :id in params
+match ':controller/:action/:id', via: [:get, :post]
+
+ +

Note that :controller, :action, and :id are interpreted as URL query parameters and thus available through params in an action.

+ +

If you want to expose your action to GET, use get in the router:

+ +

Instead of:

+ +
match ":controller/:action/:id"
+
+ +

Do:

+ +
get ":controller/:action/:id"
+
+ +

Two of these symbols are special, :controller maps to the controller and :action to the controller’s action. A pattern can also map wildcard segments (globs) to params:

+ +
get 'songs/*category/:title', to: 'songs#show'
+
+# 'songs/rock/classic/stairway-to-heaven' sets
+#  params[:category] = 'rock/classic'
+#  params[:title] = 'stairway-to-heaven'
+
+ +

To match a wildcard parameter, it must have a name assigned to it. Without a variable name to attach the glob parameter to, the route can’t be parsed.

+ +

When a pattern points to an internal route, the route’s :action and :controller should be set in options or hash shorthand. Examples:

+ +
match 'photos/:id' => 'photos#show', via: :get
+match 'photos/:id', to: 'photos#show', via: :get
+match 'photos/:id', controller: 'photos', action: 'show', via: :get
+
+ +

A pattern can also point to a Rack endpoint i.e. anything that responds to call:

+ +
match 'photos/:id', to: -> (hash) { [200, {}, ["Coming soon"]] }, via: :get
+match 'photos/:id', to: PhotoRackApp, via: :get
+# Yes, controller actions are just rack endpoints
+match 'photos/:id', to: PhotosController.action(:show), via: :get
+
+ +

Because requesting various HTTP verbs with a single action has security implications, you must either specify the actions in the via options or use one of the HttpHelpers instead match

+ +

Options

+ +

Any options not seen here are passed on as params with the URL.

+
:controller +
+

The route’s controller.

+
:action +
+

The route’s action.

+
:param +
+

Overrides the default resource identifier :id (name of the dynamic segment used to generate the routes). You can access that segment from your controller using params[<:param>]. In your router:

+ +
resources :users, param: :name
+
+ +

The users resource here will have the following routes generated for it:

+ +
GET       /users(.:format)
+POST      /users(.:format)
+GET       /users/new(.:format)
+GET       /users/:name/edit(.:format)
+GET       /users/:name(.:format)
+PATCH/PUT /users/:name(.:format)
+DELETE    /users/:name(.:format)
+
+ +

You can override ActiveRecord::Base#to_param of a related model to construct a URL:

+ +
class User < ActiveRecord::Base
+  def to_param
+    name
+  end
+end
+
+user = User.find_by(name: 'Phusion')
+user_path(user)  # => "/users/Phusion"
+
+
:path +
+

The path prefix for the routes.

+
:module +
+

The namespace for :controller.

+ +
match 'path', to: 'c#a', module: 'sekret', controller: 'posts', via: :get
+# => Sekret::PostsController
+
+ +

See Scoping#namespace for its scope equivalent.

+
:as +
+

The name used to generate routing helpers.

+
:via +
+

Allowed HTTP verb(s) for route.

+ +
match 'path', to: 'c#a', via: :get
+match 'path', to: 'c#a', via: [:get, :post]
+match 'path', to: 'c#a', via: :all
+
+
:to +
+

Points to a Rack endpoint. Can be an object that responds to call or a string representing a controller’s action.

+ +
match 'path', to: 'controller#action', via: :get
+match 'path', to: -> (env) { [200, {}, ["Success!"]] }, via: :get
+match 'path', to: RackApp, via: :get
+
+
:on +
+

Shorthand for wrapping routes in a specific RESTful context. Valid values are :member, :collection, and :new. Only use within resource(s) block. For example:

+ +
resource :bar do
+  match 'foo', to: 'c#a', on: :member, via: [:get, :post]
+end
+
+ +

Is equivalent to:

+ +
resource :bar do
+  member do
+    match 'foo', to: 'c#a', via: [:get, :post]
+  end
+end
+
+
:constraints +
+

Constrains parameters with a hash of regular expressions or an object that responds to matches?. In addition, constraints other than path can also be specified with any object that responds to === (e.g. String, Array, Range, etc.).

+ +
match 'path/:id', constraints: { id: /[A-Z]\d{5}/ }, via: :get
+
+match 'json_only', constraints: { format: 'json' }, via: :get
+
+class PermitList
+  def matches?(request) request.remote_ip == '1.2.3.4' end
+end
+match 'path', to: 'c#a', constraints: PermitList.new, via: :get
+
+ +

See Scoping#constraints for more examples with its scope equivalent.

+
:defaults +
+

Sets defaults for parameters

+ +
# Sets params[:format] to 'jpg' by default
+match 'path', to: 'c#a', defaults: { format: 'jpg' }, via: :get
+
+ +

See Scoping#defaults for its scope equivalent.

+
:anchor +
+

Boolean to anchor a match pattern. Default is true. When set to false, the pattern matches any request prefixed with the given path.

+ +
# Matches any request starting with 'path'
+match 'path', to: 'c#a', anchor: false, via: :get
+
+
:format +
+

Allows you to specify the default value for optional format segment or disable it by supplying false.

+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 566
+def match(path, options = nil)
+end
+
+
+ +
+ +
+

+ + mount(app, options = nil) + +

+ + +
+

Mount a Rack-based application to be used within the application.

+ +
mount SomeRackApp, at: "some_route"
+
+ +

Alternatively:

+ +
mount(SomeRackApp => "some_route")
+
+ +

For options, see match, as mount uses it internally.

+ +

All mounted applications come with routing helpers to access them. These are named after the class specified, so for the above example the helper is either some_rack_app_path or some_rack_app_url. To customize this helper’s name, use the :as option:

+ +
mount(SomeRackApp => "some_route", as: "exciting")
+
+ +

This will generate the exciting_path and exciting_url helpers which can be used to navigate to this mounted app.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 588
+        def mount(app, options = nil)
+          if options
+            path = options.delete(:at)
+          elsif Hash === app
+            options = app
+            app, path = options.find { |k, _| k.respond_to?(:call) }
+            options.delete(app) if app
+          end
+
+          raise ArgumentError, "A rack application must be specified" unless app.respond_to?(:call)
+          raise ArgumentError, <<~MSG unless path
+            Must be called with mount point
+
+              mount SomeRackApp, at: "some_route"
+              or
+              mount(SomeRackApp => "some_route")
+          MSG
+
+          rails_app = rails_app? app
+          options[:as] ||= app_name(app, rails_app)
+
+          target_as       = name_for_action(options[:as], path)
+          options[:via] ||= :all
+
+          match(path, { to: app, anchor: false, format: false }.merge(options))
+
+          define_generate_prefix(app, target_as) if rails_app
+          self
+        end
+
+
+ +
+ +
+

+ + with_default_scope(scope, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 623
+def with_default_scope(scope, &block)
+  scope(scope) do
+    instance_exec(&block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/Concerns.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/Concerns.html new file mode 100644 index 0000000000..95bec01024 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/Concerns.html @@ -0,0 +1,236 @@ +--- +title: ActionDispatch::Routing::Mapper::Concerns +layout: default +--- +
+ +
+
+ +
+ +

Routing Concerns allow you to declare common routes that can be reused inside others resources and routes.

+ +
concern :commentable do
+  resources :comments
+end
+
+concern :image_attachable do
+  resources :images, only: :index
+end
+
+ +

These concerns are used in Resources routing:

+ +
resources :messages, concerns: [:commentable, :image_attachable]
+
+ +

or in a scope or namespace:

+ +
namespace :posts do
+  concerns :commentable
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + concern(name, callable = nil, &block) + +

+ + +
+

Define a routing concern using a name.

+ +

Concerns may be defined inline, using a block, or handled by another object, by passing that object as the second parameter.

+ +

The concern object, if supplied, should respond to call, which will receive two parameters:

+ +
* The current mapper
+* A hash of options which the concern object may use
+
+ +

Options may also be used by concerns defined in a block by accepting a block parameter. So, using a block, you might do something as simple as limit the actions available on certain resources, passing standard resource options through the concern:

+ +
concern :commentable do |options|
+  resources :comments, options
+end
+
+resources :posts, concerns: :commentable
+resources :archived_posts do
+  # Don't allow comments on archived posts
+  concerns :commentable, only: [:index, :show]
+end
+
+ +

Or, using a callable object, you might implement something more specific to your application, which would be out of place in your routes file.

+ +
# purchasable.rb
+class Purchasable
+  def initialize(defaults = {})
+    @defaults = defaults
+  end
+
+  def call(mapper, options = {})
+    options = @defaults.merge(options)
+    mapper.resources :purchases
+    mapper.resources :receipts
+    mapper.resources :returns if options[:returnable]
+  end
+end
+
+# routes.rb
+concern :purchasable, Purchasable.new(returnable: true)
+
+resources :toys, concerns: :purchasable
+resources :electronics, concerns: :purchasable
+resources :pets do
+  concerns :purchasable, returnable: false
+end
+
+ +

Any routing helpers can be used inside a concern. If using a callable, they’re accessible from the Mapper that’s passed to call.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2071
+def concern(name, callable = nil, &block)
+  callable ||= lambda { |mapper, options| mapper.instance_exec(options, &block) }
+  @concerns[name] = callable
+end
+
+
+ +
+ +
+

+ + concerns(*args) + +

+ + +
+

Use the named concerns

+ +
resources :posts do
+  concerns :commentable
+end
+
+ +

Concerns also work in any routes helper that you want to use:

+ +
namespace :posts do
+  concerns :commentable
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2087
+def concerns(*args)
+  options = args.extract_options!
+  args.flatten.each do |name|
+    if concern = @concerns[name]
+      concern.call(self, options)
+    else
+      raise ArgumentError, "No concern named #{name} was found!"
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/CustomUrls.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/CustomUrls.html new file mode 100644 index 0000000000..ecf8c0c910 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/CustomUrls.html @@ -0,0 +1,234 @@ +--- +title: ActionDispatch::Routing::Mapper::CustomUrls +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + direct(name, options = {}, &block) + +

+ + +
+

Define custom URL helpers that will be added to the application’s routes. This allows you to override and/or replace the default behavior of routing helpers, e.g:

+ +
direct :homepage do
+  "https://rubyonrails.org"
+end
+
+direct :commentable do |model|
+  [ model, anchor: model.dom_id ]
+end
+
+direct :main do
+  { controller: "pages", action: "index", subdomain: "www" }
+end
+
+ +

The return value from the block passed to direct must be a valid set of arguments for url_for which will actually build the URL string. This can be one of the following:

+
  • +

    A string, which is treated as a generated URL

    +
  • +

    A hash, e.g. { controller: "pages", action: "index" }

    +
  • +

    An array, which is passed to polymorphic_url

    +
  • +

    An Active Model instance

    +
  • +

    An Active Model class

    +
+ +

NOTE: Other URL helpers can be called in the block but be careful not to invoke your custom URL helper again otherwise it will result in a stack overflow error.

+ +

You can also specify default options that will be passed through to your URL helper definition, e.g:

+ +
direct :browse, page: 1, size: 10 do |options|
+  [ :products, options.merge(params.permit(:page, :size).to_h.symbolize_keys) ]
+end
+
+ +

In this instance the params object comes from the context in which the block is executed, e.g. generating a URL inside a controller action or a view. If the block is executed where there isn’t a params object such as this:

+ +
Rails.application.routes.url_helpers.browse_path
+
+ +

then it will raise a NameError. Because of this you need to be aware of the context in which you will use your custom URL helper when defining it.

+ +

NOTE: The direct method can’t be used inside of a scope block such as namespace or scope and will raise an error if it detects that it is.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2147
+def direct(name, options = {}, &block)
+  unless @scope.root?
+    raise RuntimeError, "The direct method can't be used inside a routes scope block"
+  end
+
+  @set.add_url_helper(name, options, &block)
+end
+
+
+ +
+ +
+

+ + resolve(*args, &block) + +

+ + +
+

Define custom polymorphic mappings of models to URLs. This alters the behavior of polymorphic_url and consequently the behavior of link_to and form_for when passed a model instance, e.g:

+ +
resource :basket
+
+resolve "Basket" do
+  [:basket]
+end
+
+ +

This will now generate “/basket” when a Basket instance is passed to link_to or form_for instead of the standard “/baskets/:id”.

+ +

NOTE: This custom behavior only applies to simple polymorphic URLs where a single model instance is passed and not more complicated forms, e.g:

+ +
# config/routes.rb
+resource :profile
+namespace :admin do
+  resources :users
+end
+
+resolve("User") { [:profile] }
+
+# app/views/application/_menu.html.erb
+link_to "Profile", @current_user
+link_to "Profile", [:admin, @current_user]
+
+ +

The first link_to will generate “/profile” but the second will generate the standard polymorphic URL of “/admin/users/1”.

+ +

You can pass options to a polymorphic mapping - the arity for the block needs to be two as the instance is passed as the first argument, e.g:

+ +
resolve "Basket", anchor: "items" do |basket, options|
+  [:basket, options]
+end
+
+ +

This generates the URL “/basket#items” because when the last item in an array passed to polymorphic_url is a hash then it’s treated as options to the URL helper that gets called.

+ +

NOTE: The resolve method can’t be used inside of a scope block such as namespace or scope and will raise an error if it detects that it is.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 2199
+def resolve(*args, &block)
+  unless @scope.root?
+    raise RuntimeError, "The resolve method can't be used inside a routes scope block"
+  end
+
+  options = args.extract_options!
+  args = args.flatten(1)
+
+  args.each do |klass|
+    @set.add_polymorphic_mapping(klass, options, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html new file mode 100644 index 0000000000..e3833e13d9 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/HttpHelpers.html @@ -0,0 +1,314 @@ +--- +title: ActionDispatch::Routing::Mapper::HttpHelpers +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + delete(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP DELETE. For supported arguments, see match

+ +
delete 'broccoli', to: 'food#broccoli'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 719
+def delete(*args, &block)
+  map_method(:delete, args, &block)
+end
+
+
+ +
+ +
+

+ + get(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP GET. For supported arguments, see match

+ +
get 'bacon', to: 'food#bacon'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 687
+def get(*args, &block)
+  map_method(:get, args, &block)
+end
+
+
+ +
+ +
+

+ + options(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP OPTIONS. For supported arguments, see match

+ +
options 'carrots', to: 'food#carrots'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 727
+def options(*args, &block)
+  map_method(:options, args, &block)
+end
+
+
+ +
+ +
+

+ + patch(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP PATCH. For supported arguments, see match

+ +
patch 'bacon', to: 'food#bacon'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 703
+def patch(*args, &block)
+  map_method(:patch, args, &block)
+end
+
+
+ +
+ +
+

+ + post(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP POST. For supported arguments, see match

+ +
post 'bacon', to: 'food#bacon'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 695
+def post(*args, &block)
+  map_method(:post, args, &block)
+end
+
+
+ +
+ +
+

+ + put(*args, &block) + +

+ + +
+

Define a route that only recognizes HTTP PUT. For supported arguments, see match

+ +
put 'bacon', to: 'food#bacon'
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 711
+def put(*args, &block)
+  map_method(:put, args, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/Resources.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/Resources.html new file mode 100644 index 0000000000..d6d2158caf --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/Resources.html @@ -0,0 +1,1155 @@ +--- +title: ActionDispatch::Routing::Mapper::Resources +layout: default +--- +
+ +
+
+ +
+ +

Resource routing allows you to quickly declare all of the common routes for a given resourceful controller. Instead of declaring separate routes for your index, show, new, edit, create, update, and destroy actions, a resourceful route declares them in a single line of code:

+ +
resources :photos
+
+ +

Sometimes, you have a resource that clients always look up without referencing an ID. A common example, /profile always shows the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action.

+ +
resource :profile
+
+ +

It’s common to have resources that are logically children of other resources:

+ +
resources :magazines do
+  resources :ads
+end
+
+ +

You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an admin namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:

+ +
namespace "admin" do
+  resources :posts, :comments
+end
+
+ +

By default the :id parameter doesn’t accept dots. If you need to use dots as part of the :id parameter add a constraint which overrides this restriction, e.g:

+ +
resources :articles, id: /[^\/]+/
+
+ +

This allows any character other than a slash as part of your :id.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CANONICAL_ACTIONS=%w(index create new show update destroy)
 
RESOURCE_OPTIONS=[:as, :controller, :path, :only, :except, :param, :concerns]
 
VALID_ON_OPTIONS=[:new, :collection, :member]
 

CANONICAL_ACTIONS holds all actions that does not need a prefix or a path appended since they fit properly in their scope level.

+ + + + + + + +

Instance Public methods

+ +
+

+ + collection(&block) + +

+ + +
+

To add a route to the collection:

+ +
resources :photos do
+  collection do
+    get 'search'
+  end
+end
+
+ +

This will enable Rails to recognize paths such as /photos/search with GET, and route to the search action of PhotosController. It will also create the search_photos_url and search_photos_path route helpers.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1500
+def collection(&block)
+  unless resource_scope?
+    raise ArgumentError, "can't use collection outside resource(s) scope"
+  end
+
+  with_scope_level(:collection) do
+    path_scope(parent_resource.collection_scope, &block)
+  end
+end
+
+
+ +
+ +
+

+ + draw(name) + +

+ + +
+

Loads another routes file with the given name located inside the config/routes directory. In that file, you can use the normal routing DSL, but do not surround it with a Rails.application.routes.draw block.

+ +
# config/routes.rb
+Rails.application.routes.draw do
+  draw :admin                 # Loads `config/routes/admin.rb`
+  draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
+end
+
+# config/routes/admin.rb
+namespace :admin do
+  resources :accounts
+end
+
+# config/routes/third_party/some_gem.rb
+mount SomeGem::Engine, at: "/some_gem"
+
+ +

CAUTION: Use this feature with care. Having multiple routes files can negatively impact discoverability and readability. For most applications — even those with a few hundred routes — it’s easier for developers to have a single routes file.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1610
+def draw(name)
+  path = @draw_paths.find do |_path|
+    File.exist? "#{_path}/#{name}.rb"
+  end
+
+  unless path
+    msg  = "Your router tried to #draw the external file #{name}.rb,\n" \
+           "but the file was not found in:\n\n"
+    msg += @draw_paths.map { |_path| " * #{_path}" }.join("\n")
+    raise ArgumentError, msg
+  end
+
+  route_path = "#{path}/#{name}.rb"
+  instance_eval(File.read(route_path), route_path.to_s)
+end
+
+
+ +
+ +
+

+ + match(path, *rest, &block) + +

+ + +
+

Matches a URL pattern to one or more routes. For more information, see match.

+ +
match 'path' => 'controller#action', via: :patch
+match 'path', to: 'controller#action', via: :post
+match 'path', 'otherpath', on: :member, via: :get
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1632
+def match(path, *rest, &block)
+  if rest.empty? && Hash === path
+    options  = path
+    path, to = options.find { |name, _value| name.is_a?(String) }
+
+    raise ArgumentError, "Route path not specified" if path.nil?
+
+    case to
+    when Symbol
+      options[:action] = to
+    when String
+      if /#/.match?(to)
+        options[:to] = to
+      else
+        options[:controller] = to
+      end
+    else
+      options[:to] = to
+    end
+
+    options.delete(path)
+    paths = [path]
+  else
+    options = rest.pop || {}
+    paths = [path] + rest
+  end
+
+  if options.key?(:defaults)
+    defaults(options.delete(:defaults)) { map_match(paths, options, &block) }
+  else
+    map_match(paths, options, &block)
+  end
+end
+
+
+ +
+ +
+

+ + member(&block) + +

+ + +
+

To add a member route, add a member block into the resource block:

+ +
resources :photos do
+  member do
+    get 'preview'
+  end
+end
+
+ +

This will recognize /photos/1/preview with GET, and route to the preview action of PhotosController. It will also create the preview_photo_url and preview_photo_path helpers.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1521
+def member(&block)
+  unless resource_scope?
+    raise ArgumentError, "can't use member outside resource(s) scope"
+  end
+
+  with_scope_level(:member) do
+    if shallow?
+      shallow_scope {
+        path_scope(parent_resource.member_scope, &block)
+      }
+    else
+      path_scope(parent_resource.member_scope, &block)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + namespace(path, options = {}) + +

+ + + + + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1568
+def namespace(path, options = {})
+  if resource_scope?
+    nested { super }
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + nested(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1547
+def nested(&block)
+  unless resource_scope?
+    raise ArgumentError, "can't use nested outside resource(s) scope"
+  end
+
+  with_scope_level(:nested) do
+    if shallow? && shallow_nesting_depth >= 1
+      shallow_scope do
+        path_scope(parent_resource.nested_scope) do
+          scope(nested_options, &block)
+        end
+      end
+    else
+      path_scope(parent_resource.nested_scope) do
+        scope(nested_options, &block)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + new(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1537
+def new(&block)
+  unless resource_scope?
+    raise ArgumentError, "can't use new outside resource(s) scope"
+  end
+
+  with_scope_level(:new) do
+    path_scope(parent_resource.new_scope(action_path(:new)), &block)
+  end
+end
+
+
+ +
+ +
+

+ + resource(*resources, &block) + +

+ + +
+

Sometimes, you have a resource that clients always look up without referencing an ID. A common example, /profile always shows the profile of the currently logged in user. In this case, you can use a singular resource to map /profile (rather than /profile/:id) to the show action:

+ +
resource :profile
+
+ +

This creates six different routes in your application, all mapping to the Profiles controller (note that the controller is named after the plural):

+ +
GET       /profile/new
+GET       /profile
+GET       /profile/edit
+PATCH/PUT /profile
+DELETE    /profile
+POST      /profile
+
+ +

If you want instances of a model to work with this resource via record identification (e.g. in form_with or redirect_to), you will need to call resolve:

+ +
resource :profile
+resolve('Profile') { [:profile] }
+
+# Enables this to work with singular routes:
+form_with(model: @profile) {}
+
+ +

Options

+ +

Takes same options as resources

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1292
+def resource(*resources, &block)
+  options = resources.extract_options!.dup
+
+  if apply_common_behavior_for(:resource, resources, options, &block)
+    return self
+  end
+
+  with_scope_level(:resource) do
+    options = apply_action_options options
+    resource_scope(SingletonResource.new(resources.pop, api_only?, @scope[:shallow], options)) do
+      yield if block_given?
+
+      concerns(options[:concerns]) if options[:concerns]
+
+      new do
+        get :new
+      end if parent_resource.actions.include?(:new)
+
+      set_member_mappings_for_resource
+
+      collection do
+        post :create
+      end if parent_resource.actions.include?(:create)
+    end
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + resources(*resources, &block) + +

+ + +
+

In Rails, a resourceful route provides a mapping between HTTP verbs and URLs and controller actions. By convention, each action also maps to particular CRUD operations in a database. A single entry in the routing file, such as

+ +
resources :photos
+
+ +

creates seven different routes in your application, all mapping to the Photos controller:

+ +
GET       /photos
+GET       /photos/new
+POST      /photos
+GET       /photos/:id
+GET       /photos/:id/edit
+PATCH/PUT /photos/:id
+DELETE    /photos/:id
+
+ +

Resources can also be nested infinitely by using this block syntax:

+ +
resources :photos do
+  resources :comments
+end
+
+ +

This generates the following comments routes:

+ +
GET       /photos/:photo_id/comments
+GET       /photos/:photo_id/comments/new
+POST      /photos/:photo_id/comments
+GET       /photos/:photo_id/comments/:id
+GET       /photos/:photo_id/comments/:id/edit
+PATCH/PUT /photos/:photo_id/comments/:id
+DELETE    /photos/:photo_id/comments/:id
+
+ +

Options

+ +

Takes same options as match as well as:

+
:path_names +
+

Allows you to change the segment component of the edit and new actions. Actions not specified are not changed.

+ +
resources :posts, path_names: { new: "brand_new" }
+
+ +

The above example will now change /posts/new to /posts/brand_new.

+
:path +
+

Allows you to change the path prefix for the resource.

+ +
resources :posts, path: 'postings'
+
+ +

The resource and all segments will now route to /postings instead of /posts.

+
:only +
+

Only generate routes for the given actions.

+ +
resources :cows, only: :show
+resources :cows, only: [:show, :index]
+
+
:except +
+

Generate all routes except for the given actions.

+ +
resources :cows, except: :show
+resources :cows, except: [:show, :index]
+
+
:shallow +
+

Generates shallow routes for nested resource(s). When placed on a parent resource, generates shallow routes for all nested resources.

+ +
resources :posts, shallow: true do
+  resources :comments
+end
+
+ +

Is the same as:

+ +
resources :posts do
+  resources :comments, except: [:show, :edit, :update, :destroy]
+end
+resources :comments, only: [:show, :edit, :update, :destroy]
+
+ +

This allows URLs for resources that otherwise would be deeply nested such as a comment on a blog post like /posts/a-long-permalink/comments/1234 to be shortened to just /comments/1234.

+ +

Set shallow: false on a child resource to ignore a parent’s shallow parameter.

+
:shallow_path +
+

Prefixes nested shallow routes with the specified path.

+ +
scope shallow_path: "sekret" do
+  resources :posts do
+    resources :comments, shallow: true
+  end
+end
+
+ +

The comments resource here will have the following routes generated for it:

+ +
post_comments    GET       /posts/:post_id/comments(.:format)
+post_comments    POST      /posts/:post_id/comments(.:format)
+new_post_comment GET       /posts/:post_id/comments/new(.:format)
+edit_comment     GET       /sekret/comments/:id/edit(.:format)
+comment          GET       /sekret/comments/:id(.:format)
+comment          PATCH/PUT /sekret/comments/:id(.:format)
+comment          DELETE    /sekret/comments/:id(.:format)
+
+
:shallow_prefix +
+

Prefixes nested shallow route names with specified prefix.

+ +
scope shallow_prefix: "sekret" do
+  resources :posts do
+    resources :comments, shallow: true
+  end
+end
+
+ +

The comments resource here will have the following routes generated for it:

+ +
post_comments           GET       /posts/:post_id/comments(.:format)
+post_comments           POST      /posts/:post_id/comments(.:format)
+new_post_comment        GET       /posts/:post_id/comments/new(.:format)
+edit_sekret_comment     GET       /comments/:id/edit(.:format)
+sekret_comment          GET       /comments/:id(.:format)
+sekret_comment          PATCH/PUT /comments/:id(.:format)
+sekret_comment          DELETE    /comments/:id(.:format)
+
+
:format +
+

Allows you to specify the default value for optional format segment or disable it by supplying false.

+
:param +
+

Allows you to override the default param name of :id in the URL.

+
+ +

Examples

+ +
# routes call <tt>Admin::PostsController</tt>
+resources :posts, module: "admin"
+
+# resource actions are at /admin/posts.
+resources :posts, path: "admin/posts"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1458
+def resources(*resources, &block)
+  options = resources.extract_options!.dup
+
+  if apply_common_behavior_for(:resources, resources, options, &block)
+    return self
+  end
+
+  with_scope_level(:resources) do
+    options = apply_action_options options
+    resource_scope(Resource.new(resources.pop, api_only?, @scope[:shallow], options)) do
+      yield if block_given?
+
+      concerns(options[:concerns]) if options[:concerns]
+
+      collection do
+        get  :index if parent_resource.actions.include?(:index)
+        post :create if parent_resource.actions.include?(:create)
+      end
+
+      new do
+        get :new
+      end if parent_resource.actions.include?(:new)
+
+      set_member_mappings_for_resource
+    end
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + resources_path_names(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1257
+def resources_path_names(options)
+  @scope[:path_names].merge!(options)
+end
+
+
+ +
+ +
+

+ + root(path, options = {}) + +

+ + +
+

You can specify what Rails should route “/” to with the root method:

+ +
root to: 'pages#main'
+
+ +

For options, see match, as root uses it internally.

+ +

You can also pass a string which will expand

+ +
root 'pages#main'
+
+ +

You should put the root route at the top of config/routes.rb, because this means it will be matched first. As this is the most popular route of most Rails applications, this is beneficial.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1679
+def root(path, options = {})
+  if path.is_a?(String)
+    options[:to] = path
+  elsif path.is_a?(Hash) && options.empty?
+    options = path
+  else
+    raise ArgumentError, "must be called with a path and/or options"
+  end
+
+  if @scope.resources?
+    with_scope_level(:root) do
+      path_scope(parent_resource.path) do
+        match_root_route(options)
+      end
+    end
+  else
+    match_root_route(options)
+  end
+end
+
+
+ +
+ +
+

+ + shallow() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1576
+def shallow
+  @scope = @scope.new(shallow: true)
+  yield
+ensure
+  @scope = @scope.parent
+end
+
+
+ +
+ +
+

+ + shallow?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1583
+def shallow?
+  !parent_resource.singleton? && @scope[:shallow]
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + api_only?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1879
+def api_only? # :doc:
+  @set.api_only?
+end
+
+
+ +
+ +
+

+ + set_member_mappings_for_resource() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1867
+def set_member_mappings_for_resource # :doc:
+  member do
+    get :edit if parent_resource.actions.include?(:edit)
+    get :show if parent_resource.actions.include?(:show)
+    if parent_resource.actions.include?(:update)
+      patch :update
+      put   :update
+    end
+    delete :destroy if parent_resource.actions.include?(:destroy)
+  end
+end
+
+
+ +
+ +
+

+ + with_scope_level(kind) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1763
+def with_scope_level(kind) # :doc:
+  @scope = @scope.new_level(kind)
+  yield
+ensure
+  @scope = @scope.parent
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Mapper/Scoping.html b/src/7.0/classes/ActionDispatch/Routing/Mapper/Scoping.html new file mode 100644 index 0000000000..0f1d38a2dd --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Mapper/Scoping.html @@ -0,0 +1,514 @@ +--- +title: ActionDispatch::Routing::Mapper::Scoping +layout: default +--- +
+ +
+
+ +
+ +

You may wish to organize groups of controllers under a namespace. Most commonly, you might group a number of administrative controllers under an admin namespace. You would place these controllers under the app/controllers/admin directory, and you can group them together in your router:

+ +
namespace "admin" do
+  resources :posts, :comments
+end
+
+ +

This will create a number of routes for each of the posts and comments controller. For Admin::PostsController, Rails will create:

+ +
GET       /admin/posts
+GET       /admin/posts/new
+POST      /admin/posts
+GET       /admin/posts/1
+GET       /admin/posts/1/edit
+PATCH/PUT /admin/posts/1
+DELETE    /admin/posts/1
+
+ +

If you want to route /posts (without the prefix /admin) to Admin::PostsController, you could use

+ +
scope module: "admin" do
+  resources :posts
+end
+
+ +

or, for a single case

+ +
resources :posts, module: "admin"
+
+ +

If you want to route /admin/posts to PostsController (without the Admin:: module prefix), you could use

+ +
scope "/admin" do
+  resources :posts
+end
+
+ +

or, for a single case

+ +
resources :posts, path: "/admin/posts"
+
+ +

In each of these cases, the named routes remain the same as if you did not use scope. In the last case, the following paths map to PostsController:

+ +
GET       /admin/posts
+GET       /admin/posts/new
+POST      /admin/posts
+GET       /admin/posts/1
+GET       /admin/posts/1/edit
+PATCH/PUT /admin/posts/1
+DELETE    /admin/posts/1
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + constraints(constraints = {}, &block) + +

+ + +
+

Parameter Restriction

+ +

Allows you to constrain the nested routes based on a set of rules. For instance, in order to change the routes to allow for a dot character in the id parameter:

+ +
constraints(id: /\d+\.\d+/) do
+  resources :posts
+end
+
+ +

Now routes such as /posts/1 will no longer be valid, but /posts/1.1 will be. The id parameter must match the constraint passed in for this example.

+ +

You may use this to also restrict other parameters:

+ +
resources :posts do
+  constraints(post_id: /\d+\.\d+/) do
+    resources :comments
+  end
+end
+
+ +

Restricting based on IP

+ +

Routes can also be constrained to an IP or a certain range of IP addresses:

+ +
constraints(ip: /192\.168\.\d+\.\d+/) do
+  resources :posts
+end
+
+ +

Any user connecting from the 192.168.* range will be able to see this resource, where as any user connecting outside of this range will be told there is no such route.

+ +

Dynamic request matching

+ +

Requests to routes can be constrained based on specific criteria:

+ +
constraints(-> (req) { /iPhone/.match?(req.env["HTTP_USER_AGENT"]) }) do
+  resources :iphones
+end
+
+ +

You are able to move this logic out into a class if it is too complex for routes. This class must have a matches? method defined on it which either returns true if the user should be given access to that route, or false if the user should not.

+ +
class Iphone
+  def self.matches?(request)
+    /iPhone/.match?(request.env["HTTP_USER_AGENT"])
+  end
+end
+
+ +

An expected place for this code would be lib/constraints.

+ +

This class is then used like this:

+ +
constraints(Iphone) do
+  resources :iphones
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 999
+def constraints(constraints = {}, &block)
+  scope(constraints: constraints, &block)
+end
+
+
+ +
+ +
+

+ + controller(controller) + +

+ + +
+

Scopes routes to a specific controller

+ +
controller "food" do
+  match "bacon", action: :bacon, via: :get
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 884
+def controller(controller)
+  @scope = @scope.new(controller: controller)
+  yield
+ensure
+  @scope = @scope.parent
+end
+
+
+ +
+ +
+

+ + defaults(defaults = {}) + +

+ + +
+

Allows you to set default parameters for a route, such as this:

+ +
defaults id: 'home' do
+  match 'scoped_pages/(:id)', to: 'pages#show'
+end
+
+ +

Using this, the :id parameter here will default to ‘home’.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 1008
+def defaults(defaults = {})
+  @scope = @scope.new(defaults: merge_defaults_scope(@scope[:defaults], defaults))
+  yield
+ensure
+  @scope = @scope.parent
+end
+
+
+ +
+ +
+

+ + namespace(path, options = {}, &block) + +

+ + +
+

Scopes routes to a specific namespace. For example:

+ +
namespace :admin do
+  resources :posts
+end
+
+ +

This generates the following routes:

+ +
    admin_posts GET       /admin/posts(.:format)          admin/posts#index
+    admin_posts POST      /admin/posts(.:format)          admin/posts#create
+ new_admin_post GET       /admin/posts/new(.:format)      admin/posts#new
+edit_admin_post GET       /admin/posts/:id/edit(.:format) admin/posts#edit
+     admin_post GET       /admin/posts/:id(.:format)      admin/posts#show
+     admin_post PATCH/PUT /admin/posts/:id(.:format)      admin/posts#update
+     admin_post DELETE    /admin/posts/:id(.:format)      admin/posts#destroy
+
+ +

Options

+ +

The :path, :as, :module, :shallow_path, and :shallow_prefix options all default to the name of the namespace.

+ +

For options, see Base#match. For :shallow_path option, see Resources#resources.

+ +
# accessible through /sekret/posts rather than /admin/posts
+namespace :admin, path: "sekret" do
+  resources :posts
+end
+
+# maps to <tt>Sekret::PostsController</tt> rather than <tt>Admin::PostsController</tt>
+namespace :admin, module: "sekret" do
+  resources :posts
+end
+
+# generates +sekret_posts_path+ rather than +admin_posts_path+
+namespace :admin, as: "sekret" do
+  resources :posts
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 929
+def namespace(path, options = {}, &block)
+  path = path.to_s
+
+  defaults = {
+    module:         path,
+    as:             options.fetch(:as, path),
+    shallow_path:   options.fetch(:path, path),
+    shallow_prefix: options.fetch(:as, path)
+  }
+
+  path_scope(options.delete(:path) { path }) do
+    scope(defaults.merge!(options), &block)
+  end
+end
+
+
+ +
+ +
+

+ + scope(*args) + +

+ + +
+

Scopes a set of routes to the given default options.

+ +

Take the following route definition as an example:

+ +
scope path: ":account_id", as: "account" do
+  resources :projects
+end
+
+ +

This generates helpers such as account_projects_path, just like resources does. The difference here being that the routes generated are like /:account_id/projects, rather than /accounts/:account_id/projects.

+ +

Options

+ +

Takes same options as Base#match and Resources#resources.

+ +
# route /posts (without the prefix /admin) to <tt>Admin::PostsController</tt>
+scope module: "admin" do
+  resources :posts
+end
+
+# prefix the posts resource's requests with '/admin'
+scope path: "/admin" do
+  resources :posts
+end
+
+# prefix the routing helper name: +sekret_posts_path+ instead of +posts_path+
+scope as: "sekret" do
+  resources :posts
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/mapper.rb, line 825
+def scope(*args)
+  options = args.extract_options!.dup
+  scope = {}
+
+  options[:path] = args.flatten.join("/") if args.any?
+  options[:constraints] ||= {}
+
+  unless nested_scope?
+    options[:shallow_path] ||= options[:path] if options.key?(:path)
+    options[:shallow_prefix] ||= options[:as] if options.key?(:as)
+  end
+
+  if options[:constraints].is_a?(Hash)
+    defaults = options[:constraints].select do |k, v|
+      URL_OPTIONS.include?(k) && (v.is_a?(String) || v.is_a?(Integer))
+    end
+
+    options[:defaults] = defaults.merge(options[:defaults] || {})
+  else
+    block, options[:constraints] = options[:constraints], {}
+  end
+
+  if options.key?(:only) || options.key?(:except)
+    scope[:action_options] = { only: options.delete(:only),
+                               except: options.delete(:except) }
+  end
+
+  if options.key? :anchor
+    raise ArgumentError, "anchor is ignored unless passed to `match`"
+  end
+
+  @scope.options.each do |option|
+    if option == :blocks
+      value = block
+    elsif option == :options
+      value = options
+    else
+      value = options.delete(option) { POISON }
+    end
+
+    unless POISON == value
+      scope[option] = send("merge_#{option}_scope", @scope[option], value)
+    end
+  end
+
+  @scope = @scope.new scope
+  yield
+  self
+ensure
+  @scope = @scope.parent
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/PathRedirect.html b/src/7.0/classes/ActionDispatch/Routing/PathRedirect.html new file mode 100644 index 0000000000..9b7b104605 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/PathRedirect.html @@ -0,0 +1,172 @@ +--- +title: ActionDispatch::Routing::PathRedirect +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
URL_PARTS=/\A([^?]+)?(\?[^#]+)?(#.+)?\z/
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/redirection.rb, line 93
+def inspect
+  "redirect(#{status}, #{block})"
+end
+
+
+ +
+ +
+

+ + path(params, request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/redirection.rb, line 81
+def path(params, request)
+  if block.match(URL_PARTS)
+    path     = interpolation_required?($1, params) ? $1 % escape_path(params)     : $1
+    query    = interpolation_required?($2, params) ? $2 % escape(params)          : $2
+    fragment = interpolation_required?($3, params) ? $3 % escape_fragment(params) : $3
+
+    "#{path}#{query}#{fragment}"
+  else
+    interpolation_required?(block, params) ? block % escape(params) : block
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/PolymorphicRoutes.html b/src/7.0/classes/ActionDispatch/Routing/PolymorphicRoutes.html new file mode 100644 index 0000000000..da33c67b13 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/PolymorphicRoutes.html @@ -0,0 +1,273 @@ +--- +title: ActionDispatch::Routing::PolymorphicRoutes +layout: default +--- +
+ +
+
+ +
+ +

Polymorphic URL helpers are methods for smart resolution to a named route call when given an Active Record model instance. They are to be used in combination with ActionController::Resources.

+ +

These methods are useful when you want to generate the correct URL or path to a RESTful resource without having to know the exact type of the record in question.

+ +

Nested resources and/or namespaces are also supported, as illustrated in the example:

+ +
polymorphic_url([:admin, @article, @comment])
+
+ +

results in:

+ +
admin_article_comment_url(@article, @comment)
+
+ +

Usage within the framework

+ +

Polymorphic URL helpers are used in a number of places throughout the Rails framework:

+
  • +

    url_for, so you can use it with a record as the argument, e.g. url_for(@article);

    +
  • +

    ActionView::Helpers::FormHelper uses polymorphic_path, so you can write form_for(@article) without having to specify :url parameter for the form action;

    +
  • +

    redirect_to (which, in fact, uses url_for) so you can write redirect_to(post) in your controllers;

    +
  • +

    ActionView::Helpers::AtomFeedHelper, so you don’t have to explicitly specify URLs for feed entries.

    +
+ +

Prefixed polymorphic helpers

+ +

In addition to polymorphic_url and polymorphic_path methods, a number of prefixed helpers are available as a shorthand to action: "..." in options. Those are:

+
  • +

    edit_polymorphic_url, edit_polymorphic_path

    +
  • +

    new_polymorphic_url, new_polymorphic_path

    +
+ +

Example usage:

+ +
edit_polymorphic_path(@post)           # => "/posts/1/edit"
+polymorphic_path(@post, format: :pdf)  # => "/posts/1.pdf"
+
+ +

Usage with mounted engines

+ +

If you are using a mounted engine and you need to use a polymorphic_url pointing at the engine’s routes, pass in the engine’s route proxy as the first argument to the method. For example:

+ +
polymorphic_url([blog, @post])  # calls blog.post_path(@post)
+form_for([blog, @post])         # => "/blog/posts/1"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + polymorphic_path(record_or_hash_or_array, options = {}) + +

+ + +
+

Returns the path component of a URL for the given record.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/polymorphic_routes.rb, line 124
+def polymorphic_path(record_or_hash_or_array, options = {})
+  if Hash === record_or_hash_or_array
+    options = record_or_hash_or_array.merge(options)
+    record  = options.delete :id
+    return polymorphic_path record, options
+  end
+
+  if mapping = polymorphic_mapping(record_or_hash_or_array)
+    return mapping.call(self, [record_or_hash_or_array, options], true)
+  end
+
+  opts   = options.dup
+  action = opts.delete :action
+  type   = :path
+
+  HelperMethodBuilder.polymorphic_method self,
+                                         record_or_hash_or_array,
+                                         action,
+                                         type,
+                                         opts
+end
+
+
+ +
+ +
+

+ + polymorphic_url(record_or_hash_or_array, options = {}) + +

+ + +
+

Constructs a call to a named RESTful route for the given record and returns the resulting URL string. For example:

+ +
# calls post_url(post)
+polymorphic_url(post) # => "http://example.com/posts/1"
+polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"
+polymorphic_url([:admin, blog, post]) # => "http://example.com/admin/blogs/1/posts/1"
+polymorphic_url([user, :blog, post]) # => "http://example.com/users/1/blog/posts/1"
+polymorphic_url(Comment) # => "http://example.com/comments"
+
+ +

Options

+
  • +

    :action - Specifies the action prefix for the named route: :new or :edit. Default is no prefix.

    +
  • +

    :routing_type - Allowed values are :path or :url. Default is :url.

    +
+ +

Also includes all the options from url_for. These include such things as :anchor or :trailing_slash. Example usage is given below:

+ +
polymorphic_url([blog, post], anchor: 'my_anchor')
+  # => "http://example.com/blogs/1/posts/1#my_anchor"
+polymorphic_url([blog, post], anchor: 'my_anchor', script_name: "/my_app")
+  # => "http://example.com/my_app/blogs/1/posts/1#my_anchor"
+
+ +

For all of these options, see the documentation for url_for.

+ +

Functionality

+ +
# an Article record
+polymorphic_url(record)  # same as article_url(record)
+
+# a Comment record
+polymorphic_url(record)  # same as comment_url(record)
+
+# it recognizes new records and maps to the collection
+record = Comment.new
+polymorphic_url(record)  # same as comments_url()
+
+# the class of a record will also map to the collection
+polymorphic_url(Comment) # same as comments_url()
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/polymorphic_routes.rb, line 101
+def polymorphic_url(record_or_hash_or_array, options = {})
+  if Hash === record_or_hash_or_array
+    options = record_or_hash_or_array.merge(options)
+    record  = options.delete :id
+    return polymorphic_url record, options
+  end
+
+  if mapping = polymorphic_mapping(record_or_hash_or_array)
+    return mapping.call(self, [record_or_hash_or_array, options], false)
+  end
+
+  opts   = options.dup
+  action = opts.delete :action
+  type   = opts.delete(:routing_type) || :url
+
+  HelperMethodBuilder.polymorphic_method self,
+                                         record_or_hash_or_array,
+                                         action,
+                                         type,
+                                         opts
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/Redirection.html b/src/7.0/classes/ActionDispatch/Routing/Redirection.html new file mode 100644 index 0000000000..fb890c8bf8 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/Redirection.html @@ -0,0 +1,153 @@ +--- +title: ActionDispatch::Routing::Redirection +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + redirect(*args, &block) + +

+ + +
+

Redirect any path to another path:

+ +
get "/stories" => redirect("/posts")
+
+ +

This will redirect the user, while ignoring certain parts of the request, including query string, etc. /stories, /stories?foo=bar, etc all redirect to /posts.

+ +

The redirect will use a 301 Moved Permanently status code by default. This can be overridden with the :status option:

+ +
get "/stories" => redirect("/posts", status: 307)
+
+ +

You can also use interpolation in the supplied redirect argument:

+ +
get 'docs/:article', to: redirect('/wiki/%{article}')
+
+ +

Note that if you return a path without a leading slash then the URL is prefixed with the current SCRIPT_NAME environment variable. This is typically ‘/’ but may be different in a mounted engine or where the application is deployed to a subdirectory of a website.

+ +

Alternatively you can use one of the other syntaxes:

+ +

The block version of redirect allows for the easy encapsulation of any logic associated with the redirect in question. Either the params and request are supplied as arguments, or just params, depending of how many arguments your block accepts. A string is required as a return value.

+ +
get 'jokes/:number', to: redirect { |params, request|
+  path = (params[:number].to_i.even? ? "wheres-the-beef" : "i-love-lamp")
+  "http://#{request.host_with_port}/#{path}"
+}
+
+ +

Note that the do end syntax for the redirect block wouldn’t work, as Ruby would pass the block to get instead of redirect. Use { ... } instead.

+ +

The options version of redirect allows you to supply only the parts of the URL which need to change, it also supports interpolation of the path similar to the first example.

+ +
get 'stores/:name',       to: redirect(subdomain: 'stores', path: '/%{name}')
+get 'stores/:name(*all)', to: redirect(subdomain: 'stores', path: '/%{name}%{all}')
+get '/stories', to: redirect(path: '/posts')
+
+ +

This will redirect the user, while changing only the specified parts of the request, for example the path option in the last example. /stories, /stories?foo=bar, redirect to /posts and /posts?foo=bar respectively.

+ +

Finally, an object which responds to call can be supplied to redirect, allowing you to reuse common redirect routes. The call method must accept two arguments, params and request, and return a string.

+ +
get 'accounts/:name' => redirect(SubdomainRedirector.new('api'))
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/redirection.rb, line 190
+def redirect(*args, &block)
+  options = args.extract_options!
+  status  = options.delete(:status) || 301
+  path    = args.shift
+
+  return OptionRedirect.new(status, options) if options.any?
+  return PathRedirect.new(status, path) if String === path
+
+  block = path if path.respond_to? :call
+  raise ArgumentError, "redirection argument not supported" unless block
+  Redirect.new status, block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet.html new file mode 100644 index 0000000000..d06ab487c1 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet.html @@ -0,0 +1,88 @@ +--- +title: ActionDispatch::Routing::RouteSet +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/CustomUrlHelper.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/CustomUrlHelper.html new file mode 100644 index 0000000000..01671e5241 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/CustomUrlHelper.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Routing::RouteSet::CustomUrlHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/Dispatcher.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/Dispatcher.html new file mode 100644 index 0000000000..ea09a9b930 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/Dispatcher.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Routing::RouteSet::Dispatcher +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/Generator.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/Generator.html new file mode 100644 index 0000000000..3958d9c6fd --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/Generator.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Routing::RouteSet::Generator +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/MountedHelpers.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/MountedHelpers.html new file mode 100644 index 0000000000..754ef9f9b8 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/MountedHelpers.html @@ -0,0 +1,54 @@ +--- +title: ActionDispatch::Routing::RouteSet::MountedHelpers +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection.html new file mode 100644 index 0000000000..e5bcec624b --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection.html @@ -0,0 +1,73 @@ +--- +title: ActionDispatch::Routing::RouteSet::NamedRouteCollection +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper.html new file mode 100644 index 0000000000..e885a1eb2f --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper.html @@ -0,0 +1,73 @@ +--- +title: ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper/OptimizedUrlHelper.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper/OptimizedUrlHelper.html new file mode 100644 index 0000000000..f66e43c8e4 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/NamedRouteCollection/UrlHelper/OptimizedUrlHelper.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper::OptimizedUrlHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/RouteSet/StaticDispatcher.html b/src/7.0/classes/ActionDispatch/Routing/RouteSet/StaticDispatcher.html new file mode 100644 index 0000000000..f869d23b4e --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/RouteSet/StaticDispatcher.html @@ -0,0 +1,60 @@ +--- +title: ActionDispatch::Routing::RouteSet::StaticDispatcher +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Routing/UrlFor.html b/src/7.0/classes/ActionDispatch/Routing/UrlFor.html new file mode 100644 index 0000000000..bb604373a7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Routing/UrlFor.html @@ -0,0 +1,490 @@ +--- +title: ActionDispatch::Routing::UrlFor +layout: default +--- +
+ +
+
+ +
+ +

In config/routes.rb you define URL-to-controller mappings, but the reverse is also possible: a URL can be generated from one of your routing definitions. URL generation functionality is centralized in this module.

+ +

See ActionDispatch::Routing for general information about routing and config/routes.rb.

+ +

Tip: If you need to generate URLs from your models or some other place, then ActionDispatch::Routing::UrlFor is what you’re looking for. Read on for an introduction. In general, this module should not be included on its own, as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).

+ +

URL generation from parameters

+ +

As you may know, some functions, such as ActionController::Base#url_for and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set of parameters. For example, you’ve probably had the chance to write code like this in one of your views:

+ +
<%= link_to('Click here', controller: 'users',
+        action: 'new', message: 'Welcome!') %>
+# => <a href="/users/new?message=Welcome%21">Click here</a>
+
+ +

link_to, and all other functions that require URL generation functionality, actually use ActionDispatch::Routing::UrlFor under the hood. And in particular, they use the ActionDispatch::Routing::UrlFor#url_for method. One can generate the same path as the above example by using the following code:

+ +
include ActionDispatch::Routing::UrlFor
+url_for(controller: 'users',
+        action: 'new',
+        message: 'Welcome!',
+        only_path: true)
+# => "/users/new?message=Welcome%21"
+
+ +

Notice the only_path: true part. This is because UrlFor has no information about the website hostname that your Rails app is serving. So if you want to include the hostname as well, then you must also pass the :host argument:

+ +
include UrlFor
+url_for(controller: 'users',
+        action: 'new',
+        message: 'Welcome!',
+        host: 'www.example.com')
+# => "http://www.example.com/users/new?message=Welcome%21"
+
+ +

By default, all controllers and views have access to a special version of url_for, that already knows what the current hostname is. So if you use url_for in your controllers or your views, then you don’t need to explicitly pass the :host argument.

+ +

For convenience, mailers also include ActionDispatch::Routing::UrlFor. So within mailers, you can use url_for. However, mailers cannot access incoming web requests in order to derive hostname information, so you have to provide the :host option or set the default host using default_url_options. For more information on url_for in mailers see the ActionMailer::Base documentation.

+ +

URL generation for named routes

+ +

UrlFor also allows one to access methods that have been auto-generated from named routes. For example, suppose that you have a ‘users’ resource in your config/routes.rb:

+ +
resources :users
+
+ +

This generates, among other things, the method users_path. By default, this method is accessible from your controllers, views, and mailers. If you need to access this auto-generated method from other places (such as a model), then you can do that by including Rails.application.routes.url_helpers in your class:

+ +
class User < ActiveRecord::Base
+  include Rails.application.routes.url_helpers
+
+  def base_uri
+    user_path(self)
+  end
+end
+
+User.find(1).base_uri # => "/users/1"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 106
+def initialize(...)
+  @_routes = nil
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + route_for(name, *args) + +

+ + +
+

Allows calling direct or regular named route.

+ +
resources :buckets
+
+direct :recordable do |recording|
+  route_for(:bucket, recording.bucket)
+end
+
+direct :threadable do |threadable|
+  route_for(:recordable, threadable.parent)
+end
+
+ +

This maintains the context of the original caller on whether to return a path or full URL, e.g:

+ +
threadable_path(threadable)  # => "/buckets/1"
+threadable_url(threadable)   # => "http://example.com/buckets/1"
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 213
+def route_for(name, *args)
+  public_send(:"#{name}_url", *args)
+end
+
+
+ +
+ +
+

+ + url_for(options = nil) + +

+ + +
+

Generate a URL based on the options provided, default_url_options, and the routes defined in config/routes.rb. The following options are supported:

+
  • +

    :only_path - If true, the relative URL is returned. Defaults to false.

    +
  • +

    :protocol - The protocol to connect to. Defaults to "http".

    +
  • +

    :host - Specifies the host the link should be targeted at. If :only_path is false, this option must be provided either explicitly, or via default_url_options.

    +
  • +

    :subdomain - Specifies the subdomain of the link, using the tld_length to split the subdomain from the host. If false, removes all subdomains from the host part of the link.

    +
  • +

    :domain - Specifies the domain of the link, using the tld_length to split the domain from the host.

    +
  • +

    :tld_length - Number of labels the TLD id composed of, only used if :subdomain or :domain are supplied. Defaults to ActionDispatch::Http::URL.tld_length, which in turn defaults to 1.

    +
  • +

    :port - Optionally specify the port to connect to.

    +
  • +

    :anchor - An anchor name to be appended to the path.

    +
  • +

    :params - The query parameters to be appended to the path.

    +
  • +

    :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/".

    +
  • +

    :script_name - Specifies application path relative to domain root. If provided, prepends application path.

    +
+ +

Any other key (:controller, :action, etc.) given to url_for is forwarded to the Routes module.

+ +
url_for controller: 'tasks', action: 'testing', host: 'somehost.org', port: '8080'
+# => 'http://somehost.org:8080/tasks/testing'
+url_for controller: 'tasks', action: 'testing', host: 'somehost.org', anchor: 'ok', only_path: true
+# => '/tasks/testing#ok'
+url_for controller: 'tasks', action: 'testing', trailing_slash: true
+# => 'http://somehost.org/tasks/testing/'
+url_for controller: 'tasks', action: 'testing', host: 'somehost.org', number: '33'
+# => 'http://somehost.org/tasks/testing?number=33'
+url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp"
+# => 'http://somehost.org/myapp/tasks/testing'
+url_for controller: 'tasks', action: 'testing', host: 'somehost.org', script_name: "/myapp", only_path: true
+# => '/myapp/tasks/testing'
+
+ +

Missing routes keys may be filled in from the current request’s parameters (e.g. :controller, :action, :id, and any other parameters that are placed in the path). Given that the current action has been reached through GET /users/1:

+ +
url_for(only_path: true)                        # => '/users/1'
+url_for(only_path: true, action: 'edit')        # => '/users/1/edit'
+url_for(only_path: true, action: 'edit', id: 2) # => '/users/2/edit'
+
+ +

Notice that no :id parameter was provided to the first url_for call and the helper used the one from the route’s path. Any path parameter implicitly used by url_for can always be overwritten like shown on the last url_for calls.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 169
+def url_for(options = nil)
+  full_url_for(options)
+end
+
+
+ +
+ +
+

+ + url_options() + +

+ + +
+

Hook overridden in controller to add request information with default_url_options. Application logic should not go into url_options.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 114
+def url_options
+  default_url_options
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + optimize_routes_generation?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 218
+def optimize_routes_generation?
+  _routes.optimize_routes_generation? && default_url_options.empty?
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + _routes_context() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 230
+def _routes_context # :doc:
+  self
+end
+
+
+ +
+ +
+

+ + _with_routes(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/routing/url_for.rb, line 223
+def _with_routes(routes) # :doc:
+  old_routes, @_routes = @_routes, routes
+  yield
+ensure
+  @_routes = old_routes
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/SSL.html b/src/7.0/classes/ActionDispatch/SSL.html new file mode 100644 index 0000000000..49a5ea9775 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/SSL.html @@ -0,0 +1,91 @@ +--- +title: ActionDispatch::SSL +layout: default +--- +
+ +
+
+ +
+ +

This middleware is added to the stack when config.force_ssl = true, and is passed the options set in config.ssl_options. It does three jobs to enforce secure HTTP requests:

+
  1. +

    TLS redirect: Permanently redirects http:// requests to https:// with the same URL host, path, etc. Enabled by default. Set config.ssl_options to modify the destination URL (e.g. redirect: { host: "secure.widgets.com", port: 8080 }), or set redirect: false to disable this feature.

    + +

    Requests can opt-out of redirection with exclude:

    + +
    config.ssl_options = { redirect: { exclude: -> request { /healthcheck/.match?(request.path) } } }
    +
    + +

    Cookies will not be flagged as secure for excluded requests.

    +
  2. +

    Secure cookies: Sets the secure flag on cookies to tell browsers they must not be sent along with http:// requests. Enabled by default. Set config.ssl_options with secure_cookies: false to disable this feature.

    +
  3. +

    HTTP Strict Transport Security (HSTS): Tells the browser to remember this site as TLS-only and automatically redirect non-TLS requests. Enabled by default. Configure config.ssl_options with hsts: false to disable.

    + +

    Set config.ssl_options with hsts: { ... } to configure HSTS:

    +
    • +

      expires: How long, in seconds, these settings will stick. The minimum required to qualify for browser preload lists is 1 year. Defaults to 2 years (recommended).

      +
    • +

      subdomains: Set to true to tell the browser to apply these settings to all subdomains. This protects your cookies from interception by a vulnerable site on a subdomain. Defaults to true.

      +
    • +

      preload: Advertise that this site may be included in browsers’ preloaded HSTS lists. HSTS protects your site on every visit except the first visit since it hasn’t seen your HSTS header yet. To close this gap, browser vendors include a baked-in list of HSTS-enabled sites. Go to hstspreload.org to submit your site for inclusion. Defaults to false.

      +
    + +

    To turn off HSTS, omitting the header is not enough. Browsers will remember the original HSTS directive until it expires. Instead, use the header to tell browsers to expire HSTS immediately. Setting hsts: false is a shortcut for hsts: { expires: 0 }.

    +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ServerTiming.html b/src/7.0/classes/ActionDispatch/ServerTiming.html new file mode 100644 index 0000000000..839c5e23f0 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ServerTiming.html @@ -0,0 +1,183 @@ +--- +title: ActionDispatch::ServerTiming +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
SERVER_TIMING_HEADER="Server-Timing"
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/server_timing.rb, line 52
+def initialize(app)
+  @app = app
+  @subscriber = Subscriber.instance
+  @subscriber.ensure_subscribed
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/server_timing.rb, line 58
+def call(env)
+  response = nil
+  events = @subscriber.collect_events do
+    response = @app.call(env)
+  end
+
+  headers = response[1]
+
+  header_info = events.group_by(&:name).map do |event_name, events_collection|
+    "%s;dur=%.2f" % [event_name, events_collection.sum(&:duration)]
+  end
+
+  header_info.prepend(headers[SERVER_TIMING_HEADER]) if headers[SERVER_TIMING_HEADER].present?
+  headers[SERVER_TIMING_HEADER] = header_info.join(", ")
+
+  response
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session.html b/src/7.0/classes/ActionDispatch/Session.html new file mode 100644 index 0000000000..b27be46102 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session.html @@ -0,0 +1,92 @@ +--- +title: ActionDispatch::Session +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/AbstractSecureStore.html b/src/7.0/classes/ActionDispatch/Session/AbstractSecureStore.html new file mode 100644 index 0000000000..878840ea2b --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/AbstractSecureStore.html @@ -0,0 +1,129 @@ +--- +title: ActionDispatch::Session::AbstractSecureStore +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + generate_sid() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 95
+def generate_sid
+  Rack::Session::SessionId.new(super)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/AbstractStore.html b/src/7.0/classes/ActionDispatch/Session/AbstractStore.html new file mode 100644 index 0000000000..f7040e7a5c --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/AbstractStore.html @@ -0,0 +1,82 @@ +--- +title: ActionDispatch::Session::AbstractStore +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/CacheStore.html b/src/7.0/classes/ActionDispatch/Session/CacheStore.html new file mode 100644 index 0000000000..18d6534bc7 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/CacheStore.html @@ -0,0 +1,253 @@ +--- +title: ActionDispatch::Session::CacheStore +layout: default +--- +
+ +
+
+ +
+ +

A session store that uses an ActiveSupport::Cache::Store to store the sessions. This store is most useful if you don’t store critical data in your sessions and you don’t need them to live for extended periods of time.

+ +

Options

+
  • +

    cache - The cache to use. If it is not specified, Rails.cache will be used.

    +
  • +

    expire_after - The length of time a session will be stored before automatically expiring. By default, the :expires_in option of the cache is used.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cache_store.rb, line 16
+def initialize(app, options = {})
+  @cache = options[:cache] || Rails.cache
+  options[:expire_after] ||= @cache.options[:expires_in]
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + delete_session(env, sid, options) + +

+ + +
+

Remove a session from the cache.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cache_store.rb, line 42
+def delete_session(env, sid, options)
+  @cache.delete(cache_key(sid.private_id))
+  @cache.delete(cache_key(sid.public_id))
+  generate_sid
+end
+
+
+ +
+ +
+

+ + find_session(env, sid) + +

+ + +
+

Get a session from the cache.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cache_store.rb, line 23
+def find_session(env, sid)
+  unless sid && (session = get_session_with_fallback(sid))
+    sid, session = generate_sid, {}
+  end
+  [sid, session]
+end
+
+
+ +
+ +
+

+ + write_session(env, sid, session, options) + +

+ + +
+

Set a session in the cache.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cache_store.rb, line 31
+def write_session(env, sid, session, options)
+  key = cache_key(sid.private_id)
+  if session
+    @cache.write(key, session, expires_in: options[:expire_after])
+  else
+    @cache.delete(key)
+  end
+  sid
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/Compatibility.html b/src/7.0/classes/ActionDispatch/Session/Compatibility.html new file mode 100644 index 0000000000..399da7e3f4 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/Compatibility.html @@ -0,0 +1,189 @@ +--- +title: ActionDispatch::Session::Compatibility +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 21
+def initialize(app, options = {})
+  options[:key] ||= "_session_id"
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + generate_sid() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 26
+def generate_sid
+  sid = SecureRandom.hex(16)
+  sid.encode!(Encoding::UTF_8)
+  sid
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + initialize_sid() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 33
+def initialize_sid # :doc:
+  @default_options.delete(:sidbits)
+  @default_options.delete(:secure_random)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/CookieStore.html b/src/7.0/classes/ActionDispatch/Session/CookieStore.html new file mode 100644 index 0000000000..17fc11d565 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/CookieStore.html @@ -0,0 +1,238 @@ +--- +title: ActionDispatch::Session::CookieStore +layout: default +--- +
+ +
+
+ +
+ +

This cookie-based session store is the Rails default. It is dramatically faster than the alternatives.

+ +

Sessions typically contain at most a user ID and flash message; both fit within the 4096 bytes cookie size limit. A CookieOverflow exception is raised if you attempt to store more than 4096 bytes of data.

+ +

The cookie jar used for storage is automatically configured to be the best possible option given your application’s configuration.

+ +

Your cookies will be encrypted using your application’s secret_key_base. This goes a step further than signed cookies in that encrypted cookies cannot be altered or read by users. This is the default starting in Rails 4.

+ +

Configure your session store in an initializer:

+ +
Rails.application.config.session_store :cookie_store, key: '_your_app_session'
+
+ +

In the development and test environments your application’s secret_key_base is generated by Rails and stored in a temporary file in tmp/development_secret.txt. In all other environments, it is stored encrypted in the config/credentials.yml.enc file.

+ +

If your application was not updated to Rails 5.2 defaults, the secret_key_base will be found in the old config/secrets.yml file.

+ +

Note that changing your secret_key_base will invalidate all existing session. Additionally, you should take care to make sure you are not relying on the ability to decode signed cookies generated by your app in external applications or JavaScript before changing it.

+ +

Because CookieStore extends Rack::Session::Abstract::Persisted, many of the options described there can be used to customize the session cookie that is generated. For example:

+ +
Rails.application.config.session_store :cookie_store, expire_after: 14.days
+
+ +

would set the session cookie to expire automatically 14 days after creation. Other useful options include :key, :secure, :httponly, and :same_site.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cookie_store.rb, line 59
+def initialize(app, options = {})
+  super(app, options.merge!(cookie_only: true))
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + delete_session(req, session_id, options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cookie_store.rb, line 63
+def delete_session(req, session_id, options)
+  new_sid = generate_sid unless options[:drop]
+  # Reset hash and Assign the new session id
+  req.set_header("action_dispatch.request.unsigned_session_cookie", new_sid ? { "session_id" => new_sid.public_id } : {})
+  new_sid
+end
+
+
+ +
+ +
+

+ + load_session(req) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cookie_store.rb, line 70
+def load_session(req)
+  stale_session_check! do
+    data = unpacked_cookie_data(req)
+    data = persistent_session_id!(data)
+    [Rack::Session::SessionId.new(data["session_id"]), data]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/CookieStore/SessionId.html b/src/7.0/classes/ActionDispatch/Session/CookieStore/SessionId.html new file mode 100644 index 0000000000..161e183512 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/CookieStore/SessionId.html @@ -0,0 +1,122 @@ +--- +title: ActionDispatch::Session::CookieStore::SessionId +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + cookie_value
+ + + + +

Class Public methods

+ +
+

+ + new(session_id, cookie_value = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/cookie_store.rb, line 53
+def initialize(session_id, cookie_value = {})
+  super(session_id)
+  @cookie_value = cookie_value
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/MemCacheStore.html b/src/7.0/classes/ActionDispatch/Session/MemCacheStore.html new file mode 100644 index 0000000000..1122f90a68 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/MemCacheStore.html @@ -0,0 +1,141 @@ +--- +title: ActionDispatch::Session::MemCacheStore +layout: default +--- +
+ +
+
+ +
+ +

A session store that uses MemCache to implement storage.

+ +

Options

+
  • +

    expire_after - The length of time a session will be stored before automatically expiring.

    +
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb, line 22
+def initialize(app, options = {})
+  options[:expire_after] ||= options[:expires]
+  super
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Session/StaleSessionCheck.html b/src/7.0/classes/ActionDispatch/Session/StaleSessionCheck.html new file mode 100644 index 0000000000..82c5b23657 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Session/StaleSessionCheck.html @@ -0,0 +1,191 @@ +--- +title: ActionDispatch::Session::StaleSessionCheck +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + extract_session_id(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 48
+def extract_session_id(env)
+  stale_session_check! { super }
+end
+
+
+ +
+ +
+

+ + load_session(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 44
+def load_session(env)
+  stale_session_check! { super }
+end
+
+
+ +
+ +
+

+ + stale_session_check!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/session/abstract_store.rb, line 52
+def stale_session_check!
+  yield
+rescue ArgumentError => argument_error
+  if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
+    begin
+      # Note that the regexp does not allow $1 to end with a ':'.
+      $1.constantize
+    rescue LoadError, NameError
+      raise ActionDispatch::Session::SessionRestoreError
+    end
+    retry
+  else
+    raise
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/ShowExceptions.html b/src/7.0/classes/ActionDispatch/ShowExceptions.html new file mode 100644 index 0000000000..abf72a8368 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/ShowExceptions.html @@ -0,0 +1,169 @@ +--- +title: ActionDispatch::ShowExceptions +layout: default +--- +
+ +
+
+ +
+ +

This middleware rescues any exception returned by the application and calls an exceptions app that will wrap it in a format for the end user.

+ +

The exceptions app should be passed as a parameter on initialization of ShowExceptions. Every time there is an exception, ShowExceptions will store the exception in env["action_dispatch.exception"], rewrite the PATH_INFO to the exception status code and call the Rack app.

+ +

In Rails applications, the exceptions app can be configured with config.exceptions_app, which defaults to ActionDispatch::PublicExceptions.

+ +

If the application returns an "X-Cascade" => "pass" response, this middleware will send an empty response as a result with the correct status code. If any exception happens inside the exceptions app, this middleware catches the exceptions and returns a failsafe response.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, exceptions_app) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/show_exceptions.rb, line 22
+def initialize(app, exceptions_app)
+  @app = app
+  @exceptions_app = exceptions_app
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/show_exceptions.rb, line 27
+def call(env)
+  request = ActionDispatch::Request.new env
+  @app.call(env)
+rescue Exception => exception
+  if request.show_exceptions?
+    render_exception(request, exception)
+  else
+    raise exception
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/Static.html b/src/7.0/classes/ActionDispatch/Static.html new file mode 100644 index 0000000000..8a307c3840 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/Static.html @@ -0,0 +1,162 @@ +--- +title: ActionDispatch::Static +layout: default +--- +
+ +
+
+ +
+ +

This middleware serves static files from disk, if available. If no file is found, it hands off to the main app.

+ +

In Rails apps, this middleware is configured to serve assets from the public/ directory.

+ +

Only GET and HEAD requests are served. POST and other HTTP methods are handed off to the main app.

+ +

Only files in the root directory are served; path traversal is denied.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, path, index: "index", headers: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/static.rb, line 17
+def initialize(app, path, index: "index", headers: {})
+  @app = app
+  @file_handler = FileHandler.new(path, index: index, headers: headers)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/middleware/static.rb, line 22
+def call(env)
+  @file_handler.attempt(env) || @app.call(env)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/SystemTestCase.html b/src/7.0/classes/ActionDispatch/SystemTestCase.html new file mode 100644 index 0000000000..9d71b0403f --- /dev/null +++ b/src/7.0/classes/ActionDispatch/SystemTestCase.html @@ -0,0 +1,248 @@ +--- +title: ActionDispatch::SystemTestCase +layout: default +--- +
+ +
+
+ +
+ +

System Testing

+ +

System tests let you test applications in the browser. Because system tests use a real browser experience, you can test all of your JavaScript easily from your test suite.

+ +

To create a system test in your application, extend your test class from ApplicationSystemTestCase. System tests use Capybara as a base and allow you to configure the settings through your application_system_test_case.rb file that is generated with a new application or scaffold.

+ +

Here is an example system test:

+ +
require "application_system_test_case"
+
+class Users::CreateTest < ApplicationSystemTestCase
+  test "adding a new user" do
+    visit users_path
+    click_on 'New User'
+
+    fill_in 'Name', with: 'Arya'
+    click_on 'Create User'
+
+    assert_text 'Arya'
+  end
+end
+
+ +

When generating an application or scaffold, an application_system_test_case.rb file will also be generated containing the base class for system testing. This is where you can change the driver, add Capybara settings, and other configuration for your system tests.

+ +
require "test_helper"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+  driven_by :selenium, using: :chrome, screen_size: [1400, 1400]
+end
+
+ +

By default, ActionDispatch::SystemTestCase is driven by the Selenium driver, with the Chrome browser, and a browser size of 1400x1400.

+ +

Changing the driver configuration options is easy. Let’s say you want to use the Firefox browser instead of Chrome. In your application_system_test_case.rb file add the following:

+ +
require "test_helper"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+  driven_by :selenium, using: :firefox
+end
+
+ +

driven_by has a required argument for the driver name. The keyword arguments are :using for the browser and :screen_size to change the size of the browser screen. These two options are not applicable for headless drivers and will be silently ignored if passed.

+ +

Headless browsers such as headless Chrome and headless Firefox are also supported. You can use these browsers by setting the :using argument to :headless_chrome or :headless_firefox.

+ +

To use a headless driver, like Cuprite, update your Gemfile to use Cuprite instead of Selenium and then declare the driver name in the application_system_test_case.rb file. In this case, you would leave out the :using option because the driver is headless, but you can still use :screen_size to change the size of the browser screen, also you can use :options to pass options supported by the driver. Please refer to your driver documentation to learn about supported options.

+ +
require "test_helper"
+require "capybara/cuprite"
+
+class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+  driven_by :cuprite, screen_size: [1400, 1400], options:
+    { js_errors: true }
+end
+
+ +

Some drivers require browser capabilities to be passed as a block instead of through the options hash.

+ +

As an example, if you want to add mobile emulation on chrome, you’ll have to create an instance of selenium’s Chrome::Options object and add capabilities with a block.

+ +

The block will be passed an instance of <Driver>::Options where you can define the capabilities you want. Please refer to your driver documentation to learn about supported options.

+ +
class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
+  driven_by :selenium, using: :chrome, screen_size: [1024, 768] do |driver_option|
+    driver_option.add_emulation(device_name: 'iPhone 6')
+    driver_option.add_extension('path/to/chrome_extension.crx')
+  end
+end
+
+ +

Because ActionDispatch::SystemTestCase is a shim between Capybara and Rails, any driver that is supported by Capybara is supported by system tests as long as you include the required gems and files.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_HOST="http://127.0.0.1"
 
+ + + + + + +

Class Public methods

+ +
+

+ + driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities) + +

+ + +
+

System Test configuration options

+ +

The default settings are Selenium, using Chrome, with a screen size of 1400x1400.

+ +

Examples:

+ +
driven_by :cuprite
+
+driven_by :selenium, screen_size: [800, 800]
+
+driven_by :selenium, using: :chrome
+
+driven_by :selenium, using: :headless_chrome
+
+driven_by :selenium, using: :firefox
+
+driven_by :selenium, using: :headless_firefox
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/system_test_case.rb, line 156
+def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}, &capabilities)
+  driver_options = { using: using, screen_size: screen_size, options: options }
+
+  self.driver = SystemTesting::Driver.new(driver, **driver_options, &capabilities)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/SystemTesting.html b/src/7.0/classes/ActionDispatch/SystemTesting.html new file mode 100644 index 0000000000..5af7190698 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/SystemTesting.html @@ -0,0 +1,75 @@ +--- +title: ActionDispatch::SystemTesting +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers.html b/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers.html new file mode 100644 index 0000000000..1ac288df6d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers.html @@ -0,0 +1,69 @@ +--- +title: ActionDispatch::SystemTesting::TestHelpers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers/ScreenshotHelper.html b/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers/ScreenshotHelper.html new file mode 100644 index 0000000000..41352c9951 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/SystemTesting/TestHelpers/ScreenshotHelper.html @@ -0,0 +1,174 @@ +--- +title: ActionDispatch::SystemTesting::TestHelpers::ScreenshotHelper +layout: default +--- +
+ +
+
+ +
+ +

Screenshot helper for system testing.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + take_failed_screenshot() + +

+ + +
+

Takes a screenshot of the current page in the browser if the test failed.

+ +

take_failed_screenshot is called during system test teardown.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb, line 44
+def take_failed_screenshot
+  take_screenshot if failed? && supports_screenshot? && Capybara::Session.instance_created?
+end
+
+
+ +
+ +
+

+ + take_screenshot() + +

+ + +
+

Takes a screenshot of the current page in the browser.

+ +

take_screenshot can be used at any point in your system tests to take a screenshot of the current state. This can be useful for debugging or automating visual testing. You can take multiple screenshots per test to investigate changes at different points during your test. These will be named with a sequential prefix (or ‘failed’ for failing tests)

+ +

The screenshot will be displayed in your console, if supported.

+ +

The default screenshots directory is tmp/screenshots but you can set a different one with Capybara.save_path

+ +

You can set the RAILS_SYSTEM_TESTING_SCREENSHOT_HTML environment variable to save the HTML from the page that is being screenshotted so you can investigate the elements on the page at the time of the screenshot

+ +

You can set the RAILS_SYSTEM_TESTING_SCREENSHOT environment variable to control the output. Possible values are:

+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb, line 33
+def take_screenshot
+  increment_unique
+  save_html if save_html?
+  save_image
+  puts display_image
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/TestProcess.html b/src/7.0/classes/ActionDispatch/TestProcess.html new file mode 100644 index 0000000000..a18c5be7ba --- /dev/null +++ b/src/7.0/classes/ActionDispatch/TestProcess.html @@ -0,0 +1,286 @@ +--- +title: ActionDispatch::TestProcess +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assigns(key = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 30
+def assigns(key = nil)
+  raise NoMethodError,
+    "assigns has been extracted to a gem. To continue using it,
+    add `gem 'rails-controller-testing'` to your Gemfile."
+end
+
+
+ +
+ +
+

+ + cookies() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 44
+def cookies
+  @cookie_jar ||= Cookies::CookieJar.build(@request, @request.cookies)
+end
+
+
+ +
+ +
+

+ + flash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 40
+def flash
+  @request.flash
+end
+
+
+ +
+ +
+

+ + redirect_to_url() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 48
+def redirect_to_url
+  @response.redirect_url
+end
+
+
+ +
+ +
+

+ + session() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 36
+def session
+  @request.session
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/TestProcess/FixtureFile.html b/src/7.0/classes/ActionDispatch/TestProcess/FixtureFile.html new file mode 100644 index 0000000000..11db05342f --- /dev/null +++ b/src/7.0/classes/ActionDispatch/TestProcess/FixtureFile.html @@ -0,0 +1,115 @@ +--- +title: ActionDispatch::TestProcess::FixtureFile +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fixture_file_upload(path, mime_type = nil, binary = false) + +

+ + +
+

Shortcut for Rack::Test::UploadedFile.new(File.join(ActionDispatch::IntegrationTest.file_fixture_path, path), type):

+ +
post :change_avatar, params: { avatar: fixture_file_upload('david.png', 'image/png') }
+
+ +

Default fixture files location is test/fixtures/files.

+ +

To upload binary files on Windows, pass :binary as the last parameter. This will not affect other platforms:

+ +
post :change_avatar, params: { avatar: fixture_file_upload('david.png', 'image/png', :binary) }
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_process.rb, line 19
+def fixture_file_upload(path, mime_type = nil, binary = false)
+  if self.class.file_fixture_path && !File.exist?(path)
+    path = file_fixture(path)
+  end
+
+  Rack::Test::UploadedFile.new(path, mime_type, binary)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/TestRequest.html b/src/7.0/classes/ActionDispatch/TestRequest.html new file mode 100644 index 0000000000..a59420fb93 --- /dev/null +++ b/src/7.0/classes/ActionDispatch/TestRequest.html @@ -0,0 +1,564 @@ +--- +title: ActionDispatch::TestRequest +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_ENV=Rack::MockRequest.env_for("/", +"HTTP_HOST" => "test.host".b, +"REMOTE_ADDR" => "0.0.0.0".b, +"HTTP_USER_AGENT" => "Rails Testing".b, +)
 
+ + + + + + +

Class Public methods

+ +
+

+ + create(env = {}) + +

+ + +
+

Create a new test request with default env values.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 15
+def self.create(env = {})
+  env = Rails.application.env_config.merge(env) if defined?(Rails.application) && Rails.application
+  env["rack.request.cookie_hash"] ||= {}.with_indifferent_access
+  new(default_env.merge(env))
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + accept=(mime_types) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 66
+def accept=(mime_types)
+  delete_header("action_dispatch.request.accepts")
+  set_header("HTTP_ACCEPT", Array(mime_types).collect(&:to_s).join(","))
+end
+
+
+ +
+ +
+

+ + action=(action_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 46
+def action=(action_name)
+  path_parameters[:action] = action_name.to_s
+end
+
+
+ +
+ +
+

+ + host=(host) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 30
+def host=(host)
+  set_header("HTTP_HOST", host)
+end
+
+
+ +
+ +
+

+ + if_modified_since=(last_modified) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 50
+def if_modified_since=(last_modified)
+  set_header("HTTP_IF_MODIFIED_SINCE", last_modified)
+end
+
+
+ +
+ +
+

+ + if_none_match=(etag) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 54
+def if_none_match=(etag)
+  set_header("HTTP_IF_NONE_MATCH", etag)
+end
+
+
+ +
+ +
+

+ + path=(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 42
+def path=(path)
+  set_header("PATH_INFO", path)
+end
+
+
+ +
+ +
+

+ + port=(number) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 34
+def port=(number)
+  set_header("SERVER_PORT", number.to_i)
+end
+
+
+ +
+ +
+

+ + remote_addr=(addr) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 58
+def remote_addr=(addr)
+  set_header("REMOTE_ADDR", addr)
+end
+
+
+ +
+ +
+

+ + request_method=(method) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 26
+def request_method=(method)
+  super(method.to_s.upcase)
+end
+
+
+ +
+ +
+

+ + request_uri=(uri) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 38
+def request_uri=(uri)
+  set_header("REQUEST_URI", uri)
+end
+
+
+ +
+ +
+

+ + user_agent=(user_agent) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_request.rb, line 62
+def user_agent=(user_agent)
+  set_header("HTTP_USER_AGENT", user_agent)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionDispatch/TestResponse.html b/src/7.0/classes/ActionDispatch/TestResponse.html new file mode 100644 index 0000000000..6fe0b8862d --- /dev/null +++ b/src/7.0/classes/ActionDispatch/TestResponse.html @@ -0,0 +1,214 @@ +--- +title: ActionDispatch::TestResponse +layout: default +--- +
+ +
+
+ +
+ +

Integration test methods such as Integration::RequestHelpers#get and Integration::RequestHelpers#post return objects of class TestResponse, which represent the HTTP response results of the requested controller actions.

+ +

See Response for more information on controller response objects.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + from_response(response) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_response.rb, line 13
+def self.from_response(response)
+  new response.status, response.headers, response.body
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + parsed_body() + +

+ + +
+

Returns a parsed body depending on the response MIME type. When a parser corresponding to the MIME type is not found, it returns the raw body.

+ +

Examples

+ +
get "/posts"
+response.content_type      # => "text/html; charset=utf-8"
+response.parsed_body.class # => String
+response.parsed_body       # => "<!DOCTYPE html>\n<html>\n..."
+
+get "/posts.json"
+response.content_type      # => "application/json; charset=utf-8"
+response.parsed_body.class # => Array
+response.parsed_body       # => [{"id"=>42, "title"=>"Title"},...
+
+get "/posts/42.json"
+response.content_type      # => "application/json; charset=utf-8"
+response.parsed_body.class # => Hash
+response.parsed_body       # => {"id"=>42, "title"=>"Title"}
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_response.rb, line 35
+def parsed_body
+  @parsed_body ||= response_parser.call(body)
+end
+
+
+ +
+ +
+

+ + response_parser() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/testing/test_response.rb, line 39
+def response_parser
+  @response_parser ||= RequestEncoder.parser(media_type)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox.html b/src/7.0/classes/ActionMailbox.html new file mode 100644 index 0000000000..ccb796da3a --- /dev/null +++ b/src/7.0/classes/ActionMailbox.html @@ -0,0 +1,244 @@ +--- +title: ActionMailbox +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Action Mailbox as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Action Mailbox as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Base.html b/src/7.0/classes/ActionMailbox/Base.html new file mode 100644 index 0000000000..7c601b57bc --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Base.html @@ -0,0 +1,305 @@ +--- +title: ActionMailbox::Base +layout: default +--- +
+ +
+
+ +
+ +

The base class for all application mailboxes. Not intended to be inherited from directly. Inherit from ApplicationMailbox instead, as that’s where the app-specific routing is configured. This routing is specified in the following ways:

+ +
class ApplicationMailbox < ActionMailbox::Base
+  # Any of the recipients of the mail (whether to, cc, bcc) are matched against the regexp.
+  routing /^replies@/i => :replies
+
+  # Any of the recipients of the mail (whether to, cc, bcc) needs to be an exact match for the string.
+  routing "help@example.com" => :help
+
+  # Any callable (proc, lambda, etc) object is passed the inbound_email record and is a match if true.
+  routing ->(inbound_email) { inbound_email.mail.to.size > 2 } => :multiple_recipients
+
+  # Any object responding to #match? is called with the inbound_email record as an argument. Match if true.
+  routing CustomAddress.new => :custom
+
+  # Any inbound_email that has not been already matched will be sent to the BackstopMailbox.
+  routing :all => :backstop
+end
+
+ +

Application mailboxes need to override the process method, which is invoked by the framework after callbacks have been run. The callbacks available are: before_processing, after_processing, and around_processing. The primary use case is ensure certain preconditions to processing are fulfilled using before_processing callbacks.

+ +

If a precondition fails to be met, you can halt the processing using the #bounced! method, which will silently prevent any further processing, but not actually send out any bounce notice. You can also pair this behavior with the invocation of an Action Mailer class responsible for sending out an actual bounce email. This is done using the bounce_with method, which takes the mail object returned by an Action Mailer method, like so:

+ +
class ForwardsMailbox < ApplicationMailbox
+  before_processing :ensure_sender_is_a_user
+
+  private
+    def ensure_sender_is_a_user
+      unless User.exist?(email_address: mail.from)
+        bounce_with UserRequiredMailer.missing(inbound_email)
+      end
+    end
+end
+
+ +

During the processing of the inbound email, the status will be tracked. Before processing begins, the email will normally have the pending status. Once processing begins, just before callbacks and the process method is called, the status is changed to processing. If processing is allowed to complete, the status is changed to delivered. If a bounce is triggered, then bounced. If an unhandled exception is bubbled up, then failed.

+ +

Exceptions can be handled at the class level using the familiar ActiveSupport::Rescuable approach:

+ +
class ForwardsMailbox < ApplicationMailbox
+  rescue_from(ApplicationSpecificVerificationError) { bounced! }
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + inbound_email
+ + + + +

Class Public methods

+ +
+

+ + new(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/base.rb, line 77
+def initialize(inbound_email)
+  @inbound_email = inbound_email
+end
+
+
+ +
+ +
+

+ + receive(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/base.rb, line 73
+def self.receive(inbound_email)
+  new(inbound_email).perform_processing
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + bounce_with(message) + +

+ + +
+

Enqueues the given message for delivery and changes the inbound email’s status to :bounced.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/base.rb, line 102
+def bounce_with(message)
+  inbound_email.bounced!
+  message.deliver_later
+end
+
+
+ +
+ +
+

+ + process() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/base.rb, line 92
+def process
+  # Override in subclasses
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/BaseController.html b/src/7.0/classes/ActionMailbox/BaseController.html new file mode 100644 index 0000000000..50c9c2a35a --- /dev/null +++ b/src/7.0/classes/ActionMailbox/BaseController.html @@ -0,0 +1,66 @@ +--- +title: ActionMailbox::BaseController +layout: default +--- +
+ +
+
+ +
+ +

The base class for all Action Mailbox ingress controllers.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Callbacks.html b/src/7.0/classes/ActionMailbox/Callbacks.html new file mode 100644 index 0000000000..77cad5a4c2 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Callbacks.html @@ -0,0 +1,220 @@ +--- +title: ActionMailbox::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Defines the callbacks related to processing.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
TERMINATOR=->(mailbox, chain) do +chain.call +mailbox.finished_processing? +end
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + after_processing(*methods, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/callbacks.rb, line 25
+def after_processing(*methods, &block)
+  set_callback(:process, :after, *methods, &block)
+end
+
+
+ +
+ +
+

+ + around_processing(*methods, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/callbacks.rb, line 29
+def around_processing(*methods, &block)
+  set_callback(:process, :around, *methods, &block)
+end
+
+
+ +
+ +
+

+ + before_processing(*methods, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/callbacks.rb, line 21
+def before_processing(*methods, &block)
+  set_callback(:process, :before, *methods, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Engine.html b/src/7.0/classes/ActionMailbox/Engine.html new file mode 100644 index 0000000000..216718946e --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Engine.html @@ -0,0 +1,60 @@ +--- +title: ActionMailbox::Engine +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmail.html b/src/7.0/classes/ActionMailbox/InboundEmail.html new file mode 100644 index 0000000000..aebe315ebf --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmail.html @@ -0,0 +1,237 @@ +--- +title: ActionMailbox::InboundEmail +layout: default +--- +
+ +
+
+ +
+ +

The InboundEmail is an Active Record that keeps a reference to the raw email stored in Active Storage and tracks the status of processing. By default, incoming emails will go through the following lifecycle:

+
  • +

    Pending: Just received by one of the ingress controllers and scheduled for routing.

    +
  • +

    Processing: During active processing, while a specific mailbox is running its process method.

    +
  • +

    Delivered: Successfully processed by the specific mailbox.

    +
  • +

    Failed: An exception was raised during the specific mailbox’s execution of the #process method.

    +
  • +

    Bounced: Rejected processing by the specific mailbox and bounced to sender.

    +
+ +

Once the InboundEmail has reached the status of being either delivered, failed, or bounced, it’ll count as having been #processed?. Once processed, the InboundEmail will be scheduled for automatic incineration at a later point.

+ +

When working with an InboundEmail, you’ll usually interact with the parsed version of the source, which is available as a Mail object from #mail. But you can also access the raw source directly using the #source method.

+ +

Examples:

+ +
inbound_email.mail.from # => 'david@loudthinking.com'
+inbound_email.source # Returns the full rfc822 source of the email as text
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + mail() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email.rb, line 35
+def mail
+  @mail ||= Mail.from_source(source)
+end
+
+
+ +
+ +
+

+ + processed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email.rb, line 43
+def processed?
+  delivered? || failed? || bounced?
+end
+
+
+ +
+ +
+

+ + source() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email.rb, line 39
+def source
+  @source ||= raw_email.download
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable.html b/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable.html new file mode 100644 index 0000000000..9131dab4d9 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable.html @@ -0,0 +1,161 @@ +--- +title: ActionMailbox::InboundEmail::Incineratable +layout: default +--- +
+ +
+
+ +
+ +

Ensure that the InboundEmail is automatically scheduled for later incineration if the status has been changed to processed. The later incineration will be invoked at the time specified by the ActionMailbox.incinerate_after time using the IncinerationJob.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + incinerate() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/incineratable.rb, line 17
+def incinerate
+  Incineration.new(self).run
+end
+
+
+ +
+ +
+

+ + incinerate_later() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/incineratable.rb, line 13
+def incinerate_later
+  ActionMailbox::IncinerationJob.schedule self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable/Incineration.html b/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable/Incineration.html new file mode 100644 index 0000000000..19142659df --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmail/Incineratable/Incineration.html @@ -0,0 +1,155 @@ +--- +title: ActionMailbox::InboundEmail::Incineratable::Incineration +layout: default +--- +
+ +
+
+ +
+ +

Command class for carrying out the actual incineration of the InboundMail that’s been scheduled for removal. Before the incineration – which really is just a call to #destroy! – is run, we verify that it’s both eligible (by virtue of having already been processed) and time to do so (that is, the InboundEmail was processed after the incinerate_after time).

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/incineratable/incineration.rb, line 9
+def initialize(inbound_email)
+  @inbound_email = inbound_email
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + run() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/incineratable/incineration.rb, line 13
+def run
+  @inbound_email.destroy! if due? && processed?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmail/MessageId.html b/src/7.0/classes/ActionMailbox/InboundEmail/MessageId.html new file mode 100644 index 0000000000..233cab5bf3 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmail/MessageId.html @@ -0,0 +1,235 @@ +--- +title: ActionMailbox::InboundEmail::MessageId +layout: default +--- +
+ +
+
+ +
+ +

The Message-ID as specified by rfc822 is supposed to be a unique identifier for that individual email. That makes it an ideal tracking token for debugging and forensics, just like X-Request-Id does for web request.

+ +

If an inbound email does not, against the rfc822 mandate, specify a Message-ID, one will be generated using the approach from Mail::MessageIdField.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create_and_extract_message_id!(source, **options) + +

+ + +
+

Create a new InboundEmail from the raw source of the email, which is uploaded as an Active Storage attachment called raw_email. Before the upload, extract the Message-ID from the source and set it as an attribute on the new InboundEmail.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb, line 16
+def create_and_extract_message_id!(source, **options)
+  message_checksum = OpenSSL::Digest::SHA1.hexdigest(source)
+  message_id = extract_message_id(source) || generate_missing_message_id(message_checksum)
+
+  create! raw_email: create_and_upload_raw_email!(source),
+    message_id: message_id, message_checksum: message_checksum, **options
+rescue ActiveRecord::RecordNotUnique
+  nil
+end
+
+
+ +
+ +
+

+ + create_and_upload_raw_email!(source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb, line 37
+def create_and_upload_raw_email!(source)
+  ActiveStorage::Blob.create_and_upload! io: StringIO.new(source), filename: "message.eml", content_type: "message/rfc822",
+                                         service_name: ActionMailbox.storage_service
+end
+
+
+ +
+ +
+

+ + extract_message_id(source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb, line 27
+def extract_message_id(source)
+  Mail.from_source(source).message_id rescue nil
+end
+
+
+ +
+ +
+

+ + generate_missing_message_id(message_checksum) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/message_id.rb, line 31
+def generate_missing_message_id(message_checksum)
+  Mail::MessageIdField.new("<#{message_checksum}@#{::Socket.gethostname}.mail>").message_id.tap do |message_id|
+    logger.warn "Message-ID couldn't be parsed or is missing. Generated a new Message-ID: #{message_id}"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmail/Routable.html b/src/7.0/classes/ActionMailbox/InboundEmail/Routable.html new file mode 100644 index 0000000000..9539ba065d --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmail/Routable.html @@ -0,0 +1,148 @@ +--- +title: ActionMailbox::InboundEmail::Routable +layout: default +--- +
+ +
+
+ +
+ +

A newly received InboundEmail will not be routed synchronously as part of ingress controller’s receival. Instead, the routing will be done asynchronously, using a RoutingJob, to ensure maximum parallel capacity.

+ +

By default, all newly created InboundEmail records that have the status of pending, which is the default, will be scheduled for automatic, deferred routing.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + route() + +

+ + +
+

Route this InboundEmail using the routing rules declared on the ApplicationMailbox.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/routable.rb, line 21
+def route
+  ApplicationMailbox.route self
+end
+
+
+ +
+ +
+

+ + route_later() + +

+ + +
+

Enqueue a RoutingJob for this InboundEmail.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/models/action_mailbox/inbound_email/routable.rb, line 16
+def route_later
+  ActionMailbox::RoutingJob.perform_later self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/InboundEmails.html b/src/7.0/classes/ActionMailbox/InboundEmails.html new file mode 100644 index 0000000000..a123a4a889 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/InboundEmails.html @@ -0,0 +1,54 @@ +--- +title: ActionMailbox::InboundEmails +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/IncinerationJob.html b/src/7.0/classes/ActionMailbox/IncinerationJob.html new file mode 100644 index 0000000000..35d3a17f7d --- /dev/null +++ b/src/7.0/classes/ActionMailbox/IncinerationJob.html @@ -0,0 +1,159 @@ +--- +title: ActionMailbox::IncinerationJob +layout: default +--- +
+ +
+
+ +
+ +

You can configure when this IncinerationJob will be run as a time-after-processing using the config.action_mailbox.incinerate_after or ActionMailbox.incinerate_after setting.

+ +

Since this incineration is set for the future, it’ll automatically ignore any InboundEmails that have already been deleted and discard itself if so.

+ +

You can disable incinerating processed emails by setting config.action_mailbox.incinerate or ActionMailbox.incinerate to false.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + schedule(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/jobs/action_mailbox/incineration_job.rb, line 17
+def self.schedule(inbound_email)
+  set(wait: ActionMailbox.incinerate_after).perform_later(inbound_email)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + perform(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/jobs/action_mailbox/incineration_job.rb, line 21
+def perform(inbound_email)
+  inbound_email.incinerate
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses.html b/src/7.0/classes/ActionMailbox/Ingresses.html new file mode 100644 index 0000000000..c1da6a2e39 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses.html @@ -0,0 +1,83 @@ +--- +title: ActionMailbox::Ingresses +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mailgun.html b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun.html new file mode 100644 index 0000000000..4ae4859423 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun.html @@ -0,0 +1,67 @@ +--- +title: ActionMailbox::Ingresses::Mailgun +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController.html b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController.html new file mode 100644 index 0000000000..d4a9263efb --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController.html @@ -0,0 +1,173 @@ +--- +title: ActionMailbox::Ingresses::Mailgun::InboundEmailsController +layout: default +--- +
+ +
+
+ +
+ +

Ingests inbound emails from Mailgun. Requires the following parameters:

+
  • +

    body-mime: The full RFC 822 message

    +
  • +

    timestamp: The current time according to Mailgun as the number of seconds passed since the UNIX epoch

    +
  • +

    token: A randomly-generated, 50-character string

    +
  • +

    signature: A hexadecimal HMAC-SHA256 of the timestamp concatenated with the token, generated using the Mailgun Signing key

    +
+ +

Authenticates requests by validating their signatures.

+ +

Returns:

+
  • +

    204 No Content if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox

    +
  • +

    401 Unauthorized if the request’s signature could not be validated, or if its timestamp is more than 2 minutes old

    +
  • +

    404 Not Found if Action Mailbox is not configured to accept inbound emails from Mailgun

    +
  • +

    422 Unprocessable Entity if the request is missing required parameters

    +
  • +

    500 Server Error if the Mailgun Signing key is missing, or one of the Active Record database, the Active Storage service, or the Active Job backend is misconfigured or unavailable

    +
+ +

Usage

+
  1. +

    Give Action Mailbox your Mailgun Signing key (which you can find under Settings -> Security & Users -> API security in Mailgun) so it can authenticate requests to the Mailgun ingress.

    + +

    Use bin/rails credentials:edit to add your Signing key to your application’s encrypted credentials under action_mailbox.mailgun_signing_key, where Action Mailbox will automatically find it:

    + +
    action_mailbox:
    +  mailgun_signing_key: ...
    +
    + +

    Alternatively, provide your Signing key in the MAILGUN_INGRESS_SIGNING_KEY environment variable.

    +
  2. +

    Tell Action Mailbox to accept emails from Mailgun:

    + +
    # config/environments/production.rb
    +config.action_mailbox.ingress = :mailgun
    +
    +
  3. +

    Configure Mailgun to forward inbound emails to /rails/action_mailbox/mailgun/inbound_emails/mime.

    + +

    If your application lived at https://example.com, you would specify the fully-qualified URL https://example.com/rails/action_mailbox/mailgun/inbound_emails/mime.

    +
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb, line 48
+def create
+  ActionMailbox::InboundEmail.create_and_extract_message_id! mail
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController/Authenticator.html b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController/Authenticator.html new file mode 100644 index 0000000000..0c73787f83 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mailgun/InboundEmailsController/Authenticator.html @@ -0,0 +1,187 @@ +--- +title: ActionMailbox::Ingresses::Mailgun::InboundEmailsController::Authenticator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + key
+ [R] + signature
+ [R] + timestamp
+ [R] + token
+ + + + +

Class Public methods

+ +
+

+ + new(key:, timestamp:, token:, signature:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb, line 86
+def initialize(key:, timestamp:, token:, signature:)
+  @key, @timestamp, @token, @signature = key, Integer(timestamp), token, signature
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + authenticated?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller.rb, line 90
+def authenticated?
+  signed? && recent?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mandrill.html b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill.html new file mode 100644 index 0000000000..5090edc77d --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill.html @@ -0,0 +1,67 @@ +--- +title: ActionMailbox::Ingresses::Mandrill +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController.html b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController.html new file mode 100644 index 0000000000..1f58ac0566 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController.html @@ -0,0 +1,184 @@ +--- +title: ActionMailbox::Ingresses::Mandrill::InboundEmailsController +layout: default +--- +
+ +
+
+ +
+ +

Ingests inbound emails from Mandrill.

+ +

Requires a mandrill_events parameter containing a JSON array of Mandrill inbound email event objects. Each event is expected to have a msg object containing a full RFC 822 message in its raw_msg property.

+ +

Returns:

+
  • +

    204 No Content if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox

    +
  • +

    401 Unauthorized if the request’s signature could not be validated

    +
  • +

    404 Not Found if Action Mailbox is not configured to accept inbound emails from Mandrill

    +
  • +

    422 Unprocessable Entity if the request is missing required parameters

    +
  • +

    500 Server Error if the Mandrill API key is missing, or one of the Active Record database, the Active Storage service, or the Active Job backend is misconfigured or unavailable

    +
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller.rb, line 20
+def create
+  raw_emails.each { |raw_email| ActionMailbox::InboundEmail.create_and_extract_message_id! raw_email }
+  head :ok
+rescue JSON::ParserError => error
+  logger.error error.message
+  head :unprocessable_entity
+end
+
+
+ +
+ +
+

+ + health_check() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller.rb, line 28
+def health_check
+  head :ok
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController/Authenticator.html b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController/Authenticator.html new file mode 100644 index 0000000000..e4bb7015a9 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Mandrill/InboundEmailsController/Authenticator.html @@ -0,0 +1,171 @@ +--- +title: ActionMailbox::Ingresses::Mandrill::InboundEmailsController::Authenticator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + key
+ [R] + request
+ + + + +

Class Public methods

+ +
+

+ + new(request, key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller.rb, line 64
+def initialize(request, key)
+  @request, @key = request, key
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + authenticated?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller.rb, line 68
+def authenticated?
+  ActiveSupport::SecurityUtils.secure_compare given_signature, expected_signature
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Postmark.html b/src/7.0/classes/ActionMailbox/Ingresses/Postmark.html new file mode 100644 index 0000000000..ac20e82054 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Postmark.html @@ -0,0 +1,67 @@ +--- +title: ActionMailbox::Ingresses::Postmark +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Postmark/InboundEmailsController.html b/src/7.0/classes/ActionMailbox/Ingresses/Postmark/InboundEmailsController.html new file mode 100644 index 0000000000..0651e7465c --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Postmark/InboundEmailsController.html @@ -0,0 +1,164 @@ +--- +title: ActionMailbox::Ingresses::Postmark::InboundEmailsController +layout: default +--- +
+ +
+
+ +
+ +

Ingests inbound emails from Postmark. Requires a RawEmail parameter containing a full RFC 822 message.

+ +

Authenticates requests using HTTP basic access authentication. The username is always actionmailbox, and the password is read from the application’s encrypted credentials or an environment variable. See the Usage section below.

+ +

Note that basic authentication is insecure over unencrypted HTTP. An attacker that intercepts cleartext requests to the Postmark ingress can learn its password. You should only use the Postmark ingress over HTTPS.

+ +

Returns:

+
  • +

    204 No Content if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox

    +
  • +

    401 Unauthorized if the request’s signature could not be validated

    +
  • +

    404 Not Found if Action Mailbox is not configured to accept inbound emails from Postmark

    +
  • +

    422 Unprocessable Entity if the request is missing the required RawEmail parameter

    +
  • +

    500 Server Error if the ingress password is not configured, or if one of the Active Record database, the Active Storage service, or the Active Job backend is misconfigured or unavailable

    +
+ +

Usage

+
  1. +

    Tell Action Mailbox to accept emails from Postmark:

    + +
    # config/environments/production.rb
    +config.action_mailbox.ingress = :postmark
    +
    +
  2. +

    Generate a strong password that Action Mailbox can use to authenticate requests to the Postmark ingress.

    + +

    Use bin/rails credentials:edit to add the password to your application’s encrypted credentials under action_mailbox.ingress_password, where Action Mailbox will automatically find it:

    + +
    action_mailbox:
    +  ingress_password: ...
    +
    + +

    Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

    +
  3. +

    Configure Postmark to forward inbound emails to /rails/action_mailbox/postmark/inbound_emails with the username actionmailbox and the password you previously generated. If your application lived at https://example.com, you would configure your Postmark inbound webhook with the following fully-qualified URL:

    + +
    https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/postmark/inbound_emails
    +
    + +

    NOTE: When configuring your Postmark inbound webhook, be sure to check the box labeled *“Include raw email content in JSON payload”*. Action Mailbox needs the raw email content to work.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller.rb, line 50
+    def create
+      ActionMailbox::InboundEmail.create_and_extract_message_id! params.require("RawEmail")
+    rescue ActionController::ParameterMissing => error
+      logger.error <<~MESSAGE
+        #{error.message}
+
+        When configuring your Postmark inbound webhook, be sure to check the box
+        labeled "Include raw email content in JSON payload".
+      MESSAGE
+      head :unprocessable_entity
+    end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Relay.html b/src/7.0/classes/ActionMailbox/Ingresses/Relay.html new file mode 100644 index 0000000000..ae6e19d88c --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Relay.html @@ -0,0 +1,67 @@ +--- +title: ActionMailbox::Ingresses::Relay +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Relay/InboundEmailsController.html b/src/7.0/classes/ActionMailbox/Ingresses/Relay/InboundEmailsController.html new file mode 100644 index 0000000000..267ba421d1 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Relay/InboundEmailsController.html @@ -0,0 +1,165 @@ +--- +title: ActionMailbox::Ingresses::Relay::InboundEmailsController +layout: default +--- +
+ +
+
+ +
+ +

Ingests inbound emails relayed from an SMTP server.

+ +

Authenticates requests using HTTP basic access authentication. The username is always actionmailbox, and the password is read from the application’s encrypted credentials or an environment variable. See the Usage section below.

+ +

Note that basic authentication is insecure over unencrypted HTTP. An attacker that intercepts cleartext requests to the ingress can learn its password. You should only use this ingress over HTTPS.

+ +

Returns:

+
  • +

    204 No Content if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox

    +
  • +

    401 Unauthorized if the request could not be authenticated

    +
  • +

    404 Not Found if Action Mailbox is not configured to accept inbound emails relayed from an SMTP server

    +
  • +

    415 Unsupported Media Type if the request does not contain an RFC 822 message

    +
  • +

    500 Server Error if the ingress password is not configured, or if one of the Active Record database, the Active Storage service, or the Active Job backend is misconfigured or unavailable

    +
+ +

Usage

+
  1. +

    Tell Action Mailbox to accept emails from an SMTP relay:

    + +
    # config/environments/production.rb
    +config.action_mailbox.ingress = :relay
    +
    +
  2. +

    Generate a strong password that Action Mailbox can use to authenticate requests to the ingress.

    + +

    Use bin/rails credentials:edit to add the password to your application’s encrypted credentials under action_mailbox.ingress_password, where Action Mailbox will automatically find it:

    + +
    action_mailbox:
    +  ingress_password: ...
    +
    + +

    Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

    +
  3. +

    Configure your SMTP server to pipe inbound emails to the appropriate ingress command, providing the URL of the relay ingress and the INGRESS_PASSWORD you previously generated.

    + +

    If your application lives at https://example.com, you would configure the Postfix SMTP server to pipe inbound emails to the following command:

    + +
    bin/rails action_mailbox:ingress:postfix URL=https://example.com/rails/action_mailbox/postfix/inbound_emails INGRESS_PASSWORD=...
    +
    + +

    Built-in ingress commands are available for these popular SMTP servers:

    +
    • +

      Exim (<tt>bin/rails action_mailbox:ingress:exim)

      +
    • +

      Postfix (<tt>bin/rails action_mailbox:ingress:postfix)

      +
    • +

      Qmail (<tt>bin/rails action_mailbox:ingress:qmail)

      +
    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/relay/inbound_emails_controller.rb, line 54
+def create
+  ActionMailbox::InboundEmail.create_and_extract_message_id! request.body.read
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid.html b/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid.html new file mode 100644 index 0000000000..f91117f20c --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid.html @@ -0,0 +1,67 @@ +--- +title: ActionMailbox::Ingresses::Sendgrid +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid/InboundEmailsController.html b/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid/InboundEmailsController.html new file mode 100644 index 0000000000..20268c2a75 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Ingresses/Sendgrid/InboundEmailsController.html @@ -0,0 +1,159 @@ +--- +title: ActionMailbox::Ingresses::Sendgrid::InboundEmailsController +layout: default +--- +
+ +
+
+ +
+ +

Ingests inbound emails from SendGrid. Requires an email parameter containing a full RFC 822 message.

+ +

Authenticates requests using HTTP basic access authentication. The username is always actionmailbox, and the password is read from the application’s encrypted credentials or an environment variable. See the Usage section below.

+ +

Note that basic authentication is insecure over unencrypted HTTP. An attacker that intercepts cleartext requests to the SendGrid ingress can learn its password. You should only use the SendGrid ingress over HTTPS.

+ +

Returns:

+
  • +

    204 No Content if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox

    +
  • +

    401 Unauthorized if the request’s signature could not be validated

    +
  • +

    404 Not Found if Action Mailbox is not configured to accept inbound emails from SendGrid

    +
  • +

    422 Unprocessable Entity if the request is missing the required email parameter

    +
  • +

    500 Server Error if the ingress password is not configured, or if one of the Active Record database, the Active Storage service, or the Active Job backend is misconfigured or unavailable

    +
+ +

Usage

+
  1. +

    Tell Action Mailbox to accept emails from SendGrid:

    + +
    # config/environments/production.rb
    +config.action_mailbox.ingress = :sendgrid
    +
    +
  2. +

    Generate a strong password that Action Mailbox can use to authenticate requests to the SendGrid ingress.

    + +

    Use bin/rails credentials:edit to add the password to your application’s encrypted credentials under action_mailbox.ingress_password, where Action Mailbox will automatically find it:

    + +
    action_mailbox:
    +  ingress_password: ...
    +
    + +

    Alternatively, provide the password in the RAILS_INBOUND_EMAIL_PASSWORD environment variable.

    +
  3. +

    Configure SendGrid Inbound Parse to forward inbound emails to /rails/action_mailbox/sendgrid/inbound_emails with the username actionmailbox and the password you previously generated. If your application lived at https://example.com, you would configure SendGrid with the following fully-qualified URL:

    + +
    https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/sendgrid/inbound_emails
    +
    + +

    NOTE: When configuring your SendGrid Inbound Parse webhook, be sure to check the box labeled *“Post the raw, full MIME message.”* Action Mailbox needs the raw MIME message to work.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/action_mailbox/ingresses/sendgrid/inbound_emails_controller.rb, line 50
+def create
+  ActionMailbox::InboundEmail.create_and_extract_message_id! mail
+rescue JSON::ParserError => error
+  logger.error error.message
+  head :unprocessable_entity
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Relayer.html b/src/7.0/classes/ActionMailbox/Relayer.html new file mode 100644 index 0000000000..ba8bd16c6a --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Relayer.html @@ -0,0 +1,235 @@ +--- +title: ActionMailbox::Relayer +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_TYPE="message/rfc822"
 
USER_AGENT="Action Mailbox relayer v#{ActionMailbox.version}"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + password
+ [R] + uri
+ [R] + username
+ + + + +

Class Public methods

+ +
+

+ + new(url:, username: "actionmailbox", password:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 32
+def initialize(url:, username: "actionmailbox", password:)
+  @uri, @username, @password = URI(url), username, password
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + relay(source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 36
+def relay(source)
+  case response = post(source)
+  when Net::HTTPSuccess
+    Result.new "2.0.0", "Successfully relayed message to ingress"
+  when Net::HTTPUnauthorized
+    Result.new "4.7.0", "Invalid credentials for ingress"
+  else
+    Result.new "4.0.0", "HTTP #{response.code}"
+  end
+rescue IOError, SocketError, SystemCallError => error
+  Result.new "4.4.2", "Network error relaying to ingress: #{error.message}"
+rescue Timeout::Error
+  Result.new "4.4.2", "Timed out relaying to ingress"
+rescue => error
+  Result.new "4.0.0", "Error relaying to ingress: #{error.message}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Relayer/Result.html b/src/7.0/classes/ActionMailbox/Relayer/Result.html new file mode 100644 index 0000000000..a88af4c3c5 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Relayer/Result.html @@ -0,0 +1,224 @@ +--- +title: ActionMailbox::Relayer::Result +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + failure?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 14
+def failure?
+  transient_failure? || permanent_failure?
+end
+
+
+ +
+ +
+

+ + permanent_failure?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 22
+def permanent_failure?
+  status_code.start_with?("5.")
+end
+
+
+ +
+ +
+

+ + success?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 10
+def success?
+  !failure?
+end
+
+
+ +
+ +
+

+ + transient_failure?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/relayer.rb, line 18
+def transient_failure?
+  status_code.start_with?("4.")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Router.html b/src/7.0/classes/ActionMailbox/Router.html new file mode 100644 index 0000000000..0d85125025 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Router.html @@ -0,0 +1,297 @@ +--- +title: ActionMailbox::Router +layout: default +--- +
+ +
+
+ +
+ +

Encapsulates the routes that live on the ApplicationMailbox and performs the actual routing when an inbound_email is received.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router.rb, line 9
+def initialize
+  @routes = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_route(address, to:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router.rb, line 19
+def add_route(address, to:)
+  routes.append Route.new(address, to: to)
+end
+
+
+ +
+ +
+

+ + add_routes(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router.rb, line 13
+def add_routes(routes)
+  routes.each do |(address, mailbox_name)|
+    add_route address, to: mailbox_name
+  end
+end
+
+
+ +
+ +
+

+ + mailbox_for(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router.rb, line 33
+def mailbox_for(inbound_email)
+  routes.detect { |route| route.match?(inbound_email) }&.mailbox_class
+end
+
+
+ +
+ +
+

+ + route(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router.rb, line 23
+def route(inbound_email)
+  if mailbox = mailbox_for(inbound_email)
+    mailbox.receive(inbound_email)
+  else
+    inbound_email.bounced!
+
+    raise RoutingError
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Router/Route.html b/src/7.0/classes/ActionMailbox/Router/Route.html new file mode 100644 index 0000000000..59b305b3fd --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Router/Route.html @@ -0,0 +1,229 @@ +--- +title: ActionMailbox::Router::Route +layout: default +--- +
+ +
+
+ +
+ +

Encapsulates a route, which can then be matched against an inbound_email and provide a lookup of the matching mailbox class. See examples for the different route addresses and how to use them in the ActionMailbox::Base documentation.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + address
+ [R] + mailbox_name
+ + + + +

Class Public methods

+ +
+

+ + new(address, to:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router/route.rb, line 10
+def initialize(address, to:)
+  @address, @mailbox_name = address, to
+
+  ensure_valid_address
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + mailbox_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router/route.rb, line 31
+def mailbox_class
+  "#{mailbox_name.to_s.camelize}Mailbox".constantize
+end
+
+
+ +
+ +
+

+ + match?(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/router/route.rb, line 16
+def match?(inbound_email)
+  case address
+  when :all
+    true
+  when String
+    inbound_email.mail.recipients.any? { |recipient| address.casecmp?(recipient) }
+  when Regexp
+    inbound_email.mail.recipients.any? { |recipient| address.match?(recipient) }
+  when Proc
+    address.call(inbound_email)
+  else
+    address.match?(inbound_email)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Router/RoutingError.html b/src/7.0/classes/ActionMailbox/Router/RoutingError.html new file mode 100644 index 0000000000..66524e83e5 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Router/RoutingError.html @@ -0,0 +1,60 @@ +--- +title: ActionMailbox::Router::RoutingError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/Routing.html b/src/7.0/classes/ActionMailbox/Routing.html new file mode 100644 index 0000000000..dec36b1992 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/Routing.html @@ -0,0 +1,185 @@ +--- +title: ActionMailbox::Routing +layout: default +--- +
+ +
+
+ +
+ +

See ActionMailbox::Base for how to specify routing.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + mailbox_for(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/routing.rb, line 21
+def mailbox_for(inbound_email)
+  router.mailbox_for(inbound_email)
+end
+
+
+ +
+ +
+

+ + route(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/routing.rb, line 17
+def route(inbound_email)
+  router.route(inbound_email)
+end
+
+
+ +
+ +
+

+ + routing(routes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/routing.rb, line 13
+def routing(routes)
+  router.add_routes(routes)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/RoutingJob.html b/src/7.0/classes/ActionMailbox/RoutingJob.html new file mode 100644 index 0000000000..2ae9d92339 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/RoutingJob.html @@ -0,0 +1,113 @@ +--- +title: ActionMailbox::RoutingJob +layout: default +--- +
+ +
+
+ +
+ +

Routing a new InboundEmail is an asynchronous operation, which allows the ingress controllers to quickly accept new incoming emails without being burdened to hang while they’re actually being processed.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform(inbound_email) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/jobs/action_mailbox/routing_job.rb, line 9
+def perform(inbound_email)
+  inbound_email.route
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/TestCase.html b/src/7.0/classes/ActionMailbox/TestCase.html new file mode 100644 index 0000000000..b293891eb4 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/TestCase.html @@ -0,0 +1,74 @@ +--- +title: ActionMailbox::TestCase +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/TestHelper.html b/src/7.0/classes/ActionMailbox/TestHelper.html new file mode 100644 index 0000000000..da48508389 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/TestHelper.html @@ -0,0 +1,348 @@ +--- +title: ActionMailbox::TestHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create_inbound_email_from_fixture(fixture_name, status: :processing) + +

+ + +
+

Create an InboundEmail record using an eml fixture in the format of message/rfc822 referenced with fixture_name located in test/fixtures/files/fixture_name.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 9
+def create_inbound_email_from_fixture(fixture_name, status: :processing)
+  create_inbound_email_from_source file_fixture(fixture_name).read, status: status
+end
+
+
+ +
+ +
+

+ + create_inbound_email_from_mail(status: :processing, **mail_options, &block) + +

+ + +
+

Creates an InboundEmail by specifying through options or a block.

+ +

Options

+
  • +

    :status - The status to set for the created InboundEmail. For possible statuses, see its documentation.

    +
+ +

Creating a simple email

+ +

When you only need to set basic fields like from, to, subject, and body, you can pass them directly as options.

+ +
create_inbound_email_from_mail(from: "david@loudthinking.com", subject: "Hello!")
+
+ +

Creating a multi-part email

+ +

When you need to create a more intricate email, like a multi-part email that contains both a plaintext version and an HTML version, you can pass a block.

+ +
create_inbound_email_from_mail do
+  to "David Heinemeier Hansson <david@loudthinking.com>"
+  from "Bilbo Baggins <bilbo@bagend.com>"
+  subject "Come down to the Shire!"
+
+  text_part do
+    body "Please join us for a party at Bag End"
+  end
+
+  html_part do
+    body "<h1>Please join us for a party at Bag End</h1>"
+  end
+end
+
+ +

As with Mail.new, you can also use a block parameter to define the parts of the message:

+ +
create_inbound_email_from_mail do |mail|
+  mail.to "David Heinemeier Hansson <david@loudthinking.com>"
+  mail.from "Bilbo Baggins <bilbo@bagend.com>"
+  mail.subject "Come down to the Shire!"
+
+  mail.text_part do |part|
+    part.body "Please join us for a party at Bag End"
+  end
+
+  mail.html_part do |part|
+    part.body "<h1>Please join us for a party at Bag End</h1>"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 63
+def create_inbound_email_from_mail(status: :processing, **mail_options, &block)
+  mail = Mail.new(mail_options, &block)
+  # Bcc header is not encoded by default
+  mail[:bcc].include_in_headers = true if mail[:bcc]
+
+  create_inbound_email_from_source mail.to_s, status: status
+end
+
+
+ +
+ +
+

+ + create_inbound_email_from_source(source, status: :processing) + +

+ + +
+

Create an InboundEmail using the raw rfc822 source as text.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 72
+def create_inbound_email_from_source(source, status: :processing)
+  ActionMailbox::InboundEmail.create_and_extract_message_id! source, status: status
+end
+
+
+ +
+ +
+

+ + receive_inbound_email_from_fixture(*args) + +

+ + +
+

Create an InboundEmail from fixture using the same arguments as create_inbound_email_from_fixture and immediately route it to processing.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 79
+def receive_inbound_email_from_fixture(*args)
+  create_inbound_email_from_fixture(*args).tap(&:route)
+end
+
+
+ +
+ +
+

+ + receive_inbound_email_from_mail(**kwargs, &block) + +

+ + +
+

Create an InboundEmail using the same options or block as create_inbound_email_from_mail, then immediately route it for processing.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 85
+def receive_inbound_email_from_mail(**kwargs, &block)
+  create_inbound_email_from_mail(**kwargs, &block).tap(&:route)
+end
+
+
+ +
+ +
+

+ + receive_inbound_email_from_source(*args) + +

+ + +
+

Create an InboundEmail using the same arguments as create_inbound_email_from_source and immediately route it to processing.

+
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/test_helper.rb, line 91
+def receive_inbound_email_from_source(*args)
+  create_inbound_email_from_source(*args).tap(&:route)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailbox/VERSION.html b/src/7.0/classes/ActionMailbox/VERSION.html new file mode 100644 index 0000000000..20caf828a8 --- /dev/null +++ b/src/7.0/classes/ActionMailbox/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActionMailbox::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer.html b/src/7.0/classes/ActionMailer.html new file mode 100644 index 0000000000..c697de11dc --- /dev/null +++ b/src/7.0/classes/ActionMailer.html @@ -0,0 +1,220 @@ +--- +title: ActionMailer +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Action Mailer as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Action Mailer as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/version.rb, line 8
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Base.html b/src/7.0/classes/ActionMailer/Base.html new file mode 100644 index 0000000000..8da6a2063e --- /dev/null +++ b/src/7.0/classes/ActionMailer/Base.html @@ -0,0 +1,1695 @@ +--- +title: ActionMailer::Base +layout: default +--- +
+ +
+
+ +
+ +

Action Mailer allows you to send email from your application using a mailer model and views.

+ +

Mailer Models

+ +

To use Action Mailer, you need to create a mailer model.

+ +
$ bin/rails generate mailer Notifier
+
+ +

The generated model inherits from ApplicationMailer which in turn inherits from ActionMailer::Base. A mailer model defines methods used to generate an email message. In these methods, you can set up variables to be used in the mailer views, options on the mail itself such as the :from address, and attachments.

+ +
class ApplicationMailer < ActionMailer::Base
+  default from: 'from@example.com'
+  layout 'mailer'
+end
+
+class NotifierMailer < ApplicationMailer
+  default from: 'no-reply@example.com',
+          return_path: 'system@example.com'
+
+  def welcome(recipient)
+    @account = recipient
+    mail(to: recipient.email_address_with_name,
+         bcc: ["bcc@example.com", "Order Watcher <watcher@example.com>"])
+  end
+end
+
+ +

Within the mailer method, you have access to the following methods:

+
  • +

    attachments[]= - Allows you to add attachments to your email in an intuitive manner; attachments['filename.png'] = File.read('path/to/filename.png')

    +
  • +

    attachments.inline[]= - Allows you to add an inline attachment to your email in the same manner as attachments[]=

    +
  • +

    headers[]= - Allows you to specify any header field in your email such as headers['X-No-Spam'] = 'True'. Note that declaring a header multiple times will add many fields of the same name. Read headers doc for more information.

    +
  • +

    headers(hash) - Allows you to specify multiple headers in your email such as headers({'X-No-Spam' => 'True', 'In-Reply-To' => '1234@message.id'})

    +
  • +

    mail - Allows you to specify email to be sent.

    +
+ +

The hash passed to the mail method allows you to specify any header that a Mail::Message will accept (any valid email header including optional fields).

+ +

The mail method, if not passed a block, will inspect your views and send all the views with the same name as the method, so the above action would send the welcome.text.erb view file as well as the welcome.html.erb view file in a multipart/alternative email.

+ +

If you want to explicitly render only certain templates, pass a block:

+ +
mail(to: user.email) do |format|
+  format.text
+  format.html
+end
+
+ +

The block syntax is also useful in providing information specific to a part:

+ +
mail(to: user.email) do |format|
+  format.text(content_transfer_encoding: "base64")
+  format.html
+end
+
+ +

Or even to render a special view:

+ +
mail(to: user.email) do |format|
+  format.text
+  format.html { render "some_other_template" }
+end
+
+ +

Mailer views

+ +

Like Action Controller, each mailer class has a corresponding view directory in which each method of the class looks for a template with its name.

+ +

To define a template to be used with a mailer, create an .erb file with the same name as the method in your mailer model. For example, in the mailer defined above, the template at app/views/notifier_mailer/welcome.text.erb would be used to generate the email.

+ +

Variables defined in the methods of your mailer model are accessible as instance variables in their corresponding view.

+ +

Emails by default are sent in plain text, so a sample view for our model example might look like this:

+ +
Hi <%= @account.name %>,
+Thanks for joining our service! Please check back often.
+
+ +

You can even use Action View helpers in these views. For example:

+ +
You got a new note!
+<%= truncate(@note.body, length: 25) %>
+
+ +

If you need to access the subject, from, or the recipients in the view, you can do that through message object:

+ +
You got a new note from <%= message.from %>!
+<%= truncate(@note.body, length: 25) %>
+
+ +

Generating URLs

+ +

URLs can be generated in mailer views using url_for or named routes. Unlike controllers from Action Pack, the mailer instance doesn’t have any context about the incoming request, so you’ll need to provide all of the details needed to generate a URL.

+ +

When using url_for you’ll need to provide the :host, :controller, and :action:

+ +
<%= url_for(host: "example.com", controller: "welcome", action: "greeting") %>
+
+ +

When using named routes you only need to supply the :host:

+ +
<%= users_url(host: "example.com") %>
+
+ +

You should use the named_route_url style (which generates absolute URLs) and avoid using the named_route_path style (which generates relative URLs), since clients reading the mail will have no concept of a current URL from which to determine a relative path.

+ +

It is also possible to set a default host that will be used in all mailers by setting the :host option as a configuration option in config/application.rb:

+ +
config.action_mailer.default_url_options = { host: "example.com" }
+
+ +

You can also define a default_url_options method on individual mailers to override these default settings per-mailer.

+ +

By default when config.force_ssl is true, URLs generated for hosts will use the HTTPS protocol.

+ +

Sending mail

+ +

Once a mailer action and template are defined, you can deliver your message or defer its creation and delivery for later:

+ +
NotifierMailer.welcome(User.first).deliver_now # sends the email
+mail = NotifierMailer.welcome(User.first)      # => an ActionMailer::MessageDelivery object
+mail.deliver_now                               # generates and sends the email now
+
+ +

The ActionMailer::MessageDelivery class is a wrapper around a delegate that will call your method to generate the mail. If you want direct access to the delegator, or Mail::Message, you can call the message method on the ActionMailer::MessageDelivery object.

+ +
NotifierMailer.welcome(User.first).message     # => a Mail::Message object
+
+ +

Action Mailer is nicely integrated with Active Job so you can generate and send emails in the background (example: outside of the request-response cycle, so the user doesn’t have to wait on it):

+ +
NotifierMailer.welcome(User.first).deliver_later # enqueue the email sending to Active Job
+
+ +

Note that deliver_later will execute your method from the background job.

+ +

You never instantiate your mailer class. Rather, you just call the method you defined on the class itself. All instance methods are expected to return a message object to be sent.

+ +

Multipart Emails

+ +

Multipart messages can also be used implicitly because Action Mailer will automatically detect and use multipart templates, where each template is named after the name of the action, followed by the content type. Each such detected template will be added to the message, as a separate part.

+ +

For example, if the following templates exist:

+
  • +

    signup_notification.text.erb

    +
  • +

    signup_notification.html.erb

    +
  • +

    signup_notification.xml.builder

    +
  • +

    signup_notification.yml.erb

    +
+ +

Each would be rendered and added as a separate part to the message, with the corresponding content type. The content type for the entire message is automatically set to multipart/alternative, which indicates that the email contains multiple different representations of the same email body. The same instance variables defined in the action are passed to all email templates.

+ +

Implicit template rendering is not performed if any attachments or parts have been added to the email. This means that you’ll have to manually add each part to the email and set the content type of the email to multipart/alternative.

+ +

Attachments

+ +

Sending attachment in emails is easy:

+ +
class NotifierMailer < ApplicationMailer
+  def welcome(recipient)
+    attachments['free_book.pdf'] = File.read('path/to/file.pdf')
+    mail(to: recipient, subject: "New account information")
+  end
+end
+
+ +

Which will (if it had both a welcome.text.erb and welcome.html.erb template in the view directory), send a complete multipart/mixed email with two parts, the first part being a multipart/alternative with the text and HTML email parts inside, and the second being a application/pdf with a Base64 encoded copy of the file.pdf book with the filename free_book.pdf.

+ +

If you need to send attachments with no content, you need to create an empty view for it, or add an empty body parameter like this:

+ +
class NotifierMailer < ApplicationMailer
+  def welcome(recipient)
+    attachments['free_book.pdf'] = File.read('path/to/file.pdf')
+    mail(to: recipient, subject: "New account information", body: "")
+  end
+end
+
+ +

You can also send attachments with html template, in this case you need to add body, attachments, and custom content type like this:

+ +
class NotifierMailer < ApplicationMailer
+  def welcome(recipient)
+    attachments["free_book.pdf"] = File.read("path/to/file.pdf")
+    mail(to: recipient,
+         subject: "New account information",
+         content_type: "text/html",
+         body: "<html><body>Hello there</body></html>")
+  end
+end
+
+ +

Inline Attachments

+ +

You can also specify that a file should be displayed inline with other HTML. This is useful if you want to display a corporate logo or a photo.

+ +
class NotifierMailer < ApplicationMailer
+  def welcome(recipient)
+    attachments.inline['photo.png'] = File.read('path/to/photo.png')
+    mail(to: recipient, subject: "Here is what we look like")
+  end
+end
+
+ +

And then to reference the image in the view, you create a welcome.html.erb file and make a call to image_tag passing in the attachment you want to display and then call url on the attachment to get the relative content id path for the image source:

+ +
<h1>Please Don't Cringe</h1>
+
+<%= image_tag attachments['photo.png'].url -%>
+
+ +

As we are using Action View’s image_tag method, you can pass in any other options you want:

+ +
<h1>Please Don't Cringe</h1>
+
+<%= image_tag attachments['photo.png'].url, alt: 'Our Photo', class: 'photo' -%>
+
+ +

Observing and Intercepting Mails

+ +

Action Mailer provides hooks into the Mail observer and interceptor methods. These allow you to register classes that are called during the mail delivery life cycle.

+ +

An observer class must implement the :delivered_email(message) method which will be called once for every email sent after the email has been sent.

+ +

An interceptor class must implement the :delivering_email(message) method which will be called before the email is sent, allowing you to make modifications to the email before it hits the delivery agents. Your class should make any needed modifications directly to the passed in Mail::Message instance.

+ +

Default Hash

+ +

Action Mailer provides some intelligent defaults for your emails, these are usually specified in a default method inside the class definition:

+ +
class NotifierMailer < ApplicationMailer
+  default sender: 'system@example.com'
+end
+
+ +

You can pass in any header value that a Mail::Message accepts. Out of the box, ActionMailer::Base sets the following:

+
  • +

    mime_version: "1.0"

    +
  • +

    charset: "UTF-8"

    +
  • +

    content_type: "text/plain"

    +
  • +

    parts_order: [ "text/plain", "text/enriched", "text/html" ]

    +
+ +

parts_order and charset are not actually valid Mail::Message header fields, but Action Mailer translates them appropriately and sets the correct values.

+ +

As you can pass in any header, you need to either quote the header as a string, or pass it in as an underscored symbol, so the following will work:

+ +
class NotifierMailer < ApplicationMailer
+  default 'Content-Transfer-Encoding' => '7bit',
+          content_description: 'This is a description'
+end
+
+ +

Finally, Action Mailer also supports passing Proc and Lambda objects into the default hash, so you can define methods that evaluate as the message is being generated:

+ +
class NotifierMailer < ApplicationMailer
+  default 'X-Special-Header' => Proc.new { my_method }, to: -> { @inviter.email_address }
+
+  private
+    def my_method
+      'some complex call'
+    end
+end
+
+ +

Note that the proc/lambda is evaluated right at the start of the mail message generation, so if you set something in the default hash using a proc, and then set the same thing inside of your mailer method, it will get overwritten by the mailer method.

+ +

It is also possible to set these default options that will be used in all mailers through the default_options= configuration in config/application.rb:

+ +
config.action_mailer.default_options = { from: "no-reply@example.org" }
+
+ +

Callbacks

+ +

You can specify callbacks using before_action and after_action for configuring your messages. This may be useful, for example, when you want to add default inline attachments for all messages sent out by a certain mailer class:

+ +
class NotifierMailer < ApplicationMailer
+  before_action :add_inline_attachment!
+
+  def welcome
+    mail
+  end
+
+  private
+    def add_inline_attachment!
+      attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
+    end
+end
+
+ +

Callbacks in Action Mailer are implemented using AbstractController::Callbacks, so you can define and configure callbacks in the same manner that you would use callbacks in classes that inherit from ActionController::Base.

+ +

Note that unless you have a specific reason to do so, you should prefer using before_action rather than after_action in your Action Mailer classes so that headers are parsed properly.

+ +

Rescuing Errors

+ +

rescue blocks inside of a mailer method cannot rescue errors that occur outside of rendering – for example, record deserialization errors in a background job, or errors from a third-party mail delivery service.

+ +

To rescue errors that occur during any part of the mailing process, use rescue_from:

+ +
class NotifierMailer < ApplicationMailer
+  rescue_from ActiveJob::DeserializationError do
+    # ...
+  end
+
+  rescue_from "SomeThirdPartyService::ApiError" do
+    # ...
+  end
+
+  def notify(recipient)
+    mail(to: recipient, subject: "Notification")
+  end
+end
+
+ +

Previewing emails

+ +

You can preview your email templates visually by adding a mailer preview file to the ActionMailer::Base.preview_path. Since most emails do something interesting with database data, you’ll need to write some scenarios to load messages with fake data:

+ +
class NotifierMailerPreview < ActionMailer::Preview
+  def welcome
+    NotifierMailer.welcome(User.first)
+  end
+end
+
+ +

Methods must return a Mail::Message object which can be generated by calling the mailer method without the additional deliver_now / deliver_later. The location of the mailer previews directory can be configured using the preview_path option which has a default of test/mailers/previews:

+ +
config.action_mailer.preview_path = "#{Rails.root}/lib/mailer_previews"
+
+ +

An overview of all previews is accessible at http://localhost:3000/rails/mailers on a running development server instance.

+ +

Previews can also be intercepted in a similar manner as deliveries can be by registering a preview interceptor that has a previewing_email method:

+ +
class CssInlineStyler
+  def self.previewing_email(message)
+    # inline CSS styles
+  end
+end
+
+config.action_mailer.preview_interceptors :css_inline_styler
+
+ +

Note that interceptors need to be registered both with register_interceptor and register_preview_interceptor if they should operate on both sending and previewing emails.

+ +

Configuration options

+ +

These options are specified on the class level, like ActionMailer::Base.raise_delivery_errors = true

+
  • +

    default_options - You can pass this in at a class level as well as within the class itself as per the above section.

    +
  • +

    logger - the logger is used for generating information on the mailing run if available. Can be set to nil for no logging. Compatible with both Ruby’s own Logger and Log4r loggers.

    +
  • +

    smtp_settings - Allows detailed configuration for :smtp delivery method:

    +
    • +

      :address - Allows you to use a remote mail server. Just change it from its default “localhost” setting.

      +
    • +

      :port - On the off chance that your mail server doesn’t run on port 25, you can change it.

      +
    • +

      :domain - If you need to specify a HELO domain, you can do it here.

      +
    • +

      :user_name - If your mail server requires authentication, set the username in this setting.

      +
    • +

      :password - If your mail server requires authentication, set the password in this setting.

      +
    • +

      :authentication - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of :plain (will send the password Base64 encoded), :login (will send the password Base64 encoded) or :cram_md5 (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)

      +
    • +

      :enable_starttls - Use STARTTLS when connecting to your SMTP server and fail if unsupported. Defaults to false.

      +
    • +

      :enable_starttls_auto - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to true.

      +
    • +

      :openssl_verify_mode - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none' or 'peer') or directly the constant (OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER).

      +
    • +

      :ssl/:tls Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection)

      +
    • +

      :open_timeout Number of seconds to wait while attempting to open a connection.

      +
    • +

      :read_timeout Number of seconds to wait until timing-out a read(2) call.

      +
    +
  • +

    sendmail_settings - Allows you to override options for the :sendmail delivery method.

    +
    • +

      :location - The location of the sendmail executable. Defaults to /usr/sbin/sendmail.

      +
    • +

      :arguments - The command line arguments. Defaults to -i with -f sender@address added automatically before the message is sent.

      +
    +
  • +

    file_settings - Allows you to override options for the :file delivery method.

    +
    • +

      :location - The directory into which emails will be written. Defaults to the application tmp/mails.

      +
    +
  • +

    raise_delivery_errors - Whether or not errors should be raised if the email fails to be delivered.

    +
  • +

    delivery_method - Defines a delivery method. Possible values are :smtp (default), :sendmail, :test, and :file. Or you may provide a custom delivery method object e.g. MyOwnDeliveryMethodClass. See the Mail gem documentation on the interface you need to implement for a custom delivery agent.

    +
  • +

    perform_deliveries - Determines whether emails are actually sent from Action Mailer when you call .deliver on an email message or on an Action Mailer method. This is on by default but can be turned off to aid in functional testing.

    +
  • +

    deliveries - Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful for unit and functional testing.

    +
  • +

    delivery_job - The job class used with deliver_later. Defaults to ActionMailer::MailDeliveryJob.

    +
  • +

    deliver_later_queue_name - The name of the queue used with deliver_later.

    +
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PROTECTED_IVARS=AbstractController::Rendering::DEFAULT_PROTECTED_INSTANCE_VARIABLES + [:@_action_has_layout]
 
+ + + + +

Attributes

+ + + + + + + + +
+ [W] + mailer_name

Allows to set the name of current mailer.

+ + + + +

Class Public methods

+ +
+

+ + controller_path() + +

+ + +
+ +
+ + + + + +
+ Alias for: mailer_name +
+ + + +
+ +
+

+ + default(value = nil) + +

+ + +
+

Sets the defaults through app configuration:

+ +
config.action_mailer.default(from: "no-reply@example.org")
+
+ +

Aliased by ::default_options=

+
+ + + +
+ Also aliased as: default_options= +
+ + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 570
+def default(value = nil)
+  self.default_params = default_params.merge(value).freeze if value
+  default_params
+end
+
+
+ +
+ +
+

+ + default_options=(value = nil) + +

+ + +
+

Allows to set defaults through app configuration:

+ +
config.action_mailer.default_options = { from: "no-reply@example.org" }
+
+
+ + + + + +
+ Alias for: default +
+ + + +
+ +
+

+ + email_address_with_name(address, name) + +

+ + +
+

Returns an email in the format “Name <email@example.com>”.

+ +

If the name is a blank string, it returns just the address.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 595
+def email_address_with_name(address, name)
+  Mail::Address.new.tap do |builder|
+    builder.address = address
+    builder.display_name = name.presence
+  end.to_s
+end
+
+
+ +
+ +
+

+ + mailer_name() + +

+ + +
+

Returns the name of the current mailer. This method is also being used as a path for a view lookup. If this is an anonymous mailer, this method will return anonymous instead.

+
+ + + +
+ Also aliased as: controller_path +
+ + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 558
+def mailer_name
+  @mailer_name ||= anonymous? ? "anonymous" : name.underscore
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 632
+def initialize
+  super()
+  @_mail_was_called = false
+  @_message = Mail.new
+end
+
+
+ +
+ +
+

+ + register_interceptor(interceptor) + +

+ + +
+

Register an Interceptor which will be called before mail is sent. Either a class, string, or symbol can be passed in as the Interceptor. If a string or symbol is passed in it will be camelized and constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 535
+def register_interceptor(interceptor)
+  Mail.register_interceptor(observer_class_for(interceptor))
+end
+
+
+ +
+ +
+

+ + register_interceptors(*interceptors) + +

+ + +
+

Register one or more Interceptors which will be called before mail is sent.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 509
+def register_interceptors(*interceptors)
+  interceptors.flatten.compact.each { |interceptor| register_interceptor(interceptor) }
+end
+
+
+ +
+ +
+

+ + register_observer(observer) + +

+ + +
+

Register an Observer which will be notified when mail is delivered. Either a class, string, or symbol can be passed in as the Observer. If a string or symbol is passed in it will be camelized and constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 521
+def register_observer(observer)
+  Mail.register_observer(observer_class_for(observer))
+end
+
+
+ +
+ +
+

+ + register_observers(*observers) + +

+ + +
+

Register one or more Observers which will be notified when mail is delivered.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 499
+def register_observers(*observers)
+  observers.flatten.compact.each { |observer| register_observer(observer) }
+end
+
+
+ +
+ +
+

+ + unregister_interceptor(interceptor) + +

+ + +
+

Unregister a previously registered Interceptor. Either a class, string, or symbol can be passed in as the Interceptor. If a string or symbol is passed in it will be camelized and constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 542
+def unregister_interceptor(interceptor)
+  Mail.unregister_interceptor(observer_class_for(interceptor))
+end
+
+
+ +
+ +
+

+ + unregister_interceptors(*interceptors) + +

+ + +
+

Unregister one or more previously registered Interceptors.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 514
+def unregister_interceptors(*interceptors)
+  interceptors.flatten.compact.each { |interceptor| unregister_interceptor(interceptor) }
+end
+
+
+ +
+ +
+

+ + unregister_observer(observer) + +

+ + +
+

Unregister a previously registered Observer. Either a class, string, or symbol can be passed in as the Observer. If a string or symbol is passed in it will be camelized and constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 528
+def unregister_observer(observer)
+  Mail.unregister_observer(observer_class_for(observer))
+end
+
+
+ +
+ +
+

+ + unregister_observers(*observers) + +

+ + +
+

Unregister one or more previously registered Observers.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 504
+def unregister_observers(*observers)
+  observers.flatten.compact.each { |observer| unregister_observer(observer) }
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + supports_path?() + +

+ + +
+

Emails do not support relative path links.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 931
+def self.supports_path? # :doc:
+  false
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attachments() + +

+ + +
+

Allows you to add attachments to an email, like so:

+ +
mail.attachments['filename.jpg'] = File.read('/path/to/filename.jpg')
+
+ +

If you do this, then Mail will take the file name and work out the mime type. It will also set the Content-Type, Content-Disposition, and Content-Transfer-Encoding, and encode the contents of the attachment in Base64.

+ +

You can also specify overrides if you want by passing a hash instead of a string:

+ +
mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
+                                    content: File.read('/path/to/filename.jpg')}
+
+ +

If you want to use encoding other than Base64 then you will need to pass encoding type along with the pre-encoded content as Mail doesn’t know how to decode the data:

+ +
file_content = SpecialEncode(File.read('/path/to/filename.jpg'))
+mail.attachments['filename.jpg'] = {mime_type: 'application/gzip',
+                                    encoding: 'SpecialEncoding',
+                                    content: file_content }
+
+ +

You can also search for specific attachments:

+ +
# By Filename
+mail.attachments['filename.jpg']   # => Mail::Part object or nil
+
+# or by index
+mail.attachments[0]                # => Mail::Part (first attachment)
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 749
+def attachments
+  if @_mail_was_called
+    LateAttachmentsProxy.new(@_message.attachments)
+  else
+    @_message.attachments
+  end
+end
+
+
+ +
+ +
+

+ + email_address_with_name(address, name) + +

+ + +
+

Returns an email in the format “Name <email@example.com>”.

+ +

If the name is a blank string, it returns just the address.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 673
+def email_address_with_name(address, name)
+  self.class.email_address_with_name(address, name)
+end
+
+
+ +
+ +
+

+ + headers(args = nil) + +

+ + +
+

Allows you to pass random and unusual headers to the new Mail::Message object which will add them to itself.

+ +
headers['X-Special-Domain-Specific-Header'] = "SecretValue"
+
+ +

You can also pass a hash into headers of header field names and values, which will then be set on the Mail::Message object:

+ +
headers 'X-Special-Domain-Specific-Header' => "SecretValue",
+        'In-Reply-To' => incoming.message_id
+
+ +

The resulting Mail::Message will have the following in its header:

+ +
X-Special-Domain-Specific-Header: SecretValue
+
+ +

Note about replacing already defined headers:

+
  • +

    subject

    +
  • +

    sender

    +
  • +

    from

    +
  • +

    to

    +
  • +

    cc

    +
  • +

    bcc

    +
  • +

    reply-to

    +
  • +

    orig-date

    +
  • +

    message-id

    +
  • +

    references

    +
+ +

Fields can only appear once in email headers while other fields such as X-Anything can appear multiple times.

+ +

If you want to replace any header which already exists, first set it to nil in order to reset the value otherwise another field will be added for the same header.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 711
+def headers(args = nil)
+  if args
+    @_message.headers(args)
+  else
+    @_message
+  end
+end
+
+
+ +
+ +
+

+ + mail(headers = {}, &block) + +

+ + +
+

The main method that creates the message and renders the email templates. There are two ways to call this method, with a block, or without a block.

+ +

It accepts a headers hash. This hash allows you to specify the most used headers in an email message, these are:

+
  • +

    :subject - The subject of the message, if this is omitted, Action Mailer will ask the Rails I18n class for a translated :subject in the scope of [mailer_scope, action_name] or if this is missing, will translate the humanized version of the action_name

    +
  • +

    :to - Who the message is destined for, can be a string of addresses, or an array of addresses.

    +
  • +

    :from - Who the message is from

    +
  • +

    :cc - Who you would like to Carbon-Copy on this email, can be a string of addresses, or an array of addresses.

    +
  • +

    :bcc - Who you would like to Blind-Carbon-Copy on this email, can be a string of addresses, or an array of addresses.

    +
  • +

    :reply_to - Who to set the Reply-To header of the email to.

    +
  • +

    :date - The date to say the email was sent on.

    +
+ +

You can set default values for any of the above headers (except :date) by using the ::default class method:

+ +
class Notifier < ActionMailer::Base
+  default from: 'no-reply@test.lindsaar.net',
+          bcc: 'email_logger@test.lindsaar.net',
+          reply_to: 'bounces@test.lindsaar.net'
+end
+
+ +

If you need other headers not listed above, you can either pass them in as part of the headers hash or use the headers['name'] = value method.

+ +

When a :return_path is specified as header, that value will be used as the ‘envelope from’ address for the Mail message. Setting this is useful when you want delivery notifications sent to a different address than the one in :from. Mail will actually use the :return_path in preference to the :sender in preference to the :from field for the ‘envelope from’ value.

+ +

If you do not pass a block to the mail method, it will find all templates in the view paths using by default the mailer name and the method name that it is being called from, it will then create parts for each of these templates intelligently, making educated guesses on correct content type and sequence, and return a fully prepared Mail::Message ready to call :deliver on to send.

+ +

For example:

+ +
class Notifier < ActionMailer::Base
+  default from: 'no-reply@test.lindsaar.net'
+
+  def welcome
+    mail(to: 'mikel@test.lindsaar.net')
+  end
+end
+
+ +

Will look for all templates at “app/views/notifier” with name “welcome”. If no welcome template exists, it will raise an ActionView::MissingTemplate error.

+ +

However, those can be customized:

+ +
mail(template_path: 'notifications', template_name: 'another')
+
+ +

And now it will look for all templates at “app/views/notifications” with name “another”.

+ +

If you do pass a block, you can render specific templates of your choice:

+ +
mail(to: 'mikel@test.lindsaar.net') do |format|
+  format.text
+  format.html
+end
+
+ +

You can even render plain text directly without using a template:

+ +
mail(to: 'mikel@test.lindsaar.net') do |format|
+  format.text { render plain: "Hello Mikel!" }
+  format.html { render html: "<h1>Hello Mikel!</h1>".html_safe }
+end
+
+ +

Which will render a multipart/alternative email with text/plain and text/html parts.

+ +

The block syntax also allows you to customize the part headers if desired:

+ +
mail(to: 'mikel@test.lindsaar.net') do |format|
+  format.text(content_transfer_encoding: "base64")
+  format.html
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 858
+def mail(headers = {}, &block)
+  return message if @_mail_was_called && headers.blank? && !block
+
+  # At the beginning, do not consider class default for content_type
+  content_type = headers[:content_type]
+
+  headers = apply_defaults(headers)
+
+  # Apply charset at the beginning so all fields are properly quoted
+  message.charset = charset = headers[:charset]
+
+  # Set configure delivery behavior
+  wrap_delivery_behavior!(headers[:delivery_method], headers[:delivery_method_options])
+
+  assign_headers_to_message(message, headers)
+
+  # Render the templates and blocks
+  responses = collect_responses(headers, &block)
+  @_mail_was_called = true
+
+  create_parts_from_responses(message, responses)
+  wrap_inline_attachments(message)
+
+  # Set up content type, reapply charset and handle parts order
+  message.content_type = set_content_type(message, content_type, headers[:content_type])
+  message.charset      = charset
+
+  if message.multipart?
+    message.body.set_sort_order(headers[:parts_order])
+    message.body.sort_parts!
+  end
+
+  message
+end
+
+
+ +
+ +
+

+ + mailer_name() + +

+ + +
+

Returns the name of the mailer object.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 666
+def mailer_name
+  self.class.mailer_name
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + default_i18n_subject(interpolations = {}) + +

+ + +
+

Translates the subject using Rails I18n class under [mailer_scope, action_name] scope. If it does not find a translation for the subject under the specified scope it will default to a humanized version of the action_name. If the subject has interpolations, you can pass them through the interpolations parameter.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 925
+def default_i18n_subject(interpolations = {}) # :doc:
+  mailer_scope = self.class.mailer_name.tr("/", ".")
+  I18n.t(:subject, **interpolations.merge(scope: [mailer_scope, action_name], default: action_name.humanize))
+end
+
+
+ +
+ +
+

+ + set_content_type(m, user_content_type, class_default) + +

+ + +
+

Used by mail to set the content type of the message.

+ +

It will use the given user_content_type, or multipart if the mail message has any attachments. If the attachments are inline, the content type will be “multipart/related”, otherwise “multipart/mixed”.

+ +

If there is no content type passed in via headers, and there are no attachments, or the message is multipart, then the default content type is used.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 903
+def set_content_type(m, user_content_type, class_default) # :doc:
+  params = m.content_type_parameters || {}
+  case
+  when user_content_type.present?
+    user_content_type
+  when m.has_attachments?
+    if m.attachments.all?(&:inline?)
+      ["multipart", "related", params]
+    else
+      ["multipart", "mixed", params]
+    end
+  when m.multipart?
+    ["multipart", "alternative", params]
+  else
+    m.content_type || class_default
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Base/LateAttachmentsProxy.html b/src/7.0/classes/ActionMailer/Base/LateAttachmentsProxy.html new file mode 100644 index 0000000000..5eee1dda2d --- /dev/null +++ b/src/7.0/classes/ActionMailer/Base/LateAttachmentsProxy.html @@ -0,0 +1,142 @@ +--- +title: ActionMailer::Base::LateAttachmentsProxy +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + []=(_name, _content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 759
+def []=(_name, _content); _raise_error end
+
+
+ +
+ +
+

+ + inline() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/base.rb, line 758
+def inline; self end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Collector.html b/src/7.0/classes/ActionMailer/Collector.html new file mode 100644 index 0000000000..be9f4fff9b --- /dev/null +++ b/src/7.0/classes/ActionMailer/Collector.html @@ -0,0 +1,255 @@ +--- +title: ActionMailer::Collector +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + responses
+ + + + +

Class Public methods

+ +
+

+ + new(context, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/collector.rb, line 12
+def initialize(context, &block)
+  @context = context
+  @responses = []
+  @default_render = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + all(*args, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: any +
+ + + +
+ +
+

+ + any(*args, &block) + +

+ + +
+ +
+ + + +
+ Also aliased as: all +
+ + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/collector.rb, line 18
+def any(*args, &block)
+  options = args.extract_options!
+  raise ArgumentError, "You have to supply at least one format" if args.empty?
+  args.each { |type| send(type, options.dup, &block) }
+end
+
+
+ +
+ +
+

+ + custom(mime, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/collector.rb, line 25
+def custom(mime, options = {})
+  options.reverse_merge!(content_type: mime.to_s)
+  @context.formats = [mime.to_sym]
+  options[:body] = block_given? ? yield : @default_render.call
+  @responses << options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/DeliveryMethods.html b/src/7.0/classes/ActionMailer/DeliveryMethods.html new file mode 100644 index 0000000000..d717689404 --- /dev/null +++ b/src/7.0/classes/ActionMailer/DeliveryMethods.html @@ -0,0 +1,73 @@ +--- +title: ActionMailer::DeliveryMethods +layout: default +--- +
+ +
+
+ +
+ +

This module handles everything related to mail delivery, from registering new delivery methods to configuring the mail object to be sent.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/DeliveryMethods/ClassMethods.html b/src/7.0/classes/ActionMailer/DeliveryMethods/ClassMethods.html new file mode 100644 index 0000000000..63ddefff6d --- /dev/null +++ b/src/7.0/classes/ActionMailer/DeliveryMethods/ClassMethods.html @@ -0,0 +1,114 @@ +--- +title: ActionMailer::DeliveryMethods::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Helpers for creating and wrapping delivery behavior, used by DeliveryMethods.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + add_delivery_method(symbol, klass, default_options = {}) + +

+ + +
+

Adds a new delivery method through the given class using the given symbol as alias and the default options supplied.

+ +
add_delivery_method :sendmail, Mail::Sendmail,
+  location:  '/usr/sbin/sendmail',
+  arguments: '-i'
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/delivery_methods.rb, line 50
+def add_delivery_method(symbol, klass, default_options = {})
+  class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings")
+  public_send(:"#{symbol}_settings=", default_options)
+  self.delivery_methods = delivery_methods.merge(symbol.to_sym => klass).freeze
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/InlinePreviewInterceptor.html b/src/7.0/classes/ActionMailer/InlinePreviewInterceptor.html new file mode 100644 index 0000000000..87e5d1399c --- /dev/null +++ b/src/7.0/classes/ActionMailer/InlinePreviewInterceptor.html @@ -0,0 +1,101 @@ +--- +title: ActionMailer::InlinePreviewInterceptor +layout: default +--- +
+ +
+
+ +
+ +

Implements a mailer preview interceptor that converts image tag src attributes that use inline cid: style URLs to data: style URLs so that they are visible when previewing an HTML email in a web browser.

+ +

This interceptor is enabled by default. To disable it, delete it from the ActionMailer::Base.preview_interceptors array:

+ +
ActionMailer::Base.preview_interceptors.delete(ActionMailer::InlinePreviewInterceptor)
+
+ +
+ + + + + + + + + + + + + + +

Included Modules

+
    + +
  • + + Base64 + +
  • + +
+ + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PATTERN=/src=(?:"cid:[^"]+"|'cid:[^']+')/i
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/LogSubscriber.html b/src/7.0/classes/ActionMailer/LogSubscriber.html new file mode 100644 index 0000000000..69dd7eb9a7 --- /dev/null +++ b/src/7.0/classes/ActionMailer/LogSubscriber.html @@ -0,0 +1,204 @@ +--- +title: ActionMailer::LogSubscriber +layout: default +--- +
+ +
+
+ +
+ +

Implements the ActiveSupport::LogSubscriber for logging notifications when email is delivered or received.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deliver(event) + +

+ + +
+

An email was delivered.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/log_subscriber.rb, line 10
+def deliver(event)
+  info do
+    perform_deliveries = event.payload[:perform_deliveries]
+    if perform_deliveries
+      "Delivered mail #{event.payload[:message_id]} (#{event.duration.round(1)}ms)"
+    else
+      "Skipped delivery of mail #{event.payload[:message_id]} as `perform_deliveries` is false"
+    end
+  end
+
+  debug { event.payload[:mail] }
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+

Use the logger configured for ActionMailer::Base.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/log_subscriber.rb, line 33
+def logger
+  ActionMailer::Base.logger
+end
+
+
+ +
+ +
+

+ + process(event) + +

+ + +
+

An email was generated.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/log_subscriber.rb, line 24
+def process(event)
+  debug do
+    mailer = event.payload[:mailer]
+    action = event.payload[:action]
+    "#{mailer}##{action}: processed outbound mail in #{event.duration.round(1)}ms"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/MailHelper.html b/src/7.0/classes/ActionMailer/MailHelper.html new file mode 100644 index 0000000000..51d9e9ecb9 --- /dev/null +++ b/src/7.0/classes/ActionMailer/MailHelper.html @@ -0,0 +1,301 @@ +--- +title: ActionMailer::MailHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides helper methods for ActionMailer::Base that can be used for easily formatting messages, accessing mailer or message instances, and the attachments list.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attachments() + +

+ + +
+

Access the message attachments list.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/mail_helper.rb, line 43
+def attachments
+  mailer.attachments
+end
+
+
+ +
+ +
+

+ + block_format(text) + +

+ + +
+

Take the text and format it, indented two spaces for each line, and wrapped at 72 columns:

+ +
text = <<-TEXT
+  This is
+  the      paragraph.
+
+  * item1 * item2
+TEXT
+
+block_format text
+# => "  This is the paragraph.\n\n  * item1\n  * item2\n"
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/mail_helper.rb, line 20
+def block_format(text)
+  formatted = text.split(/\n\r?\n/).collect { |paragraph|
+    format_paragraph(paragraph)
+  }.join("\n\n")
+
+  # Make list points stand on their own line
+  formatted.gsub!(/[ ]*([*]+) ([^*]*)/) { "  #{$1} #{$2.strip}\n" }
+  formatted.gsub!(/[ ]*([#]+) ([^#]*)/) { "  #{$1} #{$2.strip}\n" }
+
+  formatted
+end
+
+
+ +
+ +
+

+ + format_paragraph(text, len = 72, indent = 2) + +

+ + +
+

Returns text wrapped at len columns and indented indent spaces. By default column length len equals 72 characters and indent indent equal two spaces.

+ +
my_text = 'Here is a sample text with more than 40 characters'
+
+format_paragraph(my_text, 25, 4)
+# => "    Here is a sample text with\n    more than 40 characters"
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/mail_helper.rb, line 55
+def format_paragraph(text, len = 72, indent = 2)
+  sentences = [[]]
+
+  text.split.each do |word|
+    if sentences.first.present? && (sentences.last + [word]).join(" ").length > len
+      sentences << [word]
+    else
+      sentences.last << word
+    end
+  end
+
+  indentation = " " * indent
+  sentences.map! { |sentence|
+    "#{indentation}#{sentence.join(' ')}"
+  }.join "\n"
+end
+
+
+ +
+ +
+

+ + mailer() + +

+ + +
+

Access the mailer instance.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/mail_helper.rb, line 33
+def mailer
+  @_controller
+end
+
+
+ +
+ +
+

+ + message() + +

+ + +
+

Access the message instance.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/mail_helper.rb, line 38
+def message
+  @_message
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/MessageDelivery.html b/src/7.0/classes/ActionMailer/MessageDelivery.html new file mode 100644 index 0000000000..2d632efdf9 --- /dev/null +++ b/src/7.0/classes/ActionMailer/MessageDelivery.html @@ -0,0 +1,372 @@ +--- +title: ActionMailer::MessageDelivery +layout: default +--- +
+ +
+
+ +
+ +

The ActionMailer::MessageDelivery class is used by ActionMailer::Base when creating a new mailer. MessageDelivery is a wrapper (Delegator subclass) around a lazy created Mail::Message. You can get direct access to the Mail::Message, deliver the email or schedule the email to be sent through Active Job.

+ +
Notifier.welcome(User.first)               # an ActionMailer::MessageDelivery object
+Notifier.welcome(User.first).deliver_now   # sends the email
+Notifier.welcome(User.first).deliver_later # enqueue email delivery as a job through Active Job
+Notifier.welcome(User.first).message       # a Mail::Message object
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deliver_later(options = {}) + +

+ + +
+

Enqueues the email to be delivered through Active Job. When the job runs it will send the email using deliver_now.

+ +
Notifier.welcome(User.first).deliver_later
+Notifier.welcome(User.first).deliver_later(wait: 1.hour)
+Notifier.welcome(User.first).deliver_later(wait_until: 10.hours.from_now)
+Notifier.welcome(User.first).deliver_later(priority: 10)
+
+ +

Options:

+
  • +

    :wait - Enqueue the email to be delivered with a delay.

    +
  • +

    :wait_until - Enqueue the email to be delivered at (after) a specific date / time.

    +
  • +

    :queue - Enqueue the email on the specified queue.

    +
  • +

    :priority - Enqueues the email with the specified priority

    +
+ +

By default, the email will be enqueued using ActionMailer::MailDeliveryJob. Each ActionMailer::Base class can specify the job to use by setting the class variable delivery_job.

+ +
class AccountRegistrationMailer < ApplicationMailer
+  self.delivery_job = RegistrationDeliveryJob
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 98
+def deliver_later(options = {})
+  enqueue_delivery :deliver_now, options
+end
+
+
+ +
+ +
+

+ + deliver_later!(options = {}) + +

+ + +
+

Enqueues the email to be delivered through Active Job. When the job runs it will send the email using deliver_now!. That means that the message will be sent bypassing checking perform_deliveries and raise_delivery_errors, so use with caution.

+ +
Notifier.welcome(User.first).deliver_later!
+Notifier.welcome(User.first).deliver_later!(wait: 1.hour)
+Notifier.welcome(User.first).deliver_later!(wait_until: 10.hours.from_now)
+Notifier.welcome(User.first).deliver_later!(priority: 10)
+
+ +

Options:

+
  • +

    :wait - Enqueue the email to be delivered with a delay

    +
  • +

    :wait_until - Enqueue the email to be delivered at (after) a specific date / time

    +
  • +

    :queue - Enqueue the email on the specified queue

    +
  • +

    :priority - Enqueues the email with the specified priority

    +
+ +

By default, the email will be enqueued using ActionMailer::MailDeliveryJob. Each ActionMailer::Base class can specify the job to use by setting the class variable delivery_job.

+ +
class AccountRegistrationMailer < ApplicationMailer
+  self.delivery_job = RegistrationDeliveryJob
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 72
+def deliver_later!(options = {})
+  enqueue_delivery :deliver_now!, options
+end
+
+
+ +
+ +
+

+ + deliver_now() + +

+ + +
+

Delivers an email:

+ +
Notifier.welcome(User.first).deliver_now
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 117
+def deliver_now
+  processed_mailer.handle_exceptions do
+    message.deliver
+  end
+end
+
+
+ +
+ +
+

+ + deliver_now!() + +

+ + +
+

Delivers an email without checking perform_deliveries and raise_delivery_errors, so use with caution.

+ +
Notifier.welcome(User.first).deliver_now!
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 107
+def deliver_now!
+  processed_mailer.handle_exceptions do
+    message.deliver!
+  end
+end
+
+
+ +
+ +
+

+ + message() + +

+ + +
+

Returns the resulting Mail::Message

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 39
+def message
+  __getobj__
+end
+
+
+ +
+ +
+

+ + processed?() + +

+ + +
+

Was the delegate loaded, causing the mailer action to be processed?

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/message_delivery.rb, line 44
+def processed?
+  @processed_mailer || @mail_message
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/NonInferrableMailerError.html b/src/7.0/classes/ActionMailer/NonInferrableMailerError.html new file mode 100644 index 0000000000..0794abc423 --- /dev/null +++ b/src/7.0/classes/ActionMailer/NonInferrableMailerError.html @@ -0,0 +1,109 @@ +--- +title: ActionMailer::NonInferrableMailerError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_case.rb, line 8
+def initialize(name)
+  super "Unable to determine the mailer to test from #{name}. " \
+    "You'll need to specify it using tests YourMailer in your " \
+    "test case definition"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Parameterized.html b/src/7.0/classes/ActionMailer/Parameterized.html new file mode 100644 index 0000000000..8ec1e3314f --- /dev/null +++ b/src/7.0/classes/ActionMailer/Parameterized.html @@ -0,0 +1,170 @@ +--- +title: ActionMailer::Parameterized +layout: default +--- +
+ +
+
+ +
+ +

Provides the option to parameterize mailers in order to share instance variable setup, processing, and common headers.

+ +

Consider this example that does not use parameterization:

+ +
class InvitationsMailer < ApplicationMailer
+  def account_invitation(inviter, invitee)
+    @account = inviter.account
+    @inviter = inviter
+    @invitee = invitee
+
+    subject = "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
+
+    mail \
+      subject:   subject,
+      to:        invitee.email_address,
+      from:      common_address(inviter),
+      reply_to:  inviter.email_address_with_name
+  end
+
+  def project_invitation(project, inviter, invitee)
+    @account = inviter.account
+    @project = project
+    @inviter = inviter
+    @invitee = invitee
+    @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
+
+    subject = "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
+
+    mail \
+      subject:   subject,
+      to:        invitee.email_address,
+      from:      common_address(inviter),
+      reply_to:  inviter.email_address_with_name
+  end
+
+  def bulk_project_invitation(projects, inviter, invitee)
+    @account  = inviter.account
+    @projects = projects.sort_by(&:name)
+    @inviter  = inviter
+    @invitee  = invitee
+
+    subject = "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
+
+    mail \
+      subject:   subject,
+      to:        invitee.email_address,
+      from:      common_address(inviter),
+      reply_to:  inviter.email_address_with_name
+  end
+end
+
+InvitationsMailer.account_invitation(person_a, person_b).deliver_later
+
+ +

Using parameterized mailers, this can be rewritten as:

+ +
class InvitationsMailer < ApplicationMailer
+  before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
+  before_action { @account = params[:inviter].account }
+
+  default to:       -> { @invitee.email_address },
+          from:     -> { common_address(@inviter) },
+          reply_to: -> { @inviter.email_address_with_name }
+
+  def account_invitation
+    mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
+  end
+
+  def project_invitation
+    @project    = params[:project]
+    @summarizer = ProjectInvitationSummarizer.new(@project.bucket)
+
+    mail subject: "#{@inviter.name.familiar} added you to a project in Basecamp (#{@account.name})"
+  end
+
+  def bulk_project_invitation
+    @projects = params[:projects].sort_by(&:name)
+
+    mail subject: "#{@inviter.name.familiar} added you to some new stuff in Basecamp (#{@account.name})"
+  end
+end
+
+InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + params
+ + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Parameterized/ClassMethods.html b/src/7.0/classes/ActionMailer/Parameterized/ClassMethods.html new file mode 100644 index 0000000000..9e7cfabb24 --- /dev/null +++ b/src/7.0/classes/ActionMailer/Parameterized/ClassMethods.html @@ -0,0 +1,106 @@ +--- +title: ActionMailer::Parameterized::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + with(params) + +

+ + +
+

Provide the parameters to the mailer in order to use them in the instance methods and callbacks.

+ +
InvitationsMailer.with(inviter: person_a, invitee: person_b).account_invitation.deliver_later
+
+ +

See Parameterized documentation for full example.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/parameterized.rb, line 100
+def with(params)
+  ActionMailer::Parameterized::Mailer.new(self, params)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Preview.html b/src/7.0/classes/ActionMailer/Preview.html new file mode 100644 index 0000000000..892a4f0ac0 --- /dev/null +++ b/src/7.0/classes/ActionMailer/Preview.html @@ -0,0 +1,398 @@ +--- +title: ActionMailer::Preview +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + params
+ + + + +

Class Public methods

+ +
+

+ + all() + +

+ + +
+

Returns all mailer preview classes.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 80
+def all
+  load_previews if descendants.empty?
+  descendants
+end
+
+
+ +
+ +
+

+ + call(email, params = {}) + +

+ + +
+

Returns the mail object for the given email name. The registered preview interceptors will be informed so that they can transform the message as they would if the mail was actually being delivered.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 88
+def call(email, params = {})
+  preview = new(params)
+  message = preview.public_send(email)
+  inform_preview_interceptors(message)
+  message
+end
+
+
+ +
+ +
+

+ + email_exists?(email) + +

+ + +
+

Returns true if the email exists.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 101
+def email_exists?(email)
+  emails.include?(email)
+end
+
+
+ +
+ +
+

+ + emails() + +

+ + +
+

Returns all of the available email previews.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 96
+def emails
+  public_instance_methods(false).map(&:to_s).sort
+end
+
+
+ +
+ +
+

+ + exists?(preview) + +

+ + +
+

Returns true if the preview exists.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 106
+def exists?(preview)
+  all.any? { |p| p.preview_name == preview }
+end
+
+
+ +
+ +
+

+ + find(preview) + +

+ + +
+

Find a mailer preview by its underscored class name.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 111
+def find(preview)
+  all.find { |p| p.preview_name == preview }
+end
+
+
+ +
+ +
+

+ + new(params = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 74
+def initialize(params = {})
+  @params = params
+end
+
+
+ +
+ +
+

+ + preview_name() + +

+ + +
+

Returns the underscored name of the mailer preview without the suffix.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 116
+def preview_name
+  name.delete_suffix("Preview").underscore
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Previews.html b/src/7.0/classes/ActionMailer/Previews.html new file mode 100644 index 0000000000..5234915c7e --- /dev/null +++ b/src/7.0/classes/ActionMailer/Previews.html @@ -0,0 +1,67 @@ +--- +title: ActionMailer::Previews +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Previews/ClassMethods.html b/src/7.0/classes/ActionMailer/Previews/ClassMethods.html new file mode 100644 index 0000000000..4fac346869 --- /dev/null +++ b/src/7.0/classes/ActionMailer/Previews/ClassMethods.html @@ -0,0 +1,222 @@ +--- +title: ActionMailer::Previews::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + register_preview_interceptor(interceptor) + +

+ + +
+

Register an Interceptor which will be called before mail is previewed. Either a class or a string can be passed in as the Interceptor. If a string is passed in it will be constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 42
+def register_preview_interceptor(interceptor)
+  preview_interceptor = interceptor_class_for(interceptor)
+
+  unless preview_interceptors.include?(preview_interceptor)
+    preview_interceptors << preview_interceptor
+  end
+end
+
+
+ +
+ +
+

+ + register_preview_interceptors(*interceptors) + +

+ + +
+

Register one or more Interceptors which will be called before mail is previewed.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 30
+def register_preview_interceptors(*interceptors)
+  interceptors.flatten.compact.each { |interceptor| register_preview_interceptor(interceptor) }
+end
+
+
+ +
+ +
+

+ + unregister_preview_interceptor(interceptor) + +

+ + +
+

Unregister a previously registered Interceptor. Either a class or a string can be passed in as the Interceptor. If a string is passed in it will be constantized.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 53
+def unregister_preview_interceptor(interceptor)
+  preview_interceptors.delete(interceptor_class_for(interceptor))
+end
+
+
+ +
+ +
+

+ + unregister_preview_interceptors(*interceptors) + +

+ + +
+

Unregister one or more previously registered Interceptors.

+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/preview.rb, line 35
+def unregister_preview_interceptors(*interceptors)
+  interceptors.flatten.compact.each { |interceptor| unregister_preview_interceptor(interceptor) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/Rescuable.html b/src/7.0/classes/ActionMailer/Rescuable.html new file mode 100644 index 0000000000..54302121e0 --- /dev/null +++ b/src/7.0/classes/ActionMailer/Rescuable.html @@ -0,0 +1,74 @@ +--- +title: ActionMailer::Rescuable +layout: default +--- +
+ +
+
+ +
+ +

Provides rescue_from for mailers. Wraps mailer action processing, mail job processing, and mail delivery to handle configured errors.

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/TestCase.html b/src/7.0/classes/ActionMailer/TestCase.html new file mode 100644 index 0000000000..4e9bec92ba --- /dev/null +++ b/src/7.0/classes/ActionMailer/TestCase.html @@ -0,0 +1,89 @@ +--- +title: ActionMailer::TestCase +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/TestCase/Behavior.html b/src/7.0/classes/ActionMailer/TestCase/Behavior.html new file mode 100644 index 0000000000..090976d599 --- /dev/null +++ b/src/7.0/classes/ActionMailer/TestCase/Behavior.html @@ -0,0 +1,101 @@ +--- +title: ActionMailer::TestCase::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/TestCase/Behavior/ClassMethods.html b/src/7.0/classes/ActionMailer/TestCase/Behavior/ClassMethods.html new file mode 100644 index 0000000000..de9c49f226 --- /dev/null +++ b/src/7.0/classes/ActionMailer/TestCase/Behavior/ClassMethods.html @@ -0,0 +1,194 @@ +--- +title: ActionMailer::TestCase::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + determine_default_mailer(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_case.rb, line 68
+def determine_default_mailer(name)
+  mailer = determine_constant_from_test_name(name) do |constant|
+    Class === constant && constant < ActionMailer::Base
+  end
+  raise NonInferrableMailerError.new(name) if mailer.nil?
+  mailer
+end
+
+
+ +
+ +
+

+ + mailer_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_case.rb, line 60
+def mailer_class
+  if mailer = _mailer_class
+    mailer
+  else
+    tests determine_default_mailer(name)
+  end
+end
+
+
+ +
+ +
+

+ + tests(mailer) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_case.rb, line 49
+def tests(mailer)
+  case mailer
+  when String, Symbol
+    self._mailer_class = mailer.to_s.camelize.constantize
+  when Module
+    self._mailer_class = mailer
+  else
+    raise NonInferrableMailerError.new(mailer)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/TestCase/ClearTestDeliveries.html b/src/7.0/classes/ActionMailer/TestCase/ClearTestDeliveries.html new file mode 100644 index 0000000000..19556dc134 --- /dev/null +++ b/src/7.0/classes/ActionMailer/TestCase/ClearTestDeliveries.html @@ -0,0 +1,54 @@ +--- +title: ActionMailer::TestCase::ClearTestDeliveries +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/TestHelper.html b/src/7.0/classes/ActionMailer/TestHelper.html new file mode 100644 index 0000000000..c91cc958b1 --- /dev/null +++ b/src/7.0/classes/ActionMailer/TestHelper.html @@ -0,0 +1,402 @@ +--- +title: ActionMailer::TestHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides helper methods for testing Action Mailer, including assert_emails and assert_no_emails.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_emails(number, &block) + +

+ + +
+

Asserts that the number of emails sent matches the given number.

+ +
def test_emails
+  assert_emails 0
+  ContactMailer.welcome.deliver_now
+  assert_emails 1
+  ContactMailer.welcome.deliver_now
+  assert_emails 2
+end
+
+ +

If a block is passed, that block should cause the specified number of emails to be sent.

+ +
def test_emails_again
+  assert_emails 1 do
+    ContactMailer.welcome.deliver_now
+  end
+
+  assert_emails 2 do
+    ContactMailer.welcome.deliver_now
+    ContactMailer.welcome.deliver_later
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_helper.rb, line 34
+def assert_emails(number, &block)
+  if block_given?
+    original_count = ActionMailer::Base.deliveries.size
+    perform_enqueued_jobs(only: ->(job) { delivery_job_filter(job) }, &block)
+    new_count = ActionMailer::Base.deliveries.size
+    assert_equal number, new_count - original_count, "#{number} emails expected, but #{new_count - original_count} were sent"
+  else
+    assert_equal number, ActionMailer::Base.deliveries.size
+  end
+end
+
+
+ +
+ +
+

+ + assert_enqueued_email_with(mailer, method, args: nil, queue: ActionMailer::Base.deliver_later_queue_name || "default", &block) + +

+ + +
+

Asserts that a specific email has been enqueued, optionally matching arguments.

+ +
def test_email
+  ContactMailer.welcome.deliver_later
+  assert_enqueued_email_with ContactMailer, :welcome
+end
+
+def test_email_with_arguments
+  ContactMailer.welcome("Hello", "Goodbye").deliver_later
+  assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
+end
+
+ +

If a block is passed, that block should cause the specified email to be enqueued.

+ +
def test_email_in_block
+  assert_enqueued_email_with ContactMailer, :welcome do
+    ContactMailer.welcome.deliver_later
+  end
+end
+
+ +

If args is provided as a Hash, a parameterized email is matched.

+ +
def test_parameterized_email
+  assert_enqueued_email_with ContactMailer, :welcome,
+    args: {email: 'user@example.com'} do
+    ContactMailer.with(email: 'user@example.com').welcome.deliver_later
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_helper.rb, line 126
+def assert_enqueued_email_with(mailer, method, args: nil, queue: ActionMailer::Base.deliver_later_queue_name || "default", &block)
+  args = if args.is_a?(Hash)
+    [mailer.to_s, method.to_s, "deliver_now", params: args, args: []]
+  else
+    [mailer.to_s, method.to_s, "deliver_now", args: Array(args)]
+  end
+  assert_enqueued_with(job: mailer.delivery_job, args: args, queue: queue.to_s, &block)
+end
+
+
+ +
+ +
+

+ + assert_enqueued_emails(number, &block) + +

+ + +
+

Asserts that the number of emails enqueued for later delivery matches the given number.

+ +
def test_emails
+  assert_enqueued_emails 0
+  ContactMailer.welcome.deliver_later
+  assert_enqueued_emails 1
+  ContactMailer.welcome.deliver_later
+  assert_enqueued_emails 2
+end
+
+ +

If a block is passed, that block should cause the specified number of emails to be enqueued.

+ +
def test_emails_again
+  assert_enqueued_emails 1 do
+    ContactMailer.welcome.deliver_later
+  end
+
+  assert_enqueued_emails 2 do
+    ContactMailer.welcome.deliver_later
+    ContactMailer.welcome.deliver_later
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_helper.rb, line 92
+def assert_enqueued_emails(number, &block)
+  assert_enqueued_jobs(number, only: ->(job) { delivery_job_filter(job) }, &block)
+end
+
+
+ +
+ +
+

+ + assert_no_emails(&block) + +

+ + +
+

Asserts that no emails have been sent.

+ +
def test_emails
+  assert_no_emails
+  ContactMailer.welcome.deliver_now
+  assert_emails 1
+end
+
+ +

If a block is passed, that block should not cause any emails to be sent.

+ +
def test_emails_again
+  assert_no_emails do
+    # No emails should be sent from this block
+  end
+end
+
+ +

Note: This assertion is simply a shortcut for:

+ +
assert_emails 0, &block
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_helper.rb, line 64
+def assert_no_emails(&block)
+  assert_emails 0, &block
+end
+
+
+ +
+ +
+

+ + assert_no_enqueued_emails(&block) + +

+ + +
+

Asserts that no emails are enqueued for later delivery.

+ +
def test_no_emails
+  assert_no_enqueued_emails
+  ContactMailer.welcome.deliver_later
+  assert_enqueued_emails 1
+end
+
+ +

If a block is provided, it should not cause any emails to be enqueued.

+ +
def test_no_emails
+  assert_no_enqueued_emails do
+    # No emails should be enqueued from this block
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionmailer/lib/action_mailer/test_helper.rb, line 150
+def assert_no_enqueued_emails(&block)
+  assert_enqueued_emails 0, &block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionMailer/VERSION.html b/src/7.0/classes/ActionMailer/VERSION.html new file mode 100644 index 0000000000..1625ddbbf9 --- /dev/null +++ b/src/7.0/classes/ActionMailer/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActionMailer::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText.html b/src/7.0/classes/ActionText.html new file mode 100644 index 0000000000..24d261dbc3 --- /dev/null +++ b/src/7.0/classes/ActionText.html @@ -0,0 +1,254 @@ +--- +title: ActionText +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Action Text as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Action Text as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachable.html b/src/7.0/classes/ActionText/Attachable.html new file mode 100644 index 0000000000..8b900c6980 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachable.html @@ -0,0 +1,610 @@ +--- +title: ActionText::Attachable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
LOCATOR_NAME="attachable"
 
+ + + + + + +

Class Public methods

+ +
+

+ + from_attachable_sgid(sgid, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 22
+def from_attachable_sgid(sgid, options = {})
+  method = sgid.is_a?(Array) ? :locate_many_signed : :locate_signed
+  record = GlobalID::Locator.public_send(method, sgid, options.merge(for: LOCATOR_NAME))
+  record || raise(ActiveRecord::RecordNotFound)
+end
+
+
+ +
+ +
+

+ + from_node(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 10
+def from_node(node)
+  if attachable = attachable_from_sgid(node["sgid"])
+    attachable
+  elsif attachable = ActionText::Attachables::ContentAttachment.from_node(node)
+    attachable
+  elsif attachable = ActionText::Attachables::RemoteImage.from_node(node)
+    attachable
+  else
+    ActionText::Attachables::MissingAttachable
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + as_json(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 66
+def as_json(*)
+  super.merge("attachable_sgid" => persisted? ? attachable_sgid : nil)
+end
+
+
+ +
+ +
+

+ + attachable_content_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 46
+def attachable_content_type
+  try(:content_type) || "application/octet-stream"
+end
+
+
+ +
+ +
+

+ + attachable_filename() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 50
+def attachable_filename
+  filename.to_s if respond_to?(:filename)
+end
+
+
+ +
+ +
+

+ + attachable_filesize() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 54
+def attachable_filesize
+  try(:byte_size) || try(:filesize)
+end
+
+
+ +
+ +
+

+ + attachable_metadata() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 58
+def attachable_metadata
+  try(:metadata) || {}
+end
+
+
+ +
+ +
+

+ + attachable_sgid() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 42
+def attachable_sgid
+  to_sgid(expires_in: nil, for: LOCATOR_NAME).to_s
+end
+
+
+ +
+ +
+

+ + from_attachable_sgid(sgid) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 37
+def from_attachable_sgid(sgid)
+  ActionText::Attachable.from_attachable_sgid(sgid, only: self)
+end
+
+
+ +
+ +
+

+ + previewable_attachable?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 62
+def previewable_attachable?
+  false
+end
+
+
+ +
+ +
+

+ + to_attachable_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 74
+def to_attachable_partial_path
+  to_partial_path
+end
+
+
+ +
+ +
+

+ + to_rich_text_attributes(attributes = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 78
+def to_rich_text_attributes(attributes = {})
+  attributes.dup.tap do |attrs|
+    attrs[:sgid] = attachable_sgid
+    attrs[:content_type] = attachable_content_type
+    attrs[:previewable] = true if previewable_attachable?
+    attrs[:filename] = attachable_filename
+    attrs[:filesize] = attachable_filesize
+    attrs[:width] = attachable_metadata[:width]
+    attrs[:height] = attachable_metadata[:height]
+  end.compact
+end
+
+
+ +
+ +
+

+ + to_trix_content_attachment_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachable.rb, line 70
+def to_trix_content_attachment_partial_path
+  to_partial_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachables.html b/src/7.0/classes/ActionText/Attachables.html new file mode 100644 index 0000000000..19ee42425f --- /dev/null +++ b/src/7.0/classes/ActionText/Attachables.html @@ -0,0 +1,80 @@ +--- +title: ActionText::Attachables +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachables/ContentAttachment.html b/src/7.0/classes/ActionText/Attachables/ContentAttachment.html new file mode 100644 index 0000000000..8aae5b3c35 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachables/ContentAttachment.html @@ -0,0 +1,265 @@ +--- +title: ActionText::Attachables::ContentAttachment +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + name
+ + + + +

Class Public methods

+ +
+

+ + from_node(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/content_attachment.rb, line 8
+def self.from_node(node)
+  if node["content-type"]
+    if matches = node["content-type"].match(/vnd\.rubyonrails\.(.+)\.html/)
+      attachment = new(name: matches[1])
+      attachment if attachment.valid?
+    end
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attachable_plain_text_representation(caption) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/content_attachment.rb, line 20
+def attachable_plain_text_representation(caption)
+  case name
+  when "horizontal-rule"
+    " ┄ "
+  else
+    " "
+  end
+end
+
+
+ +
+ +
+

+ + to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/content_attachment.rb, line 29
+def to_partial_path
+  "action_text/attachables/content_attachment"
+end
+
+
+ +
+ +
+

+ + to_trix_content_attachment_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/content_attachment.rb, line 33
+def to_trix_content_attachment_partial_path
+  "action_text/attachables/content_attachments/#{name.underscore}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachables/MissingAttachable.html b/src/7.0/classes/ActionText/Attachables/MissingAttachable.html new file mode 100644 index 0000000000..7c40a1e899 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachables/MissingAttachable.html @@ -0,0 +1,101 @@ +--- +title: ActionText::Attachables::MissingAttachable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/missing_attachable.rb, line 8
+def self.to_partial_path
+  "action_text/attachables/missing_attachable"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachables/RemoteImage.html b/src/7.0/classes/ActionText/Attachables/RemoteImage.html new file mode 100644 index 0000000000..a4591220fc --- /dev/null +++ b/src/7.0/classes/ActionText/Attachables/RemoteImage.html @@ -0,0 +1,270 @@ +--- +title: ActionText::Attachables::RemoteImage +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + content_type
+ [R] + height
+ [R] + url
+ [R] + width
+ + + + +

Class Public methods

+ +
+

+ + from_node(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/remote_image.rb, line 9
+def from_node(node)
+  if node["url"] && content_type_is_image?(node["content-type"])
+    new(attributes_from_node(node))
+  end
+end
+
+
+ +
+ +
+

+ + new(attributes = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/remote_image.rb, line 30
+def initialize(attributes = {})
+  @url = attributes[:url]
+  @content_type = attributes[:content_type]
+  @width = attributes[:width]
+  @height = attributes[:height]
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attachable_plain_text_representation(caption) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/remote_image.rb, line 37
+def attachable_plain_text_representation(caption)
+  "[#{caption || "Image"}]"
+end
+
+
+ +
+ +
+

+ + to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachables/remote_image.rb, line 41
+def to_partial_path
+  "action_text/attachables/remote_image"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachment.html b/src/7.0/classes/ActionText/Attachment.html new file mode 100644 index 0000000000..2bd95bc626 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachment.html @@ -0,0 +1,627 @@ +--- +title: ActionText::Attachment +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ATTRIBUTES=%w( sgid content-type url href filename filesize width height previewable presentation caption )
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + attachable
+ [R] + node
+ + + + +

Class Public methods

+ +
+

+ + fragment_by_canonicalizing_attachments(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 14
+def fragment_by_canonicalizing_attachments(content)
+  fragment_by_minifying_attachments(fragment_by_converting_trix_attachments(content))
+end
+
+
+ +
+ +
+

+ + from_attachable(attachable, attributes = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 26
+def from_attachable(attachable, attributes = {})
+  if node = node_from_attributes(attachable.to_rich_text_attributes(attributes))
+    new(node, attachable)
+  end
+end
+
+
+ +
+ +
+

+ + from_attachables(attachables) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 22
+def from_attachables(attachables)
+  Array(attachables).filter_map { |attachable| from_attachable(attachable) }
+end
+
+
+ +
+ +
+

+ + from_attributes(attributes, attachable = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 32
+def from_attributes(attributes, attachable = nil)
+  if node = node_from_attributes(attributes)
+    from_node(node, attachable)
+  end
+end
+
+
+ +
+ +
+

+ + from_node(node, attachable = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 18
+def from_node(node, attachable = nil)
+  new(node, attachable || ActionText::Attachable.from_node(node))
+end
+
+
+ +
+ +
+

+ + new(node, attachable) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 55
+def initialize(node, attachable)
+  @node = node
+  @attachable = attachable
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + caption() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 60
+def caption
+  node_attributes["caption"].presence
+end
+
+
+ +
+ +
+

+ + full_attributes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 64
+def full_attributes
+  node_attributes.merge(attachable_attributes).merge(sgid_attributes)
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 88
+def inspect
+  "#<#{self.class.name} attachable=#{attachable.inspect}>"
+end
+
+
+ +
+ +
+

+ + to_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 80
+def to_html
+  HtmlConversion.node_to_html(node)
+end
+
+
+ +
+ +
+

+ + to_plain_text() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 72
+def to_plain_text
+  if respond_to?(:attachable_plain_text_representation)
+    attachable_plain_text_representation(caption)
+  else
+    caption.to_s
+  end
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 84
+def to_s
+  to_html
+end
+
+
+ +
+ +
+

+ + with_full_attributes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment.rb, line 68
+def with_full_attributes
+  self.class.from_attributes(full_attributes, attachable)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/AttachmentGallery.html b/src/7.0/classes/ActionText/AttachmentGallery.html new file mode 100644 index 0000000000..3413470154 --- /dev/null +++ b/src/7.0/classes/ActionText/AttachmentGallery.html @@ -0,0 +1,505 @@ +--- +title: ActionText::AttachmentGallery +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + node
+ + + + +

Class Public methods

+ +
+

+ + attachment_selector() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 41
+def attachment_selector
+  "#{ActionText::Attachment.tag_name}[presentation=gallery]"
+end
+
+
+ +
+ +
+ + + +
+ +
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + fragment_by_canonicalizing_attachment_galleries(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 11
+def fragment_by_canonicalizing_attachment_galleries(content)
+  fragment_by_replacing_attachment_gallery_nodes(content) do |node|
+    "<#{TAG_NAME}>#{node.inner_html}</#{TAG_NAME}>"
+  end
+end
+
+
+ +
+ +
+ + + +
+ +
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + from_node(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 37
+def from_node(node)
+  new(node)
+end
+
+
+ +
+ +
+

+ + new(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 52
+def initialize(node)
+  @node = node
+end
+
+
+ +
+ +
+

+ + selector() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 45
+def selector
+  "#{TAG_NAME}:has(#{attachment_selector} + #{attachment_selector})"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attachments() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 56
+def attachments
+  @attachments ||= node.css(ActionText::AttachmentGallery.attachment_selector).map do |node|
+    ActionText::Attachment.from_node(node).with_full_attributes
+  end
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 66
+def inspect
+  "#<#{self.class.name} size=#{size.inspect}>"
+end
+
+
+ +
+ +
+

+ + size() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachment_gallery.rb, line 62
+def size
+  attachments.size
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachments.html b/src/7.0/classes/ActionText/Attachments.html new file mode 100644 index 0000000000..d5bff9827c --- /dev/null +++ b/src/7.0/classes/ActionText/Attachments.html @@ -0,0 +1,75 @@ +--- +title: ActionText::Attachments +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachments/Caching.html b/src/7.0/classes/ActionText/Attachments/Caching.html new file mode 100644 index 0000000000..070558fda8 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachments/Caching.html @@ -0,0 +1,101 @@ +--- +title: ActionText::Attachments::Caching +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + cache_key(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachments/caching.rb, line 6
+def cache_key(*args)
+  [self.class.name, cache_digest, *attachable.cache_key(*args)].join("/")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachments/Minification.html b/src/7.0/classes/ActionText/Attachments/Minification.html new file mode 100644 index 0000000000..abc7d5f208 --- /dev/null +++ b/src/7.0/classes/ActionText/Attachments/Minification.html @@ -0,0 +1,103 @@ +--- +title: ActionText::Attachments::Minification +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fragment_by_minifying_attachments(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachments/minification.rb, line 9
+def fragment_by_minifying_attachments(content)
+  Fragment.wrap(content).replace(ActionText::Attachment.tag_name) do |node|
+    node.tap { |n| n.inner_html = "" }
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attachments/TrixConversion.html b/src/7.0/classes/ActionText/Attachments/TrixConversion.html new file mode 100644 index 0000000000..cbafe8657b --- /dev/null +++ b/src/7.0/classes/ActionText/Attachments/TrixConversion.html @@ -0,0 +1,183 @@ +--- +title: ActionText::Attachments::TrixConversion +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fragment_by_converting_trix_attachments(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachments/trix_conversion.rb, line 11
+def fragment_by_converting_trix_attachments(content)
+  Fragment.wrap(content).replace(TrixAttachment::SELECTOR) do |node|
+    from_trix_attachment(TrixAttachment.new(node))
+  end
+end
+
+
+ +
+ +
+

+ + from_trix_attachment(trix_attachment) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachments/trix_conversion.rb, line 17
+def from_trix_attachment(trix_attachment)
+  from_attributes(trix_attachment.attributes)
+end
+
+
+ +
+ +
+

+ + to_trix_attachment(content = trix_attachment_content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attachments/trix_conversion.rb, line 22
+def to_trix_attachment(content = trix_attachment_content)
+  attributes = full_attributes.dup
+  attributes["content"] = content if content
+  TrixAttachment.from_attributes(attributes)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Attribute.html b/src/7.0/classes/ActionText/Attribute.html new file mode 100644 index 0000000000..84308e2392 --- /dev/null +++ b/src/7.0/classes/ActionText/Attribute.html @@ -0,0 +1,222 @@ +--- +title: ActionText::Attribute +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + has_rich_text(name, encrypted: false) + +

+ + +
+

Provides access to a dependent RichText model that holds the body and attachments for a single named rich text attribute. This dependent attribute is lazily instantiated and will be auto-saved when it’s been changed. Example:

+ +
class Message < ActiveRecord::Base
+  has_rich_text :content
+end
+
+message = Message.create!(content: "<h1>Funny times!</h1>")
+message.content? #=> true
+message.content.to_s # => "<h1>Funny times!</h1>"
+message.content.to_plain_text # => "Funny times!"
+
+ +

The dependent RichText model will also automatically process attachments links as sent via the Trix-powered editor. These attachments are associated with the RichText model using Active Storage.

+ +

If you wish to preload the dependent RichText model, you can use the named scope:

+ +
 Message.all.with_rich_text_content # Avoids N+1 queries when you just want the body, not the attachments.
+ Message.all.with_rich_text_content_and_embeds # Avoids N+1 queries when you just want the body and attachments.
+ Message.all.with_all_rich_text # Loads all rich text associations.
+
+=== Options
+
+* <tt>:encrypted</tt> - Pass true to encrypt the rich text attribute. The encryption will be non-deterministic. See
++ActiveRecord::Encryption::EncryptableRecord.encrypts+. Default: false.
+
+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attribute.rb, line 33
+      def has_rich_text(name, encrypted: false)
+        class_eval <<-CODE, __FILE__, __LINE__ + 1
+          def #{name}
+            rich_text_#{name} || build_rich_text_#{name}
+          end
+
+          def #{name}?
+            rich_text_#{name}.present?
+          end
+
+          def #{name}=(body)
+            self.#{name}.body = body
+          end
+        CODE
+
+        rich_text_class_name = encrypted ? "ActionText::EncryptedRichText" : "ActionText::RichText"
+        has_one :"rich_text_#{name}", -> { where(name: name) },
+          class_name: rich_text_class_name, as: :record, inverse_of: :record, autosave: true, dependent: :destroy
+
+        scope :"with_rich_text_#{name}", -> { includes("rich_text_#{name}") }
+        scope :"with_rich_text_#{name}_and_embeds", -> { includes("rich_text_#{name}": { embeds_attachments: :blob }) }
+      end
+
+
+ +
+ +
+

+ + rich_text_association_names() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attribute.rb, line 61
+def rich_text_association_names
+  reflect_on_all_associations(:has_one).collect(&:name).select { |n| n.start_with?("rich_text_") }
+end
+
+
+ +
+ +
+

+ + with_all_rich_text() + +

+ + +
+

Eager load all dependent RichText models in bulk.

+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/attribute.rb, line 57
+def with_all_rich_text
+  eager_load(rich_text_association_names)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Content.html b/src/7.0/classes/ActionText/Content.html new file mode 100644 index 0000000000..7f4b5b2df1 --- /dev/null +++ b/src/7.0/classes/ActionText/Content.html @@ -0,0 +1,849 @@ +--- +title: ActionText::Content +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + fragment
+ + + + +

Class Public methods

+ +
+

+ + fragment_by_canonicalizing_content(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 12
+def fragment_by_canonicalizing_content(content)
+  fragment = ActionText::Attachment.fragment_by_canonicalizing_attachments(content)
+  fragment = ActionText::AttachmentGallery.fragment_by_canonicalizing_attachment_galleries(fragment)
+  fragment
+end
+
+
+ +
+ +
+

+ + new(content = nil, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 19
+def initialize(content = nil, options = {})
+  options.with_defaults! canonicalize: true
+
+  if options[:canonicalize]
+    @fragment = self.class.fragment_by_canonicalizing_content(content)
+  else
+    @fragment = ActionText::Fragment.wrap(content)
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 106
+def ==(other)
+  if other.is_a?(self.class)
+    to_s == other.to_s
+  end
+end
+
+
+ +
+ +
+

+ + append_attachables(attachables) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 55
+def append_attachables(attachables)
+  attachments = ActionText::Attachment.from_attachables(attachables)
+  self.class.new([self.to_s.presence, *attachments].compact.join("\n"))
+end
+
+
+ +
+ +
+

+ + as_json(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 98
+def as_json(*)
+  to_html
+end
+
+
+ +
+ +
+

+ + attachables() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 49
+def attachables
+  @attachables ||= attachment_nodes.map do |node|
+    ActionText::Attachable.from_node(node)
+  end
+end
+
+
+ +
+ +
+

+ + attachment_galleries() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 39
+def attachment_galleries
+  @attachment_galleries ||= attachment_gallery_nodes.map do |node|
+    attachment_gallery_for_node(node)
+  end
+end
+
+
+ +
+ +
+

+ + attachments() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 33
+def attachments
+  @attachments ||= attachment_nodes.map do |node|
+    attachment_for_node(node)
+  end
+end
+
+
+ +
+ +
+ + + +
+ +
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 102
+def inspect
+  "#<#{self.class.name} #{to_s.truncate(25).inspect}>"
+end
+
+
+ +
+ +
+ + + +
+ +
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + render_attachment_galleries(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 67
+def render_attachment_galleries(&block)
+  content = ActionText::AttachmentGallery.fragment_by_replacing_attachment_gallery_nodes(fragment) do |node|
+    block.call(attachment_gallery_for_node(node))
+  end
+  self.class.new(content, canonicalize: false)
+end
+
+
+ +
+ +
+

+ + render_attachments(**options, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 60
+def render_attachments(**options, &block)
+  content = fragment.replace(ActionText::Attachment.tag_name) do |node|
+    block.call(attachment_for_node(node, **options))
+  end
+  self.class.new(content, canonicalize: false)
+end
+
+
+ +
+ +
+

+ + to_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 82
+def to_html
+  fragment.to_html
+end
+
+
+ +
+ +
+

+ + to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 90
+def to_partial_path
+  "action_text/contents/content"
+end
+
+
+ +
+ +
+

+ + to_plain_text() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 74
+def to_plain_text
+  render_attachments(with_full_attributes: false, &:to_plain_text).fragment.to_plain_text
+end
+
+
+ +
+ +
+

+ + to_rendered_html_with_layout() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 86
+def to_rendered_html_with_layout
+  render layout: "action_text/contents/content", partial: to_partial_path, formats: :html, locals: { content: self }
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 94
+def to_s
+  to_rendered_html_with_layout
+end
+
+
+ +
+ +
+

+ + to_trix_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/content.rb, line 78
+def to_trix_html
+  render_attachments(&:to_trix_attachment).to_html
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/ContentHelper.html b/src/7.0/classes/ActionText/ContentHelper.html new file mode 100644 index 0000000000..4e69c43537 --- /dev/null +++ b/src/7.0/classes/ActionText/ContentHelper.html @@ -0,0 +1,193 @@ +--- +title: ActionText::ContentHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + render_action_text_attachments(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/content_helper.rb, line 21
+def render_action_text_attachments(content)
+  content.render_attachments do |attachment|
+    unless attachment.in?(content.gallery_attachments)
+      attachment.node.tap do |node|
+        node.inner_html = render_action_text_attachment attachment, locals: { in_gallery: false }
+      end
+    end
+  end.render_attachment_galleries do |attachment_gallery|
+    render(layout: attachment_gallery, object: attachment_gallery) do
+      attachment_gallery.attachments.map do |attachment|
+        attachment.node.inner_html = render_action_text_attachment attachment, locals: { in_gallery: true }
+        attachment.to_html
+      end.join.html_safe
+    end.chomp
+  end
+end
+
+
+ +
+ +
+

+ + render_action_text_content(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/content_helper.rb, line 12
+def render_action_text_content(content)
+  self.prefix_partial_path_with_controller_namespace = false
+  sanitize_action_text_content(render_action_text_attachments(content))
+end
+
+
+ +
+ +
+

+ + sanitize_action_text_content(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/content_helper.rb, line 17
+def sanitize_action_text_content(content)
+  sanitizer.sanitize(content.to_html, tags: allowed_tags, attributes: allowed_attributes, scrubber: scrubber).html_safe
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/EncryptedRichText.html b/src/7.0/classes/ActionText/EncryptedRichText.html new file mode 100644 index 0000000000..d78a72b4ad --- /dev/null +++ b/src/7.0/classes/ActionText/EncryptedRichText.html @@ -0,0 +1,60 @@ +--- +title: ActionText::EncryptedRichText +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Encryption.html b/src/7.0/classes/ActionText/Encryption.html new file mode 100644 index 0000000000..a6e936cde0 --- /dev/null +++ b/src/7.0/classes/ActionText/Encryption.html @@ -0,0 +1,146 @@ +--- +title: ActionText::Encryption +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrypt() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/encryption.rb, line 12
+def decrypt
+  transaction do
+    super
+    decrypt_rich_texts if has_encrypted_rich_texts?
+  end
+end
+
+
+ +
+ +
+

+ + encrypt() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/encryption.rb, line 5
+def encrypt
+  transaction do
+    super
+    encrypt_rich_texts if has_encrypted_rich_texts?
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Engine.html b/src/7.0/classes/ActionText/Engine.html new file mode 100644 index 0000000000..9964eae150 --- /dev/null +++ b/src/7.0/classes/ActionText/Engine.html @@ -0,0 +1,215 @@ +--- +title: ActionText::Engine +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attachable_plain_text_representation(caption = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/engine.rb, line 43
+def attachable_plain_text_representation(caption = nil)
+  "[#{caption || filename}]"
+end
+
+
+ +
+ +
+

+ + previewable_attachable?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/engine.rb, line 39
+def previewable_attachable?
+  representable?
+end
+
+
+ +
+ +
+

+ + to_trix_content_attachment_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/engine.rb, line 47
+def to_trix_content_attachment_partial_path
+  nil
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/FixtureSet.html b/src/7.0/classes/ActionText/FixtureSet.html new file mode 100644 index 0000000000..60981ec1d3 --- /dev/null +++ b/src/7.0/classes/ActionText/FixtureSet.html @@ -0,0 +1,161 @@ +--- +title: ActionText::FixtureSet +layout: default +--- +
+ +
+
+ +
+ +

Fixtures are a way of organizing data that you want to test against; in short, sample data.

+ +

To learn more about fixtures, read the ActiveRecord::FixtureSet documentation.

+ +

YAML

+ +

Like other Active Record-backed models, ActionText::RichText records inherit from ActiveRecord::Base instances and can therefore be populated by fixtures.

+ +

Consider an Article class:

+ +
class Article < ApplicationRecord
+  has_rich_text :content
+end
+
+ +

To declare fixture data for the related content, first declare fixture data for Article instances in test/fixtures/articles.yml:

+ +
first:
+  title: An Article
+
+ +

Then declare the ActionText::RichText fixture data in test/fixtures/action_text/rich_texts.yml, making sure to declare each entry’s record: key as a polymorphic relationship:

+ +
first:
+  record: first (Article)
+  name: content
+  body: <div>Hello, world.</div>
+
+ +

When processed, Active Record will insert database records for each fixture entry and will ensure the Action Text relationship is intact.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + attachment(fixture_set_name, label, column_type: :integer) + +

+ + +
+

Fixtures support Action Text attachments as part of their body HTML.

+ +

Examples

+ +

For example, consider a second Article fixture declared in test/fixtures/articles.yml:

+ +
second:
+  title: Another Article
+
+ +

You can attach a mention of articles(:first) to second‘s content by embedding a call to ActionText::FixtureSet.attachment in the body: value in test/fixtures/action_text/rich_texts.yml:

+ +
second:
+  record: second (Article)
+  name: content
+  body: <div>Hello, <%= ActionText::FixtureSet.attachment("articles", :first) %></div>
+
+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fixture_set.rb, line 59
+def self.attachment(fixture_set_name, label, column_type: :integer)
+  signed_global_id = ActiveRecord::FixtureSet.signed_global_id fixture_set_name, label,
+    column_type: column_type, for: ActionText::Attachable::LOCATOR_NAME
+
+  %(<action-text-attachment sgid="#{signed_global_id}"></action-text-attachment>)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Fragment.html b/src/7.0/classes/ActionText/Fragment.html new file mode 100644 index 0000000000..ae9b249c8a --- /dev/null +++ b/src/7.0/classes/ActionText/Fragment.html @@ -0,0 +1,448 @@ +--- +title: ActionText::Fragment +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + source
+ + + + +

Class Public methods

+ +
+

+ + from_html(html) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 17
+def from_html(html)
+  new(ActionText::HtmlConversion.fragment_for_html(html.to_s.strip))
+end
+
+
+ +
+ +
+

+ + new(source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 24
+def initialize(source)
+  @source = source
+end
+
+
+ +
+ +
+

+ + wrap(fragment_or_html) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 6
+def wrap(fragment_or_html)
+  case fragment_or_html
+  when self
+    fragment_or_html
+  when Nokogiri::HTML::DocumentFragment
+    new(fragment_or_html)
+  else
+    from_html(fragment_or_html)
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + find_all(selector) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 28
+def find_all(selector)
+  source.css(selector)
+end
+
+
+ +
+ +
+

+ + replace(selector) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 37
+def replace(selector)
+  update do |source|
+    source.css(selector).each do |node|
+      node.replace(yield(node).to_s)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + to_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 49
+def to_html
+  @html ||= HtmlConversion.node_to_html(source)
+end
+
+
+ +
+ +
+

+ + to_plain_text() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 45
+def to_plain_text
+  @plain_text ||= PlainTextConversion.node_to_plain_text(source)
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 53
+def to_s
+  to_html
+end
+
+
+ +
+ +
+

+ + update() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/fragment.rb, line 32
+def update
+  yield source = self.source.clone
+  self.class.new(source)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/HtmlConversion.html b/src/7.0/classes/ActionText/HtmlConversion.html new file mode 100644 index 0000000000..facda39389 --- /dev/null +++ b/src/7.0/classes/ActionText/HtmlConversion.html @@ -0,0 +1,179 @@ +--- +title: ActionText::HtmlConversion +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create_element(tag_name, attributes = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/html_conversion.rb, line 15
+def create_element(tag_name, attributes = {})
+  document.create_element(tag_name, attributes)
+end
+
+
+ +
+ +
+

+ + fragment_for_html(html) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/html_conversion.rb, line 11
+def fragment_for_html(html)
+  document.fragment(html)
+end
+
+
+ +
+ +
+

+ + node_to_html(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/html_conversion.rb, line 7
+def node_to_html(node)
+  node.to_html(save_with: Nokogiri::XML::Node::SaveOptions::AS_HTML)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/PlainTextConversion.html b/src/7.0/classes/ActionText/PlainTextConversion.html new file mode 100644 index 0000000000..44a8462e47 --- /dev/null +++ b/src/7.0/classes/ActionText/PlainTextConversion.html @@ -0,0 +1,101 @@ +--- +title: ActionText::PlainTextConversion +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + node_to_plain_text(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/plain_text_conversion.rb, line 7
+def node_to_plain_text(node)
+  remove_trailing_newlines(plain_text_for_node(node))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/RichText.html b/src/7.0/classes/ActionText/RichText.html new file mode 100644 index 0000000000..3c38cd4294 --- /dev/null +++ b/src/7.0/classes/ActionText/RichText.html @@ -0,0 +1,152 @@ +--- +title: ActionText::RichText +layout: default +--- +
+ +
+
+ +
+ +

The RichText record holds the content produced by the Trix editor in a serialized body attribute. It also holds all the references to the embedded files, which are stored using Active Storage. This record is then associated with the Active Record model the application desires to have rich text content using the has_rich_text class method.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + to_plain_text() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/models/action_text/rich_text.rb, line 21
+def to_plain_text
+  body&.to_plain_text.to_s
+end
+
+
+ +
+ +
+

+ + to_trix_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/models/action_text/rich_text.rb, line 25
+def to_trix_html
+  body&.to_trix_html
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/Serialization.html b/src/7.0/classes/ActionText/Serialization.html new file mode 100644 index 0000000000..6ed9a02666 --- /dev/null +++ b/src/7.0/classes/ActionText/Serialization.html @@ -0,0 +1,188 @@ +--- +title: ActionText::Serialization +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _dump(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/serialization.rb, line 32
+def _dump(*)
+  self.class.dump(self)
+end
+
+
+ +
+ +
+

+ + dump(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/serialization.rb, line 12
+def dump(content)
+  case content
+  when nil
+    nil
+  when self
+    content.to_html
+  when ActionText::RichText
+    content.body.to_html
+  else
+    new(content).to_html
+  end
+end
+
+
+ +
+ +
+

+ + load(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/serialization.rb, line 8
+def load(content)
+  new(content) if content
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/SystemTestHelper.html b/src/7.0/classes/ActionText/SystemTestHelper.html new file mode 100644 index 0000000000..378e87d909 --- /dev/null +++ b/src/7.0/classes/ActionText/SystemTestHelper.html @@ -0,0 +1,134 @@ +--- +title: ActionText::SystemTestHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fill_in_rich_text_area(locator = nil, with:) + +

+ + +
+

Locates a Trix editor and fills it in with the given HTML.

+ +

The editor can be found by:

+
  • +

    its id

    +
  • +

    its placeholder

    +
  • +

    the text from its label element

    +
  • +

    its aria-label

    +
  • +

    the name of its input

    +
+ +

Examples:

+ +
# <trix-editor id="message_content" ...></trix-editor>
+fill_in_rich_text_area "message_content", with: "Hello <em>world!</em>"
+
+# <trix-editor placeholder="Your message here" ...></trix-editor>
+fill_in_rich_text_area "Your message here", with: "Hello <em>world!</em>"
+
+# <label for="message_content">Message content</label>
+# <trix-editor id="message_content" ...></trix-editor>
+fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
+
+# <trix-editor aria-label="Message content" ...></trix-editor>
+fill_in_rich_text_area "Message content", with: "Hello <em>world!</em>"
+
+# <input id="trix_input_1" name="message[content]" type="hidden">
+# <trix-editor input="trix_input_1"></trix-editor>
+fill_in_rich_text_area "message[content]", with: "Hello <em>world!</em>"
+
+
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/system_test_helper.rb, line 32
+def fill_in_rich_text_area(locator = nil, with:)
+  find(:rich_text_area, locator).execute_script("this.editor.loadHTML(arguments[0])", with.to_s)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/TagHelper.html b/src/7.0/classes/ActionText/TagHelper.html new file mode 100644 index 0000000000..52956c67f0 --- /dev/null +++ b/src/7.0/classes/ActionText/TagHelper.html @@ -0,0 +1,130 @@ +--- +title: ActionText::TagHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + rich_text_area_tag(name, value = nil, options = {}) + +

+ + +
+

Returns a trix-editor tag that instantiates the Trix JavaScript editor as well as a hidden field that Trix will write to on changes, so the content will be sent on form submissions.

+ +

Options

+
  • +

    :class - Defaults to “trix-content” so that default styles will be applied. Setting this to a different value will prevent default styles from being applied.

    +
  • +

    [:data][:direct_upload_url] - Defaults to rails_direct_uploads_url.

    +
  • +

    [:data][:blob_url_template] - Defaults to rails_service_blob_url(":signed_id", ":filename").

    +
+ +

Example

+ +
rich_text_area_tag "content", message.content
+# <input type="hidden" name="content" id="trix_input_post_1">
+# <trix-editor id="content" input="trix_input_post_1" class="trix-content" ...></trix-editor>
+
+
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/tag_helper.rb, line 24
+def rich_text_area_tag(name, value = nil, options = {})
+  options = options.symbolize_keys
+  form = options.delete(:form)
+
+  options[:input] ||= "trix_input_#{ActionText::TagHelper.id += 1}"
+  options[:class] ||= "trix-content"
+
+  options[:data] ||= {}
+  options[:data][:direct_upload_url] ||= main_app.rails_direct_uploads_url
+  options[:data][:blob_url_template] ||= main_app.rails_service_blob_url(":signed_id", ":filename")
+
+  editor_tag = content_tag("trix-editor", "", options)
+  input_tag = hidden_field_tag(name, value.try(:to_trix_html) || value, id: options[:input], form: form)
+
+  input_tag + editor_tag
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/TrixAttachment.html b/src/7.0/classes/ActionText/TrixAttachment.html new file mode 100644 index 0000000000..863b6ff12e --- /dev/null +++ b/src/7.0/classes/ActionText/TrixAttachment.html @@ -0,0 +1,361 @@ +--- +title: ActionText::TrixAttachment +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ATTRIBUTES=%w( sgid contentType url href filename filesize width height previewable content ) + COMPOSED_ATTRIBUTES
 
ATTRIBUTE_TYPES={ +"previewable" => ->(value) { value.to_s == "true" }, +"filesize" => ->(value) { Integer(value.to_s, exception: false) || value }, +"width" => ->(value) { Integer(value.to_s, exception: false) }, +"height" => ->(value) { Integer(value.to_s, exception: false) }, +:default => ->(value) { value.to_s } +}
 
COMPOSED_ATTRIBUTES=%w( caption presentation )
 
SELECTOR="[data-trix-attachment]"
 
TAG_NAME="figure"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + node
+ + + + +

Class Public methods

+ +
+

+ + from_attributes(attributes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/trix_attachment.rb, line 19
+def from_attributes(attributes)
+  attributes = process_attributes(attributes)
+
+  trix_attachment_attributes = attributes.except(*COMPOSED_ATTRIBUTES)
+  trix_attributes = attributes.slice(*COMPOSED_ATTRIBUTES)
+
+  node = ActionText::HtmlConversion.create_element(TAG_NAME)
+  node["data-trix-attachment"] = JSON.generate(trix_attachment_attributes)
+  node["data-trix-attributes"] = JSON.generate(trix_attributes) if trix_attributes.any?
+
+  new(node)
+end
+
+
+ +
+ +
+

+ + new(node) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/trix_attachment.rb, line 51
+def initialize(node)
+  @node = node
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + attributes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/trix_attachment.rb, line 55
+def attributes
+  @attributes ||= attachment_attributes.merge(composed_attributes).slice(*ATTRIBUTES)
+end
+
+
+ +
+ +
+

+ + to_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/trix_attachment.rb, line 59
+def to_html
+  ActionText::HtmlConversion.node_to_html(node)
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/lib/action_text/trix_attachment.rb, line 63
+def to_s
+  to_html
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionText/VERSION.html b/src/7.0/classes/ActionText/VERSION.html new file mode 100644 index 0000000000..7ea571d5cd --- /dev/null +++ b/src/7.0/classes/ActionText/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActionText::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView.html b/src/7.0/classes/ActionView.html new file mode 100644 index 0000000000..a54557f64b --- /dev/null +++ b/src/7.0/classes/ActionView.html @@ -0,0 +1,456 @@ +--- +title: ActionView +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
TemplateError=Template::Error
 
+ + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Action View as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Action View as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/AbstractRenderer.html b/src/7.0/classes/ActionView/AbstractRenderer.html new file mode 100644 index 0000000000..6424d3faea --- /dev/null +++ b/src/7.0/classes/ActionView/AbstractRenderer.html @@ -0,0 +1,73 @@ +--- +title: ActionView::AbstractRenderer +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection.html b/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection.html new file mode 100644 index 0000000000..9110e4c6c4 --- /dev/null +++ b/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection.html @@ -0,0 +1,73 @@ +--- +title: ActionView::AbstractRenderer::RenderedCollection +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection/EmptyCollection.html b/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection/EmptyCollection.html new file mode 100644 index 0000000000..38cf541d37 --- /dev/null +++ b/src/7.0/classes/ActionView/AbstractRenderer/RenderedCollection/EmptyCollection.html @@ -0,0 +1,161 @@ +--- +title: ActionView::AbstractRenderer::RenderedCollection::EmptyCollection +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + format
+ + + + +

Class Public methods

+ +
+

+ + new(format) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/abstract_renderer.rb, line 133
+def initialize(format)
+  @format = format
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + body() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/abstract_renderer.rb, line 137
+def body; nil; end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Base.html b/src/7.0/classes/ActionView/Base.html new file mode 100644 index 0000000000..e5e98f380d --- /dev/null +++ b/src/7.0/classes/ActionView/Base.html @@ -0,0 +1,481 @@ +--- +title: ActionView::Base +layout: default +--- +
+ +
+
+ +
+ +

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 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:

+ +
<b>Names of all the people</b>
+<% @people.each do |person| %>
+  Name: <%= person.name %><br/>
+<% end %>
+
+ +

The loop is set up 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:

+ +
<title><%= @page_title %></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")                                 # => <em>emphasized</em>
+xml.em { xml.b("emph & bold") }                      # => <em><b>emph &amp; bold</b></em>
+xml.a("A Link", "href" => "http://onestepback.org")  # => <a href="http://onestepback.org">A Link</a>
+xml.target("name" => "compile", "option" => "fast")  # => <target option="fast" name="compile"\>
+                                                     # 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:

+ +
<div>
+  <h1>David Heinemeier Hansson</h1>
+  <p>A product of Danish Design during the Winter of '79...</p>
+</div>
+
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + lookup_context
+ [R] + view_renderer
+ + + + +

Class Public methods

+ +
+

+ + cache_template_loading() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 171
+def cache_template_loading
+  ActionView::Resolver.caching?
+end
+
+
+ +
+ +
+

+ + cache_template_loading=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 175
+def cache_template_loading=(value)
+  ActionView::Resolver.caching = value
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 191
+def inspect
+  "#<ActionView::Base:#{'%#016x' % (object_id << 1)}>"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + _run(method, template, locals, buffer, add_to_stack: true, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 240
+def _run(method, template, locals, buffer, add_to_stack: true, &block)
+  _old_output_buffer, _old_virtual_path, _old_template = @output_buffer, @virtual_path, @current_template
+  @current_template = template if add_to_stack
+  @output_buffer = buffer
+  public_send(method, locals, buffer, &block)
+ensure
+  @output_buffer, @virtual_path, @current_template = _old_output_buffer, _old_virtual_path, _old_template
+end
+
+
+ +
+ +
+

+ + compiled_method_container() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 249
+    def compiled_method_container
+      raise NotImplementedError, <<~msg.squish
+        Subclasses of ActionView::Base must implement `compiled_method_container`
+        or use the class method `with_empty_template_cache` for constructing
+        an ActionView::Base subclass that has an empty cache.
+      msg
+    end
+
+
+ +
+ +
+

+ + in_rendering_context(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/base.rb, line 257
+def in_rendering_context(options)
+  old_view_renderer  = @view_renderer
+  old_lookup_context = @lookup_context
+
+  if !lookup_context.html_fallback_for_js && options[:formats]
+    formats = Array(options[:formats])
+    if formats == [:js]
+      formats << :html
+    end
+    @lookup_context = lookup_context.with_prepended_formats(formats)
+    @view_renderer = ActionView::Renderer.new @lookup_context
+  end
+
+  yield @view_renderer
+ensure
+  @view_renderer = old_view_renderer
+  @lookup_context = old_lookup_context
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/CacheExpiry.html b/src/7.0/classes/ActionView/CacheExpiry.html new file mode 100644 index 0000000000..6d5917d884 --- /dev/null +++ b/src/7.0/classes/ActionView/CacheExpiry.html @@ -0,0 +1,77 @@ +--- +title: ActionView::CacheExpiry +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/CacheExpiry/Executor.html b/src/7.0/classes/ActionView/CacheExpiry/Executor.html new file mode 100644 index 0000000000..2e55f1c6fd --- /dev/null +++ b/src/7.0/classes/ActionView/CacheExpiry/Executor.html @@ -0,0 +1,194 @@ +--- +title: ActionView::CacheExpiry::Executor +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(watcher:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/cache_expiry.rb, line 6
+def initialize(watcher:)
+  @execution_lock = Concurrent::ReentrantReadWriteLock.new
+  @cache_expiry = ViewModificationWatcher.new(watcher: watcher) do
+    clear_cache
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + complete(_) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/cache_expiry.rb, line 20
+def complete(_)
+  @execution_lock.release_read_lock
+end
+
+
+ +
+ +
+

+ + run() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/cache_expiry.rb, line 13
+def run
+  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+    @cache_expiry.execute_if_updated
+    @execution_lock.acquire_read_lock
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/CacheExpiry/ViewModificationWatcher.html b/src/7.0/classes/ActionView/CacheExpiry/ViewModificationWatcher.html new file mode 100644 index 0000000000..2d0bfc2c97 --- /dev/null +++ b/src/7.0/classes/ActionView/CacheExpiry/ViewModificationWatcher.html @@ -0,0 +1,164 @@ +--- +title: ActionView::CacheExpiry::ViewModificationWatcher +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(watcher:, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/cache_expiry.rb, line 33
+def initialize(watcher:, &block)
+  @watched_dirs = nil
+  @watcher_class = watcher
+  @watcher = nil
+  @mutex = Mutex.new
+  @block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + execute_if_updated() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/cache_expiry.rb, line 41
+def execute_if_updated
+  @mutex.synchronize do
+    watched_dirs = dirs_to_watch
+    return if watched_dirs.empty?
+
+    if watched_dirs != @watched_dirs
+      @watched_dirs = watched_dirs
+      @watcher = @watcher_class.new([], watched_dirs, &@block)
+      @watcher.execute
+    else
+      @watcher.execute_if_updated
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Context.html b/src/7.0/classes/ActionView/Context.html new file mode 100644 index 0000000000..ec0c573f5f --- /dev/null +++ b/src/7.0/classes/ActionView/Context.html @@ -0,0 +1,175 @@ +--- +title: ActionView::Context +layout: default +--- +
+ +
+
+ +
+ +

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).

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + output_buffer
+ [RW] + view_flow
+ + + + + +

Instance Public methods

+ +
+

+ + _layout_for(name = nil) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/context.rb, line 27
+def _layout_for(name = nil)
+  name ||= :layout
+  view_flow.get(name).html_safe
+end
+
+
+ +
+ +
+

+ + _prepare_context() + +

+ + +
+

Prepares the context by setting the appropriate instance variables.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/context.rb, line 18
+def _prepare_context
+  @view_flow     = OutputFlow.new
+  @output_buffer = nil
+  @virtual_path  = nil
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor.html b/src/7.0/classes/ActionView/Digestor.html new file mode 100644 index 0000000000..fd82f4c25c --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor.html @@ -0,0 +1,256 @@ +--- +title: ActionView::Digestor +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + digest(name:, format: nil, finder:, dependencies: nil) + +

+ + +
+

Supported options:

+
  • +

    name - Template name

    +
  • +

    format - Template format

    +
  • +

    finder - An instance of ActionView::LookupContext

    +
  • +

    dependencies - An array of dependent views

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 16
+def digest(name:, format: nil, finder:, dependencies: nil)
+  if dependencies.nil? || dependencies.empty?
+    cache_key = "#{name}.#{format}"
+  else
+    dependencies_suffix = dependencies.flatten.tap(&:compact!).join(".")
+    cache_key = "#{name}.#{format}.#{dependencies_suffix}"
+  end
+
+  # this is a correctly done double-checked locking idiom
+  # (Concurrent::Map's lookups have volatile semantics)
+  finder.digest_cache[cache_key] || @@digest_mutex.synchronize do
+    finder.digest_cache.fetch(cache_key) do # re-check under lock
+      path = TemplatePath.parse(name)
+      root = tree(path.to_s, finder, path.partial?)
+      dependencies.each do |injected_dep|
+        root.children << Injected.new(injected_dep, nil, nil)
+      end if dependencies
+      finder.digest_cache[cache_key] = root.digest(finder)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 38
+def logger
+  ActionView::Base.logger || NullLogger
+end
+
+
+ +
+ +
+

+ + tree(name, finder, partial = false, seen = {}) + +

+ + +
+

Create a dependency tree for template named name.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 43
+def tree(name, finder, partial = false, seen = {})
+  logical_name = name.gsub(%r|/_|, "/")
+  interpolated = name.include?("#")
+
+  path = TemplatePath.parse(name)
+
+  if !interpolated && (template = find_template(finder, path.name, [path.prefix], partial, []))
+    if node = seen[template.identifier] # handle cycles in the tree
+      node
+    else
+      node = seen[template.identifier] = Node.create(name, logical_name, template, partial)
+
+      deps = DependencyTracker.find_dependencies(name, template, finder.view_paths)
+      deps.uniq { |n| n.gsub(%r|/_|, "/") }.each do |dep_file|
+        node.children << tree(dep_file, finder, true, seen)
+      end
+      node
+    end
+  else
+    unless interpolated # Dynamic template partial names can never be tracked
+      logger.error "  Couldn't find template for digesting: #{name}"
+    end
+
+    seen[name] ||= Missing.new(name, logical_name, nil)
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor/Injected.html b/src/7.0/classes/ActionView/Digestor/Injected.html new file mode 100644 index 0000000000..e55658657a --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor/Injected.html @@ -0,0 +1,105 @@ +--- +title: ActionView::Digestor::Injected +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + digest(finder, _ = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 122
+def digest(finder, _ = []) name end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor/Missing.html b/src/7.0/classes/ActionView/Digestor/Missing.html new file mode 100644 index 0000000000..8a1db790bc --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor/Missing.html @@ -0,0 +1,105 @@ +--- +title: ActionView::Digestor::Missing +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + digest(finder, _ = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 118
+def digest(finder, _ = []) "" end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor/Node.html b/src/7.0/classes/ActionView/Digestor/Node.html new file mode 100644 index 0000000000..4259fa6d28 --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor/Node.html @@ -0,0 +1,317 @@ +--- +title: ActionView::Digestor::Node +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + children
+ [R] + logical_name
+ [R] + name
+ [R] + template
+ + + + +

Class Public methods

+ +
+

+ + create(name, logical_name, template, partial) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 81
+def self.create(name, logical_name, template, partial)
+  klass = partial ? Partial : Node
+  klass.new(name, logical_name, template, [])
+end
+
+
+ +
+ +
+

+ + new(name, logical_name, template, children = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 86
+def initialize(name, logical_name, template, children = [])
+  @name         = name
+  @logical_name = logical_name
+  @template     = template
+  @children     = children
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + dependency_digest(finder, stack) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 97
+def dependency_digest(finder, stack)
+  children.map do |node|
+    if stack.include?(node)
+      false
+    else
+      finder.digest_cache[node.name] ||= begin
+                                           stack.push node
+                                           node.digest(finder, stack).tap { stack.pop }
+                                         end
+    end
+  end.join("-")
+end
+
+
+ +
+ +
+

+ + digest(finder, stack = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 93
+def digest(finder, stack = [])
+  ActiveSupport::Digest.hexdigest("#{template.source}-#{dependency_digest(finder, stack)}")
+end
+
+
+ +
+ +
+

+ + to_dep_map() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 110
+def to_dep_map
+  children.any? ? { name => children.map(&:to_dep_map) } : name
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor/NullLogger.html b/src/7.0/classes/ActionView/Digestor/NullLogger.html new file mode 100644 index 0000000000..077189f890 --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor/NullLogger.html @@ -0,0 +1,142 @@ +--- +title: ActionView::Digestor::NullLogger +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + debug(_) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 126
+def self.debug(_); end
+
+
+ +
+ +
+

+ + error(_) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/digestor.rb, line 127
+def self.error(_); end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Digestor/Partial.html b/src/7.0/classes/ActionView/Digestor/Partial.html new file mode 100644 index 0000000000..e6867ffafe --- /dev/null +++ b/src/7.0/classes/ActionView/Digestor/Partial.html @@ -0,0 +1,60 @@ +--- +title: ActionView::Digestor::Partial +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/FileSystemResolver.html b/src/7.0/classes/ActionView/FileSystemResolver.html new file mode 100644 index 0000000000..d7854c1795 --- /dev/null +++ b/src/7.0/classes/ActionView/FileSystemResolver.html @@ -0,0 +1,317 @@ +--- +title: ActionView::FileSystemResolver +layout: default +--- +
+ +
+
+ +
+ +

A resolver that loads files from the filesystem.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + path
+ + + + +

Class Public methods

+ +
+

+ + new(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 92
+def initialize(path)
+  raise ArgumentError, "path already is a Resolver class" if path.is_a?(Resolver)
+  @unbound_templates = Concurrent::Map.new
+  @path_parser = PathParser.new
+  @path = File.expand_path(path)
+  super()
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(resolver) + +

+ + +
+ +
+ + + + + +
+ Alias for: eql? +
+ + + +
+ +
+

+ + clear_cache() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 100
+def clear_cache
+  @unbound_templates.clear
+  @path_parser = PathParser.new
+  super
+end
+
+
+ +
+ +
+

+ + eql?(resolver) + +

+ + +
+ +
+ + + +
+ Also aliased as: == +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 111
+def eql?(resolver)
+  self.class.equal?(resolver.class) && to_path == resolver.to_path
+end
+
+
+ +
+ +
+

+ + to_path() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_s +
+ + + +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + +
+ Also aliased as: to_path +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 106
+def to_s
+  @path.to_s
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/FixtureResolver.html b/src/7.0/classes/ActionView/FixtureResolver.html new file mode 100644 index 0000000000..a98592df17 --- /dev/null +++ b/src/7.0/classes/ActionView/FixtureResolver.html @@ -0,0 +1,196 @@ +--- +title: ActionView::FixtureResolver +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(hash = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/testing/resolvers.rb, line 11
+def initialize(hash = {})
+  super("")
+  @hash = hash
+  @path = ""
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + data() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/testing/resolvers.rb, line 17
+def data
+  @hash
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/testing/resolvers.rb, line 21
+def to_s
+  @hash.keys.join(", ")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers.html b/src/7.0/classes/ActionView/Helpers.html new file mode 100644 index 0000000000..5b6143c48d --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers.html @@ -0,0 +1,246 @@ +--- +title: ActionView::Helpers +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActionView/Helpers/ActiveModelHelper.html b/src/7.0/classes/ActionView/Helpers/ActiveModelHelper.html new file mode 100644 index 0000000000..04dd780e96 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/ActiveModelHelper.html @@ -0,0 +1,54 @@ +--- +title: ActionView::Helpers::ActiveModelHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/ActiveModelInstanceTag.html b/src/7.0/classes/ActionView/Helpers/ActiveModelInstanceTag.html new file mode 100644 index 0000000000..3982da5eab --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/ActiveModelInstanceTag.html @@ -0,0 +1,264 @@ +--- +title: ActionView::Helpers::ActiveModelInstanceTag +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + content_tag(type, options, *) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/active_model_helper.rb, line 20
+def content_tag(type, options, *)
+  select_markup_helper?(type) ? super : error_wrapping(super)
+end
+
+
+ +
+ +
+

+ + error_message() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/active_model_helper.rb, line 36
+def error_message
+  object.errors[@method_name]
+end
+
+
+ +
+ +
+

+ + error_wrapping(html_tag) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/active_model_helper.rb, line 28
+def error_wrapping(html_tag)
+  if object_has_errors?
+    @template_object.instance_exec(html_tag, self, &Base.field_error_proc)
+  else
+    html_tag
+  end
+end
+
+
+ +
+ +
+

+ + object() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/active_model_helper.rb, line 13
+def object
+  @active_model_object ||= begin
+    object = super
+    object.respond_to?(:to_model) ? object.to_model : object
+  end
+end
+
+
+ +
+ +
+

+ + tag(type, options, *) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/active_model_helper.rb, line 24
+def tag(type, options, *)
+  tag_generate_errors?(options) ? error_wrapping(super) : super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/AssetTagHelper.html b/src/7.0/classes/ActionView/Helpers/AssetTagHelper.html new file mode 100644 index 0000000000..e8688e0401 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/AssetTagHelper.html @@ -0,0 +1,824 @@ +--- +title: ActionView::Helpers::AssetTagHelper +layout: default +--- +
+ +
+
+ +
+ +

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")
+# => <img src="/assets/rails.png" />
+stylesheet_link_tag("application")
+# => <link href="/assets/application.css?body=1" rel="stylesheet" />
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MAX_HEADER_SIZE=8_000
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + audio_tag(*sources) + +

+ + +
+

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 src="/audios/sound"></audio>
+audio_tag("sound.wav")
+# => <audio src="/audios/sound.wav"></audio>
+audio_tag("sound.wav", autoplay: true, controls: true)
+# => <audio autoplay="autoplay" controls="controls" src="/audios/sound.wav"></audio>
+audio_tag("sound.wav", "sound.mid")
+# => <audio><source src="/audios/sound.wav" /><source src="/audios/sound.mid" /></audio>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_tag_helper.rb, line 486
+def audio_tag(*sources)
+  multiple_sources_tag_builder("audio", sources)
+end
+
+
+ +
+ +
+ + + +
+

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.

+ + +
  • +

    :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

    +
+ + + +
auto_discovery_link_tag
+# => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/action" />
+auto_discovery_link_tag(:atom)
+# => <link rel="alternate" type="application/atom+xml" title="ATOM" href="http://www.currenthost.com/controller/action" />
+auto_discovery_link_tag(:json)
+# => <link rel="alternate" type="application/json" title="JSON" href="http://www.currenthost.com/controller/action" />
+auto_discovery_link_tag(:rss, {action: "feed"})
+# => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/controller/feed" />
+auto_discovery_link_tag(:rss, {action: "feed"}, {title: "My RSS"})
+# => <link rel="alternate" type="application/rss+xml" title="My RSS" href="http://www.currenthost.com/controller/feed" />
+auto_discovery_link_tag(:rss, {controller: "news", action: "feed"})
+# => <link rel="alternate" type="application/rss+xml" title="RSS" href="http://www.currenthost.com/news/feed" />
+auto_discovery_link_tag(:rss, "http://www.example.com/feed.rss", {title: "Example RSS"})
+# => <link rel="alternate" type="application/rss+xml" title="Example RSS" href="http://www.example.com/feed.rss" />
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+ + + +
+

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, “icon” and “image/x-icon” respectively:

+ +
favicon_link_tag
+# => <link href="/assets/favicon.ico" rel="icon" type="image/x-icon" />
+
+favicon_link_tag 'myicon.ico'
+# => <link href="/assets/myicon.ico" rel="icon" type="image/x-icon" />
+
+ +

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'
+# => <link href="/assets/mb-icon.png" rel="apple-touch-icon" type="image/png" />
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + image_tag(source, options = {}) + +

+ + +
+

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")
+# => <img src="/assets/icon" />
+image_tag("icon.png")
+# => <img src="/assets/icon.png" />
+image_tag("icon.png", size: "16x10", alt: "Edit Entry")
+# => <img src="/assets/icon.png" width="16" height="10" alt="Edit Entry" />
+image_tag("/icons/icon.gif", size: "16")
+# => <img src="/icons/icon.gif" width="16" height="16" />
+image_tag("/icons/icon.gif", height: '32', width: '32')
+# => <img height="32" src="/icons/icon.gif" width="32" />
+image_tag("/icons/icon.gif", class: "menu_icon")
+# => <img class="menu_icon" src="/icons/icon.gif" />
+image_tag("/icons/icon.gif", data: { title: 'Rails Application' })
+# => <img data-title="Rails Application" src="/icons/icon.gif" />
+image_tag("icon.png", srcset: { "icon_2x.png" => "2x", "icon_4x.png" => "4x" })
+# => <img src="/assets/icon.png" srcset="/assets/icon_2x.png 2x, /assets/icon_4x.png 4x">
+image_tag("pic.jpg", srcset: [["pic_1024.jpg", "1024w"], ["pic_1980.jpg", "1980w"]], sizes: "100vw")
+# => <img src="/assets/pic.jpg" srcset="/assets/pic_1024.jpg 1024w, /assets/pic_1980.jpg 1980w" sizes="100vw">
+
+ +

Active Storage blobs (images that are uploaded by the users of your app):

+ +
image_tag(user.avatar)
+# => <img src="/rails/active_storage/blobs/.../tiger.jpg" />
+image_tag(user.avatar.variant(resize_to_limit: [100, 100]))
+# => <img src="/rails/active_storage/representations/.../tiger.jpg" />
+image_tag(user.avatar.variant(resize_to_limit: [100, 100]), size: '100')
+# => <img width="100" height="100" src="/rails/active_storage/representations/.../tiger.jpg" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_tag_helper.rb, line 394
+def image_tag(source, options = {})
+  options = options.symbolize_keys
+  check_for_image_tag_errors(options)
+  skip_pipeline = options.delete(:skip_pipeline)
+
+  options[:src] = resolve_image_source(source, skip_pipeline)
+
+  if options[:srcset] && !options[:srcset].is_a?(String)
+    options[:srcset] = options[:srcset].map do |src_path, size|
+      src_path = path_to_image(src_path, skip_pipeline: skip_pipeline)
+      "#{src_path} #{size}"
+    end.join(", ")
+  end
+
+  options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
+
+  options[:loading] ||= image_loading if image_loading
+  options[:decoding] ||= image_decoding if image_decoding
+
+  tag("img", options)
+end
+
+
+ +
+ +
+

+ + javascript_include_tag(*sources) + +

+ + +
+

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"
+# => <script src="/assets/xmlhr.debug-1284139606.js"></script>
+
+javascript_include_tag "xmlhr", host: "localhost", protocol: "https"
+# => <script src="https://localhost/assets/xmlhr.debug-1284139606.js"></script>
+
+javascript_include_tag "template.jst", extname: false
+# => <script src="/assets/template.debug-1284139606.jst"></script>
+
+javascript_include_tag "xmlhr.js"
+# => <script src="/assets/xmlhr.debug-1284139606.js"></script>
+
+javascript_include_tag "common.javascript", "/elsewhere/cools"
+# => <script src="/assets/common.javascript.debug-1284139606.js"></script>
+#    <script src="/elsewhere/cools.debug-1284139606.js"></script>
+
+javascript_include_tag "http://www.example.com/xmlhr"
+# => <script src="http://www.example.com/xmlhr"></script>
+
+javascript_include_tag "http://www.example.com/xmlhr.js"
+# => <script src="http://www.example.com/xmlhr.js"></script>
+
+javascript_include_tag "http://www.example.com/xmlhr.js", nonce: true
+# => <script src="http://www.example.com/xmlhr.js" nonce="..."></script>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_tag_helper.rb, line 89
+def javascript_include_tag(*sources)
+  options = sources.extract_options!.stringify_keys
+  path_options = options.extract!("protocol", "extname", "host", "skip_pipeline").symbolize_keys
+  preload_links = []
+  nopush = options["nopush"].nil? ? true : options.delete("nopush")
+  crossorigin = options.delete("crossorigin")
+  crossorigin = "anonymous" if crossorigin == true
+  integrity = options["integrity"]
+  rel = options["type"] == "module" ? "modulepreload" : "preload"
+
+  sources_tags = sources.uniq.map { |source|
+    href = path_to_javascript(source, path_options)
+    if preload_links_header && !options["defer"] && href.present? && !href.start_with?("data:")
+      preload_link = "<#{href}>; rel=#{rel}; as=script"
+      preload_link += "; crossorigin=#{crossorigin}" unless crossorigin.nil?
+      preload_link += "; integrity=#{integrity}" unless integrity.nil?
+      preload_link += "; nopush" if nopush
+      preload_links << preload_link
+    end
+    tag_options = {
+      "src" => href,
+      "crossorigin" => crossorigin
+    }.merge!(options)
+    if tag_options["nonce"] == true
+      tag_options["nonce"] = content_security_policy_nonce
+    end
+    content_tag("script", "", tag_options)
+  }.join("\n").html_safe
+
+  if preload_links_header
+    send_preload_links_header(preload_links)
+  end
+
+  sources_tags
+end
+
+
+ +
+ +
+ + + +
+

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.

+ + +
  • +

    :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.

    +
  • +

    :integrity - Specify the integrity attribute.

    +
+ + + +
preload_link_tag("custom_theme.css")
+# => <link rel="preload" href="/assets/custom_theme.css" as="style" type="text/css" />
+
+preload_link_tag("/videos/video.webm")
+# => <link rel="preload" href="/videos/video.mp4" as="video" type="video/webm" />
+
+preload_link_tag(post_path(format: :json), as: "fetch")
+# => <link rel="preload" href="/posts.json" as="fetch" type="application/json" />
+
+preload_link_tag("worker.js", as: "worker")
+# => <link rel="preload" href="/assets/worker.js" as="worker" type="text/javascript" />
+
+preload_link_tag("//example.com/font.woff2")
+# => <link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="anonymous"/>
+
+preload_link_tag("//example.com/font.woff2", crossorigin: "use-credentials")
+# => <link rel="preload" href="//example.com/font.woff2" as="font" type="font/woff2" crossorigin="use-credentials" />
+
+preload_link_tag("/media/audio.ogg", nopush: true)
+# => <link rel="preload" href="/media/audio.ogg" as="audio" type="audio/ogg" />
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+ + + +
+

Returns a stylesheet link tag for the sources specified as arguments.

+ +

When passing paths, the .css extension is optional. If you don’t specify an extension, .css will be appended automatically. If you do not want .css appended to the path, set extname: false in the options. You can modify the link attributes by passing a hash as the last argument.

+ +

If the server supports Early Hints, header links for these assets will be automatically pushed.

+ + +
  • +

    :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.

    +
+ + + +
stylesheet_link_tag "style"
+# => <link href="/assets/style.css" rel="stylesheet" />
+
+stylesheet_link_tag "style.css"
+# => <link href="/assets/style.css" rel="stylesheet" />
+
+stylesheet_link_tag "http://www.example.com/style.css"
+# => <link href="http://www.example.com/style.css" rel="stylesheet" />
+
+stylesheet_link_tag "style.less", extname: false, skip_pipeline: true, rel: "stylesheet/less"
+# => <link href="/stylesheets/style.less" rel="stylesheet/less">
+
+stylesheet_link_tag "style", media: "all"
+# => <link href="/assets/style.css" media="all" rel="stylesheet" />
+
+stylesheet_link_tag "style", media: "print"
+# => <link href="/assets/style.css" media="print" rel="stylesheet" />
+
+stylesheet_link_tag "random.styles", "/css/stylish"
+# => <link href="/assets/random.styles" rel="stylesheet" />
+#    <link href="/css/stylish.css" rel="stylesheet" />
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + video_tag(*sources) + +

+ + +
+

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 src="/videos/trailer"></video>
+video_tag("trailer.ogg")
+# => <video src="/videos/trailer.ogg"></video>
+video_tag("trailer.ogg", controls: true, preload: 'none')
+# => <video preload="none" controls="controls" src="/videos/trailer.ogg"></video>
+video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png")
+# => <video src="/videos/trailer.m4v" width="16" height="10" poster="/assets/screenshot.png"></video>
+video_tag("trailer.m4v", size: "16x10", poster: "screenshot.png", poster_skip_pipeline: true)
+# => <video src="/videos/trailer.m4v" width="16" height="10" poster="screenshot.png"></video>
+video_tag("/trailers/hd.avi", size: "16x16")
+# => <video src="/trailers/hd.avi" width="16" height="16"></video>
+video_tag("/trailers/hd.avi", size: "16")
+# => <video height="16" src="/trailers/hd.avi" width="16"></video>
+video_tag("/trailers/hd.avi", height: '32', width: '32')
+# => <video height="32" src="/trailers/hd.avi" width="32"></video>
+video_tag("trailer.ogg", "trailer.flv")
+# => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
+video_tag(["trailer.ogg", "trailer.flv"])
+# => <video><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
+video_tag(["trailer.ogg", "trailer.flv"], size: "160x120")
+# => <video height="120" width="160"><source src="/videos/trailer.ogg" /><source src="/videos/trailer.flv" /></video>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_tag_helper.rb, line 459
+def video_tag(*sources)
+  options = sources.extract_options!.symbolize_keys
+  public_poster_folder = options.delete(:poster_skip_pipeline)
+  sources << options
+  multiple_sources_tag_builder("video", sources) do |tag_options|
+    tag_options[:poster] = path_to_image(tag_options[:poster], skip_pipeline: public_poster_folder) if tag_options[:poster]
+    tag_options[:width], tag_options[:height] = extract_dimensions(tag_options.delete(:size)) if tag_options[:size]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/AssetUrlHelper.html b/src/7.0/classes/ActionView/Helpers/AssetUrlHelper.html new file mode 100644 index 0000000000..d829ac0fd2 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/AssetUrlHelper.html @@ -0,0 +1,1538 @@ +--- +title: ActionView::Helpers::AssetUrlHelper +layout: default +--- +
+ +
+
+ +
+ +

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")
+# => <img src="http://assets.example.com/assets/rails.png" />
+stylesheet_link_tag("application")
+# => <link href="http://assets.example.com/assets/application.css" rel="stylesheet" />
+
+ +

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")
+# => <img src="http://assets0.example.com/assets/rails.png" />
+stylesheet_link_tag("application")
+# => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
+
+ +

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 set up 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 www.die.net/musings/page_load_time/ for background and 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#{OpenSSL::Digest::SHA256.hexdigest(source).to_i(16) % 2 + 1}.example.com"
+}
+image_tag("rails.png")
+# => <img src="http://assets1.example.com/assets/rails.png" />
+stylesheet_link_tag("application")
+# => <link href="http://assets2.example.com/assets/application.css" rel="stylesheet" />
+
+ +

The example above generates “assets1.example.com” and “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.end_with?('.css')
+     "http://stylesheets.example.com"
+   else
+     "http://assets.example.com"
+   end
+ }
+image_tag("rails.png")
+# => <img src="http://assets.example.com/assets/rails.png" />
+stylesheet_link_tag("application")
+# => <link href="http://stylesheets.example.com/assets/application.css" rel="stylesheet" />
+
+ +

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 bin/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"
+)
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ASSET_EXTENSIONS={ +javascript: ".js", +stylesheet: ".css" +}
 
ASSET_PUBLIC_DIRECTORIES={ +audio: "/audios", +font: "/fonts", +image: "/images", +javascript: "/javascripts", +stylesheet: "/stylesheets", +video: "/videos" +}
 

Maps asset types to public directory.

URI_REGEXP=%r{^[-a-z]+://|^(?:cid|data):|^//}i
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + asset_path(source, options = {}) + +

+ + +
+

This is the entry point for all assets. When using an asset pipeline gem (e.g. propshaft or 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 asset pipeline gems.

+ +
asset_path("application.js") # => "/assets/application-60aa4fdc5cea14baf5400fba1abf4f2a46a5166bad4772b1effe341570f07de9.js"
+asset_path('application.js', host: 'example.com') # => "//example.com/assets/application.js"
+asset_path("application.js", host: 'example.com', protocol: 'https') # => "https://example.com/assets/application.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"
    +
    +
+
+ + + +
+ Also aliased as: path_to_asset +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 186
+def asset_path(source, options = {})
+  raise ArgumentError, "nil is not a valid asset source" if source.nil?
+
+  source = source.to_s
+  return "" if source.blank?
+  return source if URI_REGEXP.match?(source)
+
+  tail, source = source[/([?#].+)$/], source.sub(/([?#].+)$/, "")
+
+  if extname = compute_asset_extname(source, options)
+    source = "#{source}#{extname}"
+  end
+
+  if source[0] != ?/
+    if options[:skip_pipeline]
+      source = public_compute_asset_path(source, options)
+    else
+      source = compute_asset_path(source, options)
+    end
+  end
+
+  relative_url_root = defined?(config.relative_url_root) && config.relative_url_root
+  if relative_url_root
+    source = File.join(relative_url_root, source) unless source.start_with?("#{relative_url_root}/")
+  end
+
+  if host = compute_asset_host(source, options)
+    source = File.join(host, source)
+  end
+
+  "#{source}#{tail}"
+end
+
+
+ +
+ +
+

+ + asset_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_asset +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 230
+def asset_url(source, options = {})
+  path_to_asset(source, options.merge(protocol: :request))
+end
+
+
+ +
+ +
+

+ + audio_path(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: path_to_audio +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 429
+def audio_path(source, options = {})
+  path_to_asset(source, { type: :audio }.merge!(options))
+end
+
+
+ +
+ +
+

+ + audio_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_audio +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 441
+def audio_url(source, options = {})
+  url_to_asset(source, { type: :audio }.merge!(options))
+end
+
+
+ +
+ +
+

+ + compute_asset_extname(source, options = {}) + +

+ + +
+

Compute extname to append to asset path. Returns nil if nothing should be added.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 242
+def compute_asset_extname(source, options = {})
+  return if options[:extname] == false
+  extname = options[:extname] || ASSET_EXTENSIONS[options[:type]]
+  if extname && File.extname(source) != extname
+    extname
+  else
+    nil
+  end
+end
+
+
+ +
+ +
+

+ + compute_asset_host(source = "", options = {}) + +

+ + +
+

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).

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 276
+def compute_asset_host(source = "", options = {})
+  request = self.request if respond_to?(:request)
+  host = options[:host]
+  host ||= config.asset_host if defined? config.asset_host
+
+  if host
+    if host.respond_to?(:call)
+      arity = host.respond_to?(:arity) ? host.arity : host.method(:call).arity
+      args = [source]
+      args << request if request && (arity > 1 || arity < 0)
+      host = host.call(*args)
+    elsif host.include?("%d")
+      host = host % (Zlib.crc32(source) % 4)
+    end
+  end
+
+  host ||= request.base_url if request && options[:protocol] == :request
+  return unless host
+
+  if URI_REGEXP.match?(host)
+    host
+  else
+    protocol = options[:protocol] || config.default_asset_host_protocol || (request ? :request : :relative)
+    case protocol
+    when :relative
+      "//#{host}"
+    when :request
+      "#{request.protocol}#{host}"
+    else
+      "#{protocol}://#{host}"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + compute_asset_path(source, options = {}) + +

+ + +
+

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.

+
+ + + +
+ Also aliased as: public_compute_asset_path +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 265
+def compute_asset_path(source, options = {})
+  dir = ASSET_PUBLIC_DIRECTORIES[options[:type]] || ""
+  File.join(dir, source)
+end
+
+
+ +
+ +
+

+ + font_path(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: path_to_font +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 454
+def font_path(source, options = {})
+  path_to_asset(source, { type: :font }.merge!(options))
+end
+
+
+ +
+ +
+

+ + font_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_font +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 466
+def font_url(source, options = {})
+  url_to_asset(source, { type: :font }.merge!(options))
+end
+
+
+ +
+ +
+

+ + image_path(source, options = {}) + +

+ + +
+

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.

+
+ + + +
+ Also aliased as: path_to_image +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 377
+def image_path(source, options = {})
+  path_to_asset(source, { type: :image }.merge!(options))
+end
+
+
+ +
+ +
+

+ + image_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_image +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 389
+def image_url(source, options = {})
+  url_to_asset(source, { type: :image }.merge!(options))
+end
+
+
+ +
+ +
+

+ + javascript_path(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: path_to_javascript +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 320
+def javascript_path(source, options = {})
+  path_to_asset(source, { type: :javascript }.merge!(options))
+end
+
+
+ +
+ +
+

+ + javascript_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_javascript +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 332
+def javascript_url(source, options = {})
+  url_to_asset(source, { type: :javascript }.merge!(options))
+end
+
+
+ +
+ +
+

+ + path_to_asset(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: asset_path +
+ + + +
+ +
+

+ + path_to_audio(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: audio_path +
+ + + +
+ +
+

+ + path_to_font(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: font_path +
+ + + +
+ +
+

+ + path_to_image(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: image_path +
+ + + +
+ +
+

+ + path_to_javascript(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: javascript_path +
+ + + +
+ +
+

+ + path_to_stylesheet(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: stylesheet_path +
+ + + +
+ +
+

+ + path_to_video(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: video_path +
+ + + +
+ +
+

+ + public_compute_asset_path(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: compute_asset_path +
+ + + +
+ +
+

+ + stylesheet_path(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: path_to_stylesheet +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 347
+def stylesheet_path(source, options = {})
+  path_to_asset(source, { type: :stylesheet }.merge!(options))
+end
+
+
+ +
+ +
+

+ + stylesheet_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_stylesheet +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 359
+def stylesheet_url(source, options = {})
+  url_to_asset(source, { type: :stylesheet }.merge!(options))
+end
+
+
+ +
+ +
+

+ + url_to_asset(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: asset_url +
+ + + +
+ +
+

+ + url_to_audio(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: audio_url +
+ + + +
+ +
+

+ + url_to_font(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: font_url +
+ + + +
+ +
+

+ + url_to_image(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: image_url +
+ + + +
+ +
+

+ + url_to_javascript(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: javascript_url +
+ + + +
+ +
+

+ + url_to_stylesheet(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: stylesheet_url +
+ + + +
+ +
+

+ + url_to_video(source, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: video_url +
+ + + +
+ +
+

+ + video_path(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: path_to_video +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 403
+def video_path(source, options = {})
+  path_to_asset(source, { type: :video }.merge!(options))
+end
+
+
+ +
+ +
+

+ + video_url(source, options = {}) + +

+ + +
+

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
+
+
+ + + +
+ Also aliased as: url_to_video +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/asset_url_helper.rb, line 415
+def video_url(source, options = {})
+  url_to_asset(source, { type: :video }.merge!(options))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/AtomFeedHelper.html b/src/7.0/classes/ActionView/Helpers/AtomFeedHelper.html new file mode 100644 index 0000000000..e1a9300e07 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/AtomFeedHelper.html @@ -0,0 +1,217 @@ +--- +title: ActionView::Helpers::AtomFeedHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + atom_feed(options = {}, &block) + +

+ + +
+

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 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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/atom_feed_helper.rb, line 98
+def atom_feed(options = {}, &block)
+  if options[:schema_date]
+    options[:schema_date] = options[:schema_date].strftime("%Y-%m-%d") if options[:schema_date].respond_to?(:strftime)
+  else
+    options[:schema_date] = "2005" # The Atom spec copyright date
+  end
+
+  xml = options.delete(:xml) || eval("xml", block.binding)
+  xml.instruct!
+  if options[:instruct]
+    options[:instruct].each do |target, attrs|
+      if attrs.respond_to?(:keys)
+        xml.instruct!(target, attrs)
+      elsif attrs.respond_to?(:each)
+        attrs.each { |attr_group| xml.instruct!(target, attr_group) }
+      end
+    end
+  end
+
+  feed_opts = { "xml:lang" => options[:language] || "en-US", "xmlns" => "http://www.w3.org/2005/Atom" }
+  feed_opts.merge!(options).select! { |k, _| k.start_with?("xml") }
+
+  xml.feed(feed_opts) do
+    xml.id(options[:id] || "tag:#{request.host},#{options[:schema_date]}:#{request.fullpath.split(".")[0]}")
+    xml.link(rel: "alternate", type: "text/html", href: options[:root_url] || (request.protocol + request.host_with_port))
+    xml.link(rel: "self", type: "application/atom+xml", href: options[:url] || request.url)
+
+    yield AtomFeedBuilder.new(xml, self, options)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/CacheHelper.html b/src/7.0/classes/ActionView/Helpers/CacheHelper.html new file mode 100644 index 0000000000..ef44dc1338 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/CacheHelper.html @@ -0,0 +1,495 @@ +--- +title: ActionView::Helpers::CacheHelper +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + cache(name = {}, options = {}, &block) + +

+ + +
+

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 %>
+  <b>All the topics on this project</b>
+  <%= 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: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 %>
+  <b>All the topics on this project</b>
+  <%= 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 %>
+  <b>All the topics on this project</b>
+  <%= 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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 168
+def cache(name = {}, options = {}, &block)
+  if controller.respond_to?(:perform_caching) && controller.perform_caching
+    CachingRegistry.track_caching do
+      name_options = options.slice(:skip_digest)
+      safe_concat(fragment_for(cache_fragment_name(name, **name_options), options, &block))
+    end
+  else
+    yield
+  end
+
+  nil
+end
+
+
+ +
+ +
+

+ + cache_fragment_name(name = {}, skip_digest: nil, digest_path: nil) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 240
+def cache_fragment_name(name = {}, skip_digest: nil, digest_path: nil)
+  if skip_digest
+    name
+  else
+    fragment_name_with_digest(name, digest_path)
+  end
+end
+
+
+ +
+ +
+

+ + cache_if(condition, name = {}, options = {}, &block) + +

+ + +
+

Cache fragments of a view if condition is true

+ +
<% cache_if admin?, project do %>
+  <b>All the topics on this project</b>
+  <%= render project.topics %>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 215
+def cache_if(condition, name = {}, options = {}, &block)
+  if condition
+    cache(name, options, &block)
+  else
+    yield
+  end
+
+  nil
+end
+
+
+ +
+ +
+

+ + cache_unless(condition, name = {}, options = {}, &block) + +

+ + +
+

Cache fragments of a view unless condition is true

+ +
<% cache_unless admin?, project do %>
+  <b>All the topics on this project</b>
+  <%= render project.topics %>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 231
+def cache_unless(condition, name = {}, options = {}, &block)
+  cache_if !condition, name, options, &block
+end
+
+
+ +
+ +
+

+ + caching?() + +

+ + +
+

Returns whether the current view fragment is within a cache block.

+ +

Useful when certain fragments aren’t cacheable:

+ +
<% cache project do %>
+  <% raise StandardError, "Caching private data!" if caching? %>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 188
+def caching?
+  CachingRegistry.caching?
+end
+
+
+ +
+ +
+

+ + uncacheable!() + +

+ + +
+

Raises UncacheableFragmentError when called from within a cache block.

+ +

Useful to denote helper methods that can’t participate in fragment caching:

+ +
def project_name_with_time(project)
+  uncacheable!
+  "#{project.name} - #{Time.now}"
+end
+
+# Which will then raise if used within a +cache+ block:
+<% cache project do %>
+  <%= project_name_with_time(project) %>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/cache_helper.rb, line 205
+def uncacheable!
+  raise UncacheableFragmentError, "can't be fragment cached" if caching?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/CacheHelper/UncacheableFragmentError.html b/src/7.0/classes/ActionView/Helpers/CacheHelper/UncacheableFragmentError.html new file mode 100644 index 0000000000..2b400ec29f --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/CacheHelper/UncacheableFragmentError.html @@ -0,0 +1,60 @@ +--- +title: ActionView::Helpers::CacheHelper::UncacheableFragmentError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/CaptureHelper.html b/src/7.0/classes/ActionView/Helpers/CaptureHelper.html new file mode 100644 index 0000000000..a911d631d5 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/CaptureHelper.html @@ -0,0 +1,396 @@ +--- +title: ActionView::Helpers::CaptureHelper +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + capture(*args) + +

+ + +
+

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:

+ +
<html>
+<head><title><%= @greeting %></title></head>
+<body>
+<b><%= @greeting %></b>
+</body>
+</html>
+
+ +

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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/capture_helper.rb, line 43
+def capture(*args)
+  value = nil
+  buffer = with_output_buffer { value = yield(*args) }
+  if (string = buffer.presence || value) && string.is_a?(String)
+    ERB::Util.html_escape string
+  end
+end
+
+
+ +
+ +
+

+ + content_for(name, content = nil, options = {}, &block) + +

+ + +
+

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 %>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>My Website</title>
+  <%= yield :script %>
+</head>
+<body>
+  <%= yield %>
+</body>
+</html>
+
+ +

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 %>
+  <script>alert('You are not authorized to view this page!')</script>
+<% 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 %>
+  <li><%= link_to 'Home', action: 'index' %></li>
+<% end %>
+
+ +

And in another place:

+ +
<% content_for :navigation do %>
+  <li><%= link_to 'Login', action: 'login' %></li>
+<% end %>
+
+ +

Then, in another template or layout, this code would render both links in order:

+ +
<ul><%= content_for :navigation %></ul>
+
+ +

If the flush parameter is true content_for replaces the blocks it is given. For example:

+ +
<% content_for :navigation do %>
+  <li><%= link_to 'Home', action: 'index' %></li>
+<% end %>
+
+<%# Add some other content, or use a different template: %>
+
+<% content_for :navigation, flush: true do %>
+  <li><%= link_to 'Login', action: 'login' %></li>
+<% end %>
+
+ +

Then, in another template or layout, this code would render only the last link:

+ +
<ul><%= content_for :navigation %></ul>
+
+ +

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/capture_helper.rb, line 155
+def content_for(name, content = nil, options = {}, &block)
+  if content || block_given?
+    if block_given?
+      options = content if content
+      content = capture(&block)
+    end
+    if content
+      options[:flush] ? @view_flow.set(name, content) : @view_flow.append(name, content)
+    end
+    nil
+  else
+    @view_flow.get(name).presence
+  end
+end
+
+
+ +
+ +
+

+ + content_for?(name) + +

+ + +
+

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 %>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+  <title>My Website</title>
+  <%= yield :script %>
+</head>
+<body class="<%= content_for?(:right_col) ? 'two-column' : 'one-column' %>">
+  <%= yield %>
+  <%= yield :right_col %>
+</body>
+</html>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/capture_helper.rb, line 195
+def content_for?(name)
+  @view_flow.get(name).present?
+end
+
+
+ +
+ +
+

+ + provide(name, content = nil, &block) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/capture_helper.rb, line 175
+def provide(name, content = nil, &block)
+  content = capture(&block) if block_given?
+  result = @view_flow.append!(name, content) if content
+  result unless content
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/CspHelper.html b/src/7.0/classes/ActionView/Helpers/CspHelper.html new file mode 100644 index 0000000000..997cff4673 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/CspHelper.html @@ -0,0 +1,112 @@ +--- +title: ActionView::Helpers::CspHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + csp_meta_tag(**options) + +

+ + +
+

Returns a meta tag “csp-nonce” with the per-session nonce value for allowing inline <script> tags.

+ +
<head>
+  <%= csp_meta_tag %>
+</head>
+
+ +

This is used by the Rails UJS helper to create dynamically loaded inline <script> elements.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/csp_helper.rb, line 17
+def csp_meta_tag(**options)
+  if content_security_policy?
+    options[:name] = "csp-nonce"
+    options[:content] = content_security_policy_nonce
+    tag("meta", options)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/CsrfHelper.html b/src/7.0/classes/ActionView/Helpers/CsrfHelper.html new file mode 100644 index 0000000000..0497e18e31 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/CsrfHelper.html @@ -0,0 +1,149 @@ +--- +title: ActionView::Helpers::CsrfHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + csrf_meta_tag() + +

+ + +
+

For backwards compatibility.

+
+ + + + + +
+ Alias for: csrf_meta_tags +
+ + + +
+ +
+

+ + csrf_meta_tags() + +

+ + +
+

Returns meta tags “csrf-param” and “csrf-token” with the name of the cross-site request forgery protection parameter and token, respectively.

+ +
<head>
+  <%= csrf_meta_tags %>
+</head>
+
+ +

These are used to generate the dynamic forms that implement non-remote links with :method.

+ +

You don’t need to use these tags for regular forms as they generate their own hidden fields.

+ +

For AJAX requests other than GETs, extract the “csrf-token” from the meta-tag and send as the X-CSRF-Token HTTP header. If you are using rails-ujs, this happens automatically.

+
+ + + +
+ Also aliased as: csrf_meta_tag +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/csrf_helper.rb, line 22
+def csrf_meta_tags
+  if defined?(protect_against_forgery?) && protect_against_forgery?
+    [
+      tag("meta", name: "csrf-param", content: request_forgery_protection_token),
+      tag("meta", name: "csrf-token", content: form_authenticity_token)
+    ].join("\n").html_safe
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/DateHelper.html b/src/7.0/classes/ActionView/Helpers/DateHelper.html new file mode 100644 index 0000000000..cc698f900e --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/DateHelper.html @@ -0,0 +1,1296 @@ +--- +title: ActionView::Helpers::DateHelper +layout: default +--- +
+ +
+
+ +
+ +

Action View Date Helpers

+ +

The Date Helper primarily creates select/option tags for different kinds of dates and times or date and time elements. All of the select-type methods share a number of common options that are as follows:

+
  • +

    :prefix - overwrites the default prefix of “date” used for the select names. So specifying “birthday” would give birthday[month] instead of date[month] if passed to the select_month method.

    +
  • +

    :include_blank - set to true if it should be possible to set an empty date.

    +
  • +

    :discard_type - set to true if you want to discard the type part of the select name. If set to true, the select_month method would use simply “date” (which can be overwritten using :prefix) instead of date[month].

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MINUTES_IN_QUARTER_YEAR=131400
 
MINUTES_IN_THREE_QUARTERS_YEAR=394200
 
MINUTES_IN_YEAR=525600
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + date_select(object_name, method, options = {}, html_options = {}) + +

+ + +
+

Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based attribute (identified by method) on an object assigned to the template (identified by object).

+ +

Options

+
  • +

    :use_month_numbers - Set to true if you want to use month numbers rather than month names (e.g. “2” instead of “February”).

    +
  • +

    :use_two_digit_numbers - Set to true if you want to display two digit month and day numbers (e.g. “02” instead of “February” and “08” instead of “8”).

    +
  • +

    :use_short_month - Set to true if you want to use abbreviated month names instead of full month names (e.g. “Feb” instead of “February”).

    +
  • +

    :add_month_numbers - Set to true if you want to use both month numbers and month names (e.g. “2 - February” instead of “February”).

    +
  • +

    :use_month_names - Set to an array with 12 month names if you want to customize month names. Note: You can also use Rails’ i18n functionality for this.

    +
  • +

    :month_format_string - Set to a format string. The string gets passed keys :number (integer) and :name (string). A format string would be something like “%{name} (%<number>02d)” for example. See Kernel.sprintf for documentation on format sequences.

    +
  • +

    :date_separator - Specifies a string to separate the date fields. Default is “” (i.e. nothing).

    +
  • +

    :time_separator - Specifies a string to separate the time fields. Default is “ : ”.

    +
  • +

    :datetime_separator- Specifies a string to separate the date and time fields. Default is “ &mdash; ”.

    +
  • +

    :start_year - Set the start year for the year select. Default is Date.today.year - 5 if you are creating new record. While editing existing record, :start_year defaults to the current selected year minus 5.

    +
  • +

    :end_year - Set the end year for the year select. Default is Date.today.year + 5 if you are creating new record. While editing existing record, :end_year defaults to the current selected year plus 5.

    +
  • +

    :year_format - Set format of years for year select. Lambda should be passed.

    +
  • +

    :day_format - Set format of days for day select. Lambda should be passed.

    +
  • +

    :discard_day - Set to true if you don’t want to show a day select. This includes the day as a hidden field instead of showing a select field. Also note that this implicitly sets the day to be the first of the given month in order to not create invalid dates like 31 February.

    +
  • +

    :discard_month - Set to true if you don’t want to show a month select. This includes the month as a hidden field instead of showing a select field. Also note that this implicitly sets :discard_day to true.

    +
  • +

    :discard_year - Set to true if you don’t want to show a year select. This includes the year as a hidden field instead of showing a select field.

    +
  • +

    :order - Set to an array containing :day, :month and :year to customize the order in which the select fields are shown. If you leave out any of the symbols, the respective select will not be shown (like when you set discard_xxx: true. Defaults to the order defined in the respective locale (e.g. [:year, :month, :day] in the en locale that ships with Rails).

    +
  • +

    :include_blank - Include a blank option in every select field so it’s possible to set empty dates.

    +
  • +

    :default - Set a default date if the affected date isn’t set or is nil.

    +
  • +

    :selected - Set a date that overrides the actual value.

    +
  • +

    :disabled - Set to true if you want show the select fields as disabled.

    +
  • +

    :prompt - Set to true (for a generic prompt), a prompt string or a hash of prompt strings for :year, :month, :day, :hour, :minute and :second. Setting this option prepends a select option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds) or the given prompt string.

    +
  • +

    :with_css_classes - Set to true or a hash of strings. Use true if you want to assign generic styles for select tags. This automatically set classes ‘year’, ‘month’, ‘day’, ‘hour’, ‘minute’ and ‘second’. A hash of strings for :year, :month, :day, :hour, :minute, :second will extend the select type with the given value. Use html_options to modify every select tag in the set.

    +
  • +

    :use_hidden - Set to true if you only want to generate hidden input tags.

    +
+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +

NOTE: Discarded selects will default to 1. So if no month select is available, January will be assumed.

+ +
# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute.
+date_select("article", "written_on")
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute,
+# with the year in the year drop down box starting at 1995.
+date_select("article", "written_on", start_year: 1995)
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute,
+# with the year in the year drop down box starting at 1995, numbers used for months instead of words,
+# and without a day select box.
+date_select("article", "written_on", start_year: 1995, use_month_numbers: true,
+                                  discard_day: true, include_blank: true)
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute,
+# with two digit numbers used for months and days.
+date_select("article", "written_on", use_two_digit_numbers: true)
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute
+# with the fields ordered as day, month, year rather than month, day, year.
+date_select("article", "written_on", order: [:day, :month, :year])
+
+# Generates a date select that when POSTed is stored in the user variable, in the birthday attribute
+# lacking a year field.
+date_select("user", "birthday", order: [:month, :day])
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute
+# which is initially set to the date 3 days from the current date
+date_select("article", "written_on", default: 3.days.from_now)
+
+# Generates a date select that when POSTed is stored in the article variable, in the written_on attribute
+# which is set in the form with today's date, regardless of the value in the Active Record object.
+date_select("article", "written_on", selected: Date.today)
+
+# Generates a date select that when POSTed is stored in the credit_card variable, in the bill_due attribute
+# that will have a default day of 20.
+date_select("credit_card", "bill_due", default: { day: 20 })
+
+# Generates a date select with custom prompts.
+date_select("article", "written_on", prompt: { day: 'Select day', month: 'Select month', year: 'Select year' })
+
+# Generates a date select with custom year format.
+date_select("article", "written_on", year_format: ->(year) { "Heisei #{year - 1988}" })
+
+# Generates a date select with custom day format.
+date_select("article", "written_on", day_format: ->(day) { day.ordinalize })
+
+ +

The selects are prepared for multi-parameter assignment to an Active Record object.

+ +

Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month choices are valid.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 290
+def date_select(object_name, method, options = {}, html_options = {})
+  Tags::DateSelect.new(object_name, method, self, options, html_options).render
+end
+
+
+ +
+ +
+

+ + datetime_select(object_name, method, options = {}, html_options = {}) + +

+ + +
+

Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based attribute (identified by method) on an object assigned to the template (identified by object).

+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +
# Generates a datetime select that, when POSTed, will be stored in the article variable in the written_on
+# attribute.
+datetime_select("article", "written_on")
+
+# Generates a datetime select with a year select that starts at 1995 that, when POSTed, will be stored in the
+# article variable in the written_on attribute.
+datetime_select("article", "written_on", start_year: 1995)
+
+# Generates a datetime select with a default value of 3 days from the current time that, when POSTed, will
+# be stored in the trip variable in the departing attribute.
+datetime_select("trip", "departing", default: 3.days.from_now)
+
+# Generate a datetime select with hours in the AM/PM format
+datetime_select("article", "written_on", ampm: true)
+
+# Generates a datetime select that discards the type that, when POSTed, will be stored in the article variable
+# as the written_on attribute.
+datetime_select("article", "written_on", discard_type: true)
+
+# Generates a datetime select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
+datetime_select("article", "written_on", prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
+datetime_select("article", "written_on", prompt: { hour: true }) # generic prompt for hours
+datetime_select("article", "written_on", prompt: true) # generic prompts for all
+
+ +

The selects are prepared for multi-parameter assignment to an Active Record object.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 362
+def datetime_select(object_name, method, options = {}, html_options = {})
+  Tags::DatetimeSelect.new(object_name, method, self, options, html_options).render
+end
+
+
+ +
+ +
+

+ + distance_of_time_in_words(from_time, to_time = 0, options = {}) + +

+ + +
+

Reports the approximate distance in time between two Time, Date, or DateTime objects or integers as seconds. Pass include_seconds: true if you want more detailed approximations when distance < 1 min, 29 secs. Distances are reported based on the following table:

+ +
0 <-> 29 secs                                                             # => less than a minute
+30 secs <-> 1 min, 29 secs                                                # => 1 minute
+1 min, 30 secs <-> 44 mins, 29 secs                                       # => [2..44] minutes
+44 mins, 30 secs <-> 89 mins, 29 secs                                     # => about 1 hour
+89 mins, 30 secs <-> 23 hrs, 59 mins, 29 secs                             # => about [2..24] hours
+23 hrs, 59 mins, 30 secs <-> 41 hrs, 59 mins, 29 secs                     # => 1 day
+41 hrs, 59 mins, 30 secs  <-> 29 days, 23 hrs, 59 mins, 29 secs           # => [2..29] days
+29 days, 23 hrs, 59 mins, 30 secs <-> 44 days, 23 hrs, 59 mins, 29 secs   # => about 1 month
+44 days, 23 hrs, 59 mins, 30 secs <-> 59 days, 23 hrs, 59 mins, 29 secs   # => about 2 months
+59 days, 23 hrs, 59 mins, 30 secs <-> 1 yr minus 1 sec                    # => [2..12] months
+1 yr <-> 1 yr, 3 months                                                   # => about 1 year
+1 yr, 3 months <-> 1 yr, 9 months                                         # => over 1 year
+1 yr, 9 months <-> 2 yr minus 1 sec                                       # => almost 2 years
+2 yrs <-> max time or date                                                # => (same rules as 1 yr)
+
+ +

With include_seconds: true and the difference < 1 minute 29 seconds:

+ +
0-4   secs      # => less than 5 seconds
+5-9   secs      # => less than 10 seconds
+10-19 secs      # => less than 20 seconds
+20-39 secs      # => half a minute
+40-59 secs      # => less than a minute
+60-89 secs      # => 1 minute
+
+from_time = Time.now
+distance_of_time_in_words(from_time, from_time + 50.minutes)                                # => about 1 hour
+distance_of_time_in_words(from_time, 50.minutes.from_now)                                   # => about 1 hour
+distance_of_time_in_words(from_time, from_time + 15.seconds)                                # => less than a minute
+distance_of_time_in_words(from_time, from_time + 15.seconds, include_seconds: true)         # => less than 20 seconds
+distance_of_time_in_words(from_time, 3.years.from_now)                                      # => about 3 years
+distance_of_time_in_words(from_time, from_time + 60.hours)                                  # => 3 days
+distance_of_time_in_words(from_time, from_time + 45.seconds, include_seconds: true)         # => less than a minute
+distance_of_time_in_words(from_time, from_time - 45.seconds, include_seconds: true)         # => less than a minute
+distance_of_time_in_words(from_time, 76.seconds.from_now)                                   # => 1 minute
+distance_of_time_in_words(from_time, from_time + 1.year + 3.days)                           # => about 1 year
+distance_of_time_in_words(from_time, from_time + 3.years + 6.months)                        # => over 3 years
+distance_of_time_in_words(from_time, from_time + 4.years + 9.days + 30.minutes + 5.seconds) # => about 4 years
+
+to_time = Time.now + 6.years + 19.days
+distance_of_time_in_words(from_time, to_time, include_seconds: true)                        # => about 6 years
+distance_of_time_in_words(to_time, from_time, include_seconds: true)                        # => about 6 years
+distance_of_time_in_words(Time.now, Time.now)                                               # => less than a minute
+
+ +

With the scope option, you can define a custom scope for Rails to look up the translation.

+ +

For example you can define the following in your locale (e.g. en.yml).

+ +
datetime:
+  distance_in_words:
+    short:
+      about_x_hours:
+        one: 'an hour'
+        other: '%{count} hours'
+
+ +

See github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml for more examples.

+ +

Which will then result in the following:

+ +
from_time = Time.now
+distance_of_time_in_words(from_time, from_time + 50.minutes, scope: 'datetime.distance_in_words.short') # => "an hour"
+distance_of_time_in_words(from_time, from_time + 3.hours, scope: 'datetime.distance_in_words.short')    # => "3 hours"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 95
+def distance_of_time_in_words(from_time, to_time = 0, options = {})
+  options = {
+    scope: :'datetime.distance_in_words'
+  }.merge!(options)
+
+  from_time = normalize_distance_of_time_argument_to_time(from_time)
+  to_time = normalize_distance_of_time_argument_to_time(to_time)
+  from_time, to_time = to_time, from_time if from_time > to_time
+  distance_in_minutes = ((to_time - from_time) / 60.0).round
+  distance_in_seconds = (to_time - from_time).round
+
+  I18n.with_options locale: options[:locale], scope: options[:scope] do |locale|
+    case distance_in_minutes
+    when 0..1
+      return distance_in_minutes == 0 ?
+             locale.t(:less_than_x_minutes, count: 1) :
+             locale.t(:x_minutes, count: distance_in_minutes) unless options[:include_seconds]
+
+      case distance_in_seconds
+      when 0..4   then locale.t :less_than_x_seconds, count: 5
+      when 5..9   then locale.t :less_than_x_seconds, count: 10
+      when 10..19 then locale.t :less_than_x_seconds, count: 20
+      when 20..39 then locale.t :half_a_minute
+      when 40..59 then locale.t :less_than_x_minutes, count: 1
+      else             locale.t :x_minutes,           count: 1
+      end
+
+    when 2...45           then locale.t :x_minutes,      count: distance_in_minutes
+    when 45...90          then locale.t :about_x_hours,  count: 1
+      # 90 mins up to 24 hours
+    when 90...1440        then locale.t :about_x_hours,  count: (distance_in_minutes.to_f / 60.0).round
+      # 24 hours up to 42 hours
+    when 1440...2520      then locale.t :x_days,         count: 1
+      # 42 hours up to 30 days
+    when 2520...43200     then locale.t :x_days,         count: (distance_in_minutes.to_f / 1440.0).round
+      # 30 days up to 60 days
+    when 43200...86400    then locale.t :about_x_months, count: (distance_in_minutes.to_f / 43200.0).round
+      # 60 days up to 365 days
+    when 86400...525600   then locale.t :x_months,       count: (distance_in_minutes.to_f / 43200.0).round
+    else
+      from_year = from_time.year
+      from_year += 1 if from_time.month >= 3
+      to_year = to_time.year
+      to_year -= 1 if to_time.month < 3
+      leap_years = (from_year > to_year) ? 0 : (from_year..to_year).count { |x| Date.leap?(x) }
+      minute_offset_for_leap_year = leap_years * 1440
+      # Discount the leap year days when calculating year distance.
+      # e.g. if there are 20 leap year days between 2 dates having the same day
+      # and month then based on 365 days calculation
+      # the distance in years will come out to over 80 years when in written
+      # English it would read better as about 80 years.
+      minutes_with_offset = distance_in_minutes - minute_offset_for_leap_year
+      remainder                   = (minutes_with_offset % MINUTES_IN_YEAR)
+      distance_in_years           = (minutes_with_offset.div MINUTES_IN_YEAR)
+      if remainder < MINUTES_IN_QUARTER_YEAR
+        locale.t(:about_x_years,  count: distance_in_years)
+      elsif remainder < MINUTES_IN_THREE_QUARTERS_YEAR
+        locale.t(:over_x_years,   count: distance_in_years)
+      else
+        locale.t(:almost_x_years, count: distance_in_years + 1)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + distance_of_time_in_words_to_now(from_time, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: time_ago_in_words +
+ + + +
+ +
+

+ + select_date(date = Date.current, options = {}, html_options = {}) + +

+ + +
+

Returns a set of HTML select-tags (one for year, month, and day) pre-selected with the date. It’s possible to explicitly set the order of the tags using the :order option with an array of symbols :year, :month and :day in the desired order. If the array passed to the :order option does not contain all the three symbols, all tags will be hidden.

+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +
my_date = Time.now + 6.days
+
+# Generates a date select that defaults to the date in my_date (six days after today).
+select_date(my_date)
+
+# Generates a date select that defaults to today (no specified date).
+select_date()
+
+# Generates a date select that defaults to the date in my_date (six days after today)
+# with the fields ordered year, month, day rather than month, day, year.
+select_date(my_date, order: [:year, :month, :day])
+
+# Generates a date select that discards the type of the field and defaults to the date in
+# my_date (six days after today).
+select_date(my_date, discard_type: true)
+
+# Generates a date select that defaults to the date in my_date,
+# which has fields separated by '/'.
+select_date(my_date, date_separator: '/')
+
+# Generates a date select that defaults to the datetime in my_date (six days after today)
+# prefixed with 'payday' rather than 'date'.
+select_date(my_date, prefix: 'payday')
+
+# Generates a date select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
+select_date(my_date, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
+select_date(my_date, prompt: { hour: true }) # generic prompt for hours
+select_date(my_date, prompt: true) # generic prompts for all
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 450
+def select_date(date = Date.current, options = {}, html_options = {})
+  DateTimeSelector.new(date, options, html_options).select_date
+end
+
+
+ +
+ +
+

+ + select_datetime(datetime = Time.current, options = {}, html_options = {}) + +

+ + +
+

Returns a set of HTML select-tags (one for year, month, day, hour, minute, and second) pre-selected with the datetime. It’s also possible to explicitly set the order of the tags using the :order option with an array of symbols :year, :month and :day in the desired order. If you do not supply a Symbol, it will be appended onto the :order passed in. You can also add :date_separator, :datetime_separator and :time_separator keys to the options to control visual display of the elements.

+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +
my_date_time = Time.now + 4.days
+
+# Generates a datetime select that defaults to the datetime in my_date_time (four days after today).
+select_datetime(my_date_time)
+
+# Generates a datetime select that defaults to today (no specified datetime)
+select_datetime()
+
+# Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+# with the fields ordered year, month, day rather than month, day, year.
+select_datetime(my_date_time, order: [:year, :month, :day])
+
+# Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+# with a '/' between each date field.
+select_datetime(my_date_time, date_separator: '/')
+
+# Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+# with a date fields separated by '/', time fields separated by '' and the date and time fields
+# separated by a comma (',').
+select_datetime(my_date_time, date_separator: '/', time_separator: '', datetime_separator: ',')
+
+# Generates a datetime select that discards the type of the field and defaults to the datetime in
+# my_date_time (four days after today)
+select_datetime(my_date_time, discard_type: true)
+
+# Generate a datetime field with hours in the AM/PM format
+select_datetime(my_date_time, ampm: true)
+
+# Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+# prefixed with 'payday' rather than 'date'
+select_datetime(my_date_time, prefix: 'payday')
+
+# Generates a datetime select with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
+select_datetime(my_date_time, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
+select_datetime(my_date_time, prompt: { hour: true }) # generic prompt for hours
+select_datetime(my_date_time, prompt: true) # generic prompts for all
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 411
+def select_datetime(datetime = Time.current, options = {}, html_options = {})
+  DateTimeSelector.new(datetime, options, html_options).select_datetime
+end
+
+
+ +
+ +
+

+ + select_day(date, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the days 1 through 31 with the current day selected. The date can also be substituted for a day number. If you want to display days with a leading zero set the :use_two_digit_numbers key in options to true. Override the field name using the :field_name option, ‘day’ by default.

+ +
my_date = Time.now + 2.days
+
+# Generates a select field for days that defaults to the day for the date in my_date.
+select_day(my_date)
+
+# Generates a select field for days that defaults to the number given.
+select_day(5)
+
+# Generates a select field for days that defaults to the number given, but displays it with two digits.
+select_day(5, use_two_digit_numbers: true)
+
+# Generates a select field for days that defaults to the day for the date in my_date
+# that is named 'due' rather than 'day'.
+select_day(my_date, field_name: 'due')
+
+# Generates a select field for days with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_day(5, prompt: 'Choose day')
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 593
+def select_day(date, options = {}, html_options = {})
+  DateTimeSelector.new(date, options, html_options).select_day
+end
+
+
+ +
+ +
+

+ + select_hour(datetime, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the hours 0 through 23 with the current hour selected. The datetime can be either a Time or DateTime object or an integer. Override the field name using the :field_name option, ‘hour’ by default.

+ +
my_time = Time.now + 6.hours
+
+# Generates a select field for hours that defaults to the hour for the time in my_time.
+select_hour(my_time)
+
+# Generates a select field for hours that defaults to the number given.
+select_hour(13)
+
+# Generates a select field for hours that defaults to the hour for the time in my_time
+# that is named 'stride' rather than 'hour'.
+select_hour(my_time, field_name: 'stride')
+
+# Generates a select field for hours with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_hour(13, prompt: 'Choose hour')
+
+# Generate a select field for hours in the AM/PM format
+select_hour(my_time, ampm: true)
+
+# Generates a select field that includes options for hours from 2 to 14.
+select_hour(my_time, start_hour: 2, end_hour: 14)
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 566
+def select_hour(datetime, options = {}, html_options = {})
+  DateTimeSelector.new(datetime, options, html_options).select_hour
+end
+
+
+ +
+ +
+

+ + select_minute(datetime, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected. Also can return a select tag with options by minute_step from 0 through 59 with the 00 minute selected. The datetime can be either a Time or DateTime object or an integer. Override the field name using the :field_name option, ‘minute’ by default.

+ +
my_time = Time.now + 10.minutes
+
+# Generates a select field for minutes that defaults to the minutes for the time in my_time.
+select_minute(my_time)
+
+# Generates a select field for minutes that defaults to the number given.
+select_minute(14)
+
+# Generates a select field for minutes that defaults to the minutes for the time in my_time
+# that is named 'moment' rather than 'minute'.
+select_minute(my_time, field_name: 'moment')
+
+# Generates a select field for minutes with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_minute(14, prompt: 'Choose minutes')
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 537
+def select_minute(datetime, options = {}, html_options = {})
+  DateTimeSelector.new(datetime, options, html_options).select_minute
+end
+
+
+ +
+ +
+

+ + select_month(date, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the months January through December with the current month selected. The month names are presented as keys (what’s shown to the user) and the month numbers (1-12) are used as values (what’s submitted to the server). It’s also possible to use month numbers for the presentation instead of names – set the :use_month_numbers key in options to true for this to happen. If you want both numbers and names, set the :add_month_numbers key in options to true. If you would prefer to show month names as abbreviations, set the :use_short_month key in options to true. If you want to use your own month names, set the :use_month_names key in options to an array of 12 month names. If you want to display months with a leading zero set the :use_two_digit_numbers key in options to true. Override the field name using the :field_name option, ‘month’ by default.

+ +
# Generates a select field for months that defaults to the current month that
+# will use keys like "January", "March".
+select_month(Date.today)
+
+# Generates a select field for months that defaults to the current month that
+# is named "start" rather than "month".
+select_month(Date.today, field_name: 'start')
+
+# Generates a select field for months that defaults to the current month that
+# will use keys like "1", "3".
+select_month(Date.today, use_month_numbers: true)
+
+# Generates a select field for months that defaults to the current month that
+# will use keys like "1 - January", "3 - March".
+select_month(Date.today, add_month_numbers: true)
+
+# Generates a select field for months that defaults to the current month that
+# will use keys like "Jan", "Mar".
+select_month(Date.today, use_short_month: true)
+
+# Generates a select field for months that defaults to the current month that
+# will use keys like "Januar", "Marts."
+select_month(Date.today, use_month_names: %w(Januar Februar Marts ...))
+
+# Generates a select field for months that defaults to the current month that
+# will use keys with two digit numbers like "01", "03".
+select_month(Date.today, use_two_digit_numbers: true)
+
+# Generates a select field for months with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_month(14, prompt: 'Choose month')
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 638
+def select_month(date, options = {}, html_options = {})
+  DateTimeSelector.new(date, options, html_options).select_month
+end
+
+
+ +
+ +
+

+ + select_second(datetime, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the seconds 0 through 59 with the current second selected. The datetime can be either a Time or DateTime object or an integer. Override the field name using the :field_name option, ‘second’ by default.

+ +
my_time = Time.now + 16.seconds
+
+# Generates a select field for seconds that defaults to the seconds for the time in my_time.
+select_second(my_time)
+
+# Generates a select field for seconds that defaults to the number given.
+select_second(33)
+
+# Generates a select field for seconds that defaults to the seconds for the time in my_time
+# that is named 'interval' rather than 'second'.
+select_second(my_time, field_name: 'interval')
+
+# Generates a select field for seconds with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_second(14, prompt: 'Choose seconds')
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 513
+def select_second(datetime, options = {}, html_options = {})
+  DateTimeSelector.new(datetime, options, html_options).select_second
+end
+
+
+ +
+ +
+

+ + select_time(datetime = Time.current, options = {}, html_options = {}) + +

+ + +
+

Returns a set of HTML select-tags (one for hour and minute). You can set :time_separator key to format the output, and the :include_seconds option to include an input for seconds.

+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +
my_time = Time.now + 5.days + 7.hours + 3.minutes + 14.seconds
+
+# Generates a time select that defaults to the time in my_time.
+select_time(my_time)
+
+# Generates a time select that defaults to the current time (no specified time).
+select_time()
+
+# Generates a time select that defaults to the time in my_time,
+# which has fields separated by ':'.
+select_time(my_time, time_separator: ':')
+
+# Generates a time select that defaults to the time in my_time,
+# that also includes an input for seconds.
+select_time(my_time, include_seconds: true)
+
+# Generates a time select that defaults to the time in my_time, that has fields
+# separated by ':' and includes an input for seconds.
+select_time(my_time, time_separator: ':', include_seconds: true)
+
+# Generate a time select field with hours in the AM/PM format
+select_time(my_time, ampm: true)
+
+# Generates a time select field with hours that range from 2 to 14
+select_time(my_time, start_hour: 2, end_hour: 14)
+
+# Generates a time select with a custom prompt. Use <tt>:prompt</tt> to true for generic prompts.
+select_time(my_time, prompt: { day: 'Choose day', month: 'Choose month', year: 'Choose year' })
+select_time(my_time, prompt: { hour: true }) # generic prompt for hours
+select_time(my_time, prompt: true) # generic prompts for all
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 490
+def select_time(datetime = Time.current, options = {}, html_options = {})
+  DateTimeSelector.new(datetime, options, html_options).select_time
+end
+
+
+ +
+ +
+

+ + select_year(date, options = {}, html_options = {}) + +

+ + +
+

Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius can be changed using the :start_year and :end_year keys in the options. Both ascending and descending year lists are supported by making :start_year less than or greater than :end_year. The date can also be substituted for a year given as a number. Override the field name using the :field_name option, ‘year’ by default.

+ +
# Generates a select field for years that defaults to the current year that
+# has ascending year values.
+select_year(Date.today, start_year: 1992, end_year: 2007)
+
+# Generates a select field for years that defaults to the current year that
+# is named 'birth' rather than 'year'.
+select_year(Date.today, field_name: 'birth')
+
+# Generates a select field for years that defaults to the current year that
+# has descending year values.
+select_year(Date.today, start_year: 2005, end_year: 1900)
+
+# Generates a select field for years that defaults to the year 2006 that
+# has ascending year values.
+select_year(2006, start_year: 2000, end_year: 2010)
+
+# Generates a select field for years with a custom prompt. Use <tt>prompt: true</tt> for a
+# generic prompt.
+select_year(14, prompt: 'Choose year')
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 667
+def select_year(date, options = {}, html_options = {})
+  DateTimeSelector.new(date, options, html_options).select_year
+end
+
+
+ +
+ +
+

+ + time_ago_in_words(from_time, options = {}) + +

+ + +
+

Like distance_of_time_in_words, but where to_time is fixed to Time.now.

+ +
time_ago_in_words(3.minutes.from_now)                 # => 3 minutes
+time_ago_in_words(3.minutes.ago)                      # => 3 minutes
+time_ago_in_words(Time.now - 15.hours)                # => about 15 hours
+time_ago_in_words(Time.now)                           # => less than a minute
+time_ago_in_words(Time.now, include_seconds: true) # => less than 5 seconds
+
+from_time = Time.now - 3.days - 14.minutes - 25.seconds
+time_ago_in_words(from_time)      # => 3 days
+
+from_time = (3.days + 14.minutes + 25.seconds).ago
+time_ago_in_words(from_time)      # => 3 days
+
+ +

Note that you cannot pass a Numeric value to time_ago_in_words.

+
+ + + +
+ Also aliased as: distance_of_time_in_words_to_now +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 176
+def time_ago_in_words(from_time, options = {})
+  distance_of_time_in_words(from_time, Time.now, options)
+end
+
+
+ +
+ +
+

+ + time_select(object_name, method, options = {}, html_options = {}) + +

+ + +
+

Returns a set of select tags (one for hour, minute, and optionally second) pre-selected for accessing a specified time-based attribute (identified by method) on an object assigned to the template (identified by object). You can include the seconds with :include_seconds. You can get hours in the AM/PM format with :ampm option.

+ +

This method will also generate 3 input hidden tags, for the actual year, month, and day unless the option :ignore_date is set to true. If you set the :ignore_date to true, you must have a date_select on the same method within the form otherwise an exception will be raised.

+ +

If anything is passed in the html_options hash it will be applied to every select tag in the set.

+ +
# Creates a time select tag that, when POSTed, will be stored in the article variable in the sunrise attribute.
+time_select("article", "sunrise")
+
+# Creates a time select tag with a seconds field that, when POSTed, will be stored in the article variables in
+# the sunrise attribute.
+time_select("article", "start_time", include_seconds: true)
+
+# You can set the <tt>:minute_step</tt> to 15 which will give you: 00, 15, 30, and 45.
+time_select 'game', 'game_time', { minute_step: 15 }
+
+# Creates a time select tag with a custom prompt. Use <tt>prompt: true</tt> for generic prompts.
+time_select("article", "written_on", prompt: { hour: 'Choose hour', minute: 'Choose minute', second: 'Choose seconds' })
+time_select("article", "written_on", prompt: { hour: true }) # generic prompt for hours
+time_select("article", "written_on", prompt: true) # generic prompts for all
+
+# You can set :ampm option to true which will show the hours as: 12 PM, 01 AM .. 11 PM.
+time_select 'game', 'game_time', { ampm: true }
+
+ +

The selects are prepared for multi-parameter assignment to an Active Record object.

+ +

Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month choices are valid.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 327
+def time_select(object_name, method, options = {}, html_options = {})
+  Tags::TimeSelect.new(object_name, method, self, options, html_options).render
+end
+
+
+ +
+ +
+

+ + time_tag(date_or_time, *args, &block) + +

+ + +
+

Returns an HTML time tag for the given date or time.

+ +
time_tag Date.today  # =>
+  <time datetime="2010-11-04">November 04, 2010</time>
+time_tag Time.now  # =>
+  <time datetime="2010-11-04T17:55:45+01:00">November 04, 2010 17:55</time>
+time_tag Date.yesterday, 'Yesterday'  # =>
+  <time datetime="2010-11-03">Yesterday</time>
+time_tag Date.today, datetime: Date.today.strftime('%G-W%V') # =>
+  <time datetime="2010-W44">November 04, 2010</time>
+
+<%= time_tag Time.now do %>
+  <span>Right now</span>
+<% end %>
+# => <time datetime="2010-11-04T17:55:45+01:00"><span>Right now</span></time>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 686
+def time_tag(date_or_time, *args, &block)
+  options  = args.extract_options!
+  format   = options.delete(:format) || :long
+  content  = args.first || I18n.l(date_or_time, format: format)
+
+  content_tag("time", content, options.reverse_merge(datetime: date_or_time.iso8601), &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/DebugHelper.html b/src/7.0/classes/ActionView/Helpers/DebugHelper.html new file mode 100644 index 0000000000..3e0eb81e51 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/DebugHelper.html @@ -0,0 +1,133 @@ +--- +title: ActionView::Helpers::DebugHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + debug(object) + +

+ + +
+

Returns a YAML representation of object wrapped with <pre> and </pre>. If the object cannot be converted to YAML using to_yaml, inspect will be called instead. Useful for inspecting an object at the time of rendering.

+ +
@user = User.new({ username: 'testing', password: 'xyz', age: 42})
+debug(@user)
+# =>
+<pre class='debug_dump'>--- !ruby/object:User
+attributes:
+  updated_at:
+  username: testing
+  age: 42
+  password: xyz
+  created_at:
+</pre>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/debug_helper.rb, line 28
+def debug(object)
+  Marshal.dump(object)
+  object = ERB::Util.html_escape(object.to_yaml)
+  content_tag(:pre, object, class: "debug_dump")
+rescue # errors from Marshal or YAML
+  # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
+  content_tag(:code, object.inspect, class: "debug_dump")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/FormBuilder.html b/src/7.0/classes/ActionView/Helpers/FormBuilder.html new file mode 100644 index 0000000000..c5f4e24dfa --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/FormBuilder.html @@ -0,0 +1,2685 @@ +--- +title: ActionView::Helpers::FormBuilder +layout: default +--- +
+ +
+
+ +
+ +

A FormBuilder object is associated with a particular model object and allows you to generate fields associated with the model object. The FormBuilder object is yielded when using form_for or fields_for. For example:

+ +
<%= form_for @person do |person_form| %>
+  Name: <%= person_form.text_field :name %>
+  Admin: <%= person_form.check_box :admin %>
+<% end %>
+
+ +

In the above block, a FormBuilder object is yielded as the person_form variable. This allows you to generate the text_field and check_box fields by specifying their eponymous methods, which modify the underlying template and associates the @person model object with the form.

+ +

The FormBuilder object can be thought of as serving as a proxy for the methods in the FormHelper module. This class, however, allows you to call methods with the model object you are building the form for.

+ +

You can create your own custom FormBuilder templates by subclassing this class. For example:

+ +
class MyFormBuilder < ActionView::Helpers::FormBuilder
+  def div_radio_button(method, tag_value, options = {})
+    @template.content_tag(:div,
+      @template.radio_button(
+        @object_name, method, tag_value, objectify_options(options)
+      )
+    )
+  end
+end
+
+ +

The above code creates a new method div_radio_button which wraps a div around the new radio button. Note that when options are passed in, you must call objectify_options in order for the model object to get correctly passed to the method. If objectify_options is not called, then the newly created helper will not be linked back to the model.

+ +

The div_radio_button code from above can now be used as follows:

+ +
<%= form_for @person, :builder => MyFormBuilder do |f| %>
+  I am a child: <%= f.div_radio_button(:admin, "child") %>
+  I am an adult: <%= f.div_radio_button(:admin, "adult") %>
+<% end -%>
+
+ +

The standard set of helper methods for form building are located in the field_helpers class attribute.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + index
+ [R] + multipart
+ [R] + multipart?
+ [RW] + object
+ [RW] + object_name
+ [RW] + options
+ + + + +

Class Public methods

+ +
+

+ + _to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1689
+def self._to_partial_path
+  @_to_partial_path ||= name.demodulize.underscore.sub!(/_builder$/, "")
+end
+
+
+ +
+ +
+

+ + new(object_name, object, template, options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1701
+def initialize(object_name, object, template, options)
+  @nested_child_index = {}
+  @object_name, @object, @template, @options = object_name, object, template, options
+  @default_options = @options ? @options.slice(:index, :namespace, :skip_default_ids, :allow_method_names_outside_object) : {}
+  @default_html_options = @default_options.except(:skip_default_ids, :allow_method_names_outside_object)
+
+  convert_to_legacy_options(@options)
+
+  if @object_name&.end_with?("[]")
+    if (object ||= @template.instance_variable_get("@#{@object_name[0..-3]}")) && object.respond_to?(:to_param)
+      @auto_index = object.to_param
+    else
+      raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
+    end
+  end
+
+  @multipart = nil
+  @index = options[:index] || options[:child_index]
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + button(value = nil, options = {}, &block) + +

+ + +
+

Add the submit button for the given form. When no value is given, it checks if the object is a new resource or not to create the proper label:

+ +
<%= form_for @post do |f| %>
+  <%= f.button %>
+<% end %>
+
+ +

In the example above, if @post is a new record, it will use “Create Post” as button label; otherwise, it uses “Update Post”.

+ +

Those labels can be customized using I18n under the helpers.submit key (the same as submit helper) and using %{model} for translation interpolation:

+ +
en:
+  helpers:
+    submit:
+      create: "Create a %{model}"
+      update: "Confirm changes to %{model}"
+
+ +

It also searches for a key specific to the given object:

+ +
en:
+  helpers:
+    submit:
+      post:
+        create: "Add %{model}"
+
+ +

Examples

+ +
button("Create post")
+# => <button name='button' type='submit'>Create post</button>
+
+button(:draft, value: true)
+# => <button id="post_draft" name="post[draft]" value="true" type="submit">Create post</button>
+
+button do
+  content_tag(:strong, 'Ask me!')
+end
+# => <button name='button' type='submit'>
+#      <strong>Ask me!</strong>
+#    </button>
+
+button do |text|
+  content_tag(:strong, text)
+end
+# => <button name='button' type='submit'>
+#      <strong>Create post</strong>
+#    </button>
+
+button(:draft, value: true) do
+  content_tag(:strong, "Save as draft")
+end
+# =>  <button id="post_draft" name="post[draft]" value="true" type="submit">
+#       <strong>Save as draft</strong>
+#     </button>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2615
+def button(value = nil, options = {}, &block)
+  case value
+  when Hash
+    value, options = nil, value
+  when Symbol
+    value, options = nil, { name: field_name(value), id: field_id(value) }.merge!(options.to_h)
+  end
+  value ||= submit_default_value
+
+  if block_given?
+    value = @template.capture { yield(value) }
+  end
+
+  formmethod = options[:formmethod]
+  if formmethod.present? && !/post|get/i.match?(formmethod) && !options.key?(:name) && !options.key?(:value)
+    options.merge! formmethod: :post, name: "_method", value: formmethod
+  end
+
+  @template.button_tag(value, options)
+end
+
+
+ +
+ +
+

+ + check_box(method, options = {}, checked_value = "1", unchecked_value = "0") + +

+ + +
+

Returns a checkbox tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). This object must be an instance object (@object) and not a local object. It’s intended that method returns an integer and if that integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a hash with options. The checked_value defaults to 1 while the default unchecked_value is set to 0 which is convenient for boolean values.

+ +

Options

+
  • +

    Any standard HTML attributes for the tag can be passed in, for example :class.

    +
  • +

    :checked - true or false forces the state of the checkbox to be checked or not.

    +
  • +

    :include_hidden - If set to false, the auxiliary hidden field described below will not be generated.

    +
+ +

Gotcha

+ +

The HTML specification says unchecked check boxes are not successful, and thus web browsers do not send them. Unfortunately this introduces a gotcha: if an Invoice model has a paid flag, and in the form that edits a paid invoice the user unchecks its check box, no paid parameter is sent. So, any mass-assignment idiom like

+ +
@invoice.update(params[:invoice])
+
+ +

wouldn’t update the flag.

+ +

To prevent this the helper generates an auxiliary hidden field before every check box. The hidden field has the same name and its attributes mimic an unchecked check box.

+ +

This way, the client either sends only the hidden field (representing the check box is unchecked), or both fields. Since the HTML specification says key/value pairs have to be sent in the same order they appear in the form, and parameters extraction gets the last occurrence of any repeated key in the query string, that works for ordinary forms.

+ +

Unfortunately that workaround does not work when the check box goes within an array-like parameter, as in

+ +
<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
+  <%= form.check_box :paid %>
+  ...
+<% end %>
+
+ +

because parameter name repetition is precisely what Rails seeks to distinguish the elements of the array. For each item with a checked check box you get an extra ghost item with only that attribute, assigned to “0”.

+ +

In that case it is preferable to either use check_box_tag or to use hashes instead of arrays.

+ +

Examples

+ +
# Let's say that @post.validated? is 1:
+check_box("validated")
+# => <input name="post[validated]" type="hidden" value="0" />
+#    <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" />
+
+# Let's say that @puppy.gooddog is "no":
+check_box("gooddog", {}, "yes", "no")
+# => <input name="puppy[gooddog]" type="hidden" value="no" />
+#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
+
+# Let's say that @eula.accepted is "no":
+check_box("accepted", { class: 'eula_check' }, "yes", "no")
+# => <input name="eula[accepted]" type="hidden" value="no" />
+#    <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2439
+def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")
+  @template.check_box(@object_name, method, objectify_options(options), checked_value, unchecked_value)
+end
+
+
+ +
+ +
+

+ + collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#collection_check_boxes for form builders:

+ +
<%= form_for @post do |f| %>
+  <%= f.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 907
+def collection_check_boxes(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
+  @template.collection_check_boxes(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
+end
+
+
+ +
+ +
+

+ + collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#collection_radio_buttons for form builders:

+ +
<%= form_for @post do |f| %>
+  <%= f.collection_radio_buttons :author_id, Author.all, :id, :name_with_initial %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 919
+def collection_radio_buttons(method, collection, value_method, text_method, options = {}, html_options = {}, &block)
+  @template.collection_radio_buttons(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options), &block)
+end
+
+
+ +
+ +
+

+ + collection_select(method, collection, value_method, text_method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#collection_select for form builders:

+ +
<%= form_for @post do |f| %>
+  <%= f.collection_select :person_id, Author.all, :id, :name_with_initial, prompt: true %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 859
+def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
+  @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_html_options.merge(html_options))
+end
+
+
+ +
+ +
+

+ + color_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#color_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.color_field :favorite_color %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1824
+      
+
+
+ +
+ +
+

+ + date_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#date_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.date_field :born_on %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1876
+      
+
+
+ +
+ +
+

+ + date_select(method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::DateHelper#date_select for form builders:

+ +
<%= form_for @person do |f| %>
+  <%= f.date_select :birth_date %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 1239
+def date_select(method, options = {}, html_options = {})
+  @template.date_select(@object_name, method, objectify_options(options), html_options)
+end
+
+
+ +
+ +
+

+ + datetime_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#datetime_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.datetime_field :graduation_day %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1902
+      
+
+
+ +
+ +
+

+ + datetime_local_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#datetime_local_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.datetime_local_field :graduation_day %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1915
+      
+
+
+ +
+ +
+

+ + datetime_select(method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::DateHelper#datetime_select for form builders:

+ +
<%= form_for @person do |f| %>
+  <%= f.datetime_select :last_request_at %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 1263
+def datetime_select(method, options = {}, html_options = {})
+  @template.datetime_select(@object_name, method, objectify_options(options), html_options)
+end
+
+
+ +
+ +
+

+ + email_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#email_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.email_field :address %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1967
+      
+
+
+ +
+ +
+

+ + field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index]) + +

+ + +
+

Generate an HTML id attribute value for the given field

+ +

Return the value generated by the FormBuilder for the given attribute name.

+ +
<%= form_for @post do |f| %>
+  <%= f.label :title %>
+  <%= f.text_field :title, aria: { describedby: f.field_id(:title, :error) } %>
+  <%= tag.span("is blank", id: f.field_id(:title, :error) %>
+<% end %>
+
+ +

In the example above, the <input type="text"> element built by the call to FormBuilder#text_field declares an aria-describedby attribute referencing the <span> element, sharing a common id root (post_title, in this case).

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1758
+def field_id(method, *suffixes, namespace: @options[:namespace], index: @options[:index])
+  @template.field_id(@object_name, method, *suffixes, namespace: namespace, index: index)
+end
+
+
+ +
+ +
+

+ + field_name(method, *methods, multiple: false, index: @options[:index]) + +

+ + +
+

Generate an HTML name attribute value for the given name and field combination

+ +

Return the value generated by the FormBuilder for the given attribute name.

+ +
<%= form_for @post do |f| %>
+  <%= f.text_field :title, name: f.field_name(:title, :subtitle) %>
+  <%# => <input type="text" name="post[title][subtitle]">
+<% end %>
+
+<%= form_for @post do |f| %>
+  <%= f.field_tag :tag, name: f.field_name(:tag, multiple: true) %>
+  <%# => <input type="text" name="post[tag][]">
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1778
+def field_name(method, *methods, multiple: false, index: @options[:index])
+  object_name = @options.fetch(:as) { @object_name }
+
+  @template.field_name(object_name, method, *methods, index: index, multiple: multiple)
+end
+
+
+ +
+ +
+

+ + fields(scope = nil, model: nil, **options, &block) + +

+ + +
+

See the docs for the ActionView::Helpers::FormHelper#fields helper method.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2295
+def fields(scope = nil, model: nil, **options, &block)
+  options[:allow_method_names_outside_object] = true
+  options[:skip_default_ids] = !FormHelper.form_with_generates_ids
+
+  convert_to_legacy_options(options)
+
+  fields_for(scope || model, model, options, &block)
+end
+
+
+ +
+ +
+

+ + fields_for(record_name, record_object = nil, fields_options = {}, &block) + +

+ + +
+

Creates a scope around a specific model object like form_for, but doesn’t create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form.

+ +

Although the usage and purpose of fields_for is similar to form_for‘s, its method signature is slightly different. Like form_for, it yields a FormBuilder object associated with a particular model object to a block, and within the block allows methods to be called on the builder to generate fields associated with the model object. Fields may reflect a model object in two ways - how they are named (hence how submitted values appear within the params hash in the controller) and what default values are shown when the form the fields appear in is first displayed. In order for both of these features to be specified independently, both an object name (represented by either a symbol or string) and the object itself can be passed to the method separately -

+ +
<%= form_for @person do |person_form| %>
+  First name: <%= person_form.text_field :first_name %>
+  Last name : <%= person_form.text_field :last_name %>
+
+  <%= fields_for :permission, @person.permission do |permission_fields| %>
+    Admin?  : <%= permission_fields.check_box :admin %>
+  <% end %>
+
+  <%= person_form.submit %>
+<% end %>
+
+ +

In this case, the checkbox field will be represented by an HTML input tag with the name attribute permission[admin], and the submitted value will appear in the controller as params[:permission][:admin]. If @person.permission is an existing record with an attribute admin, the initial state of the checkbox when first displayed will reflect the value of @person.permission.admin.

+ +

Often this can be simplified by passing just the name of the model object to fields_for -

+ +
<%= fields_for :permission do |permission_fields| %>
+  Admin?: <%= permission_fields.check_box :admin %>
+<% end %>
+
+ +

…in which case, if :permission also happens to be the name of an instance variable @permission, the initial state of the input field will reflect the value of that variable’s attribute @permission.admin.

+ +

Alternatively, you can pass just the model object itself (if the first argument isn’t a string or symbol fields_for will realize that the name has been omitted) -

+ +
<%= fields_for @person.permission do |permission_fields| %>
+  Admin?: <%= permission_fields.check_box :admin %>
+<% end %>
+
+ +

and fields_for will derive the required name of the field from the class of the model object, e.g. if @person.permission, is of class Permission, the field will still be named permission[admin].

+ +

Note: This also works for the methods in FormOptionsHelper and DateHelper that are designed to work with an object as base, like FormOptionsHelper#collection_select and DateHelper#datetime_select.

+ +

Nested Attributes Examples

+ +

When the object belonging to the current scope has a nested attribute writer for a certain attribute, fields_for will yield a new scope for that attribute. This allows you to create forms that set or change the attributes of a parent object and its associations in one go.

+ +

Nested attribute writers are normal setter methods named after an association. The most common way of defining these writers is either with accepts_nested_attributes_for in a model definition or by defining a method with the proper name. For example: the attribute writer for the association :address is called address_attributes=.

+ +

Whether a one-to-one or one-to-many style form builder will be yielded depends on whether the normal reader method returns a single object or an array of objects.

+ +

One-to-one

+ +

Consider a Person class which returns a single Address from the address reader method and responds to the address_attributes= writer method:

+ +
class Person
+  def address
+    @address
+  end
+
+  def address_attributes=(attributes)
+    # Process the attributes hash
+  end
+end
+
+ +

This model can now be used with a nested fields_for, like so:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :address do |address_fields| %>
+    Street  : <%= address_fields.text_field :street %>
+    Zip code: <%= address_fields.text_field :zip_code %>
+  <% end %>
+  ...
+<% end %>
+
+ +

When address is already an association on a Person you can use accepts_nested_attributes_for to define the writer method for you:

+ +
class Person < ActiveRecord::Base
+  has_one :address
+  accepts_nested_attributes_for :address
+end
+
+ +

If you want to destroy the associated model through the form, you have to enable it first using the :allow_destroy option for accepts_nested_attributes_for:

+ +
class Person < ActiveRecord::Base
+  has_one :address
+  accepts_nested_attributes_for :address, allow_destroy: true
+end
+
+ +

Now, when you use a form element with the _destroy parameter, with a value that evaluates to true, you will destroy the associated model (e.g. 1, ‘1’, true, or ‘true’):

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :address do |address_fields| %>
+    ...
+    Delete: <%= address_fields.check_box :_destroy %>
+  <% end %>
+  ...
+<% end %>
+
+ +

One-to-many

+ +

Consider a Person class which returns an array of Project instances from the projects reader method and responds to the projects_attributes= writer method:

+ +
class Person
+  def projects
+    [@project1, @project2]
+  end
+
+  def projects_attributes=(attributes)
+    # Process the attributes hash
+  end
+end
+
+ +

Note that the projects_attributes= writer method is in fact required for fields_for to correctly identify :projects as a collection, and the correct indices to be set in the form markup.

+ +

When projects is already an association on Person you can use accepts_nested_attributes_for to define the writer method for you:

+ +
class Person < ActiveRecord::Base
+  has_many :projects
+  accepts_nested_attributes_for :projects
+end
+
+ +

This model can now be used with a nested fields_for. The block given to the nested fields_for call will be repeated for each instance in the collection:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    <% if project_fields.object.active? %>
+      Name: <%= project_fields.text_field :name %>
+    <% end %>
+  <% end %>
+  ...
+<% end %>
+
+ +

It’s also possible to specify the instance to be used:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <% @person.projects.each do |project| %>
+    <% if project.active? %>
+      <%= person_form.fields_for :projects, project do |project_fields| %>
+        Name: <%= project_fields.text_field :name %>
+      <% end %>
+    <% end %>
+  <% end %>
+  ...
+<% end %>
+
+ +

Or a collection to be used:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
+    Name: <%= project_fields.text_field :name %>
+  <% end %>
+  ...
+<% end %>
+
+ +

If you want to destroy any of the associated models through the form, you have to enable it first using the :allow_destroy option for accepts_nested_attributes_for:

+ +
class Person < ActiveRecord::Base
+  has_many :projects
+  accepts_nested_attributes_for :projects, allow_destroy: true
+end
+
+ +

This will allow you to specify which models to destroy in the attributes hash by adding a form element for the _destroy parameter with a value that evaluates to true (e.g. 1, ‘1’, true, or ‘true’):

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    Delete: <%= project_fields.check_box :_destroy %>
+  <% end %>
+  ...
+<% end %>
+
+ +

When a collection is used you might want to know the index of each object into the array. For this purpose, the index method is available in the FormBuilder object.

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    Project #<%= project_fields.index %>
+    ...
+  <% end %>
+  ...
+<% end %>
+
+ +

Note that fields_for will automatically generate a hidden field to store the ID of the record. There are circumstances where this hidden field is not needed and you can pass include_id: false to prevent fields_for from rendering it automatically.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2258
+def fields_for(record_name, record_object = nil, fields_options = {}, &block)
+  fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
+  fields_options[:builder] ||= options[:builder]
+  fields_options[:namespace] = options[:namespace]
+  fields_options[:parent_builder] = self
+
+  case record_name
+  when String, Symbol
+    if nested_attributes_association?(record_name)
+      return fields_for_with_nested_attributes(record_name, record_object, fields_options, block)
+    end
+  else
+    record_object = @template._object_for_form_builder(record_name)
+    record_name   = model_name_from_record_or_class(record_object).param_key
+  end
+
+  object_name = @object_name
+  index = if options.has_key?(:index)
+    options[:index]
+  elsif defined?(@auto_index)
+    object_name = object_name.to_s.delete_suffix("[]")
+    @auto_index
+  end
+
+  record_name = if index
+    "#{object_name}[#{index}][#{record_name}]"
+  elsif record_name.end_with?("[]")
+    "#{object_name}[#{record_name[0..-3]}][#{record_object.id}]"
+  else
+    "#{object_name}[#{record_name}]"
+  end
+  fields_options[:child_index] = index
+
+  @template.fields_for(record_name, record_object, fields_options, &block)
+end
+
+
+ +
+ +
+

+ + file_field(method, options = {}) + +

+ + +
+

Returns a file upload input tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown.

+ +

Using this method inside a form_with block will set the enclosing form’s encoding to multipart/form-data.

+ +

Options

+
  • +

    Creates standard HTML attributes for the tag.

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :multiple - If set to true, *in most updated browsers* the user will be allowed to select multiple files.

    +
  • +

    :include_hidden - When multiple: true and include_hidden: true, the field will be prefixed with an <input type="hidden"> field with an empty value to support submitting an empty collection of files.

    +
  • +

    :accept - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.

    +
+ +

Examples

+ +
# Let's say that @user has avatar:
+file_field(:avatar)
+# => <input type="file" id="user_avatar" name="user[avatar]" />
+
+# Let's say that @post has image:
+file_field(:image, :multiple => true)
+# => <input type="file" id="post_image" name="post[image][]" multiple="multiple" />
+
+# Let's say that @post has attached:
+file_field(:attached, accept: 'text/html')
+# => <input accept="text/html" type="file" id="post_attached" name="post[attached]" />
+
+# Let's say that @post has image:
+file_field(:image, accept: 'image/png,image/gif,image/jpeg')
+# => <input type="file" id="post_image" name="post[image]" accept="image/png,image/gif,image/jpeg" />
+
+# Let's say that @attachment has file:
+file_field(:file, class: 'file_input')
+# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2522
+def file_field(method, options = {})
+  self.multipart = true
+  @template.file_field(@object_name, method, objectify_options(options))
+end
+
+
+ +
+ +
+

+ + grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#grouped_collection_select for form builders:

+ +
<%= form_for @city do |f| %>
+  <%= f.grouped_collection_select :country_id, @continents, :countries, :name, :id, :name %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 871
+def grouped_collection_select(method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
+  @template.grouped_collection_select(@object_name, method, collection, group_method, group_label_method, option_key_method, option_value_method, objectify_options(options), @default_html_options.merge(html_options))
+end
+
+
+ +
+ +
+

+ + hidden_field(method, options = {}) + +

+ + +
+

Returns a hidden input tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown.

+ +

Examples

+ +
# Let's say that @signup.pass_confirm returns true:
+hidden_field(:pass_confirm)
+# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="true" />
+
+# Let's say that @post.tag_list returns "blog, ruby":
+hidden_field(:tag_list)
+# => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="blog, ruby" />
+
+# Let's say that @user.token returns "abcde":
+hidden_field(:token)
+# => <input type="hidden" id="user_token" name="user[token]" value="abcde" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2483
+def hidden_field(method, options = {})
+  @emitted_hidden_id = true if method == :id
+  @template.hidden_field(@object_name, method, objectify_options(options))
+end
+
+
+ +
+ +
+

+ + id() + +

+ + +
+

Generate an HTML id attribute value.

+ +

return the <form> element’s id attribute.

+ +
<%= form_for @post do |f| %>
+  <%# ... %>
+
+  <% content_for :sticky_footer do %>
+    <%= form.button(form: f.id) %>
+  <% end %>
+<% end %>
+
+ +

In the example above, the :sticky_footer content area will exist outside of the <form> element. By declaring the form HTML attribute, we hint to the browser that the generated <button> element should be treated as the <form> element’s submit button, regardless of where it exists in the DOM.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1738
+def id
+  options.dig(:html, :id) || options[:id]
+end
+
+
+ +
+ +
+

+ + label(method, text = nil, options = {}, &block) + +

+ + +
+

Returns a label tag tailored for labelling an input field for a specified attribute (identified by method) on an object assigned to the template (identified by object). The text of label will default to the attribute name unless a translation is found in the current I18n locale (through helpers.label.<modelname>.<attribute>) or you specify it explicitly. Additional options on the label tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown, except for the :value option, which is designed to target labels for radio_button tags (where the value is used in the ID of the input tag).

+ +

Examples

+ +
label(:title)
+# => <label for="post_title">Title</label>
+
+ +

You can localize your labels based on model and attribute names. For example you can define the following in your locale (e.g. en.yml)

+ +
helpers:
+  label:
+    post:
+      body: "Write your entire text here"
+
+ +

Which then will result in

+ +
label(:body)
+# => <label for="post_body">Write your entire text here</label>
+
+ +

Localization can also be based purely on the translation of the attribute-name (if you are using ActiveRecord):

+ +
activerecord:
+  attributes:
+    post:
+      cost: "Total cost"
+
+label(:cost)
+# => <label for="post_cost">Total cost</label>
+
+label(:title, "A short title")
+# => <label for="post_title">A short title</label>
+
+label(:title, "A short title", class: "title_label")
+# => <label for="post_title" class="title_label">A short title</label>
+
+label(:privacy, "Public Post", value: "public")
+# => <label for="post_privacy_public">Public Post</label>
+
+label(:cost) do |translation|
+  content_tag(:span, translation, class: "cost_label")
+end
+# => <label for="post_cost"><span class="cost_label">Total cost</span></label>
+
+label(:cost) do |builder|
+  content_tag(:span, builder.translation, class: "cost_label")
+end
+# => <label for="post_cost"><span class="cost_label">Total cost</span></label>
+
+label(:cost) do |builder|
+  content_tag(:span, builder.translation, class: [
+    "cost_label",
+    ("error_label" if builder.object.errors.include?(:cost))
+  ])
+end
+# => <label for="post_cost"><span class="cost_label error_label">Total cost</span></label>
+
+label(:terms) do
+  raw('Accept <a href="/terms">Terms</a>.')
+end
+# => <label for="post_terms">Accept <a href="/terms">Terms</a>.</label>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2370
+def label(method, text = nil, options = {}, &block)
+  @template.label(@object_name, method, text, objectify_options(options), &block)
+end
+
+
+ +
+ +
+

+ + month_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#month_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.month_field :birthday_month %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1928
+      
+
+
+ +
+ +
+

+ + multipart=(multipart) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1681
+def multipart=(multipart)
+  @multipart = multipart
+
+  if parent_builder = @options[:parent_builder]
+    parent_builder.multipart = multipart
+  end
+end
+
+
+ +
+ +
+

+ + number_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#number_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.number_field :age %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1980
+      
+
+
+ +
+ +
+

+ + password_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#password_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.password_field :password %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1798
+      
+
+
+ +
+ +
+

+ + phone_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#phone_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.phone_field :phone %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1863
+      
+
+
+ +
+ +
+

+ + radio_button(method, tag_value, options = {}) + +

+ + +
+

Returns a radio button tag for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). If the current value of method is tag_value the radio button will be checked.

+ +

To force the radio button to be checked pass checked: true in the options hash. You may pass HTML options there as well.

+ +
# Let's say that @post.category returns "rails":
+radio_button("category", "rails")
+radio_button("category", "java")
+# => <input type="radio" id="post_category_rails" name="post[category]" value="rails" checked="checked" />
+#    <input type="radio" id="post_category_java" name="post[category]" value="java" />
+
+# Let's say that @user.receive_newsletter returns "no":
+radio_button("receive_newsletter", "yes")
+radio_button("receive_newsletter", "no")
+# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
+#    <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2461
+def radio_button(method, tag_value, options = {})
+  @template.radio_button(@object_name, method, tag_value, objectify_options(options))
+end
+
+
+ +
+ +
+

+ + range_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#range_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.range_field :age %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1993
+      
+
+
+ +
+ +
+

+ + rich_text_area(method, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/tag_helper.rb, line 85
+def rich_text_area(method, options = {})
+  @template.rich_text_area(@object_name, method, objectify_options(options))
+end
+
+
+ +
+ +
+

+ + search_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#search_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.search_field :name %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1837
+      
+
+
+ +
+ +
+

+ + select(method, choices = nil, options = {}, html_options = {}, &block) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#select for form builders:

+ +
<%= form_for @post do |f| %>
+  <%= f.select :person_id, Person.all.collect { |p| [ p.name, p.id ] }, include_blank: true %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 847
+def select(method, choices = nil, options = {}, html_options = {}, &block)
+  @template.select(@object_name, method, choices, objectify_options(options), @default_html_options.merge(html_options), &block)
+end
+
+
+ +
+ +
+

+ + submit(value = nil, options = {}) + +

+ + +
+

Add the submit button for the given form. When no value is given, it checks if the object is a new resource or not to create the proper label:

+ +
<%= form_for @post do |f| %>
+  <%= f.submit %>
+<% end %>
+
+ +

In the example above, if @post is a new record, it will use “Create Post” as submit button label; otherwise, it uses “Update Post”.

+ +

Those labels can be customized using I18n under the helpers.submit key and using %{model} for translation interpolation:

+ +
en:
+  helpers:
+    submit:
+      create: "Create a %{model}"
+      update: "Confirm changes to %{model}"
+
+ +

It also searches for a key specific to the given object:

+ +
en:
+  helpers:
+    submit:
+      post:
+        create: "Add %{model}"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 2554
+def submit(value = nil, options = {})
+  value, options = nil, value if value.is_a?(Hash)
+  value ||= submit_default_value
+  @template.submit_tag(value, options)
+end
+
+
+ +
+ +
+

+ + telephone_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#telephone_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.telephone_field :phone %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1850
+      
+
+
+ +
+ +
+

+ + text_area(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#text_area for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.text_area :detail %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1811
+      
+
+
+ +
+ +
+

+ + text_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#text_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.text_field :name %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1785
+      
+
+
+ +
+ +
+

+ + time_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#time_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.time_field :born_at %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1889
+      
+
+
+ +
+ +
+

+ + time_select(method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::DateHelper#time_select for form builders:

+ +
<%= form_for @race do |f| %>
+  <%= f.time_select :average_lap %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/date_helper.rb, line 1251
+def time_select(method, options = {}, html_options = {})
+  @template.time_select(@object_name, method, objectify_options(options), html_options)
+end
+
+
+ +
+ +
+

+ + time_zone_select(method, priority_zones = nil, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#time_zone_select for form builders:

+ +
<%= form_for @user do |f| %>
+  <%= f.time_zone_select :time_zone, nil, include_blank: true %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 883
+def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
+  @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_html_options.merge(html_options))
+end
+
+
+ +
+ +
+

+ + to_model() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1697
+def to_model
+  self
+end
+
+
+ +
+ +
+

+ + to_partial_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1693
+def to_partial_path
+  self.class._to_partial_path
+end
+
+
+ +
+ +
+

+ + url_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#url_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.url_field :homepage %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1954
+      
+
+
+ +
+ +
+

+ + week_field(method, options = {}) + + +

+ + +
+

Wraps ActionView::Helpers::FormHelper#week_field for form builders:

+ +
<%= form_with model: @user do |f| %>
+  <%= f.week_field :birthday_week %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1941
+      
+
+
+ +
+ +
+

+ + weekday_select(method, options = {}, html_options = {}) + +

+ + +
+

Wraps ActionView::Helpers::FormOptionsHelper#weekday_select for form builders:

+ +
<%= form_for @user do |f| %>
+  <%= f.weekday_select :weekday, include_blank: true %>
+  <%= f.submit %>
+<% end %>
+
+ +

Please refer to the documentation of the base helper for details.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 895
+def weekday_select(method, options = {}, html_options = {})
+  @template.weekday_select(@object_name, method, objectify_options(options), @default_html_options.merge(html_options))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/FormHelper.html b/src/7.0/classes/ActionView/Helpers/FormHelper.html new file mode 100644 index 0000000000..b952d4a508 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/FormHelper.html @@ -0,0 +1,2390 @@ +--- +title: ActionView::Helpers::FormHelper +layout: default +--- +
+ +
+
+ +
+ +

Form helpers are designed to make working with resources much easier compared to using vanilla HTML.

+ +

Typically, a form designed to create or update a resource reflects the identity of the resource in several ways: (i) the URL that the form is sent to (the form element’s action attribute) should result in a request being routed to the appropriate controller action (with the appropriate :id parameter in the case of an existing resource), (ii) input fields should be named in such a way that in the controller their values appear in the appropriate places within the params hash, and (iii) for an existing record, when the form is initially displayed, input fields corresponding to attributes of the resource should show the current values of those attributes.

+ +

In Rails, this is usually achieved by creating the form using form_for and a number of related helper methods. form_for generates an appropriate form tag and yields a form builder object that knows the model the form is about. Input fields are created by calling methods defined on the form builder, which means they are able to generate the appropriate names and default values corresponding to the model attributes, as well as convenient IDs, etc. Conventions in the generated field names allow controllers to receive form data nicely structured in params with no effort on your side.

+ +

For example, to create a new person you typically set up a new instance of Person in the PeopleController#new action, @person, and in the view template pass that object to form_for:

+ +
<%= form_for @person do |f| %>
+  <%= f.label :first_name %>:
+  <%= f.text_field :first_name %><br />
+
+  <%= f.label :last_name %>:
+  <%= f.text_field :last_name %><br />
+
+  <%= f.submit %>
+<% end %>
+
+ +

The HTML generated for this would be (modulus formatting):

+ +
<form action="/people" class="new_person" id="new_person" method="post">
+  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
+  <label for="person_first_name">First name</label>:
+  <input id="person_first_name" name="person[first_name]" type="text" /><br />
+
+  <label for="person_last_name">Last name</label>:
+  <input id="person_last_name" name="person[last_name]" type="text" /><br />
+
+  <input name="commit" type="submit" value="Create Person" />
+</form>
+
+ +

As you see, the HTML reflects knowledge about the resource in several spots, like the path the form should be submitted to, or the names of the input fields.

+ +

In particular, thanks to the conventions followed in the generated field names, the controller gets a nested hash params[:person] with the person attributes set in the form. That hash is ready to be passed to Person.new:

+ +
@person = Person.new(params[:person])
+if @person.save
+  # success
+else
+  # error handling
+end
+
+ +

Interestingly, the exact same view code in the previous example can be used to edit a person. If @person is an existing record with name “John Smith” and ID 256, the code above as is would yield instead:

+ +
<form action="/people/256" class="edit_person" id="edit_person_256" method="post">
+  <input name="_method" type="hidden" value="patch" />
+  <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
+  <label for="person_first_name">First name</label>:
+  <input id="person_first_name" name="person[first_name]" type="text" value="John" /><br />
+
+  <label for="person_last_name">Last name</label>:
+  <input id="person_last_name" name="person[last_name]" type="text" value="Smith" /><br />
+
+  <input name="commit" type="submit" value="Update Person" />
+</form>
+
+ +

Note that the endpoint, default values, and submit button label are tailored for @person. That works that way because the involved helpers know whether the resource is a new record or not, and generate HTML accordingly.

+ +

The controller would receive the form data again in params[:person], ready to be passed to Person#update:

+ +
if @person.update(params[:person])
+  # success
+else
+  # error handling
+end
+
+ +

That’s how you typically work with resources.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0") + +

+ + +
+

Returns a checkbox tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). This object must be an instance object (@object) and not a local object. It’s intended that method returns an integer and if that integer is above zero, then the checkbox is checked. Additional options on the input tag can be passed as a hash with options. The checked_value defaults to 1 while the default unchecked_value is set to 0 which is convenient for boolean values.

+ +

Options

+
  • +

    Any standard HTML attributes for the tag can be passed in, for example :class.

    +
  • +

    :checked - true or false forces the state of the checkbox to be checked or not.

    +
  • +

    :include_hidden - If set to false, the auxiliary hidden field described below will not be generated.

    +
+ +

Gotcha

+ +

The HTML specification says unchecked check boxes are not successful, and thus web browsers do not send them. Unfortunately this introduces a gotcha: if an Invoice model has a paid flag, and in the form that edits a paid invoice the user unchecks its check box, no paid parameter is sent. So, any mass-assignment idiom like

+ +
@invoice.update(params[:invoice])
+
+ +

wouldn’t update the flag.

+ +

To prevent this the helper generates an auxiliary hidden field before every check box. The hidden field has the same name and its attributes mimic an unchecked check box.

+ +

This way, the client either sends only the hidden field (representing the check box is unchecked), or both fields. Since the HTML specification says key/value pairs have to be sent in the same order they appear in the form, and parameters extraction gets the last occurrence of any repeated key in the query string, that works for ordinary forms.

+ +

Unfortunately that workaround does not work when the check box goes within an array-like parameter, as in

+ +
<%= fields_for "project[invoice_attributes][]", invoice, index: nil do |form| %>
+  <%= form.check_box :paid %>
+  ...
+<% end %>
+
+ +

because parameter name repetition is precisely what Rails seeks to distinguish the elements of the array. For each item with a checked check box you get an extra ghost item with only that attribute, assigned to “0”.

+ +

In that case it is preferable to either use check_box_tag or to use hashes instead of arrays.

+ +

Examples

+ +
# Let's say that @post.validated? is 1:
+check_box("post", "validated")
+# => <input name="post[validated]" type="hidden" value="0" />
+#    <input checked="checked" type="checkbox" id="post_validated" name="post[validated]" value="1" />
+
+# Let's say that @puppy.gooddog is "no":
+check_box("puppy", "gooddog", {}, "yes", "no")
+# => <input name="puppy[gooddog]" type="hidden" value="no" />
+#    <input type="checkbox" id="puppy_gooddog" name="puppy[gooddog]" value="yes" />
+
+check_box("eula", "accepted", { class: 'eula_check' }, "yes", "no")
+# => <input name="eula[accepted]" type="hidden" value="no" />
+#    <input type="checkbox" class="eula_check" id="eula_accepted" name="eula[accepted]" value="yes" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1337
+def check_box(object_name, method, options = {}, checked_value = "1", unchecked_value = "0")
+  Tags::CheckBox.new(object_name, method, self, checked_value, unchecked_value, options).render
+end
+
+
+ +
+ +
+

+ + color_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “color”.

+ +
color_field("car", "color")
+# => <input id="car_color" name="car[color]" type="color" value="#000000" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1367
+def color_field(object_name, method, options = {})
+  Tags::ColorField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + date_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “date”.

+ +
date_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="date" />
+
+ +

The default value is generated by trying to call strftime with “%Y-%m-%d” on the object’s value, which makes it behave as expected for instances of DateTime and ActiveSupport::TimeWithZone. You can still override that by passing the “value” option explicitly, e.g.

+ +
@user.born_on = Date.new(1984, 1, 27)
+date_field("user", "born_on", value: "1984-05-12")
+# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-05-12" />
+
+ +

You can create values for the “min” and “max” attributes by passing instances of Date or Time to the options hash.

+ +
date_field("user", "born_on", min: Date.today)
+# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
+
+ +

Alternatively, you can pass a String formatted as an ISO8601 date as the values for “min” and “max.”

+ +
date_field("user", "born_on", min: "2014-05-20")
+# => <input id="user_born_on" name="user[born_on]" type="date" min="2014-05-20" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1431
+def date_field(object_name, method, options = {})
+  Tags::DateField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + datetime_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “datetime-local”.

+ +
datetime_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="datetime-local" />
+
+ +

The default value is generated by trying to call strftime with “%Y-%m-%dT%T” on the object’s value, which makes it behave as expected for instances of DateTime and ActiveSupport::TimeWithZone.

+ +
@user.born_on = Date.new(1984, 1, 12)
+datetime_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="datetime-local" value="1984-01-12T00:00:00" />
+
+ +

You can create values for the “min” and “max” attributes by passing instances of Date or Time to the options hash.

+ +
datetime_field("user", "born_on", min: Date.today)
+# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
+
+ +

Alternatively, you can pass a String formatted as an ISO8601 datetime as the values for “min” and “max.”

+ +
datetime_field("user", "born_on", min: "2014-05-20T00:00:00")
+# => <input id="user_born_on" name="user[born_on]" type="datetime-local" min="2014-05-20T00:00:00.000" />
+
+
+ + + +
+ Also aliased as: datetime_local_field +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1498
+def datetime_field(object_name, method, options = {})
+  Tags::DatetimeLocalField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + datetime_local_field(object_name, method, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: datetime_field +
+ + + +
+ +
+

+ + email_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “email”.

+ +
email_field("user", "address")
+# => <input id="user_address" name="user[address]" type="email" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1552
+def email_field(object_name, method, options = {})
+  Tags::EmailField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + fields(scope = nil, model: nil, **options, &block) + +

+ + +
+

Scopes input fields with either an explicit scope or model. Like form_with does with :scope or :model, except it doesn’t output the form tags.

+ +
# Using a scope prefixes the input field names:
+<%= fields :comment do |fields| %>
+  <%= fields.text_field :body %>
+<% end %>
+# => <input type="text" name="comment[body]">
+
+# Using a model infers the scope and assigns field values:
+<%= fields model: Comment.new(body: "full bodied") do |fields| %>
+  <%= fields.text_field :body %>
+<% end %>
+# => <input type="text" name="comment[body]" value="full bodied">
+
+# Using +fields+ with +form_with+:
+<%= form_with model: @post do |form| %>
+  <%= form.text_field :title %>
+
+  <%= form.fields :comment do |fields| %>
+    <%= fields.text_field :body %>
+  <% end %>
+<% end %>
+
+ +

Much like form_with a FormBuilder instance associated with the scope or model is yielded, so any generated field names are prefixed with either the passed scope or the scope inferred from the :model.

+ +

Mixing with other form helpers

+ +

While form_with uses a FormBuilder object it’s possible to mix and match the stand-alone FormHelper methods and methods from FormTagHelper:

+ +
<%= fields model: @comment do |fields| %>
+  <%= fields.text_field :body %>
+
+  <%= text_area :commenter, :biography %>
+  <%= check_box_tag "comment[all_caps]", "1", @comment.commenter.hulk_mode? %>
+<% end %>
+
+ +

Same goes for the methods in FormOptionsHelper and DateHelper designed to work with an object as a base, like FormOptionsHelper#collection_select and DateHelper#datetime_select.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1073
+def fields(scope = nil, model: nil, **options, &block)
+  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
+
+  if model
+    model   = _object_for_form_builder(model)
+    scope ||= model_name_from_record_or_class(model).param_key
+  end
+
+  builder = instantiate_builder(scope, model, options)
+  capture(builder, &block)
+end
+
+
+ +
+ +
+

+ + fields_for(record_name, record_object = nil, options = {}, &block) + +

+ + +
+

Creates a scope around a specific model object like form_for, but doesn’t create the form tags themselves. This makes fields_for suitable for specifying additional model objects in the same form.

+ +

Although the usage and purpose of fields_for is similar to form_for‘s, its method signature is slightly different. Like form_for, it yields a FormBuilder object associated with a particular model object to a block, and within the block allows methods to be called on the builder to generate fields associated with the model object. Fields may reflect a model object in two ways - how they are named (hence how submitted values appear within the params hash in the controller) and what default values are shown when the form the fields appear in is first displayed. In order for both of these features to be specified independently, both an object name (represented by either a symbol or string) and the object itself can be passed to the method separately -

+ +
<%= form_for @person do |person_form| %>
+  First name: <%= person_form.text_field :first_name %>
+  Last name : <%= person_form.text_field :last_name %>
+
+  <%= fields_for :permission, @person.permission do |permission_fields| %>
+    Admin?  : <%= permission_fields.check_box :admin %>
+  <% end %>
+
+  <%= person_form.submit %>
+<% end %>
+
+ +

In this case, the checkbox field will be represented by an HTML input tag with the name attribute permission[admin], and the submitted value will appear in the controller as params[:permission][:admin]. If @person.permission is an existing record with an attribute admin, the initial state of the checkbox when first displayed will reflect the value of @person.permission.admin.

+ +

Often this can be simplified by passing just the name of the model object to fields_for -

+ +
<%= fields_for :permission do |permission_fields| %>
+  Admin?: <%= permission_fields.check_box :admin %>
+<% end %>
+
+ +

…in which case, if :permission also happens to be the name of an instance variable @permission, the initial state of the input field will reflect the value of that variable’s attribute @permission.admin.

+ +

Alternatively, you can pass just the model object itself (if the first argument isn’t a string or symbol fields_for will realize that the name has been omitted) -

+ +
<%= fields_for @person.permission do |permission_fields| %>
+  Admin?: <%= permission_fields.check_box :admin %>
+<% end %>
+
+ +

and fields_for will derive the required name of the field from the class of the model object, e.g. if @person.permission, is of class Permission, the field will still be named permission[admin].

+ +

Note: This also works for the methods in FormOptionsHelper and DateHelper that are designed to work with an object as base, like FormOptionsHelper#collection_select and DateHelper#datetime_select.

+ +

Nested Attributes Examples

+ +

When the object belonging to the current scope has a nested attribute writer for a certain attribute, fields_for will yield a new scope for that attribute. This allows you to create forms that set or change the attributes of a parent object and its associations in one go.

+ +

Nested attribute writers are normal setter methods named after an association. The most common way of defining these writers is either with accepts_nested_attributes_for in a model definition or by defining a method with the proper name. For example: the attribute writer for the association :address is called address_attributes=.

+ +

Whether a one-to-one or one-to-many style form builder will be yielded depends on whether the normal reader method returns a single object or an array of objects.

+ +

One-to-one

+ +

Consider a Person class which returns a single Address from the address reader method and responds to the address_attributes= writer method:

+ +
class Person
+  def address
+    @address
+  end
+
+  def address_attributes=(attributes)
+    # Process the attributes hash
+  end
+end
+
+ +

This model can now be used with a nested fields_for, like so:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :address do |address_fields| %>
+    Street  : <%= address_fields.text_field :street %>
+    Zip code: <%= address_fields.text_field :zip_code %>
+  <% end %>
+  ...
+<% end %>
+
+ +

When address is already an association on a Person you can use accepts_nested_attributes_for to define the writer method for you:

+ +
class Person < ActiveRecord::Base
+  has_one :address
+  accepts_nested_attributes_for :address
+end
+
+ +

If you want to destroy the associated model through the form, you have to enable it first using the :allow_destroy option for accepts_nested_attributes_for:

+ +
class Person < ActiveRecord::Base
+  has_one :address
+  accepts_nested_attributes_for :address, allow_destroy: true
+end
+
+ +

Now, when you use a form element with the _destroy parameter, with a value that evaluates to true, you will destroy the associated model (e.g. 1, ‘1’, true, or ‘true’):

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :address do |address_fields| %>
+    ...
+    Delete: <%= address_fields.check_box :_destroy %>
+  <% end %>
+  ...
+<% end %>
+
+ +

One-to-many

+ +

Consider a Person class which returns an array of Project instances from the projects reader method and responds to the projects_attributes= writer method:

+ +
class Person
+  def projects
+    [@project1, @project2]
+  end
+
+  def projects_attributes=(attributes)
+    # Process the attributes hash
+  end
+end
+
+ +

Note that the projects_attributes= writer method is in fact required for fields_for to correctly identify :projects as a collection, and the correct indices to be set in the form markup.

+ +

When projects is already an association on Person you can use accepts_nested_attributes_for to define the writer method for you:

+ +
class Person < ActiveRecord::Base
+  has_many :projects
+  accepts_nested_attributes_for :projects
+end
+
+ +

This model can now be used with a nested fields_for. The block given to the nested fields_for call will be repeated for each instance in the collection:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    <% if project_fields.object.active? %>
+      Name: <%= project_fields.text_field :name %>
+    <% end %>
+  <% end %>
+  ...
+<% end %>
+
+ +

It’s also possible to specify the instance to be used:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <% @person.projects.each do |project| %>
+    <% if project.active? %>
+      <%= person_form.fields_for :projects, project do |project_fields| %>
+        Name: <%= project_fields.text_field :name %>
+      <% end %>
+    <% end %>
+  <% end %>
+  ...
+<% end %>
+
+ +

Or a collection to be used:

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
+    Name: <%= project_fields.text_field :name %>
+  <% end %>
+  ...
+<% end %>
+
+ +

If you want to destroy any of the associated models through the form, you have to enable it first using the :allow_destroy option for accepts_nested_attributes_for:

+ +
class Person < ActiveRecord::Base
+  has_many :projects
+  accepts_nested_attributes_for :projects, allow_destroy: true
+end
+
+ +

This will allow you to specify which models to destroy in the attributes hash by adding a form element for the _destroy parameter with a value that evaluates to true (e.g. 1, ‘1’, true, or ‘true’):

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    Delete: <%= project_fields.check_box :_destroy %>
+  <% end %>
+  ...
+<% end %>
+
+ +

When a collection is used you might want to know the index of each object into the array. For this purpose, the index method is available in the FormBuilder object.

+ +
<%= form_for @person do |person_form| %>
+  ...
+  <%= person_form.fields_for :projects do |project_fields| %>
+    Project #<%= project_fields.index %>
+    ...
+  <% end %>
+  ...
+<% end %>
+
+ +

Note that fields_for will automatically generate a hidden field to store the ID of the record if it responds to persisted?. There are circumstances where this hidden field is not needed and you can pass include_id: false to prevent fields_for from rendering it automatically.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1022
+def fields_for(record_name, record_object = nil, options = {}, &block)
+  options = { model: record_object, allow_method_names_outside_object: false, skip_default_ids: false }.merge!(options)
+
+  fields(record_name, **options, &block)
+end
+
+
+ +
+ +
+

+ + file_field(object_name, method, options = {}) + +

+ + +
+

Returns a file upload input tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown.

+ +

Using this method inside a form_for block will set the enclosing form’s encoding to multipart/form-data.

+ +

Options

+
  • +

    Creates standard HTML attributes for the tag.

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :multiple - If set to true, *in most updated browsers* the user will be allowed to select multiple files.

    +
  • +

    :include_hidden - When multiple: true and include_hidden: true, the field will be prefixed with an <input type="hidden"> field with an empty value to support submitting an empty collection of files.

    +
  • +

    :accept - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.

    +
+ +

Examples

+ +
file_field(:user, :avatar)
+# => <input type="file" id="user_avatar" name="user[avatar]" />
+
+file_field(:post, :image, multiple: true)
+# => <input type="file" id="post_image" name="post[image][]" multiple="multiple" />
+
+file_field(:post, :attached, accept: 'text/html')
+# => <input accept="text/html" type="file" id="post_attached" name="post[attached]" />
+
+file_field(:post, :image, accept: 'image/png,image/gif,image/jpeg')
+# => <input type="file" id="post_image" name="post[image]" accept="image/png,image/gif,image/jpeg" />
+
+file_field(:attachment, :file, class: 'file_input')
+# => <input type="file" id="attachment_file" name="attachment[file]" class="file_input" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1239
+def file_field(object_name, method, options = {})
+  options = { include_hidden: multiple_file_field_include_hidden }.merge!(options)
+
+  Tags::FileField.new(object_name, method, self, convert_direct_upload_option_to_url(options.dup)).render
+end
+
+
+ +
+ +
+

+ + form_for(record, options = {}, &block) + +

+ + +
+

Creates a form that allows the user to create or update the attributes of a specific model object.

+ +

The method can be used in several slightly different ways, depending on how much you wish to rely on Rails to infer automatically from the model how the form should be constructed. For a generic model object, a form can be created by passing form_for a string or symbol representing the object we are concerned with:

+ +
<%= form_for :person do |f| %>
+  First name: <%= f.text_field :first_name %><br />
+  Last name : <%= f.text_field :last_name %><br />
+  Biography : <%= f.text_area :biography %><br />
+  Admin?    : <%= f.check_box :admin %><br />
+  <%= f.submit %>
+<% end %>
+
+ +

The variable f yielded to the block is a FormBuilder object that incorporates the knowledge about the model object represented by :person passed to form_for. Methods defined on the FormBuilder are used to generate fields bound to this model. Thus, for example,

+ +
<%= f.text_field :first_name %>
+
+ +

will get expanded to

+ +
<%= text_field :person, :first_name %>
+
+ +

which results in an HTML <input> tag whose name attribute is person[first_name]. This means that when the form is submitted, the value entered by the user will be available in the controller as params[:person][:first_name].

+ +

For fields generated in this way using the FormBuilder, if :person also happens to be the name of an instance variable @person, the default value of the field shown when the form is initially displayed (e.g. in the situation where you are editing an existing record) will be the value of the corresponding attribute of @person.

+ +

The rightmost argument to form_for is an optional hash of options -

+
  • +

    :url - The URL the form is to be submitted to. This may be represented in the same way as values passed to url_for or link_to. So for example you may use a named route directly. When the model is represented by a string or symbol, as in the example above, if the :url option is not specified, by default the form will be sent back to the current URL (We will describe below an alternative resource-oriented usage of form_for in which the URL does not need to be specified explicitly).

    +
  • +

    :namespace - A namespace for your form to ensure uniqueness of id attributes on form elements. The namespace attribute will be prefixed with underscore on the generated HTML id.

    +
  • +

    :method - The method to use when submitting the form, usually either “get” or “post”. If “patch”, “put”, “delete”, or another verb is used, a hidden input with name _method is added to simulate the verb over post.

    +
  • +

    :authenticity_token - Authenticity token to use in the form. Use only if you need to pass custom authenticity token string, or to not add authenticity_token field at all (by passing false). Remote forms may omit the embedded authenticity token by setting config.action_view.embed_authenticity_token_in_remote_forms = false. This is helpful when you’re fragment-caching the form. Remote forms get the authenticity token from the meta tag, so embedding is unnecessary unless you support browsers without JavaScript.

    +
  • +

    :remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the submit behavior.

    +
  • +

    :enforce_utf8 - If set to false, a hidden input with name utf8 is not output.

    +
  • +

    :html - Optional HTML attributes for the form tag.

    +
+ +

Also note that form_for doesn’t create an exclusive scope. It’s still possible to use both the stand-alone FormHelper methods and methods from FormTagHelper. For example:

+ +
<%= form_for :person do |f| %>
+  First name: <%= f.text_field :first_name %>
+  Last name : <%= f.text_field :last_name %>
+  Biography : <%= text_area :person, :biography %>
+  Admin?    : <%= check_box_tag "person[admin]", "1", @person.company.admin? %>
+  <%= f.submit %>
+<% end %>
+
+ +

This also works for the methods in FormOptionsHelper and DateHelper that are designed to work with an object as base, like FormOptionsHelper#collection_select and DateHelper#datetime_select.

+ +

form_for with a model object

+ +

In the examples above, the object to be created or edited was represented by a symbol passed to form_for, and we noted that a string can also be used equivalently. It is also possible, however, to pass a model object itself to form_for. For example, if @post is an existing record you wish to edit, you can create the form using

+ +
<%= form_for @post do |f| %>
+  ...
+<% end %>
+
+ +

This behaves in almost the same way as outlined previously, with a couple of small exceptions. First, the prefix used to name the input elements within the form (hence the key that denotes them in the params hash) is actually derived from the object’s class, e.g. params[:post] if the object’s class is Post. However, this can be overwritten using the :as option, e.g. -

+ +
<%= form_for(@person, as: :client) do |f| %>
+  ...
+<% end %>
+
+ +

would result in params[:client].

+ +

Secondly, the field values shown when the form is initially displayed are taken from the attributes of the object passed to form_for, regardless of whether the object is an instance variable. So, for example, if we had a local variable post representing an existing record,

+ +
<%= form_for post do |f| %>
+  ...
+<% end %>
+
+ +

would produce a form with fields whose initial state reflect the current values of the attributes of post.

+ +

Resource-oriented style

+ +

In the examples just shown, although not indicated explicitly, we still need to use the :url option in order to specify where the form is going to be sent. However, further simplification is possible if the record passed to form_for is a resource, i.e. it corresponds to a set of RESTful routes, e.g. defined using the resources method in config/routes.rb. In this case Rails will simply infer the appropriate URL from the record itself. For example,

+ +
<%= form_for @post do |f| %>
+  ...
+<% end %>
+
+ +

is then equivalent to something like:

+ +
<%= form_for @post, as: :post, url: post_path(@post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
+  ...
+<% end %>
+
+ +

And for a new record

+ +
<%= form_for(Post.new) do |f| %>
+  ...
+<% end %>
+
+ +

is equivalent to something like:

+ +
<%= form_for @post, as: :post, url: posts_path, html: { class: "new_post", id: "new_post" } do |f| %>
+  ...
+<% end %>
+
+ +

However you can still overwrite individual conventions, such as:

+ +
<%= form_for(@post, url: super_posts_path) do |f| %>
+  ...
+<% end %>
+
+ +

You can omit the action attribute by passing url: false:

+ +
<%= form_for(@post, url: false) do |f| %>
+  ...
+<% end %>
+
+ +

You can also set the answer format, like this:

+ +
<%= form_for(@post, format: :json) do |f| %>
+  ...
+<% end %>
+
+ +

For namespaced routes, like admin_post_url:

+ +
<%= form_for([:admin, @post]) do |f| %>
+ ...
+<% end %>
+
+ +

If your resource has associations defined, for example, you want to add comments to the document given that the routes are set correctly:

+ +
<%= form_for([@document, @comment]) do |f| %>
+ ...
+<% end %>
+
+ +

Where @document = Document.find(params[:id]) and @comment = Comment.new.

+ +

Setting the method

+ +

You can force the form to use the full array of HTTP verbs by setting

+ +
method: (:get|:post|:patch|:put|:delete)
+
+ +

in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the form will be set to POST and a hidden input called _method will carry the intended verb for the server to interpret.

+ +

Unobtrusive JavaScript

+ +

Specifying:

+ +
remote: true
+
+ +

in the options hash creates a form that will allow the unobtrusive JavaScript drivers to modify its behavior. The form submission will work just like a regular submission as viewed by the receiving side (all elements available in params).

+ +

Example:

+ +
<%= form_for(@post, remote: true) do |f| %>
+  ...
+<% end %>
+
+ +

The HTML generated for this would be:

+ +
<form action='http://www.example.com' method='post' data-remote='true'>
+  <input name='_method' type='hidden' value='patch' />
+  ...
+</form>
+
+ +

Setting HTML options

+ +

You can set data attributes directly by passing in a data hash, but all other HTML options must be wrapped in the HTML key. Example:

+ +
<%= form_for(@post, data: { behavior: "autosave" }, html: { name: "go" }) do |f| %>
+  ...
+<% end %>
+
+ +

The HTML generated for this would be:

+ +
<form action='http://www.example.com' method='post' data-behavior='autosave' name='go'>
+  <input name='_method' type='hidden' value='patch' />
+  ...
+</form>
+
+ +

Removing hidden model id’s

+ +

The form_for method automatically includes the model id as a hidden field in the form. This is used to maintain the correlation between the form data and its associated model. Some ORM systems do not use IDs on nested models so in this case you want to be able to disable the hidden id.

+ +

In the following example the Post model has many Comments stored within it in a NoSQL database, thus there is no primary key for comments.

+ +

Example:

+ +
<%= form_for(@post) do |f| %>
+  <%= f.fields_for(:comments, include_id: false) do |cf| %>
+    ...
+  <% end %>
+<% end %>
+
+ +

Customized form builders

+ +

You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder. For example, let’s say you made a helper to automatically add labels to form inputs.

+ +
<%= form_for @person, url: { action: "create" }, builder: LabellingFormBuilder do |f| %>
+  <%= f.text_field :first_name %>
+  <%= f.text_field :last_name %>
+  <%= f.text_area :biography %>
+  <%= f.check_box :admin %>
+  <%= f.submit %>
+<% end %>
+
+ +

In this case, if you use this:

+ +
<%= render f %>
+
+ +

The rendered template is people/_labelling_form and the local variable referencing the form builder is called labelling_form.

+ +

The custom FormBuilder class is automatically merged with the options of a nested fields_for call, unless it’s explicitly set.

+ +

In many cases you will want to wrap the above in another helper, so you could do something like the following:

+ +
def labelled_form_for(record_or_name_or_array, *args, &block)
+  options = args.extract_options!
+  form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
+end
+
+ +

If you don’t need to attach a form to a model instance, then check out FormTagHelper#form_tag.

+ +

Form to external resources

+ +

When you build forms to external resources sometimes you need to set an authenticity token or just render a form without it, for example when you submit data to a payment gateway number and types of fields could be limited.

+ +

To set an authenticity token you need to pass an :authenticity_token parameter

+ +
<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>
+  ...
+<% end %>
+
+ +

If you don’t want to an authenticity token field be rendered at all just pass false:

+ +
<%= form_for @invoice, url: external_url, authenticity_token: false do |f| %>
+  ...
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 433
+def form_for(record, options = {}, &block)
+  raise ArgumentError, "Missing block" unless block_given?
+
+  case record
+  when String, Symbol
+    model       = nil
+    object_name = record
+  else
+    model       = convert_to_model(record)
+    object      = _object_for_form_builder(record)
+    raise ArgumentError, "First argument in form cannot contain nil or be empty" unless object
+    object_name = options[:as] || model_name_from_record_or_class(object).param_key
+    apply_form_for_options!(object, options)
+  end
+
+  remote = options.delete(:remote)
+
+  if remote && !embed_authenticity_token_in_remote_forms && options[:authenticity_token].blank?
+    options[:authenticity_token] = false
+  end
+
+  options[:model]                               = model
+  options[:scope]                               = object_name
+  options[:local]                               = !remote
+  options[:skip_default_ids]                    = false
+  options[:allow_method_names_outside_object]   = options.fetch(:allow_method_names_outside_object, false)
+
+  form_with(**options, &block)
+end
+
+
+ +
+ +
+

+ + form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block) + +

+ + +
+

Creates a form tag based on mixing URLs, scopes, or models.

+ +
# Using just a URL:
+<%= form_with url: posts_path do |form| %>
+  <%= form.text_field :title %>
+<% end %>
+# =>
+<form action="/posts" method="post">
+  <input type="text" name="title">
+</form>
+
+# With an intentionally empty URL:
+<%= form_with url: false do |form| %>
+  <%= form.text_field :title %>
+<% end %>
+# =>
+<form method="post" data-remote="true">
+  <input type="text" name="title">
+</form>
+
+# Adding a scope prefixes the input field names:
+<%= form_with scope: :post, url: posts_path do |form| %>
+  <%= form.text_field :title %>
+<% end %>
+# =>
+<form action="/posts" method="post">
+  <input type="text" name="post[title]">
+</form>
+
+# Using a model infers both the URL and scope:
+<%= form_with model: Post.new do |form| %>
+  <%= form.text_field :title %>
+<% end %>
+# =>
+<form action="/posts" method="post">
+  <input type="text" name="post[title]">
+</form>
+
+# An existing model makes an update form and fills out field values:
+<%= form_with model: Post.first do |form| %>
+  <%= form.text_field :title %>
+<% end %>
+# =>
+<form action="/posts/1" method="post">
+  <input type="hidden" name="_method" value="patch">
+  <input type="text" name="post[title]" value="<the title of the post>">
+</form>
+
+# Though the fields don't have to correspond to model attributes:
+<%= form_with model: Cat.new do |form| %>
+  <%= form.text_field :cats_dont_have_gills %>
+  <%= form.text_field :but_in_forms_they_can %>
+<% end %>
+# =>
+<form action="/cats" method="post">
+  <input type="text" name="cat[cats_dont_have_gills]">
+  <input type="text" name="cat[but_in_forms_they_can]">
+</form>
+
+ +

The parameters in the forms are accessible in controllers according to their name nesting. So inputs named title and post[title] are accessible as params[:title] and params[:post][:title] respectively.

+ +

For ease of comparison the examples above left out the submit button, as well as the auto generated hidden fields that enable UTF-8 support and adds an authenticity token needed for cross site request forgery protection.

+ +

Resource-oriented style

+ +

In many of the examples just shown, the :model passed to form_with is a resource. It corresponds to a set of RESTful routes, most likely defined via resources in config/routes.rb.

+ +

So when passing such a model record, Rails infers the URL and method.

+ +
<%= form_with model: @post do |form| %>
+  ...
+<% end %>
+
+ +

is then equivalent to something like:

+ +
<%= form_with scope: :post, url: post_path(@post), method: :patch do |form| %>
+  ...
+<% end %>
+
+ +

And for a new record

+ +
<%= form_with model: Post.new do |form| %>
+  ...
+<% end %>
+
+ +

is equivalent to something like:

+ +
<%= form_with scope: :post, url: posts_path do |form| %>
+  ...
+<% end %>
+
+ +

form_with options

+
  • +

    :url - The URL the form submits to. Akin to values passed to url_for or link_to. For example, you may use a named route directly. When a :scope is passed without a :url the form just submits to the current URL.

    +
  • +

    :method - The method to use when submitting the form, usually either “get” or “post”. If “patch”, “put”, “delete”, or another verb is used, a hidden input named _method is added to simulate the verb over post.

    +
  • +

    :format - The format of the route the form submits to. Useful when submitting to another resource type, like :json. Skipped if a :url is passed.

    +
  • +

    :scope - The scope to prefix input field names with and thereby how the submitted parameters are grouped in controllers.

    +
  • +

    :namespace - A namespace for your form to ensure uniqueness of id attributes on form elements. The namespace attribute will be prefixed with underscore on the generated HTML id.

    +
  • +

    :model - A model object to infer the :url and :scope by, plus fill out input field values. So if a title attribute is set to “Ahoy!” then a title input field’s value would be “Ahoy!”. If the model is a new record a create form is generated, if an existing record, however, an update form is generated. Pass :scope or :url to override the defaults. E.g. turn params[:post] into params[:article].

    +
  • +

    :authenticity_token - Authenticity token to use in the form. Override with a custom authenticity token or pass false to skip the authenticity token field altogether. Useful when submitting to an external resource like a payment gateway that might limit the valid fields. Remote forms may omit the embedded authenticity token by setting config.action_view.embed_authenticity_token_in_remote_forms = false. This is helpful when fragment-caching the form. Remote forms get the authenticity token from the meta tag, so embedding is unnecessary unless you support browsers without JavaScript.

    +
  • +

    :local - Whether to use standard HTTP form submission. When set to true, the form is submitted via standard HTTP. When set to false, the form is submitted as a “remote form”, which is handled by Rails UJS as an XHR. When unspecified, the behavior is derived from config.action_view.form_with_generates_remote_forms where the config’s value is actually the inverse of what local‘s value would be. As of Rails 6.1, that configuration option defaults to false (which has the equivalent effect of passing local: true). In previous versions of Rails, that configuration option defaults to true (the equivalent of passing local: false).

    +
  • +

    :skip_enforcing_utf8 - If set to true, a hidden input with name utf8 is not output.

    +
  • +

    :builder - Override the object used to build the form.

    +
  • +

    :id - Optional HTML id attribute.

    +
  • +

    :class - Optional HTML class attribute.

    +
  • +

    :data - Optional HTML data attributes.

    +
  • +

    :html - Other optional HTML attributes for the form tag.

    +
+ +

Examples

+ +

When not passing a block, form_with just generates an opening form tag.

+ +
<%= form_with(model: @post, url: super_posts_path) %>
+<%= form_with(model: @post, scope: :article) %>
+<%= form_with(model: @post, format: :json) %>
+<%= form_with(model: @post, authenticity_token: false) %> # Disables the token.
+
+ +

For namespaced routes, like admin_post_url:

+ +
<%= form_with(model: [ :admin, @post ]) do |form| %>
+  ...
+<% end %>
+
+ +

If your resource has associations defined, for example, you want to add comments to the document given that the routes are set correctly:

+ +
<%= form_with(model: [ @document, Comment.new ]) do |form| %>
+  ...
+<% end %>
+
+ +

Where @document = Document.find(params[:id]).

+ +

Mixing with other form helpers

+ +

While form_with uses a FormBuilder object it’s possible to mix and match the stand-alone FormHelper methods and methods from FormTagHelper:

+ +
<%= form_with scope: :person do |form| %>
+  <%= form.text_field :first_name %>
+  <%= form.text_field :last_name %>
+
+  <%= text_area :person, :biography %>
+  <%= check_box_tag "person[admin]", "1", @person.company.admin? %>
+
+  <%= form.submit %>
+<% end %>
+
+ +

Same goes for the methods in FormOptionsHelper and DateHelper designed to work with an object as a base, like FormOptionsHelper#collection_select and DateHelper#datetime_select.

+ +

Setting the method

+ +

You can force the form to use the full array of HTTP verbs by setting

+ +
method: (:get|:post|:patch|:put|:delete)
+
+ +

in the options hash. If the verb is not GET or POST, which are natively supported by HTML forms, the form will be set to POST and a hidden input called _method will carry the intended verb for the server to interpret.

+ +

Setting HTML options

+ +

You can set data attributes directly in a data hash, but HTML options besides id and class must be wrapped in an HTML key:

+ +
<%= form_with(model: @post, data: { behavior: "autosave" }, html: { name: "go" }) do |form| %>
+  ...
+<% end %>
+
+ +

generates

+ +
<form action="/posts/123" method="post" data-behavior="autosave" name="go">
+  <input name="_method" type="hidden" value="patch" />
+  ...
+</form>
+
+ +

Removing hidden model id’s

+ +

The form_with method automatically includes the model id as a hidden field in the form. This is used to maintain the correlation between the form data and its associated model. Some ORM systems do not use IDs on nested models so in this case you want to be able to disable the hidden id.

+ +

In the following example the Post model has many Comments stored within it in a NoSQL database, thus there is no primary key for comments.

+ +
<%= form_with(model: @post) do |form| %>
+  <%= form.fields(:comments, skip_id: true) do |fields| %>
+    ...
+  <% end %>
+<% end %>
+
+ +

Customized form builders

+ +

You can also build forms using a customized FormBuilder class. Subclass FormBuilder and override or define some more helpers, then use your custom builder. For example, let’s say you made a helper to automatically add labels to form inputs.

+ +
<%= form_with model: @person, url: { action: "create" }, builder: LabellingFormBuilder do |form| %>
+  <%= form.text_field :first_name %>
+  <%= form.text_field :last_name %>
+  <%= form.text_area :biography %>
+  <%= form.check_box :admin %>
+  <%= form.submit %>
+<% end %>
+
+ +

In this case, if you use:

+ +
<%= render form %>
+
+ +

The rendered template is people/_labelling_form and the local variable referencing the form builder is called labelling_form.

+ +

The custom FormBuilder class is automatically merged with the options of a nested fields call, unless it’s explicitly set.

+ +

In many cases you will want to wrap the above in another helper, so you could do something like the following:

+ +
def labelled_form_with(**options, &block)
+  form_with(**options.merge(builder: LabellingFormBuilder), &block)
+end
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 755
+def form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
+  options = { allow_method_names_outside_object: true, skip_default_ids: !form_with_generates_ids }.merge!(options)
+
+  if model
+    if url != false
+      url ||= polymorphic_path(model, format: format)
+    end
+
+    model   = _object_for_form_builder(model)
+    scope ||= model_name_from_record_or_class(model).param_key
+  end
+
+  if block_given?
+    builder = instantiate_builder(scope, model, options)
+    output  = capture(builder, &block)
+    options[:multipart] ||= builder.multipart?
+
+    html_options = html_options_for_form_with(url, model, **options)
+    form_tag_with_body(html_options, output)
+  else
+    html_options = html_options_for_form_with(url, model, **options)
+    form_tag_html(html_options)
+  end
+end
+
+
+ +
+ +
+

+ + hidden_field(object_name, method, options = {}) + +

+ + +
+

Returns a hidden input tag tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown.

+ +

Examples

+ +
hidden_field(:signup, :pass_confirm)
+# => <input type="hidden" id="signup_pass_confirm" name="signup[pass_confirm]" value="#{@signup.pass_confirm}" />
+
+hidden_field(:post, :tag_list)
+# => <input type="hidden" id="post_tag_list" name="post[tag_list]" value="#{@post.tag_list}" />
+
+hidden_field(:user, :token)
+# => <input type="hidden" id="user_token" name="user[token]" value="#{@user.token}" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1206
+def hidden_field(object_name, method, options = {})
+  Tags::HiddenField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + label(object_name, method, content_or_options = nil, options = nil, &block) + +

+ + +
+

Returns a label tag tailored for labelling an input field for a specified attribute (identified by method) on an object assigned to the template (identified by object). The text of label will default to the attribute name unless a translation is found in the current I18n locale (through helpers.label.<modelname>.<attribute>) or you specify it explicitly. Additional options on the label tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown, except for the :value option, which is designed to target labels for radio_button tags (where the value is used in the ID of the input tag).

+ +

Examples

+ +
label(:post, :title)
+# => <label for="post_title">Title</label>
+
+ +

You can localize your labels based on model and attribute names. For example you can define the following in your locale (e.g. en.yml)

+ +
helpers:
+  label:
+    post:
+      body: "Write your entire text here"
+
+ +

Which then will result in

+ +
label(:post, :body)
+# => <label for="post_body">Write your entire text here</label>
+
+ +

Localization can also be based purely on the translation of the attribute-name (if you are using ActiveRecord):

+ +
activerecord:
+  attributes:
+    post:
+      cost: "Total cost"
+
+label(:post, :cost)
+# => <label for="post_cost">Total cost</label>
+
+label(:post, :title, "A short title")
+# => <label for="post_title">A short title</label>
+
+label(:post, :title, "A short title", class: "title_label")
+# => <label for="post_title" class="title_label">A short title</label>
+
+label(:post, :privacy, "Public Post", value: "public")
+# => <label for="post_privacy_public">Public Post</label>
+
+label(:post, :cost) do |translation|
+  content_tag(:span, translation, class: "cost_label")
+end
+# => <label for="post_cost"><span class="cost_label">Total cost</span></label>
+
+label(:post, :cost) do |builder|
+  content_tag(:span, builder.translation, class: "cost_label")
+end
+# => <label for="post_cost"><span class="cost_label">Total cost</span></label>
+
+label(:post, :terms) do
+  raw('Accept <a href="/terms">Terms</a>.')
+end
+# => <label for="post_terms">Accept <a href="/terms">Terms</a>.</label>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1143
+def label(object_name, method, content_or_options = nil, options = nil, &block)
+  Tags::Label.new(object_name, method, self, content_or_options, options).render(&block)
+end
+
+
+ +
+ +
+

+ + month_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “month”.

+ +
month_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="month" />
+
+ +

The default value is generated by trying to call strftime with “%Y-%m” on the object’s value, which makes it behave as expected for instances of DateTime and ActiveSupport::TimeWithZone.

+ +
@user.born_on = Date.new(1984, 1, 27)
+month_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-01" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1517
+def month_field(object_name, method, options = {})
+  Tags::MonthField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + number_field(object_name, method, options = {}) + +

+ + +
+

Returns an input tag of type “number”.

+ +

Options

+ +

Supports the same options as FormTagHelper#number_field_tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1561
+def number_field(object_name, method, options = {})
+  Tags::NumberField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + password_field(object_name, method, options = {}) + +

+ + +
+

Returns an input tag of the “password” type tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown. For security reasons this field is blank by default; pass in a value via options if this is not desired.

+ +

Examples

+ +
password_field(:login, :pass, size: 20)
+# => <input type="password" id="login_pass" name="login[pass]" size="20" />
+
+password_field(:account, :secret, class: "form_input", value: @account.secret)
+# => <input type="password" id="account_secret" name="account[secret]" value="#{@account.secret}" class="form_input" />
+
+password_field(:user, :password, onchange: "if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }")
+# => <input type="password" id="user_password" name="user[password]" onchange="if ($('#user_password').val().length > 30) { alert('Your password needs to be shorter!'); }"/>
+
+password_field(:account, :pin, size: 20, class: 'form_input')
+# => <input type="password" id="account_pin" name="account[pin]" size="20" class="form_input" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1188
+def password_field(object_name, method, options = {})
+  Tags::PasswordField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + phone_field(object_name, method, options = {}) + +

+ + +
+

aliases telephone_field

+
+ + + + + +
+ Alias for: telephone_field +
+ + + +
+ +
+

+ + radio_button(object_name, method, tag_value, options = {}) + +

+ + +
+

Returns a radio button tag for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). If the current value of method is tag_value the radio button will be checked.

+ +

To force the radio button to be checked pass checked: true in the options hash. You may pass HTML options there as well.

+ +
# Let's say that @post.category returns "rails":
+radio_button("post", "category", "rails")
+radio_button("post", "category", "java")
+# => <input type="radio" id="post_category_rails" name="post[category]" value="rails" checked="checked" />
+#    <input type="radio" id="post_category_java" name="post[category]" value="java" />
+
+# Let's say that @user.receive_newsletter returns "no":
+radio_button("user", "receive_newsletter", "yes")
+radio_button("user", "receive_newsletter", "no")
+# => <input type="radio" id="user_receive_newsletter_yes" name="user[receive_newsletter]" value="yes" />
+#    <input type="radio" id="user_receive_newsletter_no" name="user[receive_newsletter]" value="no" checked="checked" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1359
+def radio_button(object_name, method, tag_value, options = {})
+  Tags::RadioButton.new(object_name, method, self, tag_value, options).render
+end
+
+
+ +
+ +
+

+ + range_field(object_name, method, options = {}) + +

+ + +
+

Returns an input tag of type “range”.

+ +

Options

+ +

Supports the same options as FormTagHelper#range_field_tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1570
+def range_field(object_name, method, options = {})
+  Tags::RangeField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + rich_text_area(object_name, method, options = {}) + +

+ + +
+

Returns a trix-editor tag that instantiates the Trix JavaScript editor as well as a hidden field that Trix will write to on changes, so the content will be sent on form submissions.

+ +

Options

+
  • +

    :class - Defaults to “trix-content” which ensures default styling is applied.

    +
  • +

    :value - Adds a default value to the HTML input tag.

    +
  • +

    [:data][:direct_upload_url] - Defaults to rails_direct_uploads_url.

    +
  • +

    [:data][:blob_url_template] - Defaults to rails_service_blob_url(":signed_id", ":filename").

    +
+ +

Example

+ +
form_with(model: @message) do |form|
+  form.rich_text_area :content
+end
+# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1">
+# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
+
+form_with(model: @message) do |form|
+  form.rich_text_area :content, value: "<h1>Default message</h1>"
+end
+# <input type="hidden" name="message[content]" id="message_content_trix_input_message_1" value="<h1>Default message</h1>">
+# <trix-editor id="content" input="message_content_trix_input_message_1" class="trix-content" ...></trix-editor>
+
+
+ + + + + + + + +
+ + +
+
# File actiontext/app/helpers/action_text/tag_helper.rb, line 79
+def rich_text_area(object_name, method, options = {})
+  Tags::ActionText.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + search_field(object_name, method, options = {}) + +

+ + +
+

Returns an input of type “search” for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object_name). Inputs of type “search” may be styled differently by some browsers.

+ +
search_field(:user, :name)
+# => <input id="user_name" name="user[name]" type="search" />
+search_field(:user, :name, autosave: false)
+# => <input autosave="false" id="user_name" name="user[name]" type="search" />
+search_field(:user, :name, results: 3)
+# => <input id="user_name" name="user[name]" results="3" type="search" />
+#  Assume request.host returns "www.example.com"
+search_field(:user, :name, autosave: true)
+# => <input autosave="com.example.www" id="user_name" name="user[name]" results="10" type="search" />
+search_field(:user, :name, onsearch: true)
+# => <input id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
+search_field(:user, :name, autosave: false, onsearch: true)
+# => <input autosave="false" id="user_name" incremental="true" name="user[name]" onsearch="true" type="search" />
+search_field(:user, :name, autosave: true, onsearch: true)
+# => <input autosave="com.example.www" id="user_name" incremental="true" name="user[name]" onsearch="true" results="10" type="search" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1390
+def search_field(object_name, method, options = {})
+  Tags::SearchField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + telephone_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “tel”.

+ +
telephone_field("user", "phone")
+# => <input id="user_phone" name="user[phone]" type="tel" />
+
+
+ + + +
+ Also aliased as: phone_field +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1399
+def telephone_field(object_name, method, options = {})
+  Tags::TelField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + text_area(object_name, method, options = {}) + +

+ + +
+

Returns a textarea opening and closing tag set tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options.

+ +

Examples

+ +
text_area(:post, :body, cols: 20, rows: 40)
+# => <textarea cols="20" rows="40" id="post_body" name="post[body]">
+#      #{@post.body}
+#    </textarea>
+
+text_area(:comment, :text, size: "20x30")
+# => <textarea cols="20" rows="30" id="comment_text" name="comment[text]">
+#      #{@comment.text}
+#    </textarea>
+
+text_area(:application, :notes, cols: 40, rows: 15, class: 'app_input')
+# => <textarea cols="40" rows="15" id="application_notes" name="application[notes]" class="app_input">
+#      #{@application.notes}
+#    </textarea>
+
+text_area(:entry, :body, size: "20x20", disabled: 'disabled')
+# => <textarea cols="20" rows="20" id="entry_body" name="entry[body]" disabled="disabled">
+#      #{@entry.body}
+#    </textarea>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1269
+def text_area(object_name, method, options = {})
+  Tags::TextArea.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + text_field(object_name, method, options = {}) + +

+ + +
+

Returns an input tag of the “text” type tailored for accessing a specified attribute (identified by method) on an object assigned to the template (identified by object). Additional options on the input tag can be passed as a hash with options. These options will be tagged onto the HTML as an HTML element attribute as in the example shown.

+ +

Examples

+ +
text_field(:post, :title, size: 20)
+# => <input type="text" id="post_title" name="post[title]" size="20" value="#{@post.title}" />
+
+text_field(:post, :title, class: "create_input")
+# => <input type="text" id="post_title" name="post[title]" value="#{@post.title}" class="create_input" />
+
+text_field(:post, :title,  maxlength: 30, class: "title_input")
+# => <input type="text" id="post_title" name="post[title]" maxlength="30" size="30" value="#{@post.title}" class="title_input" />
+
+text_field(:session, :user, onchange: "if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }")
+# => <input type="text" id="session_user" name="session[user]" value="#{@session.user}" onchange="if ($('#session_user').val() === 'admin') { alert('Your login cannot be admin!'); }"/>
+
+text_field(:snippet, :code, size: 20, class: 'code_input')
+# => <input type="text" id="snippet_code" name="snippet[code]" size="20" value="#{@snippet.code}" class="code_input" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1167
+def text_field(object_name, method, options = {})
+  Tags::TextField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + time_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “time”.

+ +

The default value is generated by trying to call strftime with “%T.%L” on the object’s value. If you pass include_seconds: false, it will be formatted by trying to call strftime with “%H:%M” on the object’s value. It is also possible to override this by passing the “value” option.

+ +

Options

+ +

Supports the same options as FormTagHelper#time_field_tag.

+ +

Examples

+ +
time_field("task", "started_at")
+# => <input id="task_started_at" name="task[started_at]" type="time" />
+
+ +

You can create values for the “min” and “max” attributes by passing instances of Date or Time to the options hash.

+ +
time_field("task", "started_at", min: Time.now)
+# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
+
+ +

Alternatively, you can pass a String formatted as an ISO8601 time as the values for “min” and “max.”

+ +
time_field("task", "started_at", min: "01:00:00")
+# => <input id="task_started_at" name="task[started_at]" type="time" min="01:00:00.000" />
+
+ +

By default, provided times will be formatted including seconds. You can render just the hour and minute by passing include_seconds: false. Some browsers will render a simpler UI if you exclude seconds in the timestamp format.

+ +
time_field("task", "started_at", value: Time.now, include_seconds: false)
+# => <input id="task_started_at" name="task[started_at]" type="time" value="01:00" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1469
+def time_field(object_name, method, options = {})
+  Tags::TimeField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + url_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “url”.

+ +
url_field("user", "homepage")
+# => <input id="user_homepage" name="user[homepage]" type="url" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1543
+def url_field(object_name, method, options = {})
+  Tags::UrlField.new(object_name, method, self, options).render
+end
+
+
+ +
+ +
+

+ + week_field(object_name, method, options = {}) + +

+ + +
+

Returns a text_field of type “week”.

+ +
week_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="week" />
+
+ +

The default value is generated by trying to call strftime with “%Y-W%W” on the object’s value, which makes it behave as expected for instances of DateTime and ActiveSupport::TimeWithZone.

+ +
@user.born_on = Date.new(1984, 5, 12)
+week_field("user", "born_on")
+# => <input id="user_born_on" name="user[born_on]" type="date" value="1984-W19" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_helper.rb, line 1534
+def week_field(object_name, method, options = {})
+  Tags::WeekField.new(object_name, method, self, options).render
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/FormOptionsHelper.html b/src/7.0/classes/ActionView/Helpers/FormOptionsHelper.html new file mode 100644 index 0000000000..8245b6544a --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/FormOptionsHelper.html @@ -0,0 +1,1264 @@ +--- +title: ActionView::Helpers::FormOptionsHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides a number of methods for turning different kinds of containers into a set of option tags.

+ +

The collection_select, select and time_zone_select methods take an options parameter, a hash:

+
  • +

    :include_blank - set to true or a prompt string if the first option element of the select element is a blank. Useful if there is not a default value required for the select element.

    + +
    select(:post, :category, Post::CATEGORIES, { include_blank: true })
    +
    + +

    could become:

    + +
    <select name="post[category]" id="post_category">
    +  <option value="" label=" "></option>
    +  <option value="joke">joke</option>
    +  <option value="poem">poem</option>
    +</select>
    +
    + +

    Another common case is a select tag for a belongs_to-associated object.

    + +

    Example with @post.person_id => 2:

    + +
    select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: "None" })
    +
    + +

    could become:

    + +
    <select name="post[person_id]" id="post_person_id">
    +  <option value="">None</option>
    +  <option value="1">David</option>
    +  <option value="2" selected="selected">Eileen</option>
    +  <option value="3">Rafael</option>
    +</select>
    +
    +
  • +

    :prompt - set to true or a prompt string. When the select element doesn’t have a value yet, this prepends an option with a generic prompt – “Please select” – or the given prompt string.

    + +
    select(:post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { prompt: "Select Person" })
    +
    + +

    could become:

    + +
    <select name="post[person_id]" id="post_person_id">
    +  <option value="">Select Person</option>
    +  <option value="1">David</option>
    +  <option value="2">Eileen</option>
    +  <option value="3">Rafael</option>
    +</select>
    +
    +
  • +

    :index - like the other form helpers, select can accept an :index option to manually set the ID used in the resulting output. Unlike other helpers, select expects this option to be in the html_options parameter.

    + +
    select("album[]", :genre, %w[ rap rock country ], {}, { index: nil })
    +
    + +

    becomes:

    + +
    <select name="album[][genre]" id="album__genre">
    +  <option value="rap">rap</option>
    +  <option value="rock">rock</option>
    +  <option value="country">country</option>
    +</select>
    +
    +
  • +

    :disabled - can be a single value or an array of values that will be disabled options in the final output.

    + +
    select(:post, :category, Post::CATEGORIES, { disabled: "restricted" })
    +
    + +

    could become:

    + +
    <select name="post[category]" id="post_category">
    +  <option value="joke">joke</option>
    +  <option value="poem">poem</option>
    +  <option disabled="disabled" value="restricted">restricted</option>
    +</select>
    +
    + +

    When used with the collection_select helper, :disabled can also be a Proc that identifies those options that should be disabled.

    + +
    collection_select(:post, :category_id, Category.all, :id, :name, { disabled: -> (category) { category.archived? } })
    +
    + +

    If the categories “2008 stuff” and “Christmas” return true when the method archived? is called, this would return:

    + +
    <select name="post[category_id]" id="post_category_id">
    +  <option value="1" disabled="disabled">2008 stuff</option>
    +  <option value="2" disabled="disabled">Christmas</option>
    +  <option value="3">Jokes</option>
    +  <option value="4">Poems</option>
    +</select>
    +
    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block) + +

+ + +
+

Returns check box tags for the collection of existing return values of method for object‘s class. The value returned from calling method on the instance object will be selected. If calling method returns nil, no selection is made.

+ +

The :value_method and :text_method parameters are methods to be called on each member of collection. The return values are used as the value attribute and contents of each check box tag, respectively. They can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value/text.

+ +

Example object structure for use with this method:

+ +
class Post < ActiveRecord::Base
+  has_and_belongs_to_many :authors
+end
+class Author < ActiveRecord::Base
+  has_and_belongs_to_many :posts
+  def name_with_initial
+    "#{first_name.first}. #{last_name}"
+  end
+end
+
+ +

Sample usage (selecting the associated Author for an instance of Post, @post):

+ +
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial)
+
+ +

If @post.author_ids is already [1], this would return:

+ +
<input id="post_author_ids_1" name="post[author_ids][]" type="checkbox" value="1" checked="checked" />
+<label for="post_author_ids_1">D. Heinemeier Hansson</label>
+<input id="post_author_ids_2" name="post[author_ids][]" type="checkbox" value="2" />
+<label for="post_author_ids_2">D. Thomas</label>
+<input id="post_author_ids_3" name="post[author_ids][]" type="checkbox" value="3" />
+<label for="post_author_ids_3">M. Clark</label>
+<input name="post[author_ids][]" type="hidden" value="" />
+
+ +

It is also possible to customize the way the elements will be shown by giving a block to the method:

+ +
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
+  b.label { b.check_box }
+end
+
+ +

The argument passed to the block is a special kind of builder for this collection, which has the ability to generate the label and check box for the current item in the collection, with proper text and value. Using it, you can change the label and check box display order or even use the label as wrapper, as in the example above.

+ +

The builder methods label and check_box also accept extra HTML options:

+ +
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
+  b.label(class: "check_box") { b.check_box(class: "check_box") }
+end
+
+ +

There are also three special methods available: object, text and value, which are the current item being rendered, its text and value methods, respectively. You can use them like this:

+ +
collection_check_boxes(:post, :author_ids, Author.all, :id, :name_with_initial) do |b|
+   b.label(:"data-value" => b.value) { b.check_box + b.text }
+end
+
+ +

Gotcha

+ +

When no selection is made for a collection of checkboxes most web browsers will not send any value.

+ +

For example, if we have a User model with category_ids field and we have the following code in our update action:

+ +
@user.update(params[:user])
+
+ +

If no category_ids are selected then we can safely assume this field will not be updated.

+ +

This is possible thanks to a hidden field generated by the helper method for every collection of checkboxes. This hidden field is given the same field name as the checkboxes with a blank value.

+ +

In the rare case you don’t want this hidden field, you can pass the include_hidden: false option to the helper method.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 781
+def collection_check_boxes(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
+  Tags::CollectionCheckBoxes.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
+end
+
+
+ +
+ +
+

+ + collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block) + +

+ + +
+

Returns radio button tags for the collection of existing return values of method for object‘s class. The value returned from calling method on the instance object will be selected. If calling method returns nil, no selection is made.

+ +

The :value_method and :text_method parameters are methods to be called on each member of collection. The return values are used as the value attribute and contents of each radio button tag, respectively. They can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value/text.

+ +

Example object structure for use with this method:

+ +
class Post < ActiveRecord::Base
+  belongs_to :author
+end
+
+class Author < ActiveRecord::Base
+  has_many :posts
+
+  def name_with_initial
+    "#{first_name.first}. #{last_name}"
+  end
+end
+
+ +

Sample usage (selecting the associated Author for an instance of Post, @post):

+ +
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial)
+
+ +

If @post.author_id is already 1, this would return:

+ +
<input id="post_author_id_1" name="post[author_id]" type="radio" value="1" checked="checked" />
+<label for="post_author_id_1">D. Heinemeier Hansson</label>
+<input id="post_author_id_2" name="post[author_id]" type="radio" value="2" />
+<label for="post_author_id_2">D. Thomas</label>
+<input id="post_author_id_3" name="post[author_id]" type="radio" value="3" />
+<label for="post_author_id_3">M. Clark</label>
+
+ +

It is also possible to customize the way the elements will be shown by giving a block to the method:

+ +
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
+  b.label { b.radio_button }
+end
+
+ +

The argument passed to the block is a special kind of builder for this collection, which has the ability to generate the label and radio button for the current item in the collection, with proper text and value. Using it, you can change the label and radio button display order or even use the label as wrapper, as in the example above.

+ +

The builder methods label and radio_button also accept extra HTML options:

+ +
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
+  b.label(class: "radio_button") { b.radio_button(class: "radio_button") }
+end
+
+ +

There are also three special methods available: object, text and value, which are the current item being rendered, its text and value methods, respectively. You can use them like this:

+ +
collection_radio_buttons(:post, :author_id, Author.all, :id, :name_with_initial) do |b|
+   b.label(:"data-value" => b.value) { b.radio_button + b.text }
+end
+
+ +

Gotcha

+ +

The HTML specification says when nothing is selected on a collection of radio buttons web browsers do not send any value to server. Unfortunately this introduces a gotcha: if a User model has a category_id field and in the form no category is selected, no category_id parameter is sent. So, any strong parameters idiom like:

+ +
params.require(:user).permit(...)
+
+ +

will raise an error since no {user: ...} will be present.

+ +

To prevent this the helper generates an auxiliary hidden field before every collection of radio buttons. The hidden field has the same name as collection radio button and blank value.

+ +

In case if you don’t want the helper to generate this hidden field you can specify include_hidden: false option.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 697
+def collection_radio_buttons(object, method, collection, value_method, text_method, options = {}, html_options = {}, &block)
+  Tags::CollectionRadioButtons.new(object, method, self, collection, value_method, text_method, options, html_options).render(&block)
+end
+
+
+ +
+ +
+

+ + collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {}) + +

+ + +
+

Returns <select> and <option> tags for the collection of existing return values of method for object‘s class. The value returned from calling method on the instance object will be selected. If calling method returns nil, no selection is made without including :prompt or :include_blank in the options hash.

+ +

The :value_method and :text_method parameters are methods to be called on each member of collection. The return values are used as the value attribute and contents of each <option> tag, respectively. They can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value/text.

+ +

Example object structure for use with this method:

+ +
class Post < ActiveRecord::Base
+  belongs_to :author
+end
+
+class Author < ActiveRecord::Base
+  has_many :posts
+
+  def name_with_initial
+    "#{first_name.first}. #{last_name}"
+  end
+end
+
+ +

Sample usage (selecting the associated Author for an instance of Post, @post):

+ +
collection_select(:post, :author_id, Author.all, :id, :name_with_initial, prompt: true)
+
+ +

If @post.author_id is already 1, this would return:

+ +
<select name="post[author_id]" id="post_author_id">
+  <option value="">Please select</option>
+  <option value="1" selected="selected">D. Heinemeier Hansson</option>
+  <option value="2">D. Thomas</option>
+  <option value="3">M. Clark</option>
+</select>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 198
+def collection_select(object, method, collection, value_method, text_method, options = {}, html_options = {})
+  Tags::CollectionSelect.new(object, method, self, collection, value_method, text_method, options, html_options).render
+end
+
+
+ +
+ +
+

+ + grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {}) + +

+ + +
+

Returns <select>, <optgroup> and <option> tags for the collection of existing return values of method for object‘s class. The value returned from calling method on the instance object will be selected. If calling method returns nil, no selection is made without including :prompt or :include_blank in the options hash.

+ +

Parameters:

+
  • +

    object - The instance of the class to be used for the select tag

    +
  • +

    method - The attribute of object corresponding to the select tag

    +
  • +

    collection - An array of objects representing the <optgroup> tags.

    +
  • +

    group_method - The name of a method which, when called on a member of collection, returns an array of child objects representing the <option> tags. It can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the value.

    +
  • +

    group_label_method - The name of a method which, when called on a member of collection, returns a string to be used as the label attribute for its <optgroup> tag. It can also be any object that responds to call, such as a proc, that will be called for each member of the collection to retrieve the label.

    +
  • +

    option_key_method - The name of a method which, when called on a child object of a member of collection, returns a value to be used as the value attribute for its <option> tag.

    +
  • +

    option_value_method - The name of a method which, when called on a child object of a member of collection, returns a value to be used as the contents of its <option> tag.

    +
+ +

Example object structure for use with this method:

+ +
# attributes: id, name
+class Continent < ActiveRecord::Base
+  has_many :countries
+end
+
+# attributes: id, name, continent_id
+class Country < ActiveRecord::Base
+  belongs_to :continent
+end
+
+# attributes: id, name, country_id
+class City < ActiveRecord::Base
+  belongs_to :country
+end
+
+ +

Sample usage:

+ +
grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name)
+
+ +

Possible output:

+ +
<select name="city[country_id]" id="city_country_id">
+  <optgroup label="Africa">
+    <option value="1">South Africa</option>
+    <option value="3">Somalia</option>
+  </optgroup>
+  <optgroup label="Europe">
+    <option value="7" selected="selected">Denmark</option>
+    <option value="2">Ireland</option>
+  </optgroup>
+</select>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 257
+def grouped_collection_select(object, method, collection, group_method, group_label_method, option_key_method, option_value_method, options = {}, html_options = {})
+  Tags::GroupedCollectionSelect.new(object, method, self, collection, group_method, group_label_method, option_key_method, option_value_method, options, html_options).render
+end
+
+
+ +
+ +
+

+ + grouped_options_for_select(grouped_options, selected_key = nil, options = {}) + +

+ + +
+

Returns a string of <option> tags, like options_for_select, but wraps them with <optgroup> tags:

+ +
grouped_options = [
+ ['North America',
+   [['United States','US'],'Canada']],
+ ['Europe',
+   ['Denmark','Germany','France']]
+]
+grouped_options_for_select(grouped_options)
+
+grouped_options = {
+  'North America' => [['United States','US'], 'Canada'],
+  'Europe' => ['Denmark','Germany','France']
+}
+grouped_options_for_select(grouped_options)
+
+ +

Possible output:

+ +
<optgroup label="North America">
+  <option value="US">United States</option>
+  <option value="Canada">Canada</option>
+</optgroup>
+<optgroup label="Europe">
+  <option value="Denmark">Denmark</option>
+  <option value="Germany">Germany</option>
+  <option value="France">France</option>
+</optgroup>
+
+ +

Parameters:

+
  • +

    grouped_options - Accepts a nested array or hash of strings. The first value serves as the <optgroup> label while the second value must be an array of options. The second value can be a nested array of text-value pairs. See options_for_select for more info.

    + +
    Ex. ["North America",[["United States","US"],["Canada","CA"]]]
    +
    + +

    An optional third value can be provided as HTML attributes for the optgroup.

    + +
    Ex. ["North America",[["United States","US"],["Canada","CA"]], { disabled: "disabled" }]
    +
    +
  • +

    selected_key - A value equal to the value attribute for one of the <option> tags, which will have the selected attribute set. Note: It is possible for this value to match multiple options as you might have the same option in multiple groups. Each will then get selected="selected".

    +
+ +

Options:

+
  • +

    :prompt - set to true or a prompt string. When the select element doesn’t have a value yet, this prepends an option with a generic prompt - “Please select” - or the given prompt string.

    +
  • +

    :divider - the divider for the options groups.

    + +
    grouped_options = [
    +  [['United States','US'], 'Canada'],
    +  ['Denmark','Germany','France']
    +]
    +grouped_options_for_select(grouped_options, nil, divider: '---------')
    +
    + +

    Possible output:

    + +
    <optgroup label="---------">
    +  <option value="US">United States</option>
    +  <option value="Canada">Canada</option>
    +</optgroup>
    +<optgroup label="---------">
    +  <option value="Denmark">Denmark</option>
    +  <option value="Germany">Germany</option>
    +  <option value="France">France</option>
    +</optgroup>
    +
    +
+ +

Note: Only the <optgroup> and <option> tags are returned, so you still have to wrap the output in an appropriate <select> tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 533
+def grouped_options_for_select(grouped_options, selected_key = nil, options = {})
+  prompt  = options[:prompt]
+  divider = options[:divider]
+
+  body = "".html_safe
+
+  if prompt
+    body.safe_concat content_tag("option", prompt_text(prompt), value: "")
+  end
+
+  grouped_options.each do |container|
+    html_attributes = option_html_attributes(container)
+
+    if divider
+      label = divider
+    else
+      label, container = container
+    end
+
+    html_attributes = { label: label }.merge!(html_attributes)
+    body.safe_concat content_tag("optgroup", options_for_select(container, selected_key), html_attributes)
+  end
+
+  body
+end
+
+
+ +
+ +
+

+ + option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil) + +

+ + +
+

Returns a string of <option> tags, like options_from_collection_for_select, but groups them by <optgroup> tags based on the object relationships of the arguments.

+ +

Parameters:

+
  • +

    collection - An array of objects representing the <optgroup> tags.

    +
  • +

    group_method - The name of a method which, when called on a member of collection, returns an array of child objects representing the <option> tags.

    +
  • +

    group_label_method - The name of a method which, when called on a member of collection, returns a string to be used as the label attribute for its <optgroup> tag.

    +
  • +

    option_key_method - The name of a method which, when called on a child object of a member of collection, returns a value to be used as the value attribute for its <option> tag.

    +
  • +

    option_value_method - The name of a method which, when called on a child object of a member of collection, returns a value to be used as the contents of its <option> tag.

    +
  • +

    selected_key - A value equal to the value attribute for one of the <option> tags, which will have the selected attribute set. Corresponds to the return value of one of the calls to option_key_method. If nil, no selection is made. Can also be a hash if disabled values are to be specified.

    +
+ +

Example object structure for use with this method:

+ +
class Continent < ActiveRecord::Base
+  has_many :countries
+  # attribs: id, name
+end
+
+class Country < ActiveRecord::Base
+  belongs_to :continent
+  # attribs: id, name, continent_id
+end
+
+ +

Sample usage:

+ +
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
+
+ +

Possible output:

+ +
<optgroup label="Africa">
+  <option value="1">Egypt</option>
+  <option value="4">Rwanda</option>
+  ...
+</optgroup>
+<optgroup label="Asia">
+  <option value="3" selected="selected">China</option>
+  <option value="12">India</option>
+  <option value="5">Japan</option>
+  ...
+</optgroup>
+
+ +

Note: Only the <optgroup> and <option> tags are returned, so you still have to wrap the output in an appropriate <select> tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 461
+def option_groups_from_collection_for_select(collection, group_method, group_label_method, option_key_method, option_value_method, selected_key = nil)
+  collection.map do |group|
+    option_tags = options_from_collection_for_select(
+      value_for_collection(group, group_method), option_key_method, option_value_method, selected_key)
+
+    content_tag("optgroup", option_tags, label: value_for_collection(group, group_label_method))
+  end.join.html_safe
+end
+
+
+ +
+ +
+

+ + options_for_select(container, selected = nil) + +

+ + +
+

Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container where the elements respond to first and last (such as a two-element array), the “lasts” serve as option values and the “firsts” as option text. Hashes are turned into this form automatically, so the keys become “firsts” and values become lasts. If selected is specified, the matching “last” or element will get the selected option-tag. selected may also be an array of values to be selected when using a multiple select.

+ +
options_for_select([["Dollar", "$"], ["Kroner", "DKK"]])
+# => <option value="$">Dollar</option>
+# => <option value="DKK">Kroner</option>
+
+options_for_select([ "VISA", "MasterCard" ], "MasterCard")
+# => <option value="VISA">VISA</option>
+# => <option selected="selected" value="MasterCard">MasterCard</option>
+
+options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40")
+# => <option value="$20">Basic</option>
+# => <option value="$40" selected="selected">Plus</option>
+
+options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"])
+# => <option selected="selected" value="VISA">VISA</option>
+# => <option value="MasterCard">MasterCard</option>
+# => <option selected="selected" value="Discover">Discover</option>
+
+ +

You can optionally provide HTML attributes as the last element of the array.

+ +
options_for_select([ "Denmark", ["USA", { class: 'bold' }], "Sweden" ], ["USA", "Sweden"])
+# => <option value="Denmark">Denmark</option>
+# => <option value="USA" class="bold" selected="selected">USA</option>
+# => <option value="Sweden" selected="selected">Sweden</option>
+
+options_for_select([["Dollar", "$", { class: "bold" }], ["Kroner", "DKK", { onclick: "alert('HI');" }]])
+# => <option value="$" class="bold">Dollar</option>
+# => <option value="DKK" onclick="alert('HI');">Kroner</option>
+
+ +

If you wish to specify disabled option tags, set selected to be a hash, with :disabled being either a value or array of values to be disabled. In this case, you can use :selected to specify selected option tags.

+ +
options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: "Super Platinum")
+# => <option value="Free">Free</option>
+# => <option value="Basic">Basic</option>
+# => <option value="Advanced">Advanced</option>
+# => <option value="Super Platinum" disabled="disabled">Super Platinum</option>
+
+options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], disabled: ["Advanced", "Super Platinum"])
+# => <option value="Free">Free</option>
+# => <option value="Basic">Basic</option>
+# => <option value="Advanced" disabled="disabled">Advanced</option>
+# => <option value="Super Platinum" disabled="disabled">Super Platinum</option>
+
+options_for_select(["Free", "Basic", "Advanced", "Super Platinum"], selected: "Free", disabled: "Super Platinum")
+# => <option value="Free" selected="selected">Free</option>
+# => <option value="Basic">Basic</option>
+# => <option value="Advanced">Advanced</option>
+# => <option value="Super Platinum" disabled="disabled">Super Platinum</option>
+
+ +

NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 357
+def options_for_select(container, selected = nil)
+  return container if String === container
+
+  selected, disabled = extract_selected_and_disabled(selected).map do |r|
+    Array(r).map(&:to_s)
+  end
+
+  container.map do |element|
+    html_attributes = option_html_attributes(element)
+    text, value = option_text_and_value(element).map(&:to_s)
+
+    html_attributes[:selected] ||= option_value_selected?(value, selected)
+    html_attributes[:disabled] ||= disabled && option_value_selected?(value, disabled)
+    html_attributes[:value] = value
+
+    tag_builder.content_tag_string(:option, text, html_attributes)
+  end.join("\n").html_safe
+end
+
+
+ +
+ +
+

+ + options_from_collection_for_select(collection, value_method, text_method, selected = nil) + +

+ + +
+

Returns a string of option tags that have been compiled by iterating over the collection and assigning the result of a call to the value_method as the option value and the text_method as the option text.

+ +
options_from_collection_for_select(@people, 'id', 'name')
+# => <option value="#{person.id}">#{person.name}</option>
+
+ +

This is more often than not used inside a select_tag like this example:

+ +
select_tag 'person', options_from_collection_for_select(@people, 'id', 'name')
+
+ +

If selected is specified as a value or array of values, the element(s) returning a match on value_method will be selected option tag(s).

+ +

If selected is specified as a Proc, those members of the collection that return true for the anonymous function are the selected values.

+ +

selected can also be a hash, specifying both :selected and/or :disabled values as required.

+ +

Be sure to specify the same class as the value_method when specifying selected or disabled options. Failure to do this will produce undesired results. Example:

+ +
options_from_collection_for_select(@people, 'id', 'name', '1')
+
+ +

Will not select a person with the id of 1 because 1 (an Integer) is not the same as ‘1’ (a string)

+ +
options_from_collection_for_select(@people, 'id', 'name', 1)
+
+ +

should produce the desired results.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 400
+def options_from_collection_for_select(collection, value_method, text_method, selected = nil)
+  options = collection.map do |element|
+    [value_for_collection(element, text_method), value_for_collection(element, value_method), option_html_attributes(element)]
+  end
+  selected, disabled = extract_selected_and_disabled(selected)
+  select_deselect = {
+    selected: extract_values_from_collection(collection, value_method, selected),
+    disabled: extract_values_from_collection(collection, value_method, disabled)
+  }
+
+  options_for_select(options, select_deselect)
+end
+
+
+ +
+ +
+

+ + select(object, method, choices = nil, options = {}, html_options = {}, &block) + +

+ + +
+

Create a select tag and a series of contained option tags for the provided object and method. The option currently held by the object will be selected, provided that the object is available.

+ +

There are two possible formats for the choices parameter, corresponding to other helpers’ output:

+
  • +

    A flat collection (see options_for_select).

    +
  • +

    A nested collection (see grouped_options_for_select).

    +
+ +

Example with @post.person_id => 2:

+ +
select :post, :person_id, Person.all.collect { |p| [ p.name, p.id ] }, { include_blank: true })
+
+ +

would become:

+ +
<select name="post[person_id]" id="post_person_id">
+  <option value="" label=" "></option>
+  <option value="1">David</option>
+  <option value="2" selected="selected">Eileen</option>
+  <option value="3">Rafael</option>
+</select>
+
+ +

This can be used to provide a default set of options in the standard way: before rendering the create form, a new model instance is assigned the default options and bound to @model_name. Usually this model is not saved to the database. Instead, a second model object is created when the create request is received. This allows the user to submit a form page more than once with the expected results of creating multiple records. In addition, this allows a single partial to be used to generate form inputs for both edit and create forms.

+ +

By default, post.person_id is the selected option. Specify selected: value to use a different selection or selected: nil to leave all options unselected. Similarly, you can specify values to be disabled in the option tags by specifying the :disabled option. This can either be a single value or an array of values to be disabled.

+ +

A block can be passed to select to customize how the options tags will be rendered. This is useful when the options tag has complex attributes.

+ +
select(report, :campaign_ids) do
+  available_campaigns.each do |c|
+    tag.option(c.name, value: c.id, data: { tags: c.tags.to_json })
+  end
+end
+
+ +

Gotcha

+ +

The HTML specification says when multiple parameter passed to select and all options got deselected web browsers do not send any value to server. Unfortunately this introduces a gotcha: if a User model has many roles and have role_ids accessor, and in the form that edits roles of the user the user deselects all roles from role_ids multiple select box, no role_ids parameter is sent. So, any mass-assignment idiom like

+ +
@user.update(params[:user])
+
+ +

wouldn’t update roles.

+ +

To prevent this the helper generates an auxiliary hidden field before every multiple select. The hidden field has the same name as multiple select and blank value.

+ +

Note: The client either sends only the hidden field (representing the deselected multiple select box), or both fields. This means that the resulting array always contains a blank string.

+ +

In case if you don’t want the helper to generate this hidden field you can specify include_hidden: false option.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 158
+def select(object, method, choices = nil, options = {}, html_options = {}, &block)
+  Tags::Select.new(object, method, self, choices, options, html_options, &block).render
+end
+
+
+ +
+ +
+

+ + time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone) + +

+ + +
+

Returns a string of option tags for pretty much any time zone in the world. Supply an ActiveSupport::TimeZone name as selected to have it marked as the selected option tag. You can also supply an array of ActiveSupport::TimeZone objects as priority_zones, so that they will be listed above the rest of the (long) list. (You can use ActiveSupport::TimeZone.us_zones as a convenience for obtaining a list of the US time zones, or a Regexp to select the zones of your choice)

+ +

The selected parameter must be either nil, or a string that names an ActiveSupport::TimeZone.

+ +

By default, model is the ActiveSupport::TimeZone constant (which can be obtained in Active Record as a value object). The model parameter must respond to all and return an array of objects that represent time zones; each object must respond to name. If a Regexp is given it will attempt to match the zones using match? method.

+ +

NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 578
+def time_zone_options_for_select(selected = nil, priority_zones = nil, model = ::ActiveSupport::TimeZone)
+  zone_options = "".html_safe
+
+  zones = model.all
+  convert_zones = lambda { |list| list.map { |z| [ z.to_s, z.name ] } }
+
+  if priority_zones
+    if priority_zones.is_a?(Regexp)
+      priority_zones = zones.select { |z| z.match?(priority_zones) }
+    end
+
+    zone_options.safe_concat options_for_select(convert_zones[priority_zones], selected)
+    zone_options.safe_concat content_tag("option", "-------------", value: "", disabled: true)
+    zone_options.safe_concat "\n"
+
+    zones = zones - priority_zones
+  end
+
+  zone_options.safe_concat options_for_select(convert_zones[zones], selected)
+end
+
+
+ +
+ +
+

+ + time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) + +

+ + +
+

Returns select and option tags for the given object and method, using time_zone_options_for_select to generate the list of option tags.

+ +

In addition to the :include_blank option documented above, this method also supports a :model option, which defaults to ActiveSupport::TimeZone. This may be used by users to specify a different time zone model object. (See time_zone_options_for_select for more information.)

+ +

You can also supply an array of ActiveSupport::TimeZone objects as priority_zones so that they will be listed above the rest of the (long) list. You can use ActiveSupport::TimeZone.us_zones for a list of US time zones, ActiveSupport::TimeZone.country_zones(country_code) for another country’s time zones, or a Regexp to select the zones of your choice.

+ +

Finally, this method supports a :default option, which selects a default ActiveSupport::TimeZone if the object’s time zone is nil.

+ +
time_zone_select(:user, :time_zone, nil, include_blank: true)
+
+time_zone_select(:user, :time_zone, nil, default: "Pacific Time (US & Canada)")
+
+time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.us_zones, default: "Pacific Time (US & Canada)")
+
+time_zone_select(:user, :time_zone, [ ActiveSupport::TimeZone["Alaska"], ActiveSupport::TimeZone["Hawaii"] ])
+
+time_zone_select(:user, :time_zone, /Australia/)
+
+time_zone_select(:user, :time_zone, ActiveSupport::TimeZone.all.sort, model: ActiveSupport::TimeZone)
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 291
+def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {})
+  Tags::TimeZoneSelect.new(object, method, self, priority_zones, options, html_options).render
+end
+
+
+ +
+ +
+

+ + weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week) + +

+ + +
+

Returns a string of option tags for the days of the week.

+ +

Options:

+
  • +

    :index_as_value - Defaults to false, set to true to use the indexes from I18n.translate("date.day_names") as the values. By default, Sunday is always 0.

    +
  • +

    :day_format - The I18n key of the array to use for the weekday options. Defaults to :day_names, set to :abbr_day_names for abbreviations.

    +
  • +

    :beginning_of_week - Defaults to Date.beginning_of_week.

    +
+ +

NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 610
+def weekday_options_for_select(selected = nil, index_as_value: false, day_format: :day_names, beginning_of_week: Date.beginning_of_week)
+  day_names = I18n.translate("date.#{day_format}")
+  day_names = day_names.map.with_index.to_a if index_as_value
+  day_names = day_names.rotate(Date::DAYS_INTO_WEEK.fetch(beginning_of_week))
+
+  options_for_select(day_names, selected)
+end
+
+
+ +
+ +
+

+ + weekday_select(object, method, options = {}, html_options = {}, &block) + +

+ + +
+

Returns select and option tags for the given object and method, using weekday_options_for_select to generate the list of option tags.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_options_helper.rb, line 297
+def weekday_select(object, method, options = {}, html_options = {}, &block)
+  Tags::WeekdaySelect.new(object, method, self, options, html_options, &block).render
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/FormTagHelper.html b/src/7.0/classes/ActionView/Helpers/FormTagHelper.html new file mode 100644 index 0000000000..294b87983d --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/FormTagHelper.html @@ -0,0 +1,2091 @@ +--- +title: ActionView::Helpers::FormTagHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides a number of methods for creating form tags that don’t rely on an Active Record object assigned to the template like FormHelper does. Instead, you provide the names and values manually.

+ +

NOTE: The HTML options disabled, readonly, and multiple can all be treated as booleans. So specifying disabled: true will give disabled="disabled".

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + button_tag(content_or_options = nil, options = nil, &block) + +

+ + +
+

Creates a button element that defines a submit button, reset button or a generic button which can be used in JavaScript, for example. You can use the button tag as a regular submit tag but it isn’t supported in legacy browsers. However, the button tag does allow for richer labels such as images and emphasis, so this helper will also accept a block. By default, it will create a button tag with type submit, if type is not given.

+ +

Options

+
  • +

    :data - This option can be used to add custom data attributes.

    +
  • +

    :disabled - If true, the user will not be able to use this input.

    +
  • +

    Any other key creates standard HTML options for the tag.

    +
+ +

Examples

+ +
button_tag
+# => <button name="button" type="submit">Button</button>
+
+button_tag 'Reset', type: 'reset'
+# => <button name="button" type="reset">Reset</button>
+
+button_tag 'Button', type: 'button'
+# => <button name="button" type="button">Button</button>
+
+button_tag 'Reset', type: 'reset', disabled: true
+# => <button name="button" type="reset" disabled="disabled">Reset</button>
+
+button_tag(type: 'button') do
+  content_tag(:strong, 'Ask me!')
+end
+# => <button name="button" type="button">
+#     <strong>Ask me!</strong>
+#    </button>
+
+ +

Deprecated: Rails UJS attributes

+ +

Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7, this library is no longer on by default. This library integrated with the following options:

+
  • +

    confirm: 'question?' - If present, the unobtrusive JavaScript drivers will provide a prompt with the question specified. If the user accepts, the form 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.

    + +

    button_tag “Save”, data: { confirm: “Are you sure?” } # => <button name=“button” type=“submit” data-confirm=“Are you sure?”>Save</button>

    + +

    button_tag “Checkout”, data: { disable_with: “Please wait…” } # => <button data-disable-with=“Please wait…” name=“button” type=“submit”>Checkout</button>

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 578
+def button_tag(content_or_options = nil, options = nil, &block)
+  if content_or_options.is_a? Hash
+    options = content_or_options
+  else
+    options ||= {}
+  end
+
+  options = { "name" => "button", "type" => "submit" }.merge!(options.stringify_keys)
+
+  if block_given?
+    content_tag :button, options, &block
+  else
+    content_tag :button, content_or_options || "Button", options
+  end
+end
+
+
+ +
+ +
+

+ + check_box_tag(name, value = "1", checked = false, options = {}) + +

+ + +
+

Creates a check box form input tag.

+ +

Options

+
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    Any other key creates standard HTML options for the tag.

    +
+ +

Examples

+ +
check_box_tag 'accept'
+# => <input id="accept" name="accept" type="checkbox" value="1" />
+
+check_box_tag 'rock', 'rock music'
+# => <input id="rock" name="rock" type="checkbox" value="rock music" />
+
+check_box_tag 'receive_email', 'yes', true
+# => <input checked="checked" id="receive_email" name="receive_email" type="checkbox" value="yes" />
+
+check_box_tag 'tos', 'yes', false, class: 'accept_tos'
+# => <input class="accept_tos" id="tos" name="tos" type="checkbox" value="yes" />
+
+check_box_tag 'eula', 'accepted', false, disabled: true
+# => <input disabled="disabled" id="eula" name="eula" type="checkbox" value="accepted" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 444
+def check_box_tag(name, value = "1", checked = false, options = {})
+  html_options = { "type" => "checkbox", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
+  html_options["checked"] = "checked" if checked
+  tag :input, html_options
+end
+
+
+ +
+ +
+

+ + color_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “color”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
color_field_tag 'name'
+# => <input id="name" name="name" type="color" />
+
+color_field_tag 'color', '#DEF726'
+# => <input id="color" name="color" type="color" value="#DEF726" />
+
+color_field_tag 'color', nil, class: 'special_input'
+# => <input class="special_input" id="color" name="color" type="color" />
+
+color_field_tag 'color', '#DEF726', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="color" name="color" type="color" value="#DEF726" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 676
+def color_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :color))
+end
+
+
+ +
+ +
+

+ + date_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “date”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
date_field_tag 'name'
+# => <input id="name" name="name" type="date" />
+
+date_field_tag 'date', '01/01/2014'
+# => <input id="date" name="date" type="date" value="01/01/2014" />
+
+date_field_tag 'date', nil, class: 'special_input'
+# => <input class="special_input" id="date" name="date" type="date" />
+
+date_field_tag 'date', '01/01/2014', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="date" name="date" type="date" value="01/01/2014" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 746
+def date_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :date))
+end
+
+
+ +
+ +
+

+ + datetime_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “datetime-local”.

+ +

Options

+ +

Supports the same options as text_field_tag. Additionally, supports:

+
  • +

    :min - The minimum acceptable value.

    +
  • +

    :max - The maximum acceptable value.

    +
  • +

    :step - The acceptable value granularity.

    +
+
+ + + +
+ Also aliased as: datetime_local_field_tag +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 773
+def datetime_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: "datetime-local"))
+end
+
+
+ +
+ +
+

+ + datetime_local_field_tag(name, value = nil, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: datetime_field_tag +
+ + + +
+ +
+

+ + email_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “email”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
email_field_tag 'name'
+# => <input id="name" name="name" type="email" />
+
+email_field_tag 'email', 'email@example.com'
+# => <input id="email" name="email" type="email" value="email@example.com" />
+
+email_field_tag 'email', nil, class: 'special_input'
+# => <input class="special_input" id="email" name="email" type="email" />
+
+email_field_tag 'email', 'email@example.com', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="email" name="email" type="email" value="email@example.com" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 847
+def email_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :email))
+end
+
+
+ +
+ +
+

+ + field_id(object_name, method_name, *suffixes, index: nil, namespace: nil) + +

+ + +
+

Generate an HTML id attribute value for the given name and field combination

+ +

Return the value generated by the FormBuilder for the given attribute name.

+ +
<%= label_tag :post, :title %>
+<%= text_field_tag :post, :title, aria: { describedby: field_id(:post, :title, :error) } %>
+<%= tag.span("is blank", id: field_id(:post, :title, :error) %>
+
+ +

In the example above, the <input type="text"> element built by the call to text_field_tag declares an aria-describedby attribute referencing the <span> element, sharing a common id root (post_title, in this case).

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 99
+def field_id(object_name, method_name, *suffixes, index: nil, namespace: nil)
+  if object_name.respond_to?(:model_name)
+    object_name = object_name.model_name.singular
+  end
+
+  sanitized_object_name = object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").delete_suffix("_")
+
+  sanitized_method_name = method_name.to_s.delete_suffix("?")
+
+  [
+    namespace,
+    sanitized_object_name.presence,
+    (index unless sanitized_object_name.empty?),
+    sanitized_method_name,
+    *suffixes,
+  ].tap(&:compact!).join("_")
+end
+
+
+ +
+ +
+

+ + field_name(object_name, method_name, *method_names, multiple: false, index: nil) + +

+ + +
+

Generate an HTML name attribute value for the given name and field combination

+ +

Return the value generated by the FormBuilder for the given attribute name.

+ +
<%= text_field_tag :post, :title, name: field_name(:post, :title, :subtitle) %>
+<%# => <input type="text" name="post[title][subtitle]">
+
+<%= text_field_tag :post, :tag, name: field_name(:post, :tag, multiple: true) %>
+<%# => <input type="text" name="post[tag][]">
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 129
+def field_name(object_name, method_name, *method_names, multiple: false, index: nil)
+  names = method_names.map! { |name| "[#{name}]" }.join
+
+  # a little duplication to construct fewer strings
+  case
+  when object_name.blank?
+    "#{method_name}#{names}#{multiple ? "[]" : ""}"
+  when index
+    "#{object_name}[#{index}][#{method_name}]#{names}#{multiple ? "[]" : ""}"
+  else
+    "#{object_name}[#{method_name}]#{names}#{multiple ? "[]" : ""}"
+  end
+end
+
+
+ +
+ +
+

+ + field_set_tag(legend = nil, options = nil, &block) + +

+ + +
+

Creates a field set for grouping HTML form elements.

+ +

legend will become the fieldset’s title (optional as per W3C). options accept the same values as tag.

+ +

Examples

+ +
<%= field_set_tag do %>
+  <p><%= text_field_tag 'name' %></p>
+<% end %>
+# => <fieldset><p><input id="name" name="name" type="text" /></p></fieldset>
+
+<%= field_set_tag 'Your details' do %>
+  <p><%= text_field_tag 'name' %></p>
+<% end %>
+# => <fieldset><legend>Your details</legend><p><input id="name" name="name" type="text" /></p></fieldset>
+
+<%= field_set_tag nil, class: 'format' do %>
+  <p><%= text_field_tag 'name' %></p>
+<% end %>
+# => <fieldset class="format"><p><input id="name" name="name" type="text" /></p></fieldset>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 650
+def field_set_tag(legend = nil, options = nil, &block)
+  output = tag(:fieldset, options, true)
+  output.safe_concat(content_tag("legend", legend)) unless legend.blank?
+  output.concat(capture(&block)) if block_given?
+  output.safe_concat("</fieldset>")
+end
+
+
+ +
+ +
+

+ + file_field_tag(name, options = {}) + +

+ + +
+

Creates a file upload field. If you are using file uploads then you will also need to set the multipart option for the form tag:

+ +
<%= form_tag '/upload', multipart: true do %>
+  <label for="file">File to Upload</label> <%= file_field_tag "file" %>
+  <%= submit_tag %>
+<% end %>
+
+ +

The specified URL will then be passed a File object containing the selected file, or if the field was left blank, a StringIO object.

+ +

Options

+
  • +

    Creates standard HTML attributes for the tag.

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :multiple - If set to true, *in most updated browsers* the user will be allowed to select multiple files.

    +
  • +

    :accept - If set to one or multiple mime-types, the user will be suggested a filter when choosing a file. You still need to set up model validations.

    +
+ +

Examples

+ +
file_field_tag 'attachment'
+# => <input id="attachment" name="attachment" type="file" />
+
+file_field_tag 'avatar', class: 'profile_input'
+# => <input class="profile_input" id="avatar" name="avatar" type="file" />
+
+file_field_tag 'picture', disabled: true
+# => <input disabled="disabled" id="picture" name="picture" type="file" />
+
+file_field_tag 'resume', value: '~/resume.doc'
+# => <input id="resume" name="resume" type="file" value="~/resume.doc" />
+
+file_field_tag 'user_pic', accept: 'image/png,image/gif,image/jpeg'
+# => <input accept="image/png,image/gif,image/jpeg" id="user_pic" name="user_pic" type="file" />
+
+file_field_tag 'file', accept: 'text/html', class: 'upload', value: 'index.html'
+# => <input accept="text/html" class="upload" id="file" name="file" type="file" value="index.html" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 344
+def file_field_tag(name, options = {})
+  text_field_tag(name, nil, convert_direct_upload_option_to_url(options.merge(type: :file)))
+end
+
+
+ +
+ +
+

+ + form_tag(url_for_options = {}, options = {}, &block) + +

+ + +
+

Starts a form tag that points the action to a URL configured with url_for_options just like ActionController::Base#url_for. The method for the form defaults to POST.

+ +

Options

+
  • +

    :multipart - If set to true, the enctype is set to “multipart/form-data”.

    +
  • +

    :method - The method to use when submitting the form, usually either “get” or “post”. If “patch”, “put”, “delete”, or another verb is used, a hidden input with name _method is added to simulate the verb over post.

    +
  • +

    :authenticity_token - Authenticity token to use in the form. Use only if you need to pass custom authenticity token string, or to not add authenticity_token field at all (by passing false). Remote forms may omit the embedded authenticity token by setting config.action_view.embed_authenticity_token_in_remote_forms = false. This is helpful when you’re fragment-caching the form. Remote forms get the authenticity token from the meta tag, so embedding is unnecessary unless you support browsers without JavaScript.

    +
  • +

    :remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the submit behavior. By default this behavior is an ajax submit.

    +
  • +

    :enforce_utf8 - If set to false, a hidden input with name utf8 is not output.

    +
  • +

    Any other key creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
form_tag('/posts')
+# => <form action="/posts" method="post">
+
+form_tag('/posts/1', method: :put)
+# => <form action="/posts/1" method="post"> ... <input name="_method" type="hidden" value="put" /> ...
+
+form_tag('/upload', multipart: true)
+# => <form action="/upload" method="post" enctype="multipart/form-data">
+
+<%= form_tag('/posts') do -%>
+  <div><%= submit_tag 'Save' %></div>
+<% end -%>
+# => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form>
+
+<%= form_tag('/posts', remote: true) %>
+# => <form action="/posts" method="post" data-remote="true">
+
+form_tag(false, method: :get)
+# => <form method="get">
+
+form_tag('http://far.away.com/form', authenticity_token: false)
+# form without authenticity token
+
+form_tag('http://far.away.com/form', authenticity_token: "cf50faa3fe97702ca1ae")
+# form with custom authenticity token
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 75
+def form_tag(url_for_options = {}, options = {}, &block)
+  html_options = html_options_for_form(url_for_options, options)
+  if block_given?
+    form_tag_with_body(html_options, capture(&block))
+  else
+    form_tag_html(html_options)
+  end
+end
+
+
+ +
+ +
+

+ + hidden_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a hidden form input field used to transmit data that would be lost due to HTTP’s statelessness or data that should be hidden from the user.

+ +

Options

+
  • +

    Creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
hidden_field_tag 'tags_list'
+# => <input type="hidden" name="tags_list" id="tags_list" autocomplete="off" />
+
+hidden_field_tag 'token', 'VUBJKB23UIVI1UU1VOBVI@'
+# => <input type="hidden" name="token" id="token" value="VUBJKB23UIVI1UU1VOBVI@" autocomplete="off" />
+
+hidden_field_tag 'collected_input', '', onchange: "alert('Input collected!')"
+# => <input type="hidden" name="collected_input" id="collected_input"
+     value="" onchange="alert(&#39;Input collected!&#39;)" autocomplete="off" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 305
+def hidden_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :hidden, autocomplete: "off"))
+end
+
+
+ +
+ +
+

+ + image_submit_tag(source, options = {}) + +

+ + +
+

Displays an image which when clicked will submit the form.

+ +

source is passed to AssetTagHelper#path_to_image

+ +

Options

+
  • +

    :data - This option can be used to add custom data attributes.

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    Any other key creates standard HTML options for the tag.

    +
+ +

Data attributes

+
  • +

    confirm: 'question?' - This will add a JavaScript confirm prompt with the question specified. If the user accepts, the form is processed normally, otherwise no action is taken.

    +
+ +

Examples

+ +
image_submit_tag("login.png")
+# => <input src="/assets/login.png" type="image" />
+
+image_submit_tag("purchase.png", disabled: true)
+# => <input disabled="disabled" src="/assets/purchase.png" type="image" />
+
+image_submit_tag("search.png", class: 'search_button', alt: 'Find')
+# => <input class="search_button" src="/assets/search.png" type="image" />
+
+image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
+# => <input class="agree_disagree_button" disabled="disabled" src="/assets/agree.png" type="image" />
+
+image_submit_tag("save.png", data: { confirm: "Are you sure?" })
+# => <input src="/assets/save.png" data-confirm="Are you sure?" type="image" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 624
+def image_submit_tag(source, options = {})
+  options = options.stringify_keys
+  src = path_to_image(source, skip_pipeline: options.delete("skip_pipeline"))
+  tag :input, { "type" => "image", "src" => src }.update(options)
+end
+
+
+ +
+ +
+

+ + label_tag(name = nil, content_or_options = nil, options = nil, &block) + +

+ + +
+

Creates a label element. Accepts a block.

+ +

Options

+
  • +

    Creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
label_tag 'name'
+# => <label for="name">Name</label>
+
+label_tag 'name', 'Your name'
+# => <label for="name">Your name</label>
+
+label_tag 'name', nil, class: 'small_label'
+# => <label for="name" class="small_label">Name</label>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 278
+def label_tag(name = nil, content_or_options = nil, options = nil, &block)
+  if block_given? && content_or_options.is_a?(Hash)
+    options = content_or_options = content_or_options.stringify_keys
+  else
+    options ||= {}
+    options = options.stringify_keys
+  end
+  options["for"] = sanitize_to_id(name) unless name.blank? || options.has_key?("for")
+  content_tag :label, content_or_options || name.to_s.humanize, options, &block
+end
+
+
+ +
+ +
+

+ + month_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “month”.

+ +

Options

+ +

Supports the same options as text_field_tag. Additionally, supports:

+
  • +

    :min - The minimum acceptable value.

    +
  • +

    :max - The maximum acceptable value.

    +
  • +

    :step - The acceptable value granularity.

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 788
+def month_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :month))
+end
+
+
+ +
+ +
+

+ + number_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a number field.

+ +

Options

+ +

Supports the same options as text_field_tag. Additionally, supports:

+
  • +

    :min - The minimum acceptable value.

    +
  • +

    :max - The maximum acceptable value.

    +
  • +

    :in - A range specifying the :min and :max values.

    +
  • +

    :within - Same as :in.

    +
  • +

    :step - The acceptable value granularity.

    +
+ +

Examples

+ +
number_field_tag 'quantity'
+# => <input id="quantity" name="quantity" type="number" />
+
+number_field_tag 'quantity', '1'
+# => <input id="quantity" name="quantity" type="number" value="1" />
+
+number_field_tag 'quantity', nil, class: 'special_input'
+# => <input class="special_input" id="quantity" name="quantity" type="number" />
+
+number_field_tag 'quantity', nil, min: 1
+# => <input id="quantity" name="quantity" min="1" type="number" />
+
+number_field_tag 'quantity', nil, max: 9
+# => <input id="quantity" name="quantity" max="9" type="number" />
+
+number_field_tag 'quantity', nil, in: 1...10
+# => <input id="quantity" name="quantity" min="1" max="9" type="number" />
+
+number_field_tag 'quantity', nil, within: 1...10
+# => <input id="quantity" name="quantity" min="1" max="9" type="number" />
+
+number_field_tag 'quantity', nil, min: 1, max: 10
+# => <input id="quantity" name="quantity" min="1" max="10" type="number" />
+
+number_field_tag 'quantity', nil, min: 1, max: 10, step: 2
+# => <input id="quantity" name="quantity" min="1" max="10" step="2" type="number" />
+
+number_field_tag 'quantity', '1', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="quantity" name="quantity" type="number" value="1" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 895
+def number_field_tag(name, value = nil, options = {})
+  options = options.stringify_keys
+  options["type"] ||= "number"
+  if range = options.delete("in") || options.delete("within")
+    options.update("min" => range.min, "max" => range.max)
+  end
+  text_field_tag(name, value, options)
+end
+
+
+ +
+ +
+

+ + password_field_tag(name = "password", value = nil, options = {}) + +

+ + +
+

Creates a password field, a masked text field that will hide the users input behind a mask character.

+ +

Options

+
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :size - The number of visible characters that will fit in the input.

    +
  • +

    :maxlength - The maximum number of characters that the browser will allow the user to enter.

    +
  • +

    Any other key creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
password_field_tag 'pass'
+# => <input id="pass" name="pass" type="password" />
+
+password_field_tag 'secret', 'Your secret here'
+# => <input id="secret" name="secret" type="password" value="Your secret here" />
+
+password_field_tag 'masked', nil, class: 'masked_input_field'
+# => <input class="masked_input_field" id="masked" name="masked" type="password" />
+
+password_field_tag 'token', '', size: 15
+# => <input id="token" name="token" size="15" type="password" value="" />
+
+password_field_tag 'key', nil, maxlength: 16
+# => <input id="key" maxlength="16" name="key" type="password" />
+
+password_field_tag 'confirm_pass', nil, disabled: true
+# => <input disabled="disabled" id="confirm_pass" name="confirm_pass" type="password" />
+
+password_field_tag 'pin', '1234', maxlength: 4, size: 6, class: "pin_input"
+# => <input class="pin_input" id="pin" maxlength="4" name="pin" size="6" type="password" value="1234" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 377
+def password_field_tag(name = "password", value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :password))
+end
+
+
+ +
+ +
+

+ + phone_field_tag(name, value = nil, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: telephone_field_tag +
+ + + +
+ +
+

+ + radio_button_tag(name, value, checked = false, options = {}) + +

+ + +
+

Creates a radio button; use groups of radio buttons named the same to allow users to select from a group of options.

+ +

Options

+
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    Any other key creates standard HTML options for the tag.

    +
+ +

Examples

+ +
radio_button_tag 'favorite_color', 'maroon'
+# => <input id="favorite_color_maroon" name="favorite_color" type="radio" value="maroon" />
+
+radio_button_tag 'receive_updates', 'no', true
+# => <input checked="checked" id="receive_updates_no" name="receive_updates" type="radio" value="no" />
+
+radio_button_tag 'time_slot', "3:00 p.m.", false, disabled: true
+# => <input disabled="disabled" id="time_slot_3:00_p.m." name="time_slot" type="radio" value="3:00 p.m." />
+
+radio_button_tag 'color', "green", true, class: "color_input"
+# => <input checked="checked" class="color_input" id="color_green" name="color" type="radio" value="green" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 469
+def radio_button_tag(name, value, checked = false, options = {})
+  html_options = { "type" => "radio", "name" => name, "id" => "#{sanitize_to_id(name)}_#{sanitize_to_id(value)}", "value" => value }.update(options.stringify_keys)
+  html_options["checked"] = "checked" if checked
+  tag :input, html_options
+end
+
+
+ +
+ +
+

+ + range_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a range form element.

+ +

Options

+ +

Supports the same options as number_field_tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 909
+def range_field_tag(name, value = nil, options = {})
+  number_field_tag(name, value, options.merge(type: :range))
+end
+
+
+ +
+ +
+

+ + search_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “search”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
search_field_tag 'name'
+# => <input id="name" name="name" type="search" />
+
+search_field_tag 'search', 'Enter your search query here'
+# => <input id="search" name="search" type="search" value="Enter your search query here" />
+
+search_field_tag 'search', nil, class: 'special_input'
+# => <input class="special_input" id="search" name="search" type="search" />
+
+search_field_tag 'search', 'Enter your search query here', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="search" name="search" type="search" value="Enter your search query here" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 699
+def search_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :search))
+end
+
+
+ +
+ +
+

+ + select_tag(name, option_tags = nil, options = {}) + +

+ + +
+

Creates a dropdown selection box, or if the :multiple option is set to true, a multiple choice selection box.

+ +

Helpers::FormOptions can be used to create common select boxes such as countries, time zones, or associated records. option_tags is a string containing the option tags for the select box.

+ +

Options

+
  • +

    :multiple - If set to true, the selection will allow multiple choices.

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :include_blank - If set to true, an empty option will be created. If set to a string, the string will be used as the option’s content and the value will be empty.

    +
  • +

    :prompt - Create a prompt option with blank value and the text asking user to select something.

    +
  • +

    Any other key creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
select_tag "people", options_from_collection_for_select(@people, "id", "name")
+# <select id="people" name="people"><option value="1">David</option></select>
+
+select_tag "people", options_from_collection_for_select(@people, "id", "name", "1")
+# <select id="people" name="people"><option value="1" selected="selected">David</option></select>
+
+select_tag "people", raw("<option>David</option>")
+# => <select id="people" name="people"><option>David</option></select>
+
+select_tag "count", raw("<option>1</option><option>2</option><option>3</option><option>4</option>")
+# => <select id="count" name="count"><option>1</option><option>2</option>
+#    <option>3</option><option>4</option></select>
+
+select_tag "colors", raw("<option>Red</option><option>Green</option><option>Blue</option>"), multiple: true
+# => <select id="colors" multiple="multiple" name="colors[]"><option>Red</option>
+#    <option>Green</option><option>Blue</option></select>
+
+select_tag "locations", raw("<option>Home</option><option selected='selected'>Work</option><option>Out</option>")
+# => <select id="locations" name="locations"><option>Home</option><option selected='selected'>Work</option>
+#    <option>Out</option></select>
+
+select_tag "access", raw("<option>Read</option><option>Write</option>"), multiple: true, class: 'form_input', id: 'unique_id'
+# => <select class="form_input" id="unique_id" multiple="multiple" name="access[]"><option>Read</option>
+#    <option>Write</option></select>
+
+select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: true
+# => <select id="people" name="people"><option value="" label=" "></option><option value="1">David</option></select>
+
+select_tag "people", options_from_collection_for_select(@people, "id", "name"), include_blank: "All"
+# => <select id="people" name="people"><option value="">All</option><option value="1">David</option></select>
+
+select_tag "people", options_from_collection_for_select(@people, "id", "name"), prompt: "Select something"
+# => <select id="people" name="people"><option value="">Select something</option><option value="1">David</option></select>
+
+select_tag "destination", raw("<option>NYC</option><option>Paris</option><option>Rome</option>"), disabled: true
+# => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
+#    <option>Paris</option><option>Rome</option></select>
+
+select_tag "credit_card", options_for_select([ "VISA", "MasterCard" ], "MasterCard")
+# => <select id="credit_card" name="credit_card"><option>VISA</option>
+#    <option selected="selected">MasterCard</option></select>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 198
+def select_tag(name, option_tags = nil, options = {})
+  option_tags ||= ""
+  html_name = (options[:multiple] == true && !name.end_with?("[]")) ? "#{name}[]" : name
+
+  if options.include?(:include_blank)
+    include_blank = options[:include_blank]
+    options = options.except(:include_blank)
+    options_for_blank_options_tag = { value: "" }
+
+    if include_blank == true
+      include_blank = ""
+      options_for_blank_options_tag[:label] = " "
+    end
+
+    if include_blank
+      option_tags = content_tag("option", include_blank, options_for_blank_options_tag).safe_concat(option_tags)
+    end
+  end
+
+  if prompt = options.delete(:prompt)
+    option_tags = content_tag("option", prompt, value: "").safe_concat(option_tags)
+  end
+
+  content_tag "select", option_tags, { "name" => html_name, "id" => sanitize_to_id(name) }.update(options.stringify_keys)
+end
+
+
+ +
+ +
+

+ + submit_tag(value = "Save changes", options = {}) + +

+ + +
+

Creates a submit button with the text value as the caption.

+ +

Options

+
  • +

    :data - This option can be used to add custom data attributes.

    +
  • +

    :disabled - If true, the user will not be able to use this input.

    +
  • +

    Any other key creates standard HTML options for the tag.

    +
+ +

Examples

+ +
submit_tag
+# => <input name="commit" data-disable-with="Save changes" type="submit" value="Save changes" />
+
+submit_tag "Edit this article"
+# => <input name="commit" data-disable-with="Edit this article" type="submit" value="Edit this article" />
+
+submit_tag "Save edits", disabled: true
+# => <input disabled="disabled" name="commit" data-disable-with="Save edits" type="submit" value="Save edits" />
+
+submit_tag nil, class: "form_submit"
+# => <input class="form_submit" name="commit" type="submit" />
+
+submit_tag "Edit", class: "edit_button"
+# => <input class="edit_button" data-disable-with="Edit" name="commit" type="submit" value="Edit" />
+
+ +

Deprecated: Rails UJS attributes

+ +

Prior to Rails 7, Rails shipped with the JavaScript library called @rails/ujs on by default. Following Rails 7, this library is no longer on by default. This library integrated with the following options:

+
  • +

    confirm: 'question?' - If present the unobtrusive JavaScript drivers will provide a prompt with the question specified. If the user accepts, the form 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. To disable this feature for a single submit tag pass :data => { disable_with: false } Defaults to value attribute.

    + +

    submit_tag “Complete sale”, data: { disable_with: “Submitting…” } # => <input name=“commit” data-disable-with=“Submitting…” type=“submit” value=“Complete sale” />

    + +

    submit_tag “Save”, data: { confirm: “Are you sure?” } # => <input name=‘commit’ type=‘submit’ value=‘Save’ data-disable-with=“Save” data-confirm=“Are you sure?” />

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 517
+def submit_tag(value = "Save changes", options = {})
+  options = options.deep_stringify_keys
+  tag_options = { "type" => "submit", "name" => "commit", "value" => value }.update(options)
+  set_default_disable_with value, tag_options
+  tag :input, tag_options
+end
+
+
+ +
+ +
+

+ + telephone_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “tel”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
telephone_field_tag 'name'
+# => <input id="name" name="name" type="tel" />
+
+telephone_field_tag 'tel', '0123456789'
+# => <input id="tel" name="tel" type="tel" value="0123456789" />
+
+telephone_field_tag 'tel', nil, class: 'special_input'
+# => <input class="special_input" id="tel" name="tel" type="tel" />
+
+telephone_field_tag 'tel', '0123456789', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="tel" name="tel" type="tel" value="0123456789" />
+
+
+ + + +
+ Also aliased as: phone_field_tag +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 722
+def telephone_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :tel))
+end
+
+
+ +
+ +
+

+ + text_area_tag(name, content = nil, options = {}) + +

+ + +
+

Creates a text input area; use a textarea for longer text inputs such as blog posts or descriptions.

+ +

Options

+
  • +

    :size - A string specifying the dimensions (columns by rows) of the textarea (e.g., “25x10”).

    +
  • +

    :rows - Specify the number of rows in the textarea

    +
  • +

    :cols - Specify the number of columns in the textarea

    +
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :escape - By default, the contents of the text input are HTML escaped. If you need unescaped contents, set this to false.

    +
  • +

    Any other key creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
text_area_tag 'post'
+# => <textarea id="post" name="post"></textarea>
+
+text_area_tag 'bio', @user.bio
+# => <textarea id="bio" name="bio">This is my biography.</textarea>
+
+text_area_tag 'body', nil, rows: 10, cols: 25
+# => <textarea cols="25" id="body" name="body" rows="10"></textarea>
+
+text_area_tag 'body', nil, size: "25x10"
+# => <textarea name="body" id="body" cols="25" rows="10"></textarea>
+
+text_area_tag 'description', "Description goes here.", disabled: true
+# => <textarea disabled="disabled" id="description" name="description">Description goes here.</textarea>
+
+text_area_tag 'comment', nil, class: 'comment_input'
+# => <textarea class="comment_input" id="comment" name="comment"></textarea>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 410
+def text_area_tag(name, content = nil, options = {})
+  options = options.stringify_keys
+
+  if size = options.delete("size")
+    options["cols"], options["rows"] = size.split("x") if size.respond_to?(:split)
+  end
+
+  escape = options.delete("escape") { true }
+  content = ERB::Util.html_escape(content) if escape
+
+  content_tag :textarea, content.to_s.html_safe, { "name" => name, "id" => sanitize_to_id(name) }.update(options)
+end
+
+
+ +
+ +
+

+ + text_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a standard text field; use these text fields to input smaller chunks of text like a username or a search query.

+ +

Options

+
  • +

    :disabled - If set to true, the user will not be able to use this input.

    +
  • +

    :size - The number of visible characters that will fit in the input.

    +
  • +

    :maxlength - The maximum number of characters that the browser will allow the user to enter.

    +
  • +

    :placeholder - The text contained in the field by default which is removed when the field receives focus. If set to true, use the translation found in the current I18n locale (through helpers.placeholder.<modelname>.<attribute>).

    +
  • +

    Any other key creates standard HTML attributes for the tag.

    +
+ +

Examples

+ +
text_field_tag 'name'
+# => <input id="name" name="name" type="text" />
+
+text_field_tag 'query', 'Enter your search query here'
+# => <input id="query" name="query" type="text" value="Enter your search query here" />
+
+text_field_tag 'search', nil, placeholder: 'Enter search term...'
+# => <input id="search" name="search" placeholder="Enter search term..." type="text" />
+
+text_field_tag 'request', nil, class: 'special_input'
+# => <input class="special_input" id="request" name="request" type="text" />
+
+text_field_tag 'address', '', size: 75
+# => <input id="address" name="address" size="75" type="text" value="" />
+
+text_field_tag 'zip', nil, maxlength: 5
+# => <input id="zip" maxlength="5" name="zip" type="text" />
+
+text_field_tag 'payment_amount', '$0.00', disabled: true
+# => <input disabled="disabled" id="payment_amount" name="payment_amount" type="text" value="$0.00" />
+
+text_field_tag 'ip', '0.0.0.0', maxlength: 15, size: 20, class: "ip-input"
+# => <input class="ip-input" id="ip" maxlength="15" name="ip" size="20" type="text" value="0.0.0.0" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 260
+def text_field_tag(name, value = nil, options = {})
+  tag :input, { "type" => "text", "name" => name, "id" => sanitize_to_id(name), "value" => value }.update(options.stringify_keys)
+end
+
+
+ +
+ +
+

+ + time_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “time”.

+ +

Options

+ +

Supports the same options as text_field_tag. Additionally, supports:

+
  • +

    :min - The minimum acceptable value.

    +
  • +

    :max - The maximum acceptable value.

    +
  • +

    :step - The acceptable value granularity.

    +
  • +

    :include_seconds - Include seconds and ms in the output timestamp format (true by default).

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 760
+def time_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :time))
+end
+
+
+ +
+ +
+

+ + url_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “url”.

+ +

Options

+ +

Supports the same options as text_field_tag.

+ +

Examples

+ +
url_field_tag 'name'
+# => <input id="name" name="name" type="url" />
+
+url_field_tag 'url', 'http://rubyonrails.org'
+# => <input id="url" name="url" type="url" value="http://rubyonrails.org" />
+
+url_field_tag 'url', nil, class: 'special_input'
+# => <input class="special_input" id="url" name="url" type="url" />
+
+url_field_tag 'url', 'http://rubyonrails.org', class: 'special_input', disabled: true
+# => <input disabled="disabled" class="special_input" id="url" name="url" type="url" value="http://rubyonrails.org" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 824
+def url_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :url))
+end
+
+
+ +
+ +
+

+ + utf8_enforcer_tag() + +

+ + +
+

Creates the hidden UTF-8 enforcer tag. Override this method in a helper to customize the tag.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 915
+def utf8_enforcer_tag
+  # Use raw HTML to ensure the value is written as an HTML entity; it
+  # needs to be the right character regardless of which encoding the
+  # browser infers.
+  '<input name="utf8" type="hidden" value="&#x2713;" autocomplete="off" />'.html_safe
+end
+
+
+ +
+ +
+

+ + week_field_tag(name, value = nil, options = {}) + +

+ + +
+

Creates a text field of type “week”.

+ +

Options

+ +

Supports the same options as text_field_tag. Additionally, supports:

+
  • +

    :min - The minimum acceptable value.

    +
  • +

    :max - The maximum acceptable value.

    +
  • +

    :step - The acceptable value granularity.

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/form_tag_helper.rb, line 801
+def week_field_tag(name, value = nil, options = {})
+  text_field_tag(name, value, options.merge(type: :week))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/JavaScriptHelper.html b/src/7.0/classes/ActionView/Helpers/JavaScriptHelper.html new file mode 100644 index 0000000000..47bd828135 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/JavaScriptHelper.html @@ -0,0 +1,263 @@ +--- +title: ActionView::Helpers::JavaScriptHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
JS_ESCAPE_MAP={ +"\\" => "\\\\", +"</" => '<\/', +"\r\n" => '\n', +"\n" => '\n', +"\r" => '\n', +'"' => '\\"', +"'" => "\\'", +"`" => "\\`", +"$" => "\\$" +}
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + escape_javascript(javascript) + +

+ + +
+

Escapes carriage returns and single and double quotes for JavaScript segments.

+ +

Also available through the alias j(). This is particularly helpful in JavaScript responses, like:

+ +
$('some_element').replaceWith('<%= j render 'some/element_template' %>');
+
+
+ + + +
+ Also aliased as: j +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/javascript_helper.rb, line 27
+def escape_javascript(javascript)
+  javascript = javascript.to_s
+  if javascript.empty?
+    result = ""
+  else
+    result = javascript.gsub(/(\\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"']|[`]|[$])/u, JS_ESCAPE_MAP)
+  end
+  javascript.html_safe? ? result.html_safe : result
+end
+
+
+ +
+ +
+

+ + j(javascript) + +

+ + +
+ +
+ + + + + +
+ Alias for: escape_javascript +
+ + + +
+ +
+

+ + javascript_tag(content_or_options_with_block = nil, html_options = {}, &block) + +

+ + +
+

Returns a JavaScript tag with the content inside. Example:

+ +
javascript_tag "alert('All is good')"
+
+ +

Returns:

+ +
<script>
+//<![CDATA[
+alert('All is good')
+//]]>
+</script>
+
+ +

html_options may be a hash of attributes for the <script> tag.

+ +
javascript_tag "alert('All is good')", type: 'application/javascript'
+
+ +

Returns:

+ +
<script type="application/javascript">
+//<![CDATA[
+alert('All is good')
+//]]>
+</script>
+
+ +

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 type: 'application/javascript' 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 -%>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/javascript_helper.rb, line 74
+def javascript_tag(content_or_options_with_block = nil, html_options = {}, &block)
+  content =
+    if block_given?
+      html_options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
+      capture(&block)
+    else
+      content_or_options_with_block
+    end
+
+  if html_options[:nonce] == true
+    html_options[:nonce] = content_security_policy_nonce
+  end
+
+  content_tag("script", javascript_cdata_section(content), html_options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/NumberHelper.html b/src/7.0/classes/ActionView/Helpers/NumberHelper.html new file mode 100644 index 0000000000..61b1a4c3cb --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/NumberHelper.html @@ -0,0 +1,673 @@ +--- +title: ActionView::Helpers::NumberHelper +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + number_to_currency(number, options = {}) + +

+ + +
+

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 €
+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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 127
+def number_to_currency(number, options = {})
+  delegate_number_helper_method(:number_to_currency, number, options)
+end
+
+
+ +
+ +
+

+ + number_to_human(number, options = {}) + +

+ + +
+

Pretty prints (formats and approximates) a number in a way it is more readable by humans (e.g.: 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 (e.g.: 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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 404
+def number_to_human(number, options = {})
+  delegate_number_helper_method(:number_to_human, number, options)
+end
+
+
+ +
+ +
+

+ + number_to_human_size(number, options = {}) + +

+ + +
+

Formats the bytes in number into a more understandable representation (e.g., giving it 1500 yields 1.46 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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 297
+def number_to_human_size(number, options = {})
+  delegate_number_helper_method(:number_to_human_size, number, options)
+end
+
+
+ +
+ +
+

+ + number_to_percentage(number, options = {}) + +

+ + +
+

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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 167
+def number_to_percentage(number, options = {})
+  delegate_number_helper_method(:number_to_percentage, number, options)
+end
+
+
+ +
+ +
+

+ + number_to_phone(number, options = {}) + +

+ + +
+

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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 62
+def number_to_phone(number, options = {})
+  return unless number
+  options = options.symbolize_keys
+
+  parse_float(number, true) if options.delete(:raise)
+  ERB::Util.html_escape(ActiveSupport::NumberHelper.number_to_phone(number, options))
+end
+
+
+ +
+ +
+

+ + number_with_delimiter(number, options = {}) + +

+ + +
+

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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 206
+def number_with_delimiter(number, options = {})
+  delegate_number_helper_method(:number_to_delimited, number, options)
+end
+
+
+ +
+ +
+

+ + number_with_precision(number, options = {}) + +

+ + +
+

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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 251
+def number_with_precision(number, options = {})
+  delegate_number_helper_method(:number_to_rounded, number, options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/NumberHelper/InvalidNumberError.html b/src/7.0/classes/ActionView/Helpers/NumberHelper/InvalidNumberError.html new file mode 100644 index 0000000000..a7d0c36418 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/NumberHelper/InvalidNumberError.html @@ -0,0 +1,127 @@ +--- +title: ActionView::Helpers::NumberHelper::InvalidNumberError +layout: default +--- +
+ +
+
+ +
+ +

Raised when argument number param given to the helpers is invalid and the option :raise is set to true.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + number
+ + + + +

Class Public methods

+ +
+

+ + new(number) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/number_helper.rb, line 21
+def initialize(number)
+  @number = number
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/OutputSafetyHelper.html b/src/7.0/classes/ActionView/Helpers/OutputSafetyHelper.html new file mode 100644 index 0000000000..2f78547f56 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/OutputSafetyHelper.html @@ -0,0 +1,216 @@ +--- +title: ActionView::Helpers::OutputSafetyHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + raw(stringish) + +

+ + +
+

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 <alert>Tables</alert>'
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/output_safety_helper.rb, line 18
+def raw(stringish)
+  stringish.to_s.html_safe
+end
+
+
+ +
+ +
+

+ + safe_join(array, sep = $,) + +

+ + +
+

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("<p>foo</p>"), "<p>bar</p>"], "<br />")
+# => "<p>foo</p>&lt;br /&gt;&lt;p&gt;bar&lt;/p&gt;"
+
+safe_join([raw("<p>foo</p>"), raw("<p>bar</p>")], raw("<br />"))
+# => "<p>foo</p><br /><p>bar</p>"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/output_safety_helper.rb, line 33
+def safe_join(array, sep = $,)
+  sep = ERB::Util.unwrapped_html_escape(sep)
+
+  array.flatten.map! { |i| ERB::Util.unwrapped_html_escape(i) }.join(sep).html_safe
+end
+
+
+ +
+ +
+

+ + to_sentence(array, options = {}) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/output_safety_helper.rb, line 43
+def to_sentence(array, options = {})
+  options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
+
+  default_connectors = {
+    words_connector: ", ",
+    two_words_connector: " and ",
+    last_word_connector: ", and "
+  }
+  if defined?(I18n)
+    i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
+    default_connectors.merge!(i18n_connectors)
+  end
+  options = default_connectors.merge!(options)
+
+  case array.length
+  when 0
+    "".html_safe
+  when 1
+    ERB::Util.html_escape(array[0])
+  when 2
+    safe_join([array[0], array[1]], options[:two_words_connector])
+  else
+    safe_join([safe_join(array[0...-1], options[:words_connector]), options[:last_word_connector], array[-1]], nil)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/RenderingHelper.html b/src/7.0/classes/ActionView/Helpers/RenderingHelper.html new file mode 100644 index 0000000000..a78d622c2d --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/RenderingHelper.html @@ -0,0 +1,230 @@ +--- +title: ActionView::Helpers::RenderingHelper +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _layout_for(*args, &block) + +

+ + +
+

Overrides _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
+<html>
+  <%= yield %>
+</html>
+
+ +

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

+ +
<html>
+  Content
+</html>
+
+ +

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
+<html>
+  <%= yield Struct.new(:name).new("David") %>
+</html>
+
+ +

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

+ +
<html>
+  Hello David
+</html>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/rendering_helper.rb, line 97
+def _layout_for(*args, &block)
+  name = args.first
+
+  if block && !name.is_a?(Symbol)
+    capture(*args, &block)
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + render(options = {}, locals = {}, &block) + +

+ + +
+

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 if :update is specified, then:

+ +

If an object responding to render_in is passed, render_in is called on the object, passing in the current view context.

+ +

Otherwise, a partial is rendered using the second parameter as the locals hash.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/rendering_helper.rb, line 30
+def render(options = {}, locals = {}, &block)
+  case options
+  when Hash
+    in_rendering_context(options) do |renderer|
+      if block_given?
+        view_renderer.render_partial(self, options.merge(partial: options[:layout]), &block)
+      else
+        view_renderer.render(self, options)
+      end
+    end
+  else
+    if options.respond_to?(:render_in)
+      options.render_in(self, &block)
+    else
+      view_renderer.render_partial(self, partial: options, locals: locals, &block)
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/SanitizeHelper.html b/src/7.0/classes/ActionView/Helpers/SanitizeHelper.html new file mode 100644 index 0000000000..42188d8fd0 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/SanitizeHelper.html @@ -0,0 +1,316 @@ +--- +title: ActionView::Helpers::SanitizeHelper +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + sanitize(html, options = {}) + +

+ + +
+

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 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 or Loofah::Scrubber 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 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 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']
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/sanitize_helper.rb, line 81
+def sanitize(html, options = {})
+  self.class.safe_list_sanitizer.sanitize(html, options)&.html_safe
+end
+
+
+ +
+ +
+

+ + sanitize_css(style) + +

+ + +
+

Sanitizes a block of CSS code. Used by sanitize when it comes across a style attribute.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/sanitize_helper.rb, line 86
+def sanitize_css(style)
+  self.class.safe_list_sanitizer.sanitize_css(style)
+end
+
+
+ +
+ +
+ + + +
+

Strips all link tags from html leaving just the link text.

+ +
strip_links('<a href="http://www.rubyonrails.org">Ruby on Rails</a>')
+# => Ruby on Rails
+
+strip_links('Please e-mail me at <a href="mailto:me@email.com">me@email.com</a>.')
+# => Please e-mail me at me@email.com.
+
+strip_links('Blog: <a href="http://www.myblog.com/" class="nav" target=\"_blank\">Visit</a>.')
+# => Blog: Visit.
+
+strip_links('<<a href="https://example.org">malformed & link</a>')
+# => &lt;malformed &amp; link
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + strip_tags(html) + +

+ + +
+

Strips all HTML tags from html, including comments and special characters.

+ +
strip_tags("Strip <i>these</i> tags!")
+# => Strip these tags!
+
+strip_tags("<b>Bold</b> no more!  <a href='more.html'>See more here</a>...")
+# => Bold no more!  See more here...
+
+strip_tags("<div id='top-bar'>Welcome to my website!</div>")
+# => Welcome to my website!
+
+strip_tags("> A quote from Smith & Wesson")
+# => &gt; A quote from Smith &amp; Wesson
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/sanitize_helper.rb, line 103
+def strip_tags(html)
+  self.class.full_sanitizer.sanitize(html)&.html_safe
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/TagHelper.html b/src/7.0/classes/ActionView/Helpers/TagHelper.html new file mode 100644 index 0000000000..ec0ec0c207 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/TagHelper.html @@ -0,0 +1,645 @@ +--- +title: ActionView::Helpers::TagHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides methods to generate HTML tags programmatically both as a modern HTML5 compliant builder style and legacy XHTML compliant tags.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ARIA_PREFIXES=["aria", :aria].to_set.freeze
 
BOOLEAN_ATTRIBUTES=%w(allowfullscreen allowpaymentrequest async autofocus +autoplay checked compact controls declare default +defaultchecked defaultmuted defaultselected defer +disabled enabled formnovalidate hidden indeterminate +inert ismap itemscope loop multiple muted nohref +nomodule noresize noshade novalidate nowrap open +pauseonexit playsinline readonly required reversed +scoped seamless selected sortable truespeed +typemustmatch visible).to_set
 
DATA_PREFIXES=["data", :data].to_set.freeze
 
PRE_CONTENT_STRINGS=Hash.new { "" }
 
TAG_TYPES={}
 
+ + + + + + +

Class Public methods

+ +
+

+ + build_tag_values(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 425
+def build_tag_values(*args)
+  tag_values = []
+
+  args.each do |tag_value|
+    case tag_value
+    when Hash
+      tag_value.each do |key, val|
+        tag_values << key.to_s if val && key.present?
+      end
+    when Array
+      tag_values.concat build_tag_values(*tag_value)
+    else
+      tag_values << tag_value.to_s if tag_value.present?
+    end
+  end
+
+  tag_values
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cdata_section(content) + +

+ + +
+

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 <![CDATA[ and end with (and may not contain) the string ]]>.

+ +
cdata_section("<hello world>")
+# => <![CDATA[<hello world>]]>
+
+cdata_section(File.read("hello_world.txt"))
+# => <![CDATA[<hello from a text file]]>
+
+cdata_section("hello]]>world")
+# => <![CDATA[hello]]]]><![CDATA[>world]]>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 408
+def cdata_section(content)
+  splitted = content.to_s.gsub(/\]\]>/, "]]]]><![CDATA[>")
+  "<![CDATA[#{splitted}]]>".html_safe
+end
+
+
+ +
+ +
+

+ + class_names(*args) + +

+ + +
+ +
+ + + + + +
+ Alias for: token_list +
+ + + +
+ +
+

+ + content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block) + +

+ + +
+

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 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!")
+ # => <p>Hello world!</p>
+content_tag(:div, content_tag(:p, "Hello world!"), class: "strong")
+ # => <div class="strong"><p>Hello world!</p></div>
+content_tag(:div, "Hello world!", class: ["strong", "highlight"])
+ # => <div class="strong highlight">Hello world!</div>
+content_tag(:div, "Hello world!", class: ["strong", { highlight: current_user.admin? }])
+ # => <div class="strong highlight">Hello world!</div>
+content_tag("select", options, multiple: true)
+ # => <select multiple="multiple">...options...</select>
+
+<%= content_tag :div, class: "strong" do -%>
+  Hello world!
+<% end -%>
+ # => <div class="strong">Hello world!</div>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 368
+def content_tag(name, content_or_options_with_block = nil, options = nil, escape = true, &block)
+  if block_given?
+    options = content_or_options_with_block if content_or_options_with_block.is_a?(Hash)
+    tag_builder.content_tag_string(name, capture(&block), options, escape)
+  else
+    tag_builder.content_tag_string(name, content_or_options_with_block, options, escape)
+  end
+end
+
+
+ +
+ +
+

+ + escape_once(html) + +

+ + +
+

Returns an escaped version of html without affecting existing escaped entities.

+ +
escape_once("1 < 2 &amp; 3")
+# => "1 &lt; 2 &amp; 3"
+
+escape_once("&lt;&lt; Accept & Checkout")
+# => "&lt;&lt; Accept &amp; Checkout"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 420
+def escape_once(html)
+  ERB::Util.html_escape_once(html)
+end
+
+
+ +
+ +
+

+ + tag(name = nil, options = nil, open = false, escape = true) + +

+ + +
+

Returns an HTML tag.

+ +

Building HTML tags

+ +

Builds HTML5 compliant tags with a tag proxy. Every tag can be built with:

+ +
tag.<tag name>(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' # => <h1>All titles fit to print</h1>
+
+tag.div tag.p('Hello world!')  # => <div><p>Hello world!</p></div>
+
+ +

Content can also be captured with a block, which is useful in templates:

+ +
<%= tag.p do %>
+  The next great American novel starts here.
+<% end %>
+# => <p>The next great American novel starts here.</p>
+
+ +

Options

+ +

Use symbol keyed options to add attributes to the generated tag.

+ +
tag.section class: %w( kitties puppies )
+# => <section class="kitties puppies"></section>
+
+tag.section id: dom_id(@post)
+# => <section id="<generated dom id>"></section>
+
+ +

Pass true for any attributes that can render with no values, like disabled and readonly.

+ +
tag.input type: 'text', disabled: true
+# => <input type="text" disabled="disabled">
+
+ +

HTML5 data-* and aria-* attributes can be set with a single data or aria key pointing to a hash of sub-attributes.

+ +

To play nicely with JavaScript conventions, sub-attributes are dasherized.

+ +
tag.article data: { user_id: 123 }
+# => <article data-user-id="123"></article>
+
+ +

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 ) }
+# => <div data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]"></div>
+
+ +

The generated tag names and attributes are escaped by default. This can be disabled using escape.

+ +
tag.img src: 'open & shut.png'
+# => <img src="open &amp; shut.png">
+
+tag.img src: 'open & shut.png', escape: false
+# => <img src="open & shut.png">
+
+ +

The tag builder respects HTML5 void elements if no content is passed, and omits closing tags for those elements.

+ +
# A standard element:
+tag.div # => <div></div>
+
+# A void element:
+tag.br  # => <br>
+
+ +

Building HTML attributes

+ +

Transforms a Hash into HTML attributes, ready to be interpolated into ERB. Includes or omits boolean attributes based on their truthiness. Transforms keys nested within aria: or data: objects into aria- and data- prefixed attributes:

+ +
<input <%= tag.attributes(type: :text, aria: { label: "Search" }) %>>
+# => <input type="text" aria-label="Search">
+
+<button <%= tag.attributes id: "call-to-action", disabled: false, aria: { expanded: false } %> class="primary">Get Started!</button>
+# => <button id="call-to-action" aria-expanded="false" class="primary">Get Started!</button>
+
+ +

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")
+# => <br />
+
+tag("br", nil, true)
+# => <br>
+
+tag("input", type: 'text', disabled: true)
+# => <input type="text" disabled="disabled" />
+
+tag("input", type: 'text', class: ["strong", "highlight"])
+# => <input class="strong highlight" type="text" />
+
+tag("img", src: "open & shut.png")
+# => <img src="open &amp; shut.png" />
+
+tag("img", { src: "open &amp; shut.png" }, false, false)
+# => <img src="open &amp; shut.png" />
+
+tag("div", data: { name: 'Stephen', city_state: %w(Chicago IL) })
+# => <div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />
+
+tag("div", class: { highlight: current_user.admin? })
+# => <div class="highlight" />
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 331
+def tag(name = nil, options = nil, open = false, escape = true)
+  if name.nil?
+    tag_builder
+  else
+    name = ERB::Util.xml_name_escape(name) if escape
+    "<#{name}#{tag_builder.tag_options(options, escape) if options}#{open ? ">" : " />"}".html_safe
+  end
+end
+
+
+ +
+ +
+

+ + token_list(*args) + +

+ + +
+

Returns a string of tokens built from args.

+ +

Examples

+ +
token_list("foo", "bar")
+ # => "foo bar"
+token_list("foo", "foo bar")
+ # => "foo bar"
+token_list({ foo: true, bar: false })
+ # => "foo"
+token_list(nil, false, 123, "", "foo", { bar: true })
+ # => "123 foo bar"
+
+
+ + + +
+ Also aliased as: class_names +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/tag_helper.rb, line 388
+def token_list(*args)
+  tokens = build_tag_values(*args).flat_map { |value| value.to_s.split(/\s+/) }.uniq
+
+  safe_join(tokens, " ")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/Tags.html b/src/7.0/classes/ActionView/Helpers/Tags.html new file mode 100644 index 0000000000..ea7b5f2a67 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/Tags.html @@ -0,0 +1,147 @@ +--- +title: ActionView::Helpers::Tags +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/TextHelper.html b/src/7.0/classes/ActionView/Helpers/TextHelper.html new file mode 100644 index 0000000000..e74ef18a22 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/TextHelper.html @@ -0,0 +1,831 @@ +--- +title: ActionView::Helpers::TextHelper +layout: default +--- +
+ +
+
+ +
+ +

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('<a href="http://example.com/">Example</a>')
+# => "<p><a href=\"http://example.com/\">Example</a></p>"
+
+simple_format('<a href="javascript:alert(\'no!\')">Example</a>')
+# => "<p><a>Example</a></p>"
+
+ +

If you want to escape all content, you should invoke the h method before calling the text helper.

+ +
simple_format h('<a href="http://example.com/">Example</a>')
+# => "<p>&lt;a href=\"http://example.com/\"&gt;Example&lt;/a&gt;</p>"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + concat(string) + +

+ + +
+

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
+%>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 58
+def concat(string)
+  output_buffer << string
+end
+
+
+ +
+ +
+

+ + current_cycle(name = "default") + +

+ + +
+

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| %>
+  <div style="background-color:<%= cycle("red","white","blue") %>">
+    <span style="background-color:<%= current_cycle %>"><%= item %></span>
+  </div>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 382
+def current_cycle(name = "default")
+  cycle = get_cycle(name)
+  cycle.current_value if cycle
+end
+
+
+ +
+ +
+

+ + cycle(first_value, *values) + +

+ + +
+

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]
+ <table>
+ <% @items.each do |item| %>
+   <tr class="<%= cycle("odd", "even") -%>">
+     <td><%= item %></td>
+   </tr>
+ <% end %>
+ </table>
+
+ # 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| %>
+   <tr class="<%= cycle("odd", "even", name: "row_class") -%>">
+     <td>
+       <% item.values.each do |value| %>
+         <%# Create a named cycle "colors" %>
+         <span style="color:<%= cycle("red", "green", "blue", name: "colors") -%>">
+           <%= value %>
+         </span>
+       <% end %>
+       <% reset_cycle("colors") %>
+     </td>
+  </tr>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 358
+def cycle(first_value, *values)
+  options = values.extract_options!
+  name = options.fetch(:name, "default")
+
+  values.unshift(*first_value)
+
+  cycle = get_cycle(name)
+  unless cycle && cycle.values == values
+    cycle = set_cycle(name, Cycle.new(*values))
+  end
+  cycle.to_s
+end
+
+
+ +
+ +
+

+ + excerpt(text, phrase, options = {}) + +

+ + +
+

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: '<chop> ')
+# => <chop> is also an example
+
+excerpt('This is a very beautiful morning', 'very', separator: ' ', radius: 1)
+# => ...a very beautiful...
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 179
+def excerpt(text, phrase, options = {})
+  return unless text && phrase
+
+  separator = options.fetch(:separator, nil) || ""
+  case phrase
+  when Regexp
+    regex = phrase
+  else
+    regex = /#{Regexp.escape(phrase)}/i
+  end
+
+  return unless matches = text.match(regex)
+  phrase = matches[0]
+
+  unless separator.empty?
+    text.split(separator).each do |value|
+      if value.match?(regex)
+        phrase = value
+        break
+      end
+    end
+  end
+
+  first_part, second_part = text.split(phrase, 2)
+
+  prefix, first_part   = cut_excerpt_part(:first, first_part, separator, options)
+  postfix, second_part = cut_excerpt_part(:second, second_part, separator, options)
+
+  affix = [first_part, separator, phrase, separator, second_part].join.strip
+  [prefix, affix, postfix].join
+end
+
+
+ +
+ +
+

+ + highlight(text, phrases, options = {}, &block) + +

+ + +
+

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 <mark>\1</mark>) 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: <mark>rails</mark>
+
+highlight('You searched for: rails', /for|rails/)
+# => You searched <mark>for</mark>: <mark>rails</mark>
+
+highlight('You searched for: ruby, rails, dhh', 'actionpack')
+# => You searched for: ruby, rails, dhh
+
+highlight('You searched for: rails', ['for', 'rails'], highlighter: '<em>\1</em>')
+# => You searched <em>for</em>: <em>rails</em>
+
+highlight('You searched for: rails', 'rails', highlighter: '<a href="search?q=\1">\1</a>')
+# => You searched for: <a href="search?q=rails">rails</a>
+
+highlight('You searched for: rails', 'rails') { |match| link_to(search_path(q: match, match)) }
+# => You searched for: <a href="search?q=rails">rails</a>
+
+highlight('<a href="javascript:alert(\'no!\')">ruby</a> on rails', 'rails', sanitize: false)
+# => <a href="javascript:alert('no!')">ruby</a> on <mark>rails</mark>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 136
+def highlight(text, phrases, options = {}, &block)
+  text = sanitize(text) if options.fetch(:sanitize, true)
+
+  if text.blank? || phrases.blank?
+    text || ""
+  else
+    match = Array(phrases).map do |p|
+      Regexp === p ? p.to_s : Regexp.escape(p)
+    end.join("|")
+
+    if block_given?
+      text.gsub(/(#{match})(?![^<]*?>)/i, &block)
+    else
+      highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
+      text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
+    end
+  end.html_safe
+end
+
+
+ +
+ +
+

+ + pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale) + +

+ + +
+

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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 234
+def pluralize(count, singular, plural_arg = nil, plural: plural_arg, locale: I18n.locale)
+  word = if count == 1 || count.to_s.match?(/^1(\.0+)?$/)
+    singular
+  else
+    plural || singular.pluralize(locale)
+  end
+
+  "#{count || 0} #{word}"
+end
+
+
+ +
+ +
+

+ + reset_cycle(name = "default") + +

+ + +
+

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]]
+<table>
+<% @items.each do |item| %>
+  <tr class="<%= cycle("even", "odd") -%>">
+      <% item.each do |value| %>
+        <span style="color:<%= cycle("#333", "#666", "#999", name: "colors") -%>">
+          <%= value %>
+        </span>
+      <% end %>
+
+      <% reset_cycle("colors") %>
+  </tr>
+<% end %>
+</table>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 405
+def reset_cycle(name = "default")
+  cycle = get_cycle(name)
+  cycle.reset if cycle
+end
+
+
+ +
+ +
+

+ + safe_concat(string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 62
+def safe_concat(string)
+  output_buffer.respond_to?(:safe_concat) ? output_buffer.safe_concat(string) : concat(string)
+end
+
+
+ +
+ +
+

+ + simple_format(text, html_options = {}, options = {}) + +

+ + +
+

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 <p> tags. One newline (\n or \r\n) is considered a linebreak and a <br /> 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)
+# => "<p>Here is some basic text...\n<br />...with a line break.</p>"
+
+simple_format(my_text, {}, wrapper_tag: "div")
+# => "<div>Here is some basic text...\n<br />...with a line break.</div>"
+
+more_text = "We want to put a paragraph...\n\n...right there."
+
+simple_format(more_text)
+# => "<p>We want to put a paragraph...</p>\n\n<p>...right there.</p>"
+
+simple_format("Look ma! A class!", class: 'description')
+# => "<p class='description'>Look ma! A class!</p>"
+
+simple_format("<blink>Unblinkable.</blink>")
+# => "<p>Unblinkable.</p>"
+
+simple_format("<blink>Blinkable!</blink> It's true.", {}, sanitize: false)
+# => "<p><blink>Blinkable!</blink> It's true.</p>"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 306
+def simple_format(text, html_options = {}, options = {})
+  wrapper_tag = options.fetch(:wrapper_tag, :p)
+
+  text = sanitize(text) if options.fetch(:sanitize, true)
+  paragraphs = split_paragraphs(text)
+
+  if paragraphs.empty?
+    content_tag(wrapper_tag, nil, html_options)
+  else
+    paragraphs.map! { |paragraph|
+      content_tag(wrapper_tag, raw(paragraph), html_options)
+    }.join("\n\n").html_safe
+  end
+end
+
+
+ +
+ +
+

+ + truncate(text, options = {}, &block) + +

+ + +
+

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("<p>Once upon a time in a world far far away</p>")
+# => "&lt;p&gt;Once upon a time in a wo..."
+
+truncate("<p>Once upon a time in a world far far away</p>", escape: false)
+# => "<p>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...<a href="#">Continue</a>"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 98
+def truncate(text, options = {}, &block)
+  if text
+    length  = options.fetch(:length, 30)
+
+    content = text.truncate(length, options)
+    content = options[:escape] == false ? content.html_safe : ERB::Util.html_escape(content)
+    content << capture(&block) if block_given? && text.length > length
+    content
+  end
+end
+
+
+ +
+ +
+

+ + word_wrap(text, line_width: 80, break_sequence: "\n") + +

+ + +
+

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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/text_helper.rb, line 264
+def word_wrap(text, line_width: 80, break_sequence: "\n")
+  text.split("\n").collect! do |line|
+    line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1#{break_sequence}").rstrip : line
+  end * break_sequence
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/TranslationHelper.html b/src/7.0/classes/ActionView/Helpers/TranslationHelper.html new file mode 100644 index 0000000000..720065b84c --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/TranslationHelper.html @@ -0,0 +1,301 @@ +--- +title: ActionView::Helpers::TranslationHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + raise_on_missing_translations
+ + + + + +

Instance Public methods

+ +
+

+ + l(object, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: localize +
+ + + +
+ +
+

+ + localize(object, **options) + +

+ + +
+

Delegates to I18n.localize with no additional functionality.

+ +

See www.rubydoc.info/gems/i18n/I18n/Backend/Base:localize for more information.

+
+ + + +
+ Also aliased as: l +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/translation_helper.rb, line 116
+def localize(object, **options)
+  I18n.localize(object, **options)
+end
+
+
+ +
+ +
+

+ + t(key, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: translate +
+ + + +
+ +
+

+ + translate(key, **options) + +

+ + +
+

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:

+ +
<span
+  class="translation_missing"
+  title="translation missing: en.blog.post.title">Title</span>
+
+ +

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 config.i18n.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.

+ +

To access the translated text along with the fully resolved translation key, translate accepts a block:

+ +
<%= translate(".relative_key") do |translation, resolved_key| %>
+  <span title="<%= resolved_key %>"><%= translation %></span>
+<% end %>
+
+ +

This enables annotate translated text to be aware of the scope it was resolved against.

+
+ + + +
+ Also aliased as: t +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/translation_helper.rb, line 73
+def translate(key, **options)
+  return key.map { |k| translate(k, **options) } if key.is_a?(Array)
+  key = key&.to_s unless key.is_a?(Symbol)
+
+  alternatives = if options.key?(:default)
+    options[:default].is_a?(Array) ? options.delete(:default).compact : [options.delete(:default)]
+  end
+
+  options[:raise] = true if options[:raise].nil? && TranslationHelper.raise_on_missing_translations
+  default = MISSING_TRANSLATION
+
+  translation = while key || alternatives.present?
+    if alternatives.blank? && !options[:raise].nil?
+      default = NO_DEFAULT # let I18n handle missing translation
+    end
+
+    key = scope_key_by_partial(key)
+
+    translated = ActiveSupport::HtmlSafeTranslation.translate(key, **options, default: default)
+
+    break translated unless translated == MISSING_TRANSLATION
+
+    if alternatives.present? && !alternatives.first.is_a?(Symbol)
+      break alternatives.first && I18n.translate(**options, default: alternatives)
+    end
+
+    first_key ||= key
+    key = alternatives&.shift
+  end
+
+  if key.nil? && !first_key.nil?
+    translation = missing_translation(first_key, options)
+    key = first_key
+  end
+
+  block_given? ? yield(translation, key) : translation
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/UrlHelper.html b/src/7.0/classes/ActionView/Helpers/UrlHelper.html new file mode 100644 index 0000000000..21ab61bd30 --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/UrlHelper.html @@ -0,0 +1,1107 @@ +--- +title: ActionView::Helpers::UrlHelper +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
BUTTON_TAG_METHOD_VERBS=%w{patch put delete}
 

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.

STRINGIFIED_COMMON_METHODS={ +get: "get", +delete: "delete", +patch: "patch", +post: "post", +put: "put", +}.freeze
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + _current_page?(options = nil, check_parameters: false, **options_as_kwargs) + +

+ + +
+ +
+ + + + + +
+ Alias for: current_page? +
+ + + +
+ +
+

+ + button_to(name = nil, options = nil, html_options = nil, &block) + +

+ + +
+

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.

+ +

You can control the form and button behavior with html_options. Most values in html_options are passed through to the button element. For example, passing a :class option within html_options will set the class attribute of the button element.

+ +

The class attribute of the form element can be set by passing a :form_class option within html_options. It defaults to "button_to" to allow styling of the form and its children.

+ +

The form submits a POST request by default. You can specify a different HTTP verb via the :method option within html_options.

+ +

Options

+ +

The options hash accepts the same options as url_for. To generate a <form> element without an [action] attribute, pass false:

+ +
<%= button_to "New", false %>
+# => "<form method="post" class="button_to">
+#      <button type="submit">New</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
+#    </form>"
+
+ +

Most values in html_options are passed through to the button element, but there are a few special 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.

    +
  • +

    :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.

    +
+ +

Examples

+ +
<%= button_to "New", action: "new" %>
+# => "<form method="post" action="/controller/new" class="button_to">
+#      <button type="submit">New</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
+#    </form>"
+
+<%= button_to "New", new_article_path %>
+# => "<form method="post" action="/articles/new" class="button_to">
+#      <button type="submit">New</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6" autocomplete="off"/>
+#    </form>"
+
+<%= button_to "New", new_article_path, params: { time: Time.now  } %>
+# => "<form method="post" action="/articles/new" class="button_to">
+#      <button type="submit">New</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"/>
+#      <input type="hidden" name="time" value="2021-04-08 14:06:09 -0500" autocomplete="off">
+#    </form>"
+
+<%= button_to [:make_happy, @user] do %>
+  Make happy <strong><%= @user.name %></strong>
+<% end %>
+# => "<form method="post" action="/users/1/make_happy" class="button_to">
+#      <button type="submit">
+#        Make happy <strong><%= @user.name %></strong>
+#      </button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"  autocomplete="off"/>
+#    </form>"
+
+<%= button_to "New", { action: "new" }, form_class: "new-thing" %>
+# => "<form method="post" action="/controller/new" class="new-thing">
+#      <button type="submit">New</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"  autocomplete="off"/>
+#    </form>"
+
+<%= button_to "Create", { action: "create" }, form: { "data-type" => "json" } %>
+# => "<form method="post" action="/images/create" class="button_to" data-type="json">
+#      <button type="submit">Create</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"  autocomplete="off"/>
+#    </form>"
+
+ +

Deprecated: Rails UJS Attributes

+ +

Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7, this library is no longer on by default. This library integrated with the following options:

+
  • +

    :remote - If set to true, will allow @rails/ujs to control the submit behavior. By default this behavior is an Ajax submit.

    +
+ +

@rails/ujs also integrated with the following :data options:

+
  • +

    confirm: "question?" - This will allow @rails/ujs to prompt with the question specified (in this case, the resulting text would be question?). If the user accepts, the button 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.

    +
+ +
Rails UJS Examples
+ +
<%= button_to "Create", { action: "create" }, remote: true, form: { "data-type" => "json" } %>
+# => "<form method="post" action="/images/create" class="button_to" data-remote="true" data-type="json">
+#      <button type="submit">Create</button>
+#      <input name="authenticity_token" type="hidden" value="10f2163b45388899ad4d5ae948988266befcb6c3d1b2451cf657a0c293d605a6"  autocomplete="off"/>
+#    </form>"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 331
+def button_to(name = nil, options = nil, html_options = nil, &block)
+  html_options, options = options, name if block_given?
+  html_options ||= {}
+  html_options = html_options.stringify_keys
+
+  url =
+    case options
+    when FalseClass then nil
+    else url_for(options)
+    end
+
+  remote = html_options.delete("remote")
+  params = html_options.delete("params")
+
+  authenticity_token = html_options.delete("authenticity_token")
+
+  method     = (html_options.delete("method").presence || method_for_options(options)).to_s
+  method_tag = BUTTON_TAG_METHOD_VERBS.include?(method) ? method_tag(method) : "".html_safe
+
+  form_method  = method == "get" ? "get" : "post"
+  form_options = html_options.delete("form") || {}
+  form_options[:class] ||= html_options.delete("form_class") || "button_to"
+  form_options[:method] = form_method
+  form_options[:action] = url
+  form_options[:'data-remote'] = true if remote
+
+  request_token_tag = if form_method == "post"
+    request_method = method.empty? ? "post" : method
+    token_tag(authenticity_token, form_options: { action: url, method: request_method })
+  else
+    ""
+  end
+
+  html_options = convert_options_to_data_attributes(options, html_options)
+  html_options["type"] = "submit"
+
+  button = if block_given?
+    content_tag("button", html_options, &block)
+  elsif button_to_generates_button_tag
+    content_tag("button", name || url, html_options, &block)
+  else
+    html_options["value"] = name || url
+    tag("input", html_options)
+  end
+
+  inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
+  if params
+    to_form_params(params).each do |param|
+      inner_tags.safe_concat tag(:input, type: "hidden", name: param[:name], value: param[:value],
+                                 autocomplete: "off")
+    end
+  end
+  content_tag("form", inner_tags, form_options)
+end
+
+
+ +
+ +
+

+ + current_page?(options = nil, check_parameters: false, **options_as_kwargs) + +

+ + +
+

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.

+
+ + + +
+ Also aliased as: _current_page? +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 582
+def current_page?(options = nil, check_parameters: false, **options_as_kwargs)
+  unless request
+    raise "You cannot use helpers that need to determine the current " \
+          "page unless your view context provides a Request object " \
+          "in a #request method"
+  end
+
+  return false unless request.get? || request.head?
+
+  options ||= options_as_kwargs
+  check_parameters ||= options.is_a?(Hash) && options.delete(:check_parameters)
+  url_string = URI::DEFAULT_PARSER.unescape(url_for(options)).force_encoding(Encoding::BINARY)
+
+  # We ignore any extra parameters in the request_uri if the
+  # submitted URL doesn't have any either. This lets the function
+  # work with things like ?order=asc
+  # the behaviour can be disabled with check_parameters: true
+  request_uri = url_string.index("?") || check_parameters ? request.fullpath : request.path
+  request_uri = URI::DEFAULT_PARSER.unescape(request_uri).force_encoding(Encoding::BINARY)
+
+  if %r{^\w+://}.match?(url_string)
+    request_uri = +"#{request.protocol}#{request.host_with_port}#{request_uri}"
+  end
+
+  remove_trailing_slash!(url_string)
+  remove_trailing_slash!(request_uri)
+
+  url_string == request_uri
+end
+
+
+ +
+ +
+ + + +
+

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.

+ + + +
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
+
+link_to(active_record_model)
+
+ + +
  • +

    :data - This option can be used to add custom data attributes.

    +
+ + + +

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)
+# => <a href="/profiles/1">Profile</a>
+
+ +

or the even pithier

+ +
link_to "Profile", @profile
+# => <a href="/profiles/1">Profile</a>
+
+ +

in place of the older more verbose, non-resource-oriented

+ +
link_to "Profile", controller: "profiles", action: "show", id: @profile
+# => <a href="/profiles/show/1">Profile</a>
+
+ +

Similarly,

+ +
link_to "Profiles", profiles_path
+# => <a href="/profiles">Profiles</a>
+
+ +

is better than

+ +
link_to "Profiles", controller: "profiles"
+# => <a href="/profiles">Profiles</a>
+
+ +

When name is nil the href is presented instead

+ +
link_to nil, "http://example.com"
+# => <a href="http://www.example.com">http://www.example.com</a>
+
+ +

More concise yet, when name is an Active Record model that defines a to_s method returning a default value or a model instance attribute

+ +
link_to @profile
+# => <a href="http://www.example.com/profiles/1">Eileen</a>
+
+ +

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 %>
+  <strong><%= @profile.name %></strong> -- <span>Check it out!</span>
+<% end %>
+# => <a href="/profiles/1">
+       <strong>David</strong> -- <span>Check it out!</span>
+     </a>
+
+ +

Classes and ids for CSS are easy to produce:

+ +
link_to "Articles", articles_path, id: "news", class: "article"
+# => <a href="/articles" class="article" id="news">Articles</a>
+
+ +

Be careful when using the older argument style, as an extra literal hash is needed:

+ +
link_to "Articles", { controller: "articles" }, id: "news", class: "article"
+# => <a href="/articles" class="article" id="news">Articles</a>
+
+ +

Leaving the hash off gives the wrong link:

+ +
link_to "WRONG!", controller: "articles", id: "news", class: "article"
+# => <a href="/articles/index/news?class=article">WRONG!</a>
+
+ +

link_to can also produce links with anchors or query strings:

+ +
link_to "Comment wall", profile_path(@profile, anchor: "wall")
+# => <a href="/profiles/1#wall">Comment wall</a>
+
+link_to "Ruby on Rails search", controller: "searches", query: "ruby on rails"
+# => <a href="/searches?query=ruby+on+rails">Ruby on Rails search</a>
+
+link_to "Nonsense search", searches_path(foo: "bar", baz: "quux")
+# => <a href="/searches?foo=bar&baz=quux">Nonsense search</a>
+
+ +

You can set any link attributes such as target, rel, type:

+ +
link_to "External link", "http://www.rubyonrails.org/", target: "_blank", rel: "nofollow"
+# => <a href="http://www.rubyonrails.org/" target="_blank" rel="nofollow">External link</a>
+
+ + + +

Prior to Rails 7, Rails shipped with a JavaScript library called @rails/ujs on by default. Following Rails 7, this library is no longer on by default. This library integrated with the following options:

+
  • +

    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 @rails/ujs to make an Ajax request to the URL in question instead of following the link.

    +
+ +

@rails/ujs also integrated with the following :data options:

+
  • +

    confirm: "question?" - This will allow @rails/ujs 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.

    +
+ + + +
link_to "Remove Profile", profile_path(@profile), method: :delete
+# => <a href="/profiles/1" rel="nofollow" data-method="delete">Remove Profile</a>
+
+link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
+# => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+ + + +
+

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_if.

+ + + +
<%= link_to_if(@current_user.nil?, "Login", { controller: "sessions", action: "new" }) %>
+# If the user isn't logged in...
+# => <a href="/sessions/new/">Login</a>
+
+<%=
+   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...
+# => <a href="/sessions/new/">Login</a>
+# If they are logged in...
+# => <a href="/accounts/show/3">my_username</a>
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+ + + +
+

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.

+ + + +
<%= link_to_unless(@current_user.nil?, "Reply", { action: "reply" }) %>
+# If the user is logged in...
+# => <a href="/controller/reply/">Reply</a>
+
+<%=
+   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...
+# => <a href="/controller/reply/">Reply</a>
+# If not...
+# => <a href="/accounts/signup">Reply</a>
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+ + + +
+

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).

+ + + +

Let’s say you have a navigation menu…

+ +
<ul id="navbar">
+  <li><%= link_to_unless_current("Home", { action: "index" }) %></li>
+  <li><%= link_to_unless_current("About Us", { action: "about" }) %></li>
+</ul>
+
+ +

If in the “about” action, it will render…

+ +
<ul id="navbar">
+  <li><a href="/controller/index">Home</a></li>
+  <li>About Us</li>
+</ul>
+
+ +

…but if in the “index” action, it will render:

+ +
<ul id="navbar">
+  <li>Home</li>
+  <li><a href="/controller/about">About Us</a></li>
+</ul>
+
+ +

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
+ %>
+
+
+ + + + + + + + +
+ + + +
+ +
+ +
+

+ + mail_to(email_address, name = nil, html_options = {}, &block) + +

+ + +
+

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"
+# => <a href="mailto:me@domain.com">me@domain.com</a>
+
+mail_to "me@domain.com", "My email"
+# => <a href="mailto:me@domain.com">My email</a>
+
+mail_to "me@domain.com", cc: "ccaddress@domain.com",
+         subject: "This is an example email"
+# => <a href="mailto:me@domain.com?cc=ccaddress@domain.com&subject=This%20is%20an%20example%20email">me@domain.com</a>
+
+ +

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 %>
+  <strong>Email me:</strong> <span>me@domain.com</span>
+<% end %>
+# => <a href="mailto:me@domain.com">
+       <strong>Email me:</strong> <span>me@domain.com</span>
+     </a>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 521
+def mail_to(email_address, name = nil, html_options = {}, &block)
+  html_options, name = name, nil if name.is_a?(Hash)
+  html_options = (html_options || {}).stringify_keys
+
+  extras = %w{ cc bcc body subject reply_to }.map! { |item|
+    option = html_options.delete(item).presence || next
+    "#{item.dasherize}=#{ERB::Util.url_encode(option)}"
+  }.compact
+  extras = extras.empty? ? "" : "?" + extras.join("&")
+
+  encoded_email_address = ERB::Util.url_encode(email_address).gsub("%40", "@")
+  html_options["href"] = "mailto:#{encoded_email_address}#{extras}"
+
+  content_tag("a", name || email_address, html_options, &block)
+end
+
+
+ +
+ +
+

+ + phone_to(phone_number, name = nil, html_options = {}, &block) + +

+ + +
+

Creates a TEL anchor link tag to the specified phone_number. When the link is clicked, the default app to make phone calls is opened and prepopulated with the phone number.

+ +

If name is not specified, phone_number will be used as the name of the link.

+ +

A country_code option is supported, which prepends a plus sign and the given country code to the linked phone number. For example, country_code: "01" will prepend +01 to the linked phone number.

+ +

Additional HTML attributes for the link can be passed via html_options.

+ +

Options

+
  • +

    :country_code - Prepends the country code to the phone number

    +
+ +

Examples

+ +
phone_to "1234567890"
+# => <a href="tel:1234567890">1234567890</a>
+
+phone_to "1234567890", "Phone me"
+# => <a href="tel:1234567890">Phone me</a>
+
+phone_to "1234567890", country_code: "01"
+# => <a href="tel:+011234567890">1234567890</a>
+
+ +

You can use a block as well if your link target is hard to fit into the name parameter. ERB example:

+ +
<%= phone_to "1234567890" do %>
+  <strong>Phone me:</strong>
+<% end %>
+# => <a href="tel:1234567890">
+       <strong>Phone me:</strong>
+     </a>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 716
+def phone_to(phone_number, name = nil, html_options = {}, &block)
+  html_options, name = name, nil if name.is_a?(Hash)
+  html_options = (html_options || {}).stringify_keys
+
+  country_code = html_options.delete("country_code").presence
+  country_code = country_code.nil? ? "" : "+#{ERB::Util.url_encode(country_code)}"
+
+  encoded_phone_number = ERB::Util.url_encode(phone_number)
+  html_options["href"] = "tel:#{country_code}#{encoded_phone_number}"
+
+  content_tag("a", name || phone_number, html_options, &block)
+end
+
+
+ +
+ +
+

+ + sms_to(phone_number, name = nil, html_options = {}, &block) + +

+ + +
+

Creates an SMS anchor link tag to the specified phone_number. When the link is clicked, the default SMS messaging app is opened ready to send a message to the linked phone number. If the body option is specified, the contents of the message will be preset to body.

+ +

If name is not specified, phone_number will be used as the name of the link.

+ +

A country_code option is supported, which prepends a plus sign and the given country code to the linked phone number. For example, country_code: "01" will prepend +01 to the linked phone number.

+ +

Additional HTML attributes for the link can be passed via html_options.

+ +

Options

+
  • +

    :country_code - Prepend the country code to the phone number.

    +
  • +

    :body - Preset the body of the message.

    +
+ +

Examples

+ +
sms_to "5155555785"
+# => <a href="sms:5155555785;">5155555785</a>
+
+sms_to "5155555785", country_code: "01"
+# => <a href="sms:+015155555785;">5155555785</a>
+
+sms_to "5155555785", "Text me"
+# => <a href="sms:5155555785;">Text me</a>
+
+sms_to "5155555785", body: "I have a question about your product."
+# => <a href="sms:5155555785;?body=I%20have%20a%20question%20about%20your%20product">5155555785</a>
+
+ +

You can use a block as well if your link target is hard to fit into the name parameter. ERB example:

+ +
<%= sms_to "5155555785" do %>
+  <strong>Text me:</strong>
+<% end %>
+# => <a href="sms:5155555785;">
+       <strong>Text me:</strong>
+     </a>
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 665
+def sms_to(phone_number, name = nil, html_options = {}, &block)
+  html_options, name = name, nil if name.is_a?(Hash)
+  html_options = (html_options || {}).stringify_keys
+
+  country_code = html_options.delete("country_code").presence
+  country_code = country_code ? "+#{ERB::Util.url_encode(country_code)}" : ""
+
+  body = html_options.delete("body").presence
+  body = body ? "?&body=#{ERB::Util.url_encode(body)}" : ""
+
+  encoded_phone_number = ERB::Util.url_encode(phone_number)
+  html_options["href"] = "sms:#{country_code}#{encoded_phone_number};#{body}"
+
+  content_tag("a", name || phone_number, html_options, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Helpers/UrlHelper/ClassMethods.html b/src/7.0/classes/ActionView/Helpers/UrlHelper/ClassMethods.html new file mode 100644 index 0000000000..2427191a5a --- /dev/null +++ b/src/7.0/classes/ActionView/Helpers/UrlHelper/ClassMethods.html @@ -0,0 +1,101 @@ +--- +title: ActionView::Helpers::UrlHelper::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _url_for_modules() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/helpers/url_helper.rb, line 27
+def _url_for_modules
+  ActionView::RoutingUrlFor
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Layouts.html b/src/7.0/classes/ActionView/Layouts.html new file mode 100644 index 0000000000..c66508464a --- /dev/null +++ b/src/7.0/classes/ActionView/Layouts.html @@ -0,0 +1,331 @@ +--- +title: ActionView::Layouts +layout: default +--- +
+ +
+
+ +
+ +

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:

+ +
<h1><%= @page_title %></h1>
+<%= 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:

+ +
<h1>Welcome</h1>
+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.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + action_has_layout?() + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/layouts.rb, line 372
+def action_has_layout?
+  @_action_has_layout
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Layouts/ClassMethods.html b/src/7.0/classes/ActionView/Layouts/ClassMethods.html new file mode 100644 index 0000000000..23b02c4dc6 --- /dev/null +++ b/src/7.0/classes/ActionView/Layouts/ClassMethods.html @@ -0,0 +1,142 @@ +--- +title: ActionView::Layouts::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + layout(layout, conditions = {}) + +

+ + +
+

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.

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/layouts.rb, line 269
+def layout(layout, conditions = {})
+  include LayoutConditions unless conditions.empty?
+
+  conditions.each { |k, v| conditions[k] = Array(v).map(&:to_s) }
+  self._layout_conditions = conditions
+
+  self._layout = layout
+  _write_layout_method
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/LogSubscriber.html b/src/7.0/classes/ActionView/LogSubscriber.html new file mode 100644 index 0000000000..894ae05ca8 --- /dev/null +++ b/src/7.0/classes/ActionView/LogSubscriber.html @@ -0,0 +1,575 @@ +--- +title: ActionView::LogSubscriber +layout: default +--- +
+ +
+
+ +
+ +

Action View Log Subscriber

+ +

Provides functionality so that Rails can output logs from Action View.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
EMPTY=""
 
VIEWS_PATTERN=/^app\/views\//
 
+ + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 12
+def initialize
+  @root = nil
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 59
+def logger
+  ActionView::Base.logger
+end
+
+
+ +
+ +
+

+ + render_collection(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 42
+def render_collection(event)
+  identifier = event.payload[:identifier] || "templates"
+
+  debug do
+    message = +"  Rendered collection of #{from_rails_root(identifier)}"
+    message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
+    message << " #{render_count(event.payload)} (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
+    message
+  end
+end
+
+
+ +
+ +
+

+ + render_layout(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 35
+def render_layout(event)
+  info do
+    message = +"  Rendered layout #{from_rails_root(event.payload[:identifier])}"
+    message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
+  end
+end
+
+
+ +
+ +
+

+ + render_partial(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 25
+def render_partial(event)
+  debug do
+    message = +"  Rendered #{from_rails_root(event.payload[:identifier])}"
+    message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
+    message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
+    message << " #{cache_message(event.payload)}" unless event.payload[:cache_hit].nil?
+    message
+  end
+end
+
+
+ +
+ +
+

+ + render_template(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 17
+def render_template(event)
+  info do
+    message = +"  Rendered #{from_rails_root(event.payload[:identifier])}"
+    message << " within #{from_rails_root(event.payload[:layout])}" if event.payload[:layout]
+    message << " (Duration: #{event.duration.round(1)}ms | Allocations: #{event.allocations})"
+  end
+end
+
+
+ +
+ +
+

+ + start(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 53
+def start(name, id, payload)
+  log_rendering_start(payload, name)
+
+  super
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + cache_message(payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 83
+def cache_message(payload) # :doc:
+  case payload[:cache_hit]
+  when :hit
+    "[cache hit]"
+  when :miss
+    "[cache miss]"
+  end
+end
+
+
+ +
+ +
+

+ + from_rails_root(string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 65
+def from_rails_root(string) # :doc:
+  string = string.sub(rails_root, EMPTY)
+  string.sub!(VIEWS_PATTERN, EMPTY)
+  string
+end
+
+
+ +
+ +
+

+ + rails_root() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 71
+def rails_root # :doc:
+  @root ||= "#{Rails.root}/"
+end
+
+
+ +
+ +
+

+ + render_count(payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/log_subscriber.rb, line 75
+def render_count(payload) # :doc:
+  if payload[:cache_hits]
+    "[#{payload[:cache_hits]} / #{payload[:count]} cache hits]"
+  else
+    "[#{payload[:count]} times]"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/LookupContext.html b/src/7.0/classes/ActionView/LookupContext.html new file mode 100644 index 0000000000..9028f1b747 --- /dev/null +++ b/src/7.0/classes/ActionView/LookupContext.html @@ -0,0 +1,77 @@ +--- +title: ActionView::LookupContext +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/LookupContext/DetailsCache.html b/src/7.0/classes/ActionView/LookupContext/DetailsCache.html new file mode 100644 index 0000000000..9732bc03bd --- /dev/null +++ b/src/7.0/classes/ActionView/LookupContext/DetailsCache.html @@ -0,0 +1,169 @@ +--- +title: ActionView::LookupContext::DetailsCache +layout: default +--- +
+ +
+
+ +
+ +

Add caching behavior on top of Details.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + cache
+ + + + + +

Instance Public methods

+ +
+

+ + disable_cache() + +

+ + +
+

Temporary skip passing the details_key forward.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 104
+def disable_cache
+  old_value, @cache = @cache, false
+  yield
+ensure
+  @cache = old_value
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + _set_detail(key, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 112
+def _set_detail(key, value) # :doc:
+  @details = @details.dup if @digest_cache || @details_key
+  @digest_cache = nil
+  @details_key = nil
+  @details[key] = value
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/LookupContext/ViewPaths.html b/src/7.0/classes/ActionView/LookupContext/ViewPaths.html new file mode 100644 index 0000000000..ee86e563d6 --- /dev/null +++ b/src/7.0/classes/ActionView/LookupContext/ViewPaths.html @@ -0,0 +1,401 @@ +--- +title: ActionView::LookupContext::ViewPaths +layout: default +--- +
+ +
+
+ +
+ +

Helpers related to template lookup using the lookup context information.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + html_fallback_for_js
+ [R] + view_paths
+ + + + + +

Instance Public methods

+ +
+

+ + any?(name, prefixes = [], partial = false) + +

+ + +
+ +
+ + + +
+ Also aliased as: any_templates? +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 144
+def any?(name, prefixes = [], partial = false)
+  name, prefixes = normalize_name(name, prefixes)
+  details, details_key = detail_args_for_any
+  @view_paths.exists?(name, prefixes, partial, details, details_key, [])
+end
+
+
+ +
+ +
+

+ + any_templates?(name, prefixes = [], partial = false) + +

+ + +
+ +
+ + + + + +
+ Alias for: any? +
+ + + +
+ +
+

+ + exists?(name, prefixes = [], partial = false, keys = [], **options) + +

+ + +
+ +
+ + + +
+ Also aliased as: template_exists? +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 137
+def exists?(name, prefixes = [], partial = false, keys = [], **options)
+  name, prefixes = normalize_name(name, prefixes)
+  details, details_key = detail_args_for(options)
+  @view_paths.exists?(name, prefixes, partial, details, details_key, keys)
+end
+
+
+ +
+ +
+

+ + find(name, prefixes = [], partial = false, keys = [], options = {}) + +

+ + +
+ +
+ + + +
+ Also aliased as: find_template +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 124
+def find(name, prefixes = [], partial = false, keys = [], options = {})
+  name, prefixes = normalize_name(name, prefixes)
+  details, details_key = detail_args_for(options)
+  @view_paths.find(name, prefixes, partial, details, details_key, keys)
+end
+
+
+ +
+ +
+

+ + find_all(name, prefixes = [], partial = false, keys = [], options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 131
+def find_all(name, prefixes = [], partial = false, keys = [], options = {})
+  name, prefixes = normalize_name(name, prefixes)
+  details, details_key = detail_args_for(options)
+  @view_paths.find_all(name, prefixes, partial, details, details_key, keys)
+end
+
+
+ +
+ +
+

+ + find_template(name, prefixes = [], partial = false, keys = [], options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: find +
+ + + +
+ +
+

+ + template_exists?(name, prefixes = [], partial = false, keys = [], **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: exists? +
+ + + +
+ + +

Instance Private methods

+ +
+

+ + detail_args_for(options) + +

+ + +
+

Compute details hash and key according to user options (e.g. passed from render).

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/lookup_context.rb, line 159
+def detail_args_for(options) # :doc:
+  return @details, details_key if options.empty? # most common path.
+  user_details = @details.merge(options)
+
+  if @cache
+    details_key = DetailsKey.details_cache_key(user_details)
+  else
+    details_key = nil
+  end
+
+  [user_details, details_key]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/NullResolver.html b/src/7.0/classes/ActionView/NullResolver.html new file mode 100644 index 0000000000..479aced1bc --- /dev/null +++ b/src/7.0/classes/ActionView/NullResolver.html @@ -0,0 +1,109 @@ +--- +title: ActionView::NullResolver +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + find_templates(name, prefix, partial, details, locals = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/testing/resolvers.rb, line 38
+def find_templates(name, prefix, partial, details, locals = [])
+  path = TemplatePath.build(name, prefix, partial)
+  handler = ActionView::Template::Handlers::Raw
+  [ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: nil, variant: nil, locals: locals)]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/PartialIteration.html b/src/7.0/classes/ActionView/PartialIteration.html new file mode 100644 index 0000000000..14c336c3d6 --- /dev/null +++ b/src/7.0/classes/ActionView/PartialIteration.html @@ -0,0 +1,211 @@ +--- +title: ActionView::PartialIteration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + index

The current iteration of the partial.

+ [R] + size

The number of iterations that will be done by the partial.

+ + + + +

Class Public methods

+ +
+

+ + new(size) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/collection_renderer.rb, line 13
+def initialize(size)
+  @size  = size
+  @index = 0
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + first?() + +

+ + +
+

Check if this is the first iteration of the partial.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/collection_renderer.rb, line 19
+def first?
+  index == 0
+end
+
+
+ +
+ +
+

+ + last?() + +

+ + +
+

Check if this is the last iteration of the partial.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/collection_renderer.rb, line 24
+def last?
+  index == size - 1
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/PartialRenderer.html b/src/7.0/classes/ActionView/PartialRenderer.html new file mode 100644 index 0000000000..2d79e3424f --- /dev/null +++ b/src/7.0/classes/ActionView/PartialRenderer.html @@ -0,0 +1,370 @@ +--- +title: ActionView::PartialRenderer +layout: default +--- +
+ +
+
+ +
+ +

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 %>
+<div id="administrator">
+  Budget: $<%= user.budget %>
+  <%= yield %>
+</div>
+
+<%# app/views/users/_editor.html.erb %>
+<div id="editor">
+  Deadline: <%= user.deadline %>
+  <%= yield %>
+</div>
+
+ +

…this will return:

+ +
Here's the administrator:
+<div id="administrator">
+  Budget: $<%= user.budget %>
+  Name: <%= user.name %>
+</div>
+
+Here's the editor:
+<div id="editor">
+  Deadline: <%= user.deadline %>
+  Name: <%= user.name %>
+</div>
+
+ +

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 %>
+<ul>
+  <% users.each do |user| -%>
+    <li>
+      <%= render partial: "user", locals: { user: user } %>
+    </li>
+  <% end -%>
+</ul>
+
+<%# app/views/users/_li_layout.html.erb %>
+<li>
+  <%= yield %>
+</li>
+
+<%# app/views/users/index.html.erb %>
+<ul>
+  <%= render partial: "user", layout: "li_layout", collection: users %>
+</ul>
+
+ +

Given two users whose names are Alice and Bob, these snippets return:

+ +
<ul>
+  <li>
+    Name: Alice
+  </li>
+  <li>
+    Name: Bob
+  </li>
+</ul>
+
+ +

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:

+ +
<div id="administrator">
+  Budget: $<%= user.budget %>
+  Title: <%= chief.name %>
+</div>
+
+ +

As you can see, the :locals hash is shared between both the partial and its layout.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(lookup_context, options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 223
+def initialize(lookup_context, options)
+  super(lookup_context)
+  @options = options
+  @locals  = @options[:locals] || {}
+  @details = extract_details(@options)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + render(partial, context, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/partial_renderer.rb, line 230
+def render(partial, context, block)
+  template = find_template(partial, template_keys(partial))
+
+  if !block && (layout = @options[:layout])
+    layout = find_template(layout.to_s, template_keys(partial))
+  end
+
+  render_partial_template(context, @locals, template, layout, block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/RecordIdentifier.html b/src/7.0/classes/ActionView/RecordIdentifier.html new file mode 100644 index 0000000000..85ff85c263 --- /dev/null +++ b/src/7.0/classes/ActionView/RecordIdentifier.html @@ -0,0 +1,288 @@ +--- +title: ActionView::RecordIdentifier +layout: default +--- +
+ +
+
+ +
+ +

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:

+ +
<form class="new_post" id="new_post" action="/posts" accept-charset="UTF-8" method="post">
+  <input type="text" name="post[body]" id="post_body" />
+</form>
+
+ +

When post is a persisted ActiveRecord::Base instance, the resulting HTML is:

+ +
<form class="edit_post" id="edit_post_42" action="/posts/42" accept-charset="UTF-8" method="post">
+  <input type="text" value="What a wonderful world!" name="post[body]" id="post_body" />
+</form>
+
+ +

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
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
JOIN="_"
 
NEW="new"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + dom_class(record_or_class, prefix = nil) + +

+ + +
+

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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/record_identifier.rb, line 74
+def dom_class(record_or_class, prefix = nil)
+  singular = model_name_from_record_or_class(record_or_class).param_key
+  prefix ? "#{prefix}#{JOIN}#{singular}" : singular
+end
+
+
+ +
+ +
+

+ + dom_id(record, prefix = nil) + +

+ + +
+

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"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/record_identifier.rb, line 89
+def dom_id(record, prefix = nil)
+  if record_id = record_key_for_dom_id(record)
+    "#{dom_class(record, prefix)}#{JOIN}#{record_id}"
+  else
+    dom_class(record, prefix || NEW)
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + record_key_for_dom_id(record) + +

+ + +
+

Returns a string representation of the key attribute(s) that is suitable for use in an HTML DOM id. This can be overwritten to customize the default generated string representation if desired. If you need to read back a key from a dom_id in order to query for the underlying database record, you should write a helper like ‘person_record_from_dom_id’ that will extract the key either based on the default implementation (which just joins all key attributes with ‘_’) or on your own overwritten version of the method. By default, this implementation passes the key string through a method that replaces all characters that are invalid inside DOM ids, with valid ones. You need to make sure yourself that your dom ids are valid, in case you override this method.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/record_identifier.rb, line 106
+def record_key_for_dom_id(record) # :doc:
+  key = convert_to_model(record).to_key
+  key ? key.join(JOIN) : key
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Renderer.html b/src/7.0/classes/ActionView/Renderer.html new file mode 100644 index 0000000000..e3c81faa4b --- /dev/null +++ b/src/7.0/classes/ActionView/Renderer.html @@ -0,0 +1,216 @@ +--- +title: ActionView::Renderer +layout: default +--- +
+ +
+
+ +
+ +

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.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + lookup_context
+ + + + +

Class Public methods

+ +
+

+ + new(lookup_context) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/renderer.rb, line 16
+def initialize(lookup_context)
+  @lookup_context = lookup_context
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + render(context, options) + +

+ + +
+

Main render entry point shared by Action View and Action Controller.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/renderer.rb, line 21
+def render(context, options)
+  render_to_object(context, options).body
+end
+
+
+ +
+ +
+

+ + render_body(context, options) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/renderer/renderer.rb, line 38
+def render_body(context, options)
+  if options.key?(:partial)
+    [render_partial(context, options)]
+  else
+    StreamingTemplateRenderer.new(@lookup_context).render(context, options)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Rendering.html b/src/7.0/classes/ActionView/Rendering.html new file mode 100644 index 0000000000..e7f4e06765 --- /dev/null +++ b/src/7.0/classes/ActionView/Rendering.html @@ -0,0 +1,273 @@ +--- +title: ActionView::Rendering +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + rendered_format
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 31
+def initialize
+  @rendered_format = nil
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + render_to_body(options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 101
+def render_to_body(options = {})
+  _process_options(options)
+  _render_template(options)
+end
+
+
+ +
+ +
+

+ + view_context() + +

+ + +
+

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) — Create a new ActionView instance for a controller and we can also pass the arguments.

    +
  • +

    View#render(option) — Returns String with the rendered template.

    +
+ +

Override this method in a module to change the default behavior.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 91
+def view_context
+  view_context_class.new(lookup_context, view_assigns, self)
+end
+
+
+ +
+ +
+

+ + view_context_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 77
+def view_context_class
+  self.class.view_context_class
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Rendering/ClassMethods.html b/src/7.0/classes/ActionView/Rendering/ClassMethods.html new file mode 100644 index 0000000000..33302dec43 --- /dev/null +++ b/src/7.0/classes/ActionView/Rendering/ClassMethods.html @@ -0,0 +1,233 @@ +--- +title: ActionView::Rendering::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _helpers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 48
+def _helpers
+end
+
+
+ +
+ +
+

+ + _routes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 45
+def _routes
+end
+
+
+ +
+ +
+

+ + build_view_context_class(klass, supports_path, routes, helpers) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 51
+def build_view_context_class(klass, supports_path, routes, helpers)
+  Class.new(klass) do
+    if routes
+      include routes.url_helpers(supports_path)
+      include routes.mounted_helpers
+    end
+
+    if helpers
+      include helpers
+    end
+  end
+end
+
+
+ +
+ +
+

+ + view_context_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/rendering.rb, line 64
+def view_context_class
+  klass = ActionView::LookupContext::DetailsKey.view_context_class(ActionView::Base)
+
+  @view_context_class ||= build_view_context_class(klass, supports_path?, _routes, _helpers)
+
+  if klass.changed?(@view_context_class)
+    @view_context_class = build_view_context_class(klass, supports_path?, _routes, _helpers)
+  end
+
+  @view_context_class
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Resolver.html b/src/7.0/classes/ActionView/Resolver.html new file mode 100644 index 0000000000..d9de1805b0 --- /dev/null +++ b/src/7.0/classes/ActionView/Resolver.html @@ -0,0 +1,169 @@ +--- +title: ActionView::Resolver +layout: default +--- +
+ +
+
+ +
+ +

Action View Resolver

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
Path=ActionView::TemplatePath
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + clear_cache() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 60
+def clear_cache
+end
+
+
+ +
+ +
+

+ + find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = []) + +

+ + +
+

Normalizes the arguments and passes it on to find_templates.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/resolver.rb, line 64
+def find_all(name, prefix = nil, partial = false, details = {}, key = nil, locals = [])
+  _find_all(name, prefix, partial, details, key, locals)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/RoutingUrlFor.html b/src/7.0/classes/ActionView/RoutingUrlFor.html new file mode 100644 index 0000000000..96cfc5c57e --- /dev/null +++ b/src/7.0/classes/ActionView/RoutingUrlFor.html @@ -0,0 +1,215 @@ +--- +title: ActionView::RoutingUrlFor +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + url_for(options = nil) + +

+ + +
+

Returns the URL for the set of options provided. This takes the same options as url_for in Action Controller (see the documentation for ActionDispatch::Routing::UrlFor#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) %>
+# => /workshops
+
+<%= 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
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/routing_url_for.rb, line 82
+def url_for(options = nil)
+  case options
+  when String
+    options
+  when nil
+    super(only_path: _generate_paths_by_default)
+  when Hash
+    options = options.symbolize_keys
+    ensure_only_path_option(options)
+
+    super(options)
+  when ActionController::Parameters
+    ensure_only_path_option(options)
+
+    super(options)
+  when :back
+    _back_url
+  when Array
+    components = options.dup
+    options = components.extract_options!
+    ensure_only_path_option(options)
+
+    if options[:only_path]
+      polymorphic_path(components, options)
+    else
+      polymorphic_url(components, options)
+    end
+  else
+    method = _generate_paths_by_default ? :path : :url
+    builder = ActionDispatch::Routing::PolymorphicRoutes::HelperMethodBuilder.public_send(method)
+
+    case options
+    when Symbol
+      builder.handle_string_call(self, options)
+    when Class
+      builder.handle_class_call(self, options)
+    else
+      builder.handle_model_call(self, options)
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template.html b/src/7.0/classes/ActionView/Template.html new file mode 100644 index 0000000000..dcf6266380 --- /dev/null +++ b/src/7.0/classes/ActionView/Template.html @@ -0,0 +1,667 @@ +--- +title: ActionView::Template +layout: default +--- +
+ +
+
+ +
+ +

Action View Template

+ +

Action View Renderable Template for objects that respond to render_in

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + format
+ [RW] + frozen_string_literal
+ [R] + handler
+ [R] + identifier
+ [R] + locals
+ [R] + variable
+ [R] + variant
+ [R] + virtual_path
+ + + + +

Class Public methods

+ +
+

+ + new(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 123
+def initialize(source, identifier, handler, locals:, format: nil, variant: nil, virtual_path: nil)
+  @source            = source
+  @identifier        = identifier
+  @handler           = handler
+  @compiled          = false
+  @locals            = locals
+  @virtual_path      = virtual_path
+
+  @variable = if @virtual_path
+    base = @virtual_path.end_with?("/") ? "" : ::File.basename(@virtual_path)
+    base =~ /\A_?(.*?)(?:\.\w+)*\z/
+    $1.to_sym
+  end
+
+  @format            = format
+  @variant           = variant
+  @compile_mutex     = Mutex.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + encode!() + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 189
+def encode!
+  source = self.source
+
+  return source unless source.encoding == Encoding::BINARY
+
+  # Look for # encoding: *. If we find one, we'll encode the
+  # String in that encoding, otherwise, we'll use the
+  # default external encoding.
+  if source.sub!(/\A#{ENCODING_FLAG}/, "")
+    encoding = magic_encoding = $1
+  else
+    encoding = Encoding.default_external
+  end
+
+  # Tag the source with the default external encoding
+  # or the encoding specified in the file
+  source.force_encoding(encoding)
+
+  # If the user didn't specify an encoding, and the handler
+  # handles encodings, we simply pass the String as is to
+  # the handler (with the default_external tag)
+  if !magic_encoding && @handler.respond_to?(:handles_encoding?) && @handler.handles_encoding?
+    source
+  # Otherwise, if the String is valid in the encoding,
+  # encode immediately to default_internal. This means
+  # that if a handler doesn't handle encodings, it will
+  # always get Strings in the default_internal
+  elsif source.valid_encoding?
+    source.encode!
+  # Otherwise, since the String is invalid in the encoding
+  # specified, raise an exception
+  else
+    raise WrongEncodingError.new(source, encoding)
+  end
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 171
+def inspect
+  "#<#{self.class.name} #{short_identifier} locals=#{@locals.inspect}>"
+end
+
+
+ +
+ +
+

+ + local_assigns + +

+ + +
+

Returns a hash with the defined local variables.

+ +

Given this sub template rendering:

+ +
<%= render "shared/header", { headline: "Welcome", person: person } %>
+
+ +

You can use local_assigns in the sub templates to access the local variables:

+ +
local_assigns[:headline] # => "Welcome"
+
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 103
+eager_autoload do
+  autoload :Error
+  autoload :RawFile
+  autoload :Renderable
+  autoload :Handlers
+  autoload :HTML
+  autoload :Inline
+  autoload :Sources
+  autoload :Text
+  autoload :Types
+end
+
+
+ +
+ +
+

+ + render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block) + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 154
+def render(view, locals, buffer = ActionView::OutputBuffer.new, add_to_stack: true, &block)
+  instrument_render_template do
+    compile!(view)
+    view._run(method_name, self, locals, buffer, add_to_stack: add_to_stack, &block)
+  end
+rescue => e
+  handle_render_error(view, e)
+end
+
+
+ +
+ +
+

+ + short_identifier() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 167
+def short_identifier
+  @short_identifier ||= defined?(Rails.root) ? identifier.delete_prefix("#{Rails.root}/") : identifier
+end
+
+
+ +
+ +
+

+ + source() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 175
+def source
+  @source.to_s
+end
+
+
+ +
+ +
+

+ + supports_streaming?() + +

+ + +
+

Returns whether the underlying handler supports streaming. If so, a streaming buffer may be passed when it starts rendering.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 144
+def supports_streaming?
+  handler.respond_to?(:supports_streaming?) && handler.supports_streaming?
+end
+
+
+ +
+ +
+

+ + type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 163
+def type
+  @type ||= Types[format]
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + instrument(action, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template.rb, line 356
+def instrument(action, &block) # :doc:
+  ActiveSupport::Notifications.instrument("#{action}.action_view", instrument_payload, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Handlers.html b/src/7.0/classes/ActionView/Template/Handlers.html new file mode 100644 index 0000000000..f58f2b9e2b --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Handlers.html @@ -0,0 +1,85 @@ +--- +title: ActionView::Template::Handlers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Handlers/Builder.html b/src/7.0/classes/ActionView/Template/Handlers/Builder.html new file mode 100644 index 0000000000..d697015523 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Handlers/Builder.html @@ -0,0 +1,156 @@ +--- +title: ActionView::Template::Handlers::Builder +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + call(template, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/builder.rb, line 8
+def call(template, source)
+  require_engine
+  "xml = ::Builder::XmlMarkup.new(:indent => 2);" \
+    "self.output_buffer = xml.target!;" +
+    source +
+    ";xml.target!;"
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + require_engine() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/builder.rb, line 17
+def require_engine # :doc:
+  @required ||= begin
+    require "builder"
+    true
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Handlers/ERB.html b/src/7.0/classes/ActionView/Template/Handlers/ERB.html new file mode 100644 index 0000000000..ccddae55f0 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Handlers/ERB.html @@ -0,0 +1,274 @@ +--- +title: ActionView::Template::Handlers::ERB +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ENCODING_TAG=Regexp.new("\\A(<%#{ENCODING_FLAG}-?%>)[ \\t]*")
 
+ + + + + + +

Class Public methods

+ +
+

+ + call(template, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/erb.rb, line 24
+def self.call(template, source)
+  new.call(template, source)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(template, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/erb.rb, line 36
+def call(template, source)
+  # First, convert to BINARY, so in case the encoding is
+  # wrong, we can still find an encoding tag
+  # (<%# encoding %>) inside the String using a regular
+  # expression
+  template_source = source.b
+
+  erb = template_source.gsub(ENCODING_TAG, "")
+  encoding = $2
+
+  erb.force_encoding valid_encoding(source.dup, encoding)
+
+  # Always make sure we return a String in the default_internal
+  erb.encode!
+
+  # Strip trailing newlines from the template if enabled
+  erb.chomp! if strip_trailing_newlines
+
+  options = {
+    escape: (self.class.escape_ignore_list.include? template.type),
+    trim: (self.class.erb_trim_mode == "-")
+  }
+
+  if ActionView::Base.annotate_rendered_view_with_filenames && template.format == :html
+    options[:preamble] = "@output_buffer.safe_append='<!-- BEGIN #{template.short_identifier} -->';"
+    options[:postamble] = "@output_buffer.safe_append='<!-- END #{template.short_identifier} -->';@output_buffer.to_s"
+  end
+
+  self.class.erb_implementation.new(erb, options).src
+end
+
+
+ +
+ +
+

+ + handles_encoding?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/erb.rb, line 32
+def handles_encoding?
+  true
+end
+
+
+ +
+ +
+

+ + supports_streaming?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/erb.rb, line 28
+def supports_streaming?
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Handlers/Html.html b/src/7.0/classes/ActionView/Template/Handlers/Html.html new file mode 100644 index 0000000000..a8cf7b98e6 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Handlers/Html.html @@ -0,0 +1,107 @@ +--- +title: ActionView::Template::Handlers::Html +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + call(template, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/html.rb, line 6
+def call(template, source)
+  "ActionView::OutputBuffer.new #{super}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Handlers/Raw.html b/src/7.0/classes/ActionView/Template/Handlers/Raw.html new file mode 100644 index 0000000000..22367ffa47 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Handlers/Raw.html @@ -0,0 +1,107 @@ +--- +title: ActionView::Template::Handlers::Raw +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + call(template, source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/handlers/raw.rb, line 6
+def call(template, source)
+  "#{source.inspect}.html_safe;"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Sources.html b/src/7.0/classes/ActionView/Template/Sources.html new file mode 100644 index 0000000000..ace5247f2a --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Sources.html @@ -0,0 +1,69 @@ +--- +title: ActionView::Template::Sources +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Sources/File.html b/src/7.0/classes/ActionView/Template/Sources/File.html new file mode 100644 index 0000000000..9c06922291 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Sources/File.html @@ -0,0 +1,149 @@ +--- +title: ActionView::Template::Sources::File +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/sources/file.rb, line 7
+def initialize(filename)
+  @filename = filename
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/sources/file.rb, line 11
+def to_s
+  ::File.binread @filename
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Types.html b/src/7.0/classes/ActionView/Template/Types.html new file mode 100644 index 0000000000..575f58cac9 --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Types.html @@ -0,0 +1,206 @@ +--- +title: ActionView::Template::Types +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + type_klass
+ + + + +

Class Public methods

+ +
+

+ + [](type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 47
+def [](type)
+  type_klass[type]
+end
+
+
+ +
+ +
+

+ + delegate_to(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 43
+def delegate_to(klass)
+  self.type_klass = klass
+end
+
+
+ +
+ +
+

+ + symbols() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 51
+def symbols
+  type_klass::SET.symbols
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/Template/Types/Type.html b/src/7.0/classes/ActionView/Template/Types/Type.html new file mode 100644 index 0000000000..e4cff3881f --- /dev/null +++ b/src/7.0/classes/ActionView/Template/Types/Type.html @@ -0,0 +1,366 @@ +--- +title: ActionView::Template::Types::Type +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
SET=Struct.new(:symbols).new([ :html, :text, :js, :css, :xml, :json ])
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + symbol
+ + + + +

Class Public methods

+ +
+

+ + [](type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 11
+def self.[](type)
+  if type.is_a?(self)
+    type
+  else
+    new(type)
+  end
+end
+
+
+ +
+ +
+

+ + new(symbol) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 21
+def initialize(symbol)
+  @symbol = symbol.to_sym
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 35
+def ==(type)
+  @symbol == type.to_sym unless type.blank?
+end
+
+
+ +
+ +
+

+ + ref() + +

+ + +
+ +
+ + + +
+ Also aliased as: to_sym +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 30
+def ref
+  @symbol
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + +
+ Also aliased as: to_str +
+ + + + + + +
+ + +
+
# File actionview/lib/action_view/template/types.rb, line 25
+def to_s
+  @symbol.to_s
+end
+
+
+ +
+ +
+

+ + to_str() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_s +
+ + + +
+ +
+

+ + to_sym() + +

+ + +
+ +
+ + + + + +
+ Alias for: ref +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TemplateDetails.html b/src/7.0/classes/ActionView/TemplateDetails.html new file mode 100644 index 0000000000..67dbb206e1 --- /dev/null +++ b/src/7.0/classes/ActionView/TemplateDetails.html @@ -0,0 +1,73 @@ +--- +title: ActionView::TemplateDetails +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TemplateDetails/Requested.html b/src/7.0/classes/ActionView/TemplateDetails/Requested.html new file mode 100644 index 0000000000..f84ecc9ab9 --- /dev/null +++ b/src/7.0/classes/ActionView/TemplateDetails/Requested.html @@ -0,0 +1,207 @@ +--- +title: ActionView::TemplateDetails::Requested +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ANY_HASH=Hash.new(1).merge(nil => 0).freeze
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + formats
+ [R] + formats_idx
+ [R] + handlers
+ [R] + handlers_idx
+ [R] + locale
+ [R] + locale_idx
+ [R] + variants
+ [R] + variants_idx
+ + + + +

Class Public methods

+ +
+

+ + new(locale:, handlers:, formats:, variants:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template_details.rb, line 11
+def initialize(locale:, handlers:, formats:, variants:)
+  @locale = locale
+  @handlers = handlers
+  @formats = formats
+  @variants = variants
+
+  @locale_idx   = build_idx_hash(locale)
+  @handlers_idx = build_idx_hash(handlers)
+  @formats_idx  = build_idx_hash(formats)
+  if variants == :any
+    @variants_idx = ANY_HASH
+  else
+    @variants_idx = build_idx_hash(variants)
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TemplatePath.html b/src/7.0/classes/ActionView/TemplatePath.html new file mode 100644 index 0000000000..1eb7b07437 --- /dev/null +++ b/src/7.0/classes/ActionView/TemplatePath.html @@ -0,0 +1,321 @@ +--- +title: ActionView::TemplatePath +layout: default +--- +
+ +
+
+ +
+ +

Represents a template path within ActionView’s lookup and rendering system, like “users/show”

+ +

TemplatePath makes it convenient to convert between separate name, prefix, partial arguments and the virtual path.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + name
+ [R] + partial
+ [R] + partial?
+ [R] + prefix
+ [R] + to_s
+ [R] + to_str
+ [R] + virtual
+ [R] + virtual_path
+ + + + +

Class Public methods

+ +
+

+ + build(name, prefix, partial) + +

+ + +
+

Convert name, prefix, and partial into a TemplatePath

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template_path.rb, line 41
+def self.build(name, prefix, partial)
+  new name, prefix, partial, virtual(name, prefix, partial)
+end
+
+
+ +
+ +
+

+ + new(name, prefix, partial, virtual) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template_path.rb, line 45
+def initialize(name, prefix, partial, virtual)
+  @name    = name
+  @prefix  = prefix
+  @partial = partial
+  @virtual = virtual
+end
+
+
+ +
+ +
+

+ + parse(virtual) + +

+ + +
+

Build a TemplatePath form a virtual path

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template_path.rb, line 26
+def self.parse(virtual)
+  if nameidx = virtual.rindex("/")
+    prefix = virtual[0, nameidx]
+    name = virtual.from(nameidx + 1)
+    prefix = prefix[1..] if prefix.start_with?("/")
+  else
+    prefix = ""
+    name = virtual
+  end
+  partial = name.start_with?("_")
+  name = name[1..] if partial
+  new name, prefix, partial, virtual
+end
+
+
+ +
+ +
+

+ + virtual(name, prefix, partial) + +

+ + +
+

Convert name, prefix, and partial into a virtual path string

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/template_path.rb, line 15
+def self.virtual(name, prefix, partial)
+  if prefix.empty?
+    "#{partial ? "_" : ""}#{name}"
+  elsif partial
+    "#{prefix}/_#{name}"
+  else
+    "#{prefix}/#{name}"
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase.html b/src/7.0/classes/ActionView/TestCase.html new file mode 100644 index 0000000000..a66be701f6 --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase.html @@ -0,0 +1,100 @@ +--- +title: ActionView::TestCase +layout: default +--- +
+ +
+
+ +
+ +

Action View Test Case

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase/Behavior.html b/src/7.0/classes/ActionView/TestCase/Behavior.html new file mode 100644 index 0000000000..d0cd615fff --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase/Behavior.html @@ -0,0 +1,522 @@ +--- +title: ActionView::TestCase::Behavior +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
INTERNAL_IVARS=[ +:@NAME, +:@failures, +:@assertions, +:@__io__, +:@_assertion_wrapped, +:@_assertions, +:@_result, +:@_routes, +:@controller, +:@_layouts, +:@_files, +:@_rendered_views, +:@method_name, +:@output_buffer, +:@_partials, +:@passed, +:@rendered, +:@request, +:@routes, +:@tagged_logger, +:@_templates, +:@options, +:@test_passed, +:@view, +:@view_context_class, +:@view_flow, +:@_subscribers, +:@html_document +]
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + controller
+ [RW] + output_buffer
+ [RW] + rendered
+ [RW] + request
+ + + + + +

Instance Public methods

+ +
+

+ + _routes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 136
+def _routes
+  @controller._routes if @controller.respond_to?(:_routes)
+end
+
+
+ +
+ +
+

+ + _test_case() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 175
+def _test_case
+  controller._test_case
+end
+
+
+ +
+ +
+

+ + config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 122
+def config
+  @controller.config if @controller.respond_to?(:config)
+end
+
+
+ +
+ +
+

+ + protect_against_forgery?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 171
+def protect_against_forgery?
+  false
+end
+
+
+ +
+ +
+

+ + render(options = {}, local_assigns = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 126
+def render(options = {}, local_assigns = {}, &block)
+  view.assign(view_assigns)
+  @rendered << output = view.render(options, local_assigns, &block)
+  output
+end
+
+
+ +
+ +
+

+ + rendered_views() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 132
+def rendered_views
+  @_rendered_views ||= RenderedViewsCollection.new
+end
+
+
+ +
+ +
+

+ + setup_with_controller() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 108
+def setup_with_controller
+  controller_class = Class.new(ActionView::TestCase::TestController)
+  @controller = controller_class.new
+  @request = @controller.request
+  @view_flow = ActionView::OutputFlow.new
+  # empty string ensures buffer has UTF-8 encoding as
+  # new without arguments returns ASCII-8BIT encoded buffer like String#new
+  @output_buffer = ActiveSupport::SafeBuffer.new ""
+  @rendered = +""
+
+  test_case_instance = self
+  controller_class.define_method(:_test_case) { test_case_instance }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase/Behavior/ClassMethods.html b/src/7.0/classes/ActionView/TestCase/Behavior/ClassMethods.html new file mode 100644 index 0000000000..a0635584b8 --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase/Behavior/ClassMethods.html @@ -0,0 +1,287 @@ +--- +title: ActionView::TestCase::Behavior::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [W] + helper_class
+ + + + + +

Instance Public methods

+ +
+

+ + determine_default_helper_class(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 72
+def determine_default_helper_class(name)
+  determine_constant_from_test_name(name) do |constant|
+    Module === constant && !(Class === constant)
+  end
+end
+
+
+ +
+ +
+

+ + helper_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 92
+def helper_class
+  @helper_class ||= determine_default_helper_class(name)
+end
+
+
+ +
+ +
+

+ + helper_method(*methods) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 78
+        def helper_method(*methods)
+          # Almost a duplicate from ActionController::Helpers
+          methods.flatten.each do |method|
+            _helpers_for_modification.module_eval <<~end_eval, __FILE__, __LINE__ + 1
+              def #{method}(*args, &block)                    # def current_user(*args, &block)
+                _test_case.send(:'#{method}', *args, &block)  #   _test_case.send(:'current_user', *args, &block)
+              end                                             # end
+              ruby2_keywords(:'#{method}')
+            end_eval
+          end
+        end
+
+
+ +
+ +
+

+ + new(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 96
+def new(*)
+  include_helper_modules!
+  super
+end
+
+
+ +
+ +
+

+ + tests(helper_class) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 63
+def tests(helper_class)
+  case helper_class
+  when String, Symbol
+    self.helper_class = "#{helper_class.to_s.underscore}_helper".camelize.safe_constantize
+  when Module
+    self.helper_class = helper_class
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase/Behavior/Locals.html b/src/7.0/classes/ActionView/TestCase/Behavior/Locals.html new file mode 100644 index 0000000000..d8b0efdb13 --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase/Behavior/Locals.html @@ -0,0 +1,126 @@ +--- +title: ActionView::TestCase::Behavior::Locals +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + rendered_views
+ + + + + +

Instance Public methods

+ +
+

+ + render(options = {}, local_assigns = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 190
+def render(options = {}, local_assigns = {})
+  case options
+  when Hash
+    if block_given?
+      rendered_views.add options[:layout], options[:locals]
+    elsif options.key?(:partial)
+      rendered_views.add options[:partial], options[:locals]
+    end
+  else
+    rendered_views.add options, local_assigns
+  end
+
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase/Behavior/RenderedViewsCollection.html b/src/7.0/classes/ActionView/TestCase/Behavior/RenderedViewsCollection.html new file mode 100644 index 0000000000..511360b693 --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase/Behavior/RenderedViewsCollection.html @@ -0,0 +1,275 @@ +--- +title: ActionView::TestCase::Behavior::RenderedViewsCollection +layout: default +--- +
+ +
+
+ +
+ +

Need to experiment if this priority is the best one: rendered => output_buffer

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 142
+def initialize
+  @rendered_views ||= Hash.new { |hash, key| hash[key] = [] }
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add(view, locals) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 146
+def add(view, locals)
+  @rendered_views[view] ||= []
+  @rendered_views[view] << locals
+end
+
+
+ +
+ +
+

+ + locals_for(view) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 151
+def locals_for(view)
+  @rendered_views[view]
+end
+
+
+ +
+ +
+

+ + rendered_views() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 155
+def rendered_views
+  @rendered_views.keys
+end
+
+
+ +
+ +
+

+ + view_rendered?(view, expected_locals) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 159
+def view_rendered?(view, expected_locals)
+  locals_for(view).any? do |actual_locals|
+    expected_locals.all? { |key, value| value == actual_locals[key] }
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/TestCase/TestController.html b/src/7.0/classes/ActionView/TestCase/TestController.html new file mode 100644 index 0000000000..3f59133ef2 --- /dev/null +++ b/src/7.0/classes/ActionView/TestCase/TestController.html @@ -0,0 +1,246 @@ +--- +title: ActionView::TestCase::TestController +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + controller_path

Overrides AbstractController::Base#controller_path

+ [RW] + params
+ [RW] + request
+ [RW] + response
+ + + + +

Class Public methods

+ +
+

+ + controller_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 27
+def self.controller_name
+  "test"
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 31
+def initialize
+  super
+  self.class.controller_path = ""
+  @request = ActionController::TestRequest.create(self.class)
+  @response = ActionDispatch::TestResponse.new
+
+  @request.env.delete("PATH_INFO")
+  @params = ActionController::Parameters.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + controller_path=(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/test_case.rb, line 23
+def controller_path=(path)
+  self.class.controller_path = path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/UnboundTemplate.html b/src/7.0/classes/ActionView/UnboundTemplate.html new file mode 100644 index 0000000000..26c1cb0792 --- /dev/null +++ b/src/7.0/classes/ActionView/UnboundTemplate.html @@ -0,0 +1,191 @@ +--- +title: ActionView::UnboundTemplate +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + details
+ [R] + virtual_path
+ + + + +

Class Public methods

+ +
+

+ + new(source, identifier, details:, virtual_path:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/unbound_template.rb, line 10
+def initialize(source, identifier, details:, virtual_path:)
+  @source = source
+  @identifier = identifier
+  @details = details
+  @virtual_path = virtual_path
+
+  @templates = Concurrent::Map.new(initial_capacity: 2)
+  @write_lock = Mutex.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + bind_locals(locals) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/unbound_template.rb, line 20
+def bind_locals(locals)
+  if template = @templates[locals]
+    template
+  else
+    @write_lock.synchronize do
+      normalized_locals = normalize_locals(locals)
+
+      # We need ||=, both to dedup on the normalized locals and to check
+      # while holding the lock.
+      @templates[normalized_locals] ||= build_template(normalized_locals)
+
+      # This may have already been assigned, but we've already de-dup'd so
+      # reassignment is fine.
+      @templates[locals.dup] = @templates[normalized_locals]
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/VERSION.html b/src/7.0/classes/ActionView/VERSION.html new file mode 100644 index 0000000000..fc8f232faa --- /dev/null +++ b/src/7.0/classes/ActionView/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActionView::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/ViewPaths.html b/src/7.0/classes/ActionView/ViewPaths.html new file mode 100644 index 0000000000..eb4bd175ca --- /dev/null +++ b/src/7.0/classes/ActionView/ViewPaths.html @@ -0,0 +1,242 @@ +--- +title: ActionView::ViewPaths +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + append_view_path(path) + +

+ + +
+

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)

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 112
+def append_view_path(path)
+  lookup_context.view_paths.push(*path)
+end
+
+
+ +
+ +
+

+ + details_for_lookup() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 102
+def details_for_lookup
+  {}
+end
+
+
+ +
+ +
+

+ + lookup_context() + +

+ + +
+

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.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 97
+def lookup_context
+  @_lookup_context ||=
+    ActionView::LookupContext.new(self.class._view_paths, details_for_lookup, _prefixes)
+end
+
+
+ +
+ +
+

+ + prepend_view_path(path) + +

+ + +
+

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)

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 122
+def prepend_view_path(path)
+  lookup_context.view_paths.unshift(*path)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActionView/ViewPaths/ClassMethods.html b/src/7.0/classes/ActionView/ViewPaths/ClassMethods.html new file mode 100644 index 0000000000..121e5f05a0 --- /dev/null +++ b/src/7.0/classes/ActionView/ViewPaths/ClassMethods.html @@ -0,0 +1,311 @@ +--- +title: ActionView::ViewPaths::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _view_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 15
+def _view_paths
+  ViewPaths.get_view_paths(self)
+end
+
+
+ +
+ +
+

+ + _view_paths=(paths) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 19
+def _view_paths=(paths)
+  ViewPaths.set_view_paths(self, paths)
+end
+
+
+ +
+ +
+

+ + append_view_path(path) + +

+ + +
+

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)

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 37
+def append_view_path(path)
+  self._view_paths = view_paths + Array(path)
+end
+
+
+ +
+ +
+

+ + prepend_view_path(path) + +

+ + +
+

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)

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 47
+def prepend_view_path(path)
+  self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
+end
+
+
+ +
+ +
+

+ + view_paths() + +

+ + +
+

A list of all of the default view paths for this controller.

+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 52
+def view_paths
+  _view_paths
+end
+
+
+ +
+ +
+

+ + view_paths=(paths) + +

+ + +
+

Set the view paths.

+ +

Parameters

+
  • +

    paths - If a PathSet is provided, use that; otherwise, process the parameter into a PathSet.

    +
+
+ + + + + + + + +
+ + +
+
# File actionview/lib/action_view/view_paths.rb, line 61
+def view_paths=(paths)
+  self._view_paths = ActionView::PathSet.new(Array(paths))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob.html b/src/7.0/classes/ActiveJob.html new file mode 100644 index 0000000000..465306a446 --- /dev/null +++ b/src/7.0/classes/ActiveJob.html @@ -0,0 +1,282 @@ +--- +title: ActiveJob +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Active Job as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Active Job as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Arguments.html b/src/7.0/classes/ActiveJob/Arguments.html new file mode 100644 index 0000000000..1dde01e693 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Arguments.html @@ -0,0 +1,159 @@ +--- +title: ActiveJob::Arguments +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deserialize(arguments) + +

+ + +
+

Deserializes a set of arguments. Intrinsic types that can safely be deserialized without mutation are returned as-is. Arrays/Hashes are deserialized element by element. All other types are deserialized using GlobalID.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/arguments.rb, line 42
+def deserialize(arguments)
+  arguments.map { |argument| deserialize_argument(argument) }
+rescue
+  raise DeserializationError
+end
+
+
+ +
+ +
+

+ + serialize(arguments) + +

+ + +
+

Serializes a set of arguments. Intrinsic types that can safely be serialized without mutation are returned as-is. Arrays/Hashes are serialized element by element. All other types are serialized using GlobalID.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/arguments.rb, line 34
+def serialize(arguments)
+  arguments.map { |argument| serialize_argument(argument) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Arguments/Hash.html b/src/7.0/classes/ActiveJob/Arguments/Hash.html new file mode 100644 index 0000000000..e9b6f1f8cd --- /dev/null +++ b/src/7.0/classes/ActiveJob/Arguments/Hash.html @@ -0,0 +1,140 @@ +--- +title: ActiveJob::Arguments::Hash +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + ruby2_keywords_hash(hash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/arguments.rb, line 81
+def ruby2_keywords_hash(hash)
+  _ruby2_keywords_hash(**hash)
+end
+
+
+ +
+ +
+

+ + ruby2_keywords_hash?(hash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/arguments.rb, line 77
+def ruby2_keywords_hash?(hash)
+  !new(*[hash]).default.equal?(hash)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Base.html b/src/7.0/classes/ActiveJob/Base.html new file mode 100644 index 0000000000..5e7b767477 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Base.html @@ -0,0 +1,183 @@ +--- +title: ActiveJob::Base +layout: default +--- +
+ +
+
+ +
+ +

Active Job

+ +

Active Job objects can be configured to work with different backend queuing frameworks. To specify a queue adapter to use:

+ +
ActiveJob::Base.queue_adapter = :inline
+
+ +

A list of supported adapters can be found in QueueAdapters.

+ +

Active Job objects can be defined by creating a class that inherits from the ActiveJob::Base class. The only necessary method to implement is the “perform” method.

+ +

To define an Active Job object:

+ +
class ProcessPhotoJob < ActiveJob::Base
+  def perform(photo)
+    photo.watermark!('Rails')
+    photo.rotate!(90.degrees)
+    photo.resize_to_fit!(300, 300)
+    photo.upload!
+  end
+end
+
+ +

Records that are passed in are serialized/deserialized using Global ID. More information can be found in Arguments.

+ +

To enqueue a job to be performed as soon as the queuing system is free:

+ +
ProcessPhotoJob.perform_later(photo)
+
+ +

To enqueue a job to be processed at some point in the future:

+ +
ProcessPhotoJob.set(wait_until: Date.tomorrow.noon).perform_later(photo)
+
+ +

More information can be found in ActiveJob::Core::ClassMethods#set

+ +

A job can also be processed immediately without sending to the queue:

+ +
ProcessPhotoJob.perform_now(photo)
+
+ +

Exceptions

+ + +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Callbacks.html b/src/7.0/classes/ActiveJob/Callbacks.html new file mode 100644 index 0000000000..9e8dbc27bb --- /dev/null +++ b/src/7.0/classes/ActiveJob/Callbacks.html @@ -0,0 +1,104 @@ +--- +title: ActiveJob::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Active Job Callbacks

+ +

Active Job provides hooks during the life cycle of a job. Callbacks allow you to trigger logic during this cycle. Available callbacks are:

+
  • +

    before_enqueue

    +
  • +

    around_enqueue

    +
  • +

    after_enqueue

    +
  • +

    before_perform

    +
  • +

    around_perform

    +
  • +

    after_perform

    +
+ +

NOTE: Calling the same callback multiple times will overwrite previous callback definitions.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Callbacks/ClassMethods.html b/src/7.0/classes/ActiveJob/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..3a2798bd91 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Callbacks/ClassMethods.html @@ -0,0 +1,398 @@ +--- +title: ActiveJob::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

These methods will be included into any Active Job object, adding callbacks for perform and enqueue methods.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_enqueue(*filters, &blk) + +

+ + +
+

Defines a callback that will get called right after the job is enqueued.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  after_enqueue do |job|
+    $statsd.increment "enqueue-video-job.success"
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 146
+def after_enqueue(*filters, &blk)
+  set_callback(:enqueue, :after, *filters, &blk)
+end
+
+
+ +
+ +
+

+ + after_perform(*filters, &blk) + +

+ + +
+

Defines a callback that will get called right after the job’s perform method has finished.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  after_perform do |job|
+    UserMailer.notify_video_processed(job.arguments.first)
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 75
+def after_perform(*filters, &blk)
+  set_callback(:perform, :after, *filters, &blk)
+end
+
+
+ +
+ +
+

+ + around_enqueue(*filters, &blk) + +

+ + +
+

Defines a callback that will get called around the enqueuing of the job.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  around_enqueue do |job, block|
+    $statsd.time "video-job.process" do
+      block.call
+    end
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 167
+def around_enqueue(*filters, &blk)
+  set_callback(:enqueue, :around, *filters, &blk)
+end
+
+
+ +
+ +
+

+ + around_perform(*filters, &blk) + +

+ + +
+

Defines a callback that will get called around the job’s perform method.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  around_perform do |job, block|
+    UserMailer.notify_video_started_processing(job.arguments.first)
+    block.call
+    UserMailer.notify_video_processed(job.arguments.first)
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+ +

You can access the return value of the job only if the execution wasn’t halted.

+ +
class VideoProcessJob < ActiveJob::Base
+  around_perform do |job, block|
+    value = block.call
+    puts value # => "Hello World!"
+  end
+
+  def perform
+    "Hello World!"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 108
+def around_perform(*filters, &blk)
+  set_callback(:perform, :around, *filters, &blk)
+end
+
+
+ +
+ +
+

+ + before_enqueue(*filters, &blk) + +

+ + +
+

Defines a callback that will get called right before the job is enqueued.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  before_enqueue do |job|
+    $statsd.increment "enqueue-video-job.try"
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 127
+def before_enqueue(*filters, &blk)
+  set_callback(:enqueue, :before, *filters, &blk)
+end
+
+
+ +
+ +
+

+ + before_perform(*filters, &blk) + +

+ + +
+

Defines a callback that will get called right before the job’s perform method is executed.

+ +
class VideoProcessJob < ActiveJob::Base
+  queue_as :default
+
+  before_perform do |job|
+    UserMailer.notify_video_started_processing(job.arguments.first)
+  end
+
+  def perform(video_id)
+    Video.find(video_id).process
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/callbacks.rb, line 56
+def before_perform(*filters, &blk)
+  set_callback(:perform, :before, *filters, &blk)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Core.html b/src/7.0/classes/ActiveJob/Core.html new file mode 100644 index 0000000000..71b23eb1a1 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Core.html @@ -0,0 +1,402 @@ +--- +title: ActiveJob::Core +layout: default +--- +
+ +
+
+ +
+ +

Provides general behavior that will be included into every Active Job object that inherits from ActiveJob::Base.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + arguments

Job arguments

+ [RW] + enqueue_error

Track any exceptions raised by the backend so callers can inspect the errors.

+ [RW] + enqueued_at

Track when a job was enqueued

+ [RW] + exception_executions

Hash that contains the number of times this job handled errors for each specific retry_on declaration. Keys are the string representation of the exceptions listed in the retry_on declaration, while its associated value holds the number of executions where the corresponding retry_on declaration handled one of its listed exceptions.

+ [RW] + executions

Number of times this job has been executed (which increments on every retry, like after an exception).

+ [RW] + job_id

Job Identifier

+ [RW] + locale

I18n.locale to be used during the job.

+ [W] + priority

Priority that the job will have (lower is more priority).

+ [RW] + provider_job_id

ID optionally provided by adapter

+ [W] + queue_name

Queue in which the job will reside.

+ [RW] + scheduled_at

Timestamp when the job should be performed

+ [W] + serialized_arguments
+ [RW] + timezone

Timezone to be used during the job.

+ + + + +

Class Public methods

+ +
+

+ + new(*arguments) + +

+ + +
+

Creates a new job instance. Takes the arguments that will be passed to the perform method.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 91
+def initialize(*arguments)
+  @arguments  = arguments
+  @job_id     = SecureRandom.uuid
+  @queue_name = self.class.queue_name
+  @priority   = self.class.priority
+  @executions = 0
+  @exception_executions = {}
+  @timezone   = Time.zone&.name
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + deserialize(job_data) + +

+ + +
+

Attaches the stored job data to the current instance. Receives a hash returned from serialize

+ +

Examples

+ +
class DeliverWebhookJob < ActiveJob::Base
+  attr_writer :attempt_number
+
+  def attempt_number
+    @attempt_number ||= 0
+  end
+
+  def serialize
+    super.merge('attempt_number' => attempt_number + 1)
+  end
+
+  def deserialize(job_data)
+    super
+    self.attempt_number = job_data['attempt_number']
+  end
+
+  rescue_from(Timeout::Error) do |exception|
+    raise exception if attempt_number > 5
+    retry_job(wait: 10)
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 146
+def deserialize(job_data)
+  self.job_id               = job_data["job_id"]
+  self.provider_job_id      = job_data["provider_job_id"]
+  self.queue_name           = job_data["queue_name"]
+  self.priority             = job_data["priority"]
+  self.serialized_arguments = job_data["arguments"]
+  self.executions           = job_data["executions"]
+  self.exception_executions = job_data["exception_executions"]
+  self.locale               = job_data["locale"] || I18n.locale.to_s
+  self.timezone             = job_data["timezone"] || Time.zone&.name
+  self.enqueued_at          = job_data["enqueued_at"]
+end
+
+
+ +
+ +
+

+ + serialize() + +

+ + +
+

Returns a hash with the job data that can safely be passed to the queuing adapter.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 104
+def serialize
+  {
+    "job_class"  => self.class.name,
+    "job_id"     => job_id,
+    "provider_job_id" => provider_job_id,
+    "queue_name" => queue_name,
+    "priority"   => priority,
+    "arguments"  => serialize_arguments_if_needed(arguments),
+    "executions" => executions,
+    "exception_executions" => exception_executions,
+    "locale"     => I18n.locale.to_s,
+    "timezone"   => timezone,
+    "enqueued_at" => Time.now.utc.iso8601
+  }
+end
+
+
+ +
+ +
+

+ + successfully_enqueued?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 49
+def successfully_enqueued?
+  @successfully_enqueued
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Core/ClassMethods.html b/src/7.0/classes/ActiveJob/Core/ClassMethods.html new file mode 100644 index 0000000000..4d56026d31 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Core/ClassMethods.html @@ -0,0 +1,169 @@ +--- +title: ActiveJob::Core::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

These methods will be included into any Active Job object, adding helpers for de/serialization and creation of job instances.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deserialize(job_data) + +

+ + +
+

Creates a new job instance from a hash created with serialize

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 60
+def deserialize(job_data)
+  job = job_data["job_class"].constantize.new
+  job.deserialize(job_data)
+  job
+end
+
+
+ +
+ +
+

+ + set(options = {}) + +

+ + +
+

Creates a job preconfigured with the given options. You can call perform_later with the job arguments to enqueue the job with the preconfigured options

+ +

Options

+
  • +

    :wait - Enqueues the job with the specified delay

    +
  • +

    :wait_until - Enqueues the job at the time specified

    +
  • +

    :queue - Enqueues the job on the specified queue

    +
  • +

    :priority - Enqueues the job with the specified priority

    +
+ +

Examples

+ +
VideoJob.set(queue: :some_queue).perform_later(Video.last)
+VideoJob.set(wait: 5.minutes).perform_later(Video.last)
+VideoJob.set(wait_until: Time.now.tomorrow).perform_later(Video.last)
+VideoJob.set(queue: :some_queue, wait: 5.minutes).perform_later(Video.last)
+VideoJob.set(queue: :some_queue, wait_until: Time.now.tomorrow).perform_later(Video.last)
+VideoJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later(Video.last)
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/core.rb, line 84
+def set(options = {})
+  ConfiguredJob.new(self, options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/DeserializationError.html b/src/7.0/classes/ActiveJob/DeserializationError.html new file mode 100644 index 0000000000..a88733b101 --- /dev/null +++ b/src/7.0/classes/ActiveJob/DeserializationError.html @@ -0,0 +1,68 @@ +--- +title: ActiveJob::DeserializationError +layout: default +--- +
+ +
+
+ +
+ +

Raised when an exception is raised during job arguments deserialization.

+ +

Wraps the original exception raised as cause.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/EnqueueError.html b/src/7.0/classes/ActiveJob/EnqueueError.html new file mode 100644 index 0000000000..54852a8233 --- /dev/null +++ b/src/7.0/classes/ActiveJob/EnqueueError.html @@ -0,0 +1,66 @@ +--- +title: ActiveJob::EnqueueError +layout: default +--- +
+ +
+
+ +
+ +

Can be raised by adapters if they wish to communicate to the caller a reason why the adapter was unexpectedly unable to enqueue a job.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Enqueuing.html b/src/7.0/classes/ActiveJob/Enqueuing.html new file mode 100644 index 0000000000..50c9392750 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Enqueuing.html @@ -0,0 +1,153 @@ +--- +title: ActiveJob::Enqueuing +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + enqueue(options = {}) + +

+ + +
+

Enqueues the job to be performed by the queue adapter.

+ +

Options

+
  • +

    :wait - Enqueues the job with the specified delay

    +
  • +

    :wait_until - Enqueues the job at the time specified

    +
  • +

    :queue - Enqueues the job on the specified queue

    +
  • +

    :priority - Enqueues the job with the specified priority

    +
+ +

Examples

+ +
my_job_instance.enqueue
+my_job_instance.enqueue wait: 5.minutes
+my_job_instance.enqueue queue: :important
+my_job_instance.enqueue wait_until: Date.tomorrow.midnight
+my_job_instance.enqueue priority: 10
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/enqueuing.rb, line 59
+def enqueue(options = {})
+  set(options)
+  self.successfully_enqueued = false
+
+  run_callbacks :enqueue do
+    if scheduled_at
+      queue_adapter.enqueue_at self, scheduled_at
+    else
+      queue_adapter.enqueue self
+    end
+
+    self.successfully_enqueued = true
+  rescue EnqueueError => e
+    self.enqueue_error = e
+  end
+
+  if successfully_enqueued?
+    self
+  else
+    false
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Enqueuing/ClassMethods.html b/src/7.0/classes/ActiveJob/Enqueuing/ClassMethods.html new file mode 100644 index 0000000000..8370da7069 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Enqueuing/ClassMethods.html @@ -0,0 +1,158 @@ +--- +title: ActiveJob::Enqueuing::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Includes the perform_later method for job initialization.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform_later(...) + +

+ + +
+

Push a job onto the queue. By default the arguments must be either String, Integer, Float, NilClass, TrueClass, FalseClass, BigDecimal, Symbol, Date, Time, DateTime, ActiveSupport::TimeWithZone, ActiveSupport::Duration, Hash, ActiveSupport::HashWithIndifferentAccess, Array, Range, or GlobalID::Identification instances, although this can be extended by adding custom serializers.

+ +

Returns an instance of the job class queued with arguments available in Job#arguments or false if the enqueue did not succeed.

+ +

After the attempted enqueue, the job will be yielded to an optional block.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/enqueuing.rb, line 28
+def perform_later(...)
+  job = job_or_instantiate(...)
+  enqueue_result = job.enqueue
+
+  yield job if block_given?
+
+  enqueue_result
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + job_or_instantiate(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/enqueuing.rb, line 38
+def job_or_instantiate(*args) # :doc:
+  args.first.is_a?(self) ? args.first : new(*args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Exceptions.html b/src/7.0/classes/ActiveJob/Exceptions.html new file mode 100644 index 0000000000..dddd0998c7 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Exceptions.html @@ -0,0 +1,146 @@ +--- +title: ActiveJob::Exceptions +layout: default +--- +
+ +
+
+ +
+ +

Provides behavior for retrying and discarding jobs on exceptions.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + retry_job(options = {}) + +

+ + +
+

Reschedules the job to be re-executed. This is useful in combination with rescue_from. When you rescue an exception from your job you can ask Active Job to retry performing your job.

+ +

Options

+
  • +

    :wait - Enqueues the job with the specified delay in seconds

    +
  • +

    :wait_until - Enqueues the job at the time specified

    +
  • +

    :queue - Enqueues the job on the specified queue

    +
  • +

    :priority - Enqueues the job with the specified priority

    +
+ +

Examples

+ +
class SiteScraperJob < ActiveJob::Base
+  rescue_from(ErrorLoadingSite) do
+    retry_job queue: :low_priority
+  end
+
+  def perform(*args)
+    # raise ErrorLoadingSite if cannot scrape
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/exceptions.rb, line 125
+def retry_job(options = {})
+  instrument :enqueue_retry, options.slice(:error, :wait) do
+    enqueue options
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Exceptions/ClassMethods.html b/src/7.0/classes/ActiveJob/Exceptions/ClassMethods.html new file mode 100644 index 0000000000..cc66c6cbe1 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Exceptions/ClassMethods.html @@ -0,0 +1,216 @@ +--- +title: ActiveJob::Exceptions::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + discard_on(*exceptions) + +

+ + +
+

Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job, like an Active Record, is no longer available, and the job is thus no longer relevant.

+ +

You can also pass a block that’ll be invoked. This block is yielded with the job instance as the first and the error instance as the second parameter.

+ +

Example

+ +
class SearchIndexingJob < ActiveJob::Base
+  discard_on ActiveJob::DeserializationError
+  discard_on(CustomAppException) do |job, error|
+    ExceptionNotifier.caught(error)
+  end
+
+  def perform(record)
+    # Will raise ActiveJob::DeserializationError if the record can't be deserialized
+    # Might raise CustomAppException for something domain specific
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/exceptions.rb, line 94
+def discard_on(*exceptions)
+  rescue_from(*exceptions) do |error|
+    instrument :discard, error: error do
+      yield self, error if block_given?
+    end
+  end
+end
+
+
+ +
+ +
+

+ + retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT) + +

+ + +
+

Catch the exception and reschedule job for re-execution after so many seconds, for a specific number of attempts. If the exception keeps getting raised beyond the specified number of attempts, the exception is allowed to bubble up to the underlying queuing system, which may have its own retry mechanism or place it in a holding queue for inspection.

+ +

You can also pass a block that’ll be invoked if the retry attempts fail for custom logic rather than letting the exception bubble up. This block is yielded with the job instance as the first and the error instance as the second parameter.

+ +

Options

+
  • +

    :wait - Re-enqueues the job with a delay specified either in seconds (default: 3 seconds), as a computing proc that takes the number of executions so far as an argument, or as a symbol reference of :exponentially_longer, which applies the wait algorithm of ((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2 (first wait ~3s, then ~18s, then ~83s, etc)

    +
  • +

    :attempts - Re-enqueues the job the specified number of times (default: 5 attempts) or a symbol reference of :unlimited to retry the job until it succeeds

    +
  • +

    :queue - Re-enqueues the job on a different queue

    +
  • +

    :priority - Re-enqueues the job with a different priority

    +
  • +

    :jitter - A random delay of wait time used when calculating backoff. The default is 15% (0.15) which represents the upper bound of possible wait time (expressed as a percentage)

    +
+ +

Examples

+ +
class RemoteServiceJob < ActiveJob::Base
+  retry_on CustomAppException # defaults to ~3s wait, 5 attempts
+  retry_on AnotherCustomAppException, wait: ->(executions) { executions * 2 }
+  retry_on CustomInfrastructureException, wait: 5.minutes, attempts: :unlimited
+
+  retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3
+  retry_on Net::OpenTimeout, Timeout::Error, wait: :exponentially_longer, attempts: 10 # retries at most 10 times for Net::OpenTimeout and Timeout::Error combined
+  # To retry at most 10 times for each individual exception:
+  # retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10
+  # retry_on Net::ReadTimeout, wait: 5.seconds, jitter: 0.30, attempts: 10
+  # retry_on Timeout::Error, wait: :exponentially_longer, attempts: 10
+
+  retry_on(YetAnotherCustomAppException) do |job, error|
+    ExceptionNotifier.caught(error)
+  end
+
+  def perform(*args)
+    # Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific
+    # Might raise ActiveRecord::Deadlocked when a local db deadlock is detected
+    # Might raise Net::OpenTimeout or Timeout::Error when the remote service is down
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/exceptions.rb, line 58
+def retry_on(*exceptions, wait: 3.seconds, attempts: 5, queue: nil, priority: nil, jitter: JITTER_DEFAULT)
+  rescue_from(*exceptions) do |error|
+    executions = executions_for(exceptions)
+    if attempts == :unlimited || executions < attempts
+      retry_job wait: determine_delay(seconds_or_duration_or_algorithm: wait, executions: executions, jitter: jitter), queue: queue, priority: priority, error: error
+    else
+      if block_given?
+        instrument :retry_stopped, error: error do
+          yield self, error
+        end
+      else
+        instrument :retry_stopped, error: error
+        raise error
+      end
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Execution.html b/src/7.0/classes/ActiveJob/Execution.html new file mode 100644 index 0000000000..6d0447c467 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Execution.html @@ -0,0 +1,191 @@ +--- +title: ActiveJob::Execution +layout: default +--- +
+ +
+
+ +
+ +

Active Job Execution

+ +

Provides methods to execute jobs immediately, and wraps job execution so that exceptions configured with rescue_from are handled.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/execution.rb, line 57
+def perform(*)
+  fail NotImplementedError
+end
+
+
+ +
+ +
+

+ + perform_now() + +

+ + +
+

Performs the job immediately. The job is not sent to the queuing adapter but directly executed by blocking the execution of others until it’s finished. perform_now returns the value of your job’s perform method.

+ +
class MyJob < ActiveJob::Base
+  def perform
+    "Hello World!"
+  end
+end
+
+puts MyJob.new(*args).perform_now # => "Hello World!"
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/execution.rb, line 46
+def perform_now
+  # Guard against jobs that were persisted before we started counting executions by zeroing out nil counters
+  self.executions = (executions || 0) + 1
+
+  deserialize_arguments_if_needed
+
+  _perform_job
+rescue Exception => exception
+  rescue_with_handler(exception) || raise
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Execution/ClassMethods.html b/src/7.0/classes/ActiveJob/Execution/ClassMethods.html new file mode 100644 index 0000000000..cf39253aa4 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Execution/ClassMethods.html @@ -0,0 +1,110 @@ +--- +title: ActiveJob::Execution::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Includes methods for executing and performing jobs instantly.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform_now(...) + +

+ + +
+

Performs the job immediately.

+ +
MyJob.perform_now("mike")
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/execution.rb, line 23
+def perform_now(...)
+  job_or_instantiate(...).perform_now
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapter.html new file mode 100644 index 0000000000..169c27e791 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapter.html @@ -0,0 +1,67 @@ +--- +title: ActiveJob::QueueAdapter +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapter/ClassMethods.html b/src/7.0/classes/ActiveJob/QueueAdapter/ClassMethods.html new file mode 100644 index 0000000000..1a11da8353 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapter/ClassMethods.html @@ -0,0 +1,214 @@ +--- +title: ActiveJob::QueueAdapter::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Includes the setter method for changing the active queue adapter.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
QUEUE_ADAPTER_METHODS=[:enqueue, :enqueue_at].freeze
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + queue_adapter() + +

+ + +
+

Returns the backend queue provider. The default queue adapter is the :async queue. See QueueAdapters for more information.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapter.rb, line 24
+def queue_adapter
+  _queue_adapter
+end
+
+
+ +
+ +
+

+ + queue_adapter=(name_or_adapter) + +

+ + +
+

Specify the backend queue provider. The default queue adapter is the :async queue. See QueueAdapters for more information.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapter.rb, line 37
+def queue_adapter=(name_or_adapter)
+  case name_or_adapter
+  when Symbol, String
+    queue_adapter = ActiveJob::QueueAdapters.lookup(name_or_adapter).new
+    assign_adapter(name_or_adapter.to_s, queue_adapter)
+  else
+    if queue_adapter?(name_or_adapter)
+      adapter_name = "#{name_or_adapter.class.name.demodulize.remove('Adapter').underscore}"
+      assign_adapter(adapter_name, name_or_adapter)
+    else
+      raise ArgumentError
+    end
+  end
+end
+
+
+ +
+ +
+

+ + queue_adapter_name() + +

+ + +
+

Returns string denoting the name of the configured queue adapter. By default returns "async".

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapter.rb, line 30
+def queue_adapter_name
+  _queue_adapter_name
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters.html b/src/7.0/classes/ActiveJob/QueueAdapters.html new file mode 100644 index 0000000000..2b41dc095c --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters.html @@ -0,0 +1,275 @@ +--- +title: ActiveJob::QueueAdapters +layout: default +--- +
+ +
+
+ +
+ +

Active Job adapters

+ +

Active Job has adapters for the following queuing backends:

+ + +

Backends Features

+ +
|                   | Async | Queues | Delayed    | Priorities | Timeout | Retries |
+|-------------------|-------|--------|------------|------------|---------|---------|
+| Backburner        | Yes   | Yes    | Yes        | Yes        | Job     | Global  |
+| Delayed Job       | Yes   | Yes    | Yes        | Job        | Global  | Global  |
+| Que               | Yes   | Yes    | Yes        | Job        | No      | Job     |
+| queue_classic     | Yes   | Yes    | Yes*       | No         | No      | No      |
+| Resque            | Yes   | Yes    | Yes (Gem)  | Queue      | Global  | Yes     |
+| Sidekiq           | Yes   | Yes    | Yes        | Queue      | No      | Job     |
+| Sneakers          | Yes   | Yes    | No         | Queue      | Queue   | No      |
+| Sucker Punch      | Yes   | Yes    | Yes        | No         | No      | No      |
+| Active Job Async  | Yes   | Yes    | Yes        | No         | No      | No      |
+| Active Job Inline | No    | Yes    | N/A        | N/A        | N/A     | N/A     |
+
+ +

Async

+ +

Yes: The Queue Adapter has the ability to run the job in a non-blocking manner. It either runs on a separate or forked process, or on a different thread.

+ +

No: The job is run in the same process.

+ +

Queues

+ +

Yes: Jobs may set which queue they are run in with queue_as or by using the set method.

+ +

Delayed

+ +

Yes: The adapter will run the job in the future through perform_later.

+ +

(Gem): An additional gem is required to use perform_later with this adapter.

+ +

No: The adapter will run jobs at the next opportunity and cannot use perform_later.

+ +

N/A: The adapter does not support queuing.

+ +

NOTE: queue_classic supports job scheduling since version 3.1. For older versions you can use the queue_classic-later gem.

+ +

Priorities

+ +

The order in which jobs are processed can be configured differently depending on the adapter.

+ +

Job: Any class inheriting from the adapter may set the priority on the job object relative to other jobs.

+ +

Queue: The adapter can set the priority for job queues, when setting a queue with Active Job this will be respected.

+ +

Yes: Allows the priority to be set on the job object, at the queue level or as default configuration option.

+ +

No: The adapter does not allow the priority of jobs to be configured.

+ +

N/A: The adapter does not support queuing, and therefore sorting them.

+ +

Timeout

+ +

When a job will stop after the allotted time.

+ +

Job: The timeout can be set for each instance of the job class.

+ +

Queue: The timeout is set for all jobs on the queue.

+ +

Global: The adapter is configured that all jobs have a maximum run time.

+ +

No: The adapter does not allow the timeout of jobs to be configured.

+ +

N/A: This adapter does not run in a separate process, and therefore timeout is unsupported.

+ +

Retries

+ +

Job: The number of retries can be set per instance of the job class.

+ +

Yes: The Number of retries can be configured globally, for each instance or on the queue. This adapter may also present failed instances of the job class that can be restarted.

+ +

Global: The adapter has a global number of retries.

+ +

No: The adapter does not allow the number of retries to be configured.

+ +

N/A: The adapter does not run in a separate process, and therefore doesn’t support retries.

+ +

Async and Inline Queue Adapters

+ +

Active Job has two built-in queue adapters intended for development and testing: :async and :inline.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + lookup(name) + +

+ + +
+

Returns adapter for specified name.

+ +
ActiveJob::QueueAdapters.lookup(:sidekiq)
+# => ActiveJob::QueueAdapters::SidekiqAdapter
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters.rb, line 136
+def lookup(name)
+  const_get(name.to_s.camelize << ADAPTER)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/AsyncAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/AsyncAdapter.html new file mode 100644 index 0000000000..12ebd3ebf7 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/AsyncAdapter.html @@ -0,0 +1,132 @@ +--- +title: ActiveJob::QueueAdapters::AsyncAdapter +layout: default +--- +
+ +
+
+ +
+ +

Active Job Async adapter

+ +

The Async adapter runs jobs with an in-process thread pool.

+ +

This is the default queue adapter. It’s well-suited for dev/test since it doesn’t need an external infrastructure, but it’s a poor fit for production since it drops pending jobs on restart.

+ +

To use this adapter, set queue adapter to :async:

+ +
config.active_job.queue_adapter = :async
+
+ +

To configure the adapter’s thread pool, instantiate the adapter and pass your own config:

+ +
config.active_job.queue_adapter = ActiveJob::QueueAdapters::AsyncAdapter.new \
+  min_threads: 1,
+  max_threads: 2 * Concurrent.processor_count,
+  idletime: 600.seconds
+
+ +

The adapter uses a Concurrent Ruby thread pool to schedule and execute jobs. Since jobs share a single thread pool, long-running jobs will block short-lived jobs. Fine for dev/test; bad for production.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(**executor_options) + +

+ + +
+

See Concurrent::ThreadPoolExecutor for executor options.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters/async_adapter.rb, line 35
+def initialize(**executor_options)
+  @scheduler = Scheduler.new(**executor_options)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/BackburnerAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/BackburnerAdapter.html new file mode 100644 index 0000000000..56b244eed2 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/BackburnerAdapter.html @@ -0,0 +1,73 @@ +--- +title: ActiveJob::QueueAdapters::BackburnerAdapter +layout: default +--- +
+ +
+
+ +
+ +

Backburner adapter for Active Job

+ +

Backburner is a beanstalkd-powered job queue that can handle a very high volume of jobs. You create background jobs and place them on multiple work queues to be processed later. Read more about Backburner here.

+ +

To use Backburner set the queue_adapter config to :backburner.

+ +
Rails.application.config.active_job.queue_adapter = :backburner
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/DelayedJobAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/DelayedJobAdapter.html new file mode 100644 index 0000000000..85aa4b2348 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/DelayedJobAdapter.html @@ -0,0 +1,73 @@ +--- +title: ActiveJob::QueueAdapters::DelayedJobAdapter +layout: default +--- +
+ +
+
+ +
+ +

Delayed Job adapter for Active Job

+ +

Delayed::Job (or DJ) encapsulates the common pattern of asynchronously executing longer tasks in the background. Although DJ can have many storage backends, one of the most used is based on Active Record. Read more about Delayed Job here.

+ +

To use Delayed Job, set the queue_adapter config to :delayed_job.

+ +
Rails.application.config.active_job.queue_adapter = :delayed_job
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/InlineAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/InlineAdapter.html new file mode 100644 index 0000000000..6110aac45f --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/InlineAdapter.html @@ -0,0 +1,73 @@ +--- +title: ActiveJob::QueueAdapters::InlineAdapter +layout: default +--- +
+ +
+
+ +
+ +

Active Job Inline adapter

+ +

When enqueuing jobs with the Inline adapter the job will be executed immediately.

+ +

To use the Inline set the queue_adapter config to :inline.

+ +
Rails.application.config.active_job.queue_adapter = :inline
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/QueAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/QueAdapter.html new file mode 100644 index 0000000000..4d50782cd9 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/QueAdapter.html @@ -0,0 +1,75 @@ +--- +title: ActiveJob::QueueAdapters::QueAdapter +layout: default +--- +
+ +
+
+ +
+ +

Que adapter for Active Job

+ +

Que is a high-performance alternative to DelayedJob or QueueClassic that improves the reliability of your application by protecting your jobs with the same ACID guarantees as the rest of your data. Que is a queue for Ruby and PostgreSQL that manages jobs using advisory locks.

+ +

Read more about Que here.

+ +

To use Que set the queue_adapter config to :que.

+ +
Rails.application.config.active_job.queue_adapter = :que
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/QueueClassicAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/QueueClassicAdapter.html new file mode 100644 index 0000000000..b03d2f689c --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/QueueClassicAdapter.html @@ -0,0 +1,124 @@ +--- +title: ActiveJob::QueueAdapters::QueueClassicAdapter +layout: default +--- +
+ +
+
+ +
+ +

queue_classic adapter for Active Job

+ +

queue_classic provides a simple interface to a PostgreSQL-backed message queue. queue_classic specializes in concurrent locking and minimizing database load while providing a simple, intuitive developer experience. queue_classic assumes that you are already using PostgreSQL in your production environment and that adding another dependency (e.g. redis, beanstalkd, 0mq) is undesirable.

+ +

Read more about queue_classic here.

+ +

To use queue_classic set the queue_adapter config to :queue_classic.

+ +
Rails.application.config.active_job.queue_adapter = :queue_classic
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + build_queue(queue_name) + +

+ + +
+

Builds a QC::Queue object to schedule jobs on.

+ +

If you have a custom QC::Queue subclass you’ll need to subclass ActiveJob::QueueAdapters::QueueClassicAdapter and override the build_queue method.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb, line 45
+def build_queue(queue_name)
+  QC::Queue.new(queue_name)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/ResqueAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/ResqueAdapter.html new file mode 100644 index 0000000000..c7d59afeef --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/ResqueAdapter.html @@ -0,0 +1,75 @@ +--- +title: ActiveJob::QueueAdapters::ResqueAdapter +layout: default +--- +
+ +
+
+ +
+ +

Resque adapter for Active Job

+ +

Resque (pronounced like “rescue”) is a Redis-backed library for creating background jobs, placing those jobs on multiple queues, and processing them later.

+ +

Read more about Resque here.

+ +

To use Resque set the queue_adapter config to :resque.

+ +
Rails.application.config.active_job.queue_adapter = :resque
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/SidekiqAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/SidekiqAdapter.html new file mode 100644 index 0000000000..fb0d30ba1f --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/SidekiqAdapter.html @@ -0,0 +1,75 @@ +--- +title: ActiveJob::QueueAdapters::SidekiqAdapter +layout: default +--- +
+ +
+
+ +
+ +

Sidekiq adapter for Active Job

+ +

Simple, efficient background processing for Ruby. Sidekiq uses threads to handle many jobs at the same time in the same process. It does not require Rails but will integrate tightly with it to make background processing dead simple.

+ +

Read more about Sidekiq here.

+ +

To use Sidekiq set the queue_adapter config to :sidekiq.

+ +
Rails.application.config.active_job.queue_adapter = :sidekiq
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/SneakersAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/SneakersAdapter.html new file mode 100644 index 0000000000..772b9c1be1 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/SneakersAdapter.html @@ -0,0 +1,122 @@ +--- +title: ActiveJob::QueueAdapters::SneakersAdapter +layout: default +--- +
+ +
+
+ +
+ +

Sneakers adapter for Active Job

+ +

A high-performance RabbitMQ background processing framework for Ruby. Sneakers is being used in production for both I/O and CPU intensive workloads, and have achieved the goals of high-performance and 0-maintenance, as designed.

+ +

Read more about Sneakers here.

+ +

To use Sneakers set the queue_adapter config to :sneakers.

+ +
Rails.application.config.active_job.queue_adapter = :sneakers
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters/sneakers_adapter.rb, line 21
+def initialize
+  @monitor = Monitor.new
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/SuckerPunchAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/SuckerPunchAdapter.html new file mode 100644 index 0000000000..d6467695c9 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/SuckerPunchAdapter.html @@ -0,0 +1,75 @@ +--- +title: ActiveJob::QueueAdapters::SuckerPunchAdapter +layout: default +--- +
+ +
+
+ +
+ +

Sucker Punch adapter for Active Job

+ +

Sucker Punch is a single-process Ruby asynchronous processing library. This reduces the cost of hosting on a service like Heroku along with the memory footprint of having to maintain additional jobs if hosting on a dedicated server. All queues can run within a single application (e.g. Rails, Sinatra, etc.) process.

+ +

Read more about Sucker Punch here.

+ +

To use Sucker Punch set the queue_adapter config to :sucker_punch.

+ +
Rails.application.config.active_job.queue_adapter = :sucker_punch
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueAdapters/TestAdapter.html b/src/7.0/classes/ActiveJob/QueueAdapters/TestAdapter.html new file mode 100644 index 0000000000..7b87c7f05c --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueAdapters/TestAdapter.html @@ -0,0 +1,229 @@ +--- +title: ActiveJob::QueueAdapters::TestAdapter +layout: default +--- +
+ +
+
+ +
+ +

Test adapter for Active Job

+ +

The test adapter should be used only in testing. Along with ActiveJob::TestCase and ActiveJob::TestHelper it makes a great tool to test your Rails application.

+ +

To use the test adapter set queue_adapter config to :test.

+ +
Rails.application.config.active_job.queue_adapter = :test
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + at
+ [W] + enqueued_jobs
+ [RW] + filter
+ [RW] + perform_enqueued_at_jobs
+ [RW] + perform_enqueued_jobs
+ [W] + performed_jobs
+ [RW] + queue
+ [RW] + reject
+ + + + + +

Instance Public methods

+ +
+

+ + enqueued_jobs() + +

+ + +
+

Provides a store of all the enqueued jobs with the TestAdapter so you can check them.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters/test_adapter.rb, line 19
+def enqueued_jobs
+  @enqueued_jobs ||= []
+end
+
+
+ +
+ +
+

+ + performed_jobs() + +

+ + +
+

Provides a store of all the performed jobs with the TestAdapter so you can check them.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_adapters/test_adapter.rb, line 24
+def performed_jobs
+  @performed_jobs ||= []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueName.html b/src/7.0/classes/ActiveJob/QueueName.html new file mode 100644 index 0000000000..18baf7a151 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueName.html @@ -0,0 +1,117 @@ +--- +title: ActiveJob::QueueName +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + queue_name() + +

+ + +
+

Returns the name of the queue the job will be run on.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_name.rb, line 61
+def queue_name
+  if @queue_name.is_a?(Proc)
+    @queue_name = self.class.queue_name_from_part(instance_exec(&@queue_name))
+  end
+  @queue_name
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueueName/ClassMethods.html b/src/7.0/classes/ActiveJob/QueueName/ClassMethods.html new file mode 100644 index 0000000000..68f212903c --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueueName/ClassMethods.html @@ -0,0 +1,139 @@ +--- +title: ActiveJob::QueueName::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Includes the ability to override the default queue name and prefix.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + queue_as(part_name = nil, &block) + +

+ + +
+

Specifies the name of the queue to process the job on.

+ +
class PublishToFeedJob < ActiveJob::Base
+  queue_as :feeds
+
+  def perform(post)
+    post.to_feed!
+  end
+end
+
+ +

Can be given a block that will evaluate in the context of the job so that a dynamic queue name can be applied:

+ +
class PublishToFeedJob < ApplicationJob
+  queue_as do
+    post = self.arguments.first
+
+    if post.paid?
+      :paid_feeds
+    else
+      :feeds
+    end
+  end
+
+  def perform(post)
+    post.to_feed!
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_name.rb, line 39
+def queue_as(part_name = nil, &block)
+  if block_given?
+    self.queue_name = block
+  else
+    self.queue_name = queue_name_from_part(part_name)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueuePriority.html b/src/7.0/classes/ActiveJob/QueuePriority.html new file mode 100644 index 0000000000..36e24abdd0 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueuePriority.html @@ -0,0 +1,117 @@ +--- +title: ActiveJob::QueuePriority +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + priority() + +

+ + +
+

Returns the priority that the job will be created with

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_priority.rb, line 36
+def priority
+  if @priority.is_a?(Proc)
+    @priority = instance_exec(&@priority)
+  end
+  @priority
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/QueuePriority/ClassMethods.html b/src/7.0/classes/ActiveJob/QueuePriority/ClassMethods.html new file mode 100644 index 0000000000..a9aca7d403 --- /dev/null +++ b/src/7.0/classes/ActiveJob/QueuePriority/ClassMethods.html @@ -0,0 +1,122 @@ +--- +title: ActiveJob::QueuePriority::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Includes the ability to override the default queue priority.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + queue_with_priority(priority = nil, &block) + +

+ + +
+

Specifies the priority of the queue to create the job with.

+ +
class PublishToFeedJob < ActiveJob::Base
+  queue_with_priority 50
+
+  def perform(post)
+    post.to_feed!
+  end
+end
+
+ +

Specify either an argument or a block.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/queue_priority.rb, line 22
+def queue_with_priority(priority = nil, &block)
+  if block_given?
+    self.priority = block
+  else
+    self.priority = priority
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/SerializationError.html b/src/7.0/classes/ActiveJob/SerializationError.html new file mode 100644 index 0000000000..f55ad08362 --- /dev/null +++ b/src/7.0/classes/ActiveJob/SerializationError.html @@ -0,0 +1,66 @@ +--- +title: ActiveJob::SerializationError +layout: default +--- +
+ +
+
+ +
+ +

Raised when an unsupported argument type is set as a job argument. We currently support String, Integer, Float, NilClass, TrueClass, FalseClass, BigDecimal, Symbol, Date, Time, DateTime, ActiveSupport::TimeWithZone, ActiveSupport::Duration, Hash, ActiveSupport::HashWithIndifferentAccess, Array, Range, or GlobalID::Identification instances, although this can be extended by adding custom serializers. Raised if you set the key for a Hash something else than a string or a symbol. Also raised when trying to serialize an object which can’t be identified with a GlobalID - such as an unpersisted Active Record model.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Serializers.html b/src/7.0/classes/ActiveJob/Serializers.html new file mode 100644 index 0000000000..7f60a7e363 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Serializers.html @@ -0,0 +1,89 @@ +--- +title: ActiveJob::Serializers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Serializers/ObjectSerializer.html b/src/7.0/classes/ActiveJob/Serializers/ObjectSerializer.html new file mode 100644 index 0000000000..39c2d6c5e9 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Serializers/ObjectSerializer.html @@ -0,0 +1,266 @@ +--- +title: ActiveJob::Serializers::ObjectSerializer +layout: default +--- +
+ +
+
+ +
+ +

Base class for serializing and deserializing custom objects.

+ +

Example:

+ +
class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
+  def serialize(money)
+    super("amount" => money.amount, "currency" => money.currency)
+  end
+
+  def deserialize(hash)
+    Money.new(hash["amount"], hash["currency"])
+  end
+
+  private
+
+    def klass
+      Money
+    end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deserialize(json) + +

+ + +
+

Deserializes an argument from a JSON primitive type.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/object_serializer.rb, line 42
+def deserialize(json)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + serialize(hash) + +

+ + +
+

Serializes an argument to a JSON primitive type.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/object_serializer.rb, line 37
+def serialize(hash)
+  { Arguments::OBJECT_SERIALIZER_KEY => self.class.name }.merge!(hash)
+end
+
+
+ +
+ +
+

+ + serialize?(argument) + +

+ + +
+

Determines if an argument should be serialized by a serializer.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/object_serializer.rb, line 32
+def serialize?(argument)
+  argument.is_a?(klass)
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + klass() + +

+ + +
+

The class of the object that will be serialized.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/object_serializer.rb, line 48
+def klass # :doc:
+  raise NotImplementedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/Serializers/RangeSerializer.html b/src/7.0/classes/ActiveJob/Serializers/RangeSerializer.html new file mode 100644 index 0000000000..5eeb5e70a7 --- /dev/null +++ b/src/7.0/classes/ActiveJob/Serializers/RangeSerializer.html @@ -0,0 +1,165 @@ +--- +title: ActiveJob::Serializers::RangeSerializer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
KEYS=%w[begin end exclude_end].freeze
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + deserialize(hash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/range_serializer.rb, line 13
+def deserialize(hash)
+  klass.new(*Arguments.deserialize(hash.values_at(*KEYS)))
+end
+
+
+ +
+ +
+

+ + serialize(range) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/serializers/range_serializer.rb, line 8
+def serialize(range)
+  args = Arguments.serialize([range.begin, range.end, range.exclude_end?])
+  super(KEYS.zip(args).to_h)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/TestCase.html b/src/7.0/classes/ActiveJob/TestCase.html new file mode 100644 index 0000000000..0b9be6d87f --- /dev/null +++ b/src/7.0/classes/ActiveJob/TestCase.html @@ -0,0 +1,74 @@ +--- +title: ActiveJob::TestCase +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/TestHelper.html b/src/7.0/classes/ActiveJob/TestHelper.html new file mode 100644 index 0000000000..9999d5fd51 --- /dev/null +++ b/src/7.0/classes/ActiveJob/TestHelper.html @@ -0,0 +1,990 @@ +--- +title: ActiveJob::TestHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides helper methods for testing Active Job

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block) + +

+ + +
+

Asserts that the number of enqueued jobs matches the given number.

+ +
def test_jobs
+  assert_enqueued_jobs 0
+  HelloJob.perform_later('david')
+  assert_enqueued_jobs 1
+  HelloJob.perform_later('abdelkader')
+  assert_enqueued_jobs 2
+end
+
+ +

If a block is passed, asserts that the block will cause the specified number of jobs to be enqueued.

+ +
def test_jobs_again
+  assert_enqueued_jobs 1 do
+    HelloJob.perform_later('cristian')
+  end
+
+  assert_enqueued_jobs 2 do
+    HelloJob.perform_later('aaron')
+    HelloJob.perform_later('rafael')
+  end
+end
+
+ +

Asserts the number of times a specific job was enqueued by passing :only option.

+ +
def test_logging_job
+  assert_enqueued_jobs 1, only: LoggingJob do
+    LoggingJob.perform_later
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

Asserts the number of times a job except specific class was enqueued by passing :except option.

+ +
def test_logging_job
+  assert_enqueued_jobs 1, except: HelloJob do
+    LoggingJob.perform_later
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

:only and :except options accept Class, Array of Class, or Proc. When passed a Proc, a hash containing the job’s class and it’s argument are passed as argument.

+ +

Asserts the number of times a job is enqueued to a specific queue by passing :queue option.

+ +
def test_logging_job
+  assert_enqueued_jobs 2, queue: 'default' do
+    LoggingJob.perform_later
+    HelloJob.perform_later('elfassy')
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 123
+def assert_enqueued_jobs(number, only: nil, except: nil, queue: nil, &block)
+  if block_given?
+    original_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
+
+    _assert_nothing_raised_or_warn("assert_enqueued_jobs", &block)
+
+    new_jobs = enqueued_jobs_with(only: only, except: except, queue: queue)
+
+    actual_count = (new_jobs - original_jobs).count
+  else
+    actual_count = enqueued_jobs_with(only: only, except: except, queue: queue).count
+  end
+
+  assert_equal number, actual_count, "#{number} jobs expected, but #{actual_count} were enqueued"
+end
+
+
+ +
+ +
+

+ + assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) + +

+ + +
+

Asserts that the job has been enqueued with the given arguments.

+ +
def test_assert_enqueued_with
+  MyJob.perform_later(1,2,3)
+  assert_enqueued_with(job: MyJob, args: [1,2,3])
+
+  MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
+  assert_enqueued_with(at: Date.tomorrow.noon, queue: "my_queue")
+end
+
+ +

The given arguments may also be specified as matcher procs that return a boolean value indicating whether a job’s attribute meets certain criteria.

+ +

For example, a proc can be used to match a range of times:

+ +
def test_assert_enqueued_with
+  at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
+
+  MyJob.set(wait_until: Date.today.noon).perform_later
+
+  assert_enqueued_with(job: MyJob, at: at_matcher)
+end
+
+ +

A proc can also be used to match a subset of a job’s args:

+ +
def test_assert_enqueued_with
+  args_matcher = ->(job_args) { job_args[0].key?(:foo) }
+
+  MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
+
+  assert_enqueued_with(job: MyJob, args: args_matcher)
+end
+
+ +

If a block is passed, asserts that the block will cause the job to be enqueued with the given arguments.

+ +
def test_assert_enqueued_with
+  assert_enqueued_with(job: MyJob, args: [1,2,3]) do
+    MyJob.perform_later(1,2,3)
+  end
+
+  assert_enqueued_with(job: MyJob, at: Date.tomorrow.noon) do
+    MyJob.set(wait_until: Date.tomorrow.noon).perform_later
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 392
+def assert_enqueued_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
+  expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
+  expected_args = prepare_args_for_assertion(expected)
+  potential_matches = []
+
+  if block_given?
+    original_enqueued_jobs = enqueued_jobs.dup
+
+    _assert_nothing_raised_or_warn("assert_enqueued_with", &block)
+
+    jobs = enqueued_jobs - original_enqueued_jobs
+  else
+    jobs = enqueued_jobs
+  end
+
+  matching_job = jobs.find do |enqueued_job|
+    deserialized_job = deserialize_args_for_assertion(enqueued_job)
+    potential_matches << deserialized_job
+
+    expected_args.all? do |key, value|
+      if value.respond_to?(:call)
+        value.call(deserialized_job[key])
+      else
+        value == deserialized_job[key]
+      end
+    end
+  end
+
+  matching_class = potential_matches.select do |enqueued_job|
+    enqueued_job["job_class"] == job.to_s
+  end
+
+  message = +"No enqueued job found with #{expected}"
+  if potential_matches.empty?
+    message << "\n\nNo jobs were enqueued"
+  elsif matching_class.empty?
+    message << "\n\nNo jobs of class #{expected[:job]} were enqueued, job classes enqueued: "
+    message << potential_matches.map { |job| job["job_class"] }.join(", ")
+  else
+    message << "\n\nPotential matches: #{matching_class.join("\n")}"
+  end
+
+  assert matching_job, message
+  instantiate_job(matching_job)
+end
+
+
+ +
+ +
+

+ + assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block) + +

+ + +
+

Asserts that no jobs have been enqueued.

+ +
def test_jobs
+  assert_no_enqueued_jobs
+  HelloJob.perform_later('jeremy')
+  assert_enqueued_jobs 1
+end
+
+ +

If a block is passed, asserts that the block will not cause any job to be enqueued.

+ +
def test_jobs_again
+  assert_no_enqueued_jobs do
+    # No job should be enqueued from this block
+  end
+end
+
+ +

Asserts that no jobs of a specific kind are enqueued by passing :only option.

+ +
def test_no_logging
+  assert_no_enqueued_jobs only: LoggingJob do
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

Asserts that no jobs except specific class are enqueued by passing :except option.

+ +
def test_no_logging
+  assert_no_enqueued_jobs except: HelloJob do
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

:only and :except options accept Class, Array of Class, or Proc. When passed a Proc, a hash containing the job’s class and it’s argument are passed as argument.

+ +

Asserts that no jobs are enqueued to a specific queue by passing :queue option

+ +
def test_no_logging
+  assert_no_enqueued_jobs queue: 'default' do
+    LoggingJob.set(queue: :some_queue).perform_later
+  end
+end
+
+ +

Note: This assertion is simply a shortcut for:

+ +
assert_enqueued_jobs 0, &block
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 185
+def assert_no_enqueued_jobs(only: nil, except: nil, queue: nil, &block)
+  assert_enqueued_jobs 0, only: only, except: except, queue: queue, &block
+end
+
+
+ +
+ +
+

+ + assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block) + +

+ + +
+

Asserts that no jobs have been performed.

+ +
def test_jobs
+  assert_no_performed_jobs
+
+  perform_enqueued_jobs do
+    HelloJob.perform_later('matthew')
+    assert_performed_jobs 1
+  end
+end
+
+ +

If a block is passed, asserts that the block will not cause any job to be performed.

+ +
def test_jobs_again
+  assert_no_performed_jobs do
+    # No job should be performed from this block
+  end
+end
+
+ +

The block form supports filtering. If the :only option is specified, then only the listed job(s) will not be performed.

+ +
def test_no_logging
+  assert_no_performed_jobs only: LoggingJob do
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

Also if the :except option is specified, then the job(s) except specific class will not be performed.

+ +
def test_no_logging
+  assert_no_performed_jobs except: HelloJob do
+    HelloJob.perform_later('jeremy')
+  end
+end
+
+ +

:only and :except options accept Class, Array of Class, or Proc. When passed a Proc, an instance of the job will be passed as argument.

+ +

If the :queue option is specified, then only the job(s) enqueued to a specific queue will not be performed.

+ +
def test_assert_no_performed_jobs_with_queue_option
+  assert_no_performed_jobs queue: :some_queue do
+    HelloJob.set(queue: :other_queue).perform_later("jeremy")
+  end
+end
+
+ +

Note: This assertion is simply a shortcut for:

+ +
assert_performed_jobs 0, &block
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 343
+def assert_no_performed_jobs(only: nil, except: nil, queue: nil, &block)
+  assert_performed_jobs 0, only: only, except: except, queue: queue, &block
+end
+
+
+ +
+ +
+

+ + assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block) + +

+ + +
+

Asserts that the number of performed jobs matches the given number. If no block is passed, perform_enqueued_jobs must be called around or after the job call.

+ +
def test_jobs
+  assert_performed_jobs 0
+
+  perform_enqueued_jobs do
+    HelloJob.perform_later('xavier')
+  end
+  assert_performed_jobs 1
+
+  HelloJob.perform_later('yves')
+
+  perform_enqueued_jobs
+
+  assert_performed_jobs 2
+end
+
+ +

If a block is passed, asserts that the block will cause the specified number of jobs to be performed.

+ +
def test_jobs_again
+  assert_performed_jobs 1 do
+    HelloJob.perform_later('robin')
+  end
+
+  assert_performed_jobs 2 do
+    HelloJob.perform_later('carlos')
+    HelloJob.perform_later('sean')
+  end
+end
+
+ +

This method also supports filtering. If the :only option is specified, then only the listed job(s) will be performed.

+ +
def test_hello_job
+  assert_performed_jobs 1, only: HelloJob do
+    HelloJob.perform_later('jeremy')
+    LoggingJob.perform_later
+  end
+end
+
+ +

Also if the :except option is specified, then the job(s) except specific class will be performed.

+ +
def test_hello_job
+  assert_performed_jobs 1, except: LoggingJob do
+    HelloJob.perform_later('jeremy')
+    LoggingJob.perform_later
+  end
+end
+
+ +

An array may also be specified, to support testing multiple jobs.

+ +
def test_hello_and_logging_jobs
+  assert_nothing_raised do
+    assert_performed_jobs 2, only: [HelloJob, LoggingJob] do
+      HelloJob.perform_later('jeremy')
+      LoggingJob.perform_later('stewie')
+      RescueJob.perform_later('david')
+    end
+  end
+end
+
+ +

A proc may also be specified. When passed a Proc, the job’s instance will be passed as argument.

+ +
def test_hello_and_logging_jobs
+  assert_nothing_raised do
+    assert_performed_jobs(1, only: ->(job) { job.is_a?(HelloJob) }) do
+      HelloJob.perform_later('jeremy')
+      LoggingJob.perform_later('stewie')
+      RescueJob.perform_later('david')
+    end
+  end
+end
+
+ +

If the :queue option is specified, then only the job(s) enqueued to a specific queue will be performed.

+ +
def test_assert_performed_jobs_with_queue_option
+  assert_performed_jobs 1, queue: :some_queue do
+    HelloJob.set(queue: :some_queue).perform_later("jeremy")
+    HelloJob.set(queue: :other_queue).perform_later("bogdan")
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 275
+def assert_performed_jobs(number, only: nil, except: nil, queue: nil, &block)
+  if block_given?
+    original_count = performed_jobs.size
+
+    perform_enqueued_jobs(only: only, except: except, queue: queue, &block)
+
+    new_count = performed_jobs.size
+
+    performed_jobs_size = new_count - original_count
+  else
+    performed_jobs_size = performed_jobs_with(only: only, except: except, queue: queue).count
+  end
+
+  assert_equal number, performed_jobs_size, "#{number} jobs expected, but #{performed_jobs_size} were performed"
+end
+
+
+ +
+ +
+

+ + assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block) + +

+ + +
+

Asserts that the job has been performed with the given arguments.

+ +
def test_assert_performed_with
+  MyJob.perform_later(1,2,3)
+
+  perform_enqueued_jobs
+
+  assert_performed_with(job: MyJob, args: [1,2,3])
+
+  MyJob.set(wait_until: Date.tomorrow.noon, queue: "my_queue").perform_later
+
+  perform_enqueued_jobs
+
+  assert_performed_with(at: Date.tomorrow.noon, queue: "my_queue")
+end
+
+ +

The given arguments may also be specified as matcher procs that return a boolean value indicating whether a job’s attribute meets certain criteria.

+ +

For example, a proc can be used to match a range of times:

+ +
def test_assert_performed_with
+  at_matcher = ->(job_at) { (Date.yesterday..Date.tomorrow).cover?(job_at) }
+
+  MyJob.set(wait_until: Date.today.noon).perform_later
+
+  perform_enqueued_jobs
+
+  assert_performed_with(job: MyJob, at: at_matcher)
+end
+
+ +

A proc can also be used to match a subset of a job’s args:

+ +
def test_assert_performed_with
+  args_matcher = ->(job_args) { job_args[0].key?(:foo) }
+
+  MyJob.perform_later(foo: "bar", other_arg: "No need to check in the test")
+
+  perform_enqueued_jobs
+
+  assert_performed_with(job: MyJob, args: args_matcher)
+end
+
+ +

If a block is passed, that block performs all of the jobs that were enqueued throughout the duration of the block and asserts that the job has been performed with the given arguments in the block.

+ +
def test_assert_performed_with
+  assert_performed_with(job: MyJob, args: [1,2,3]) do
+    MyJob.perform_later(1,2,3)
+  end
+
+  assert_performed_with(job: MyJob, at: Date.tomorrow.noon) do
+    MyJob.set(wait_until: Date.tomorrow.noon).perform_later
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 494
+def assert_performed_with(job: nil, args: nil, at: nil, queue: nil, priority: nil, &block)
+  expected = { job: job, args: args, at: at, queue: queue, priority: priority }.compact
+  expected_args = prepare_args_for_assertion(expected)
+  potential_matches = []
+
+  if block_given?
+    original_performed_jobs_count = performed_jobs.count
+
+    perform_enqueued_jobs(&block)
+
+    jobs = performed_jobs.drop(original_performed_jobs_count)
+  else
+    jobs = performed_jobs
+  end
+
+  matching_job = jobs.find do |enqueued_job|
+    deserialized_job = deserialize_args_for_assertion(enqueued_job)
+    potential_matches << deserialized_job
+
+    expected_args.all? do |key, value|
+      if value.respond_to?(:call)
+        value.call(deserialized_job[key])
+      else
+        value == deserialized_job[key]
+      end
+    end
+  end
+
+  matching_class = potential_matches.select do |enqueued_job|
+    enqueued_job["job_class"] == job.to_s
+  end
+
+  message = +"No performed job found with #{expected}"
+  if potential_matches.empty?
+    message << "\n\nNo jobs were performed"
+  elsif matching_class.empty?
+    message << "\n\nNo jobs of class #{expected[:job]} were performed, job classes performed: "
+    message << potential_matches.map { |job| job["job_class"] }.join(", ")
+  else
+    message << "\n\nPotential matches: #{matching_class.join("\n")}"
+  end
+
+  assert matching_job, message
+
+  instantiate_job(matching_job)
+end
+
+
+ +
+ +
+

+ + perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block) + +

+ + +
+

Performs all enqueued jobs. If a block is given, performs all of the jobs that were enqueued throughout the duration of the block. If a block is not given, performs all of the enqueued jobs up to this point in the test.

+ +
def test_perform_enqueued_jobs
+  perform_enqueued_jobs do
+    MyJob.perform_later(1, 2, 3)
+  end
+  assert_performed_jobs 1
+end
+
+def test_perform_enqueued_jobs_without_block
+  MyJob.perform_later(1, 2, 3)
+
+  perform_enqueued_jobs
+
+  assert_performed_jobs 1
+end
+
+ +

This method also supports filtering. If the :only option is specified, then only the listed job(s) will be performed.

+ +
def test_perform_enqueued_jobs_with_only
+  perform_enqueued_jobs(only: MyJob) do
+    MyJob.perform_later(1, 2, 3) # will be performed
+    HelloJob.perform_later(1, 2, 3) # will not be performed
+  end
+  assert_performed_jobs 1
+end
+
+ +

Also if the :except option is specified, then the job(s) except specific class will be performed.

+ +
def test_perform_enqueued_jobs_with_except
+  perform_enqueued_jobs(except: HelloJob) do
+    MyJob.perform_later(1, 2, 3) # will be performed
+    HelloJob.perform_later(1, 2, 3) # will not be performed
+  end
+  assert_performed_jobs 1
+end
+
+ +

:only and :except options accept Class, Array of Class, or Proc. When passed a Proc, an instance of the job will be passed as argument.

+ +

If the :queue option is specified, then only the job(s) enqueued to a specific queue will be performed.

+ +
def test_perform_enqueued_jobs_with_queue
+  perform_enqueued_jobs queue: :some_queue do
+    MyJob.set(queue: :some_queue).perform_later(1, 2, 3) # will be performed
+    HelloJob.set(queue: :other_queue).perform_later(1, 2, 3) # will not be performed
+  end
+  assert_performed_jobs 1
+end
+
+ +

If the :at option is specified, then only run jobs enqueued to run immediately or before the given time

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 598
+def perform_enqueued_jobs(only: nil, except: nil, queue: nil, at: nil, &block)
+  return flush_enqueued_jobs(only: only, except: except, queue: queue, at: at) unless block_given?
+
+  validate_option(only: only, except: except)
+
+  old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
+  old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
+  old_filter = queue_adapter.filter
+  old_reject = queue_adapter.reject
+  old_queue = queue_adapter.queue
+  old_at = queue_adapter.at
+
+  begin
+    queue_adapter.perform_enqueued_jobs = true
+    queue_adapter.perform_enqueued_at_jobs = true
+    queue_adapter.filter = only
+    queue_adapter.reject = except
+    queue_adapter.queue = queue
+    queue_adapter.at = at
+
+    _assert_nothing_raised_or_warn("perform_enqueued_jobs", &block)
+  ensure
+    queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
+    queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
+    queue_adapter.filter = old_filter
+    queue_adapter.reject = old_reject
+    queue_adapter.queue = old_queue
+    queue_adapter.at = old_at
+  end
+end
+
+
+ +
+ +
+

+ + queue_adapter() + +

+ + +
+

Accesses the queue_adapter set by ActiveJob::Base.

+ +
def test_assert_job_has_custom_queue_adapter_set
+  assert_instance_of CustomQueueAdapter, HelloJob.queue_adapter
+end
+
+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 634
+def queue_adapter
+  ActiveJob::Base.queue_adapter
+end
+
+
+ +
+ +
+

+ + queue_adapter_for_test() + +

+ + +
+

Specifies the queue adapter to use with all Active Job test helpers.

+ +

Returns an instance of the queue adapter and defaults to ActiveJob::QueueAdapters::TestAdapter.

+ +

Note: The adapter provided by this method must provide some additional methods from those expected of a standard ActiveJob::QueueAdapter in order to be used with the active job test helpers. Refer to ActiveJob::QueueAdapters::TestAdapter.

+
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 66
+def queue_adapter_for_test
+  ActiveJob::QueueAdapters::TestAdapter.new
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter.html b/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter.html new file mode 100644 index 0000000000..efbb9dee9d --- /dev/null +++ b/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter.html @@ -0,0 +1,67 @@ +--- +title: ActiveJob::TestHelper::TestQueueAdapter +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter/ClassMethods.html b/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter/ClassMethods.html new file mode 100644 index 0000000000..dcde0db9fa --- /dev/null +++ b/src/7.0/classes/ActiveJob/TestHelper/TestQueueAdapter/ClassMethods.html @@ -0,0 +1,179 @@ +--- +title: ActiveJob::TestHelper::TestQueueAdapter::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + disable_test_adapter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 27
+def disable_test_adapter
+  self._test_adapter = nil
+end
+
+
+ +
+ +
+

+ + enable_test_adapter(test_adapter) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 31
+def enable_test_adapter(test_adapter)
+  self._test_adapter = test_adapter
+end
+
+
+ +
+ +
+

+ + queue_adapter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activejob/lib/active_job/test_helper.rb, line 23
+def queue_adapter
+  self._test_adapter.nil? ? super : self._test_adapter
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveJob/VERSION.html b/src/7.0/classes/ActiveJob/VERSION.html new file mode 100644 index 0000000000..f9f9cfc7ab --- /dev/null +++ b/src/7.0/classes/ActiveJob/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActiveJob::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel.html b/src/7.0/classes/ActiveModel.html new file mode 100644 index 0000000000..fc450cbda9 --- /dev/null +++ b/src/7.0/classes/ActiveModel.html @@ -0,0 +1,366 @@ +--- +title: ActiveModel +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Active Model as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Active Model as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/API.html b/src/7.0/classes/ActiveModel/API.html new file mode 100644 index 0000000000..d1debf39d0 --- /dev/null +++ b/src/7.0/classes/ActiveModel/API.html @@ -0,0 +1,247 @@ +--- +title: ActiveModel::API +layout: default +--- +
+ +
+
+ +
+ +

Active Model API

+ +

Includes the required interface for an object to interact with Action Pack and Action View, using different Active Model modules. It includes model name introspections, conversions, translations, and validations. Besides that, it allows you to initialize the object with a hash of attributes, pretty much like Active Record does.

+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::API
+  attr_accessor :name, :age
+end
+
+person = Person.new(name: 'bob', age: '18')
+person.name # => "bob"
+person.age  # => "18"
+
+ +

Note that, by default, ActiveModel::API implements persisted? to return false, which is the most common case. You may want to override it in your class to simulate a different scenario:

+ +
class Person
+  include ActiveModel::API
+  attr_accessor :id, :name
+
+  def persisted?
+    self.id.present?
+  end
+end
+
+person = Person.new(id: 1, name: 'bob')
+person.persisted? # => true
+
+ +

Also, if for some reason you need to run code on initialize, make sure you call super if you want the attributes hash initialization to happen.

+ +
class Person
+  include ActiveModel::API
+  attr_accessor :id, :name, :omg
+
+  def initialize(attributes={})
+    super
+    @omg ||= true
+  end
+end
+
+person = Person.new(id: 1, name: 'bob')
+person.omg # => true
+
+ +

For more detailed information on other functionalities available, please refer to the specific modules included in ActiveModel::API (see below).

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(attributes = {}) + +

+ + +
+

Initializes a new model with the given params.

+ +
class Person
+  include ActiveModel::API
+  attr_accessor :name, :age
+end
+
+person = Person.new(name: 'bob', age: '18')
+person.name # => "bob"
+person.age  # => "18"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/api.rb, line 80
+def initialize(attributes = {})
+  assign_attributes(attributes) if attributes
+
+  super()
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + persisted?() + +

+ + +
+

Indicates if the model is persisted. Default is false.

+ +
class Person
+  include ActiveModel::API
+  attr_accessor :id, :name
+end
+
+person = Person.new(id: 1, name: 'bob')
+person.persisted? # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/api.rb, line 95
+def persisted?
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/AttributeAssignment.html b/src/7.0/classes/ActiveModel/AttributeAssignment.html new file mode 100644 index 0000000000..60c751bcbf --- /dev/null +++ b/src/7.0/classes/ActiveModel/AttributeAssignment.html @@ -0,0 +1,154 @@ +--- +title: ActiveModel::AttributeAssignment +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assign_attributes(new_attributes) + +

+ + +
+

Allows you to set all the attributes by passing in a hash of attributes with keys matching the attribute names.

+ +

If the passed hash responds to permitted? method and the return value of this method is false an ActiveModel::ForbiddenAttributesError exception is raised.

+ +
class Cat
+  include ActiveModel::AttributeAssignment
+  attr_accessor :name, :status
+end
+
+cat = Cat.new
+cat.assign_attributes(name: "Gorby", status: "yawning")
+cat.name # => 'Gorby'
+cat.status # => 'yawning'
+cat.assign_attributes(status: "sleeping")
+cat.name # => 'Gorby'
+cat.status # => 'sleeping'
+
+
+ + + +
+ Also aliased as: attributes= +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_assignment.rb, line 28
+def assign_attributes(new_attributes)
+  unless new_attributes.respond_to?(:each_pair)
+    raise ArgumentError, "When assigning attributes, you must pass a hash as an argument, #{new_attributes.class} passed."
+  end
+  return if new_attributes.empty?
+
+  _assign_attributes(sanitize_for_mass_assignment(new_attributes))
+end
+
+
+ +
+ +
+

+ + attributes=(new_attributes) + +

+ + +
+ +
+ + + + + +
+ Alias for: assign_attributes +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/AttributeMethods.html b/src/7.0/classes/ActiveModel/AttributeMethods.html new file mode 100644 index 0000000000..98b3c1bc15 --- /dev/null +++ b/src/7.0/classes/ActiveModel/AttributeMethods.html @@ -0,0 +1,339 @@ +--- +title: ActiveModel::AttributeMethods +layout: default +--- +
+ +
+
+ +
+ +

Active Model Attribute Methods

+ +

Provides a way to add prefixes and suffixes to your methods as well as handling the creation of ActiveRecord::Base-like class methods such as table_name.

+ +

The requirements to implement ActiveModel::AttributeMethods are to:

+
  • +

    include ActiveModel::AttributeMethods in your class.

    +
  • +

    Call each of its methods you want to add, such as attribute_method_suffix or attribute_method_prefix.

    +
  • +

    Call define_attribute_methods after the other methods are called.

    +
  • +

    Define the various generic _attribute methods that you have declared.

    +
  • +

    Define an attributes method which returns a hash with each attribute name in your model as hash key and the attribute value as hash value. Hash keys must be strings.

    +
+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attribute_method_affix  prefix: 'reset_', suffix: '_to_default!'
+  attribute_method_suffix '_contrived?'
+  attribute_method_prefix 'clear_'
+  define_attribute_methods :name
+
+  attr_accessor :name
+
+  def attributes
+    { 'name' => @name }
+  end
+
+  private
+    def attribute_contrived?(attr)
+      true
+    end
+
+    def clear_attribute(attr)
+      send("#{attr}=", nil)
+    end
+
+    def reset_attribute_to_default!(attr)
+      send("#{attr}=", 'Default Name')
+    end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CALL_COMPILABLE_REGEXP=/\A[a-zA-Z_]\w*[!?]?\z/
 
FORWARD_PARAMETERS="*args"
 
NAME_COMPILABLE_REGEXP=/\A[a-zA-Z_]\w*[!?=]?\z/
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + attribute_missing(match, *args, &block) + +

+ + +
+

attribute_missing is like method_missing, but for attributes. When method_missing is called we check to see if there is a matching attribute method. If so, we tell attribute_missing to dispatch the attribute. This method can be overloaded to customize the behavior.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 459
+def attribute_missing(match, *args, &block)
+  __send__(match.target, match.attr_name, *args, &block)
+end
+
+
+ +
+ +
+

+ + method_missing(method, *args, &block) + +

+ + +
+

Allows access to the object attributes, which are held in the hash returned by attributes, as though they were first-class methods. So a Person class with a name attribute can for example use Person#name and Person#name= and never directly use the attributes hash – except for multiple assignments with ActiveRecord::Base#attributes=.

+ +

It’s also possible to instantiate related objects, so a Client class belonging to the clients table with a master_id foreign key can instantiate master through Client#master.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 445
+def method_missing(method, *args, &block)
+  if respond_to_without_attributes?(method, true)
+    super
+  else
+    match = matched_attribute_method(method.to_s)
+    match ? attribute_missing(match, *args, &block) : super
+  end
+end
+
+
+ +
+ +
+

+ + respond_to?(method, include_private_methods = false) + +

+ + +
+ +
+ + + +
+ Also aliased as: respond_to_without_attributes? +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 468
+def respond_to?(method, include_private_methods = false)
+  if super
+    true
+  elsif !include_private_methods && super(method, true)
+    # If we're here then we haven't found among non-private methods
+    # but found among all methods. Which means that the given method is private.
+    false
+  else
+    !matched_attribute_method(method.to_s).nil?
+  end
+end
+
+
+ +
+ +
+

+ + respond_to_without_attributes?(method, include_private_methods = false) + +

+ + +
+

A Person instance with a name attribute can ask person.respond_to?(:name), person.respond_to?(:name=), and person.respond_to?(:name?) which will all return true.

+
+ + + + + +
+ Alias for: respond_to? +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/AttributeMethods/ClassMethods.html b/src/7.0/classes/ActiveModel/AttributeMethods/ClassMethods.html new file mode 100644 index 0000000000..6966af7092 --- /dev/null +++ b/src/7.0/classes/ActiveModel/AttributeMethods/ClassMethods.html @@ -0,0 +1,643 @@ +--- +title: ActiveModel::AttributeMethods::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + alias_attribute(new_name, old_name) + +

+ + +
+

Allows you to make aliases for attributes.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_suffix '_short?'
+  define_attribute_methods :name
+
+  alias_attribute :nickname, :name
+
+  private
+    def attribute_short?(attr)
+      send(attr).length < 5
+    end
+end
+
+person = Person.new
+person.name = 'Bob'
+person.name            # => "Bob"
+person.nickname        # => "Bob"
+person.name_short?     # => true
+person.nickname_short? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 204
+def alias_attribute(new_name, old_name)
+  self.attribute_aliases = attribute_aliases.merge(new_name.to_s => old_name.to_s)
+  ActiveSupport::CodeGenerator.batch(self, __FILE__, __LINE__) do |code_generator|
+    attribute_method_matchers.each do |matcher|
+      method_name = matcher.method_name(new_name).to_s
+      target_name = matcher.method_name(old_name).to_s
+      parameters = matcher.parameters
+
+      mangled_name = target_name
+      unless NAME_COMPILABLE_REGEXP.match?(target_name)
+        mangled_name = "__temp__#{target_name.unpack1("h*")}"
+      end
+
+      code_generator.define_cached_method(method_name, as: mangled_name, namespace: :alias_attribute) do |batch|
+        body = if CALL_COMPILABLE_REGEXP.match?(target_name)
+          "self.#{target_name}(#{parameters || ''})"
+        else
+          call_args = [":'#{target_name}'"]
+          call_args << parameters if parameters
+          "send(#{call_args.join(", ")})"
+        end
+
+        modifier = matcher.parameters == FORWARD_PARAMETERS ? "ruby2_keywords " : ""
+
+        batch <<
+          "#{modifier}def #{mangled_name}(#{parameters || ''})" <<
+          body <<
+          "end"
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + attribute_alias(name) + +

+ + +
+

Returns the original name for the alias name

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 243
+def attribute_alias(name)
+  attribute_aliases[name.to_s]
+end
+
+
+ +
+ +
+

+ + attribute_alias?(new_name) + +

+ + +
+

Is new_name an alias?

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 238
+def attribute_alias?(new_name)
+  attribute_aliases.key? new_name.to_s
+end
+
+
+ +
+ +
+

+ + attribute_method_affix(*affixes) + +

+ + +
+

Declares a method available for all attributes with the given prefix and suffix. Uses method_missing and respond_to? to rewrite the method.

+ +
#{prefix}#{attr}#{suffix}(*args, &block)
+
+ +

to

+ +
#{prefix}attribute#{suffix}(#{attr}, *args, &block)
+
+ +

An #{prefix}attribute#{suffix} instance method must exist and accept at least the attr argument.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_affix prefix: 'reset_', suffix: '_to_default!'
+  define_attribute_methods :name
+
+  private
+    def reset_attribute_to_default!(attr)
+      send("#{attr}=", 'Default Name')
+    end
+end
+
+person = Person.new
+person.name                         # => 'Gem'
+person.reset_name_to_default!
+person.name                         # => 'Default Name'
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 176
+def attribute_method_affix(*affixes)
+  self.attribute_method_matchers += affixes.map! { |affix| AttributeMethodMatcher.new(**affix) }
+  undefine_attribute_methods
+end
+
+
+ +
+ +
+

+ + attribute_method_prefix(*prefixes, parameters: nil) + +

+ + +
+

Declares a method available for all attributes with the given prefix. Uses method_missing and respond_to? to rewrite the method.

+ +
#{prefix}#{attr}(*args, &block)
+
+ +

to

+ +
#{prefix}attribute(#{attr}, *args, &block)
+
+ +

An instance method #{prefix}attribute must exist and accept at least the attr argument.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_prefix 'clear_'
+  define_attribute_methods :name
+
+  private
+    def clear_attribute(attr)
+      send("#{attr}=", nil)
+    end
+end
+
+person = Person.new
+person.name = 'Bob'
+person.name          # => "Bob"
+person.clear_name
+person.name          # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 107
+def attribute_method_prefix(*prefixes, parameters: nil)
+  self.attribute_method_matchers += prefixes.map! { |prefix| AttributeMethodMatcher.new(prefix: prefix, parameters: parameters) }
+  undefine_attribute_methods
+end
+
+
+ +
+ +
+

+ + attribute_method_suffix(*suffixes, parameters: nil) + +

+ + +
+

Declares a method available for all attributes with the given suffix. Uses method_missing and respond_to? to rewrite the method.

+ +
#{attr}#{suffix}(*args, &block)
+
+ +

to

+ +
attribute#{suffix}(#{attr}, *args, &block)
+
+ +

An attribute#{suffix} instance method must exist and accept at least the attr argument.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_suffix '_short?'
+  define_attribute_methods :name
+
+  private
+    def attribute_short?(attr)
+      send(attr).length < 5
+    end
+end
+
+person = Person.new
+person.name = 'Bob'
+person.name          # => "Bob"
+person.name_short?   # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 141
+def attribute_method_suffix(*suffixes, parameters: nil)
+  self.attribute_method_matchers += suffixes.map! { |suffix| AttributeMethodMatcher.new(suffix: suffix, parameters: parameters) }
+  undefine_attribute_methods
+end
+
+
+ +
+ +
+

+ + define_attribute_method(attr_name, _owner: generated_attribute_methods) + +

+ + +
+

Declares an attribute that should be prefixed and suffixed by ActiveModel::AttributeMethods.

+ +

To use, pass an attribute name (as string or symbol). Be sure to declare define_attribute_method after you define any prefix, suffix or affix method, or they will not hook in.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_suffix '_short?'
+
+  # Call to define_attribute_method must appear after the
+  # attribute_method_prefix, attribute_method_suffix or
+  # attribute_method_affix declarations.
+  define_attribute_method :name
+
+  private
+    def attribute_short?(attr)
+      send(attr).length < 5
+    end
+end
+
+person = Person.new
+person.name = 'Bob'
+person.name        # => "Bob"
+person.name_short? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 304
+def define_attribute_method(attr_name, _owner: generated_attribute_methods)
+  ActiveSupport::CodeGenerator.batch(_owner, __FILE__, __LINE__) do |owner|
+    attribute_method_matchers.each do |matcher|
+      method_name = matcher.method_name(attr_name)
+
+      unless instance_method_already_implemented?(method_name)
+        generate_method = "define_method_#{matcher.target}"
+
+        if respond_to?(generate_method, true)
+          send(generate_method, attr_name.to_s, owner: owner)
+        else
+          define_proxy_call(owner, method_name, matcher.target, matcher.parameters, attr_name.to_s, namespace: :active_model_proxy)
+        end
+      end
+    end
+    attribute_method_matchers_cache.clear
+  end
+end
+
+
+ +
+ +
+

+ + define_attribute_methods(*attr_names) + +

+ + +
+

Declares the attributes that should be prefixed and suffixed by ActiveModel::AttributeMethods.

+ +

To use, pass attribute names (as strings or symbols). Be sure to declare define_attribute_methods after you define any prefix, suffix, or affix methods, or they will not hook in.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name, :age, :address
+  attribute_method_prefix 'clear_'
+
+  # Call to define_attribute_methods must appear after the
+  # attribute_method_prefix, attribute_method_suffix or
+  # attribute_method_affix declarations.
+  define_attribute_methods :name, :age, :address
+
+  private
+    def clear_attribute(attr)
+      send("#{attr}=", nil)
+    end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 270
+def define_attribute_methods(*attr_names)
+  ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
+    attr_names.flatten.each { |attr_name| define_attribute_method(attr_name, _owner: owner) }
+  end
+end
+
+
+ +
+ +
+

+ + undefine_attribute_methods() + +

+ + +
+

Removes all the previously dynamically defined methods from the class.

+ +
class Person
+  include ActiveModel::AttributeMethods
+
+  attr_accessor :name
+  attribute_method_suffix '_short?'
+  define_attribute_method :name
+
+  private
+    def attribute_short?(attr)
+      send(attr).length < 5
+    end
+end
+
+person = Person.new
+person.name = 'Bob'
+person.name_short? # => true
+
+Person.undefine_attribute_methods
+
+person.name_short? # => NoMethodError
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attribute_methods.rb, line 345
+def undefine_attribute_methods
+  generated_attribute_methods.module_eval do
+    undef_method(*instance_methods)
+  end
+  attribute_method_matchers_cache.clear
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Attributes.html b/src/7.0/classes/ActiveModel/Attributes.html new file mode 100644 index 0000000000..3a0c2837e7 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Attributes.html @@ -0,0 +1,67 @@ +--- +title: ActiveModel::Attributes +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Attributes/ClassMethods.html b/src/7.0/classes/ActiveModel/Attributes/ClassMethods.html new file mode 100644 index 0000000000..79c8df75bd --- /dev/null +++ b/src/7.0/classes/ActiveModel/Attributes/ClassMethods.html @@ -0,0 +1,158 @@ +--- +title: ActiveModel::Attributes::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attributes.rb, line 19
+def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
+  name = name.to_s
+
+  cast_type = Type.lookup(cast_type, **options) if Symbol === cast_type
+  cast_type ||= attribute_types[name]
+
+  self.attribute_types = attribute_types.merge(name => cast_type)
+  define_default_attribute(name, default, cast_type)
+  define_attribute_method(name)
+end
+
+
+ +
+ +
+

+ + attribute_names() + +

+ + +
+

Returns an array of attribute names as strings

+ +
class Person
+  include ActiveModel::Attributes
+
+  attribute :name, :string
+  attribute :age, :integer
+end
+
+Person.attribute_names
+# => ["name", "age"]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/attributes.rb, line 41
+def attribute_names
+  attribute_types.keys
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Callbacks.html b/src/7.0/classes/ActiveModel/Callbacks.html new file mode 100644 index 0000000000..d68cea2992 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Callbacks.html @@ -0,0 +1,220 @@ +--- +title: ActiveModel::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Active Model Callbacks

+ +

Provides an interface for any class to have Active Record like callbacks.

+ +

Like the Active Record methods, the callback chain is aborted as soon as one of the methods throws :abort.

+ +

First, extend ActiveModel::Callbacks from the class you are creating:

+ +
class MyModel
+  extend ActiveModel::Callbacks
+end
+
+ +

Then define a list of methods that you want callbacks attached to:

+ +
define_model_callbacks :create, :update
+
+ +

This will provide all three standard callbacks (before, around and after) for both the :create and :update methods. To implement, you need to wrap the methods you want callbacks on in a block so that the callbacks get a chance to fire:

+ +
def create
+  run_callbacks :create do
+    # Your create action methods here
+  end
+end
+
+ +

Then in your class, you can use the before_create, after_create, and around_create methods, just as you would in an Active Record model.

+ +
before_create :action_before_create
+
+def action_before_create
+  # Your code here
+end
+
+ +

When defining an around callback remember to yield to the block, otherwise it won’t be executed:

+ +
around_create :log_status
+
+def log_status
+  puts 'going to call the block...'
+  yield
+  puts 'block successfully called.'
+end
+
+ +

You can choose to have only specific callbacks by passing a hash to the define_model_callbacks method.

+ +
define_model_callbacks :create, only: [:after, :before]
+
+ +

Would only create the after_create and before_create callback methods in your class.

+ +

NOTE: Calling the same callback multiple times will overwrite previous callback definitions.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + define_model_callbacks(*callbacks) + +

+ + +
+

define_model_callbacks accepts the same options define_callbacks does, in case you want to overwrite a default. Besides that, it also accepts an :only option, where you can choose if you want all types (before, around or after) or just some.

+ +
define_model_callbacks :initialize, only: :after
+
+ +

Note, the only: <type> hash will apply to all callbacks defined on that method call. To get around this you can call the define_model_callbacks method as many times as you need.

+ +
define_model_callbacks :create,  only: :after
+define_model_callbacks :update,  only: :before
+define_model_callbacks :destroy, only: :around
+
+ +

Would create after_create, before_update, and around_destroy methods only.

+ +

You can pass in a class to before_<type>, after_<type> and around_<type>, in which case the callback will call that class’s <action>_<type> method passing the object that the callback is being called on.

+ +
class MyModel
+  extend ActiveModel::Callbacks
+  define_model_callbacks :create
+
+  before_create AnotherClass
+end
+
+class AnotherClass
+  def self.before_create( obj )
+    # obj is the MyModel instance that the callback is being called on
+  end
+end
+
+ +

NOTE: method_name passed to define_model_callbacks must not end with !, ? or =.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/callbacks.rb, line 109
+def define_model_callbacks(*callbacks)
+  options = callbacks.extract_options!
+  options = {
+    skip_after_callbacks_if_terminated: true,
+    scope: [:kind, :name],
+    only: [:before, :around, :after]
+  }.merge!(options)
+
+  types = Array(options.delete(:only))
+
+  callbacks.each do |callback|
+    define_callbacks(callback, options)
+
+    types.each do |type|
+      send("_define_#{type}_model_callback", self, callback)
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Conversion.html b/src/7.0/classes/ActiveModel/Conversion.html new file mode 100644 index 0000000000..408d2bcc6d --- /dev/null +++ b/src/7.0/classes/ActiveModel/Conversion.html @@ -0,0 +1,293 @@ +--- +title: ActiveModel::Conversion +layout: default +--- +
+ +
+
+ +
+ +

Active Model Conversion

+ +

Handles default conversions: to_model, to_key, to_param, and to_partial_path.

+ +

Let’s take for example this non-persisted object.

+ +
class ContactMessage
+  include ActiveModel::Conversion
+
+  # ContactMessage are never persisted in the DB
+  def persisted?
+    false
+  end
+end
+
+cm = ContactMessage.new
+cm.to_model == cm  # => true
+cm.to_key          # => nil
+cm.to_param        # => nil
+cm.to_partial_path # => "contact_messages/contact_message"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + to_key() + +

+ + +
+

Returns an Array of all key attributes if any of the attributes is set, whether or not the object is persisted. Returns nil if there are no key attributes.

+ +
class Person
+  include ActiveModel::Conversion
+  attr_accessor :id
+
+  def initialize(id)
+    @id = id
+  end
+end
+
+person = Person.new(1)
+person.to_key # => [1]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/conversion.rb, line 59
+def to_key
+  key = respond_to?(:id) && id
+  key ? [key] : nil
+end
+
+
+ +
+ +
+

+ + to_model() + +

+ + +
+

If your object is already designed to implement all of the Active Model you can use the default :to_model implementation, which simply returns self.

+ +
class Person
+  include ActiveModel::Conversion
+end
+
+person = Person.new
+person.to_model == person # => true
+
+ +

If your model does not act like an Active Model object, then you should define :to_model yourself returning a proxy object that wraps your object with Active Model compliant methods.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/conversion.rb, line 41
+def to_model
+  self
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Returns a string representing the object’s key suitable for use in URLs, or nil if persisted? is false.

+ +
class Person
+  include ActiveModel::Conversion
+  attr_accessor :id
+
+  def initialize(id)
+    @id = id
+  end
+
+  def persisted?
+    true
+  end
+end
+
+person = Person.new(1)
+person.to_param # => "1"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/conversion.rb, line 82
+def to_param
+  (persisted? && key = to_key) ? key.join("-") : nil
+end
+
+
+ +
+ +
+

+ + to_partial_path() + +

+ + +
+

Returns a string identifying the path associated with the object. ActionPack uses this to find a suitable partial to represent the object.

+ +
class Person
+  include ActiveModel::Conversion
+end
+
+person = Person.new
+person.to_partial_path # => "people/person"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/conversion.rb, line 95
+def to_partial_path
+  self.class._to_partial_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Dirty.html b/src/7.0/classes/ActiveModel/Dirty.html new file mode 100644 index 0000000000..4b43572d3e --- /dev/null +++ b/src/7.0/classes/ActiveModel/Dirty.html @@ -0,0 +1,589 @@ +--- +title: ActiveModel::Dirty +layout: default +--- +
+ +
+
+ +
+ +

Active Model Dirty

+ +

Provides a way to track changes in your object in the same way as Active Record does.

+ +

The requirements for implementing ActiveModel::Dirty are:

+
  • +

    include ActiveModel::Dirty in your object.

    +
  • +

    Call define_attribute_methods passing each method you want to track.

    +
  • +

    Call [attr_name]_will_change! before each change to the tracked attribute.

    +
  • +

    Call changes_applied after the changes are persisted.

    +
  • +

    Call clear_changes_information when you want to reset the changes information.

    +
  • +

    Call restore_attributes when you want to restore previous data.

    +
+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::Dirty
+
+  define_attribute_methods :name
+
+  def initialize
+    @name = nil
+  end
+
+  def name
+    @name
+  end
+
+  def name=(val)
+    name_will_change! unless val == @name
+    @name = val
+  end
+
+  def save
+    # do persistence work
+
+    changes_applied
+  end
+
+  def reload!
+    # get the values from the persistence layer
+
+    clear_changes_information
+  end
+
+  def rollback!
+    restore_attributes
+  end
+end
+
+ +

A newly instantiated Person object is unchanged:

+ +
person = Person.new
+person.changed? # => false
+
+ +

Change the name:

+ +
person.name = 'Bob'
+person.changed?       # => true
+person.name_changed?  # => true
+person.name_changed?(from: nil, to: "Bob") # => true
+person.name_was       # => nil
+person.name_change    # => [nil, "Bob"]
+person.name = 'Bill'
+person.name_change    # => [nil, "Bill"]
+
+ +

Save the changes:

+ +
person.save
+person.changed?      # => false
+person.name_changed? # => false
+
+ +

Reset the changes:

+ +
person.previous_changes         # => {"name" => [nil, "Bill"]}
+person.name_previously_changed? # => true
+person.name_previously_changed?(from: nil, to: "Bill") # => true
+person.name_previous_change     # => [nil, "Bill"]
+person.name_previously_was      # => nil
+person.reload!
+person.previous_changes         # => {}
+
+ +

Rollback the changes:

+ +
person.name = "Uncle Bob"
+person.rollback!
+person.name          # => "Bill"
+person.name_changed? # => false
+
+ +

Assigning the same value leaves the attribute unchanged:

+ +
person.name = 'Bill'
+person.name_changed? # => false
+person.name_change   # => nil
+
+ +

Which attributes have changed?

+ +
person.name = 'Bob'
+person.changed # => ["name"]
+person.changes # => {"name" => ["Bill", "Bob"]}
+
+ +

If an attribute is modified in-place then make use of [attribute_name]_will_change! to mark that the attribute is changing. Otherwise Active Model can’t track changes to in-place attributes. Note that Active Record can detect in-place modifications automatically. You do not need to call [attribute_name]_will_change! on Active Record models.

+ +
person.name_will_change!
+person.name_change # => ["Bill", "Bill"]
+person.name << 'y'
+person.name_change # => ["Bill", "Billy"]
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + changed() + +

+ + +
+

Returns an array with the name of the attributes with unsaved changes.

+ +
person.changed # => []
+person.name = 'bob'
+person.changed # => ["name"]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 173
+def changed
+  mutations_from_database.changed_attribute_names
+end
+
+
+ +
+ +
+

+ + changed?() + +

+ + +
+

Returns true if any of the attributes has unsaved changes, false otherwise.

+ +
person.changed? # => false
+person.name = 'bob'
+person.changed? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 164
+def changed?
+  mutations_from_database.any_changes?
+end
+
+
+ +
+ +
+

+ + changed_attributes() + +

+ + +
+

Returns a hash of the attributes with unsaved changes indicating their original values like attr => original value.

+ +
person.name # => "bob"
+person.name = 'robert'
+person.changed_attributes # => {"name" => "bob"}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 221
+def changed_attributes
+  mutations_from_database.changed_values
+end
+
+
+ +
+ +
+

+ + changes() + +

+ + +
+

Returns a hash of changed attributes indicating their original and new values like attr => [original value, new value].

+ +
person.changes # => {}
+person.name = 'bob'
+person.changes # => { "name" => ["bill", "bob"] }
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 231
+def changes
+  mutations_from_database.changes
+end
+
+
+ +
+ +
+

+ + changes_applied() + +

+ + +
+

Clears dirty data and moves changes to previous_changes and mutations_from_database to mutations_before_last_save respectively.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 150
+def changes_applied
+  unless defined?(@attributes)
+    mutations_from_database.finalize_changes
+  end
+  @mutations_before_last_save = mutations_from_database
+  forget_attribute_assignments
+  @mutations_from_database = nil
+end
+
+
+ +
+ +
+

+ + clear_attribute_changes(attr_names) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 209
+def clear_attribute_changes(attr_names)
+  attr_names.each do |attr_name|
+    clear_attribute_change(attr_name)
+  end
+end
+
+
+ +
+ +
+

+ + clear_changes_information() + +

+ + +
+

Clears all dirty data: current changes and previous changes.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 203
+def clear_changes_information
+  @mutations_before_last_save = nil
+  forget_attribute_assignments
+  @mutations_from_database = nil
+end
+
+
+ +
+ +
+

+ + previous_changes() + +

+ + +
+

Returns a hash of attributes that were changed before the model was saved.

+ +
person.name # => "bob"
+person.name = 'robert'
+person.save
+person.previous_changes # => {"name" => ["bob", "robert"]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 241
+def previous_changes
+  mutations_before_last_save.changes
+end
+
+
+ +
+ +
+

+ + restore_attributes(attr_names = changed) + +

+ + +
+

Restore all previous data of the provided attributes.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/dirty.rb, line 198
+def restore_attributes(attr_names = changed)
+  attr_names.each { |attr_name| restore_attribute!(attr_name) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/EachValidator.html b/src/7.0/classes/ActiveModel/EachValidator.html new file mode 100644 index 0000000000..5aed2c9228 --- /dev/null +++ b/src/7.0/classes/ActiveModel/EachValidator.html @@ -0,0 +1,256 @@ +--- +title: ActiveModel::EachValidator +layout: default +--- +
+ +
+
+ +
+ +

EachValidator is a validator which iterates through the attributes given in the options hash invoking the validate_each method passing in the record, attribute, and value.

+ +

All Active Model validations are built on top of this validator.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + attributes
+ + + + +

Class Public methods

+ +
+

+ + new(options) + +

+ + +
+

Returns a new validator instance. All options will be available via the options reader, however the :attributes option will be removed and instead be made available through the attributes reader.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 138
+def initialize(options)
+  @attributes = Array(options.delete(:attributes))
+  raise ArgumentError, ":attributes cannot be blank" if @attributes.empty?
+  super
+  check_validity!
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + check_validity!() + +

+ + +
+

Hook method that gets called by the initializer allowing verification that the arguments supplied are valid. You could for example raise an ArgumentError when invalid options are supplied.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 166
+def check_validity!
+end
+
+
+ +
+ +
+

+ + validate(record) + +

+ + +
+

Performs validation on the supplied record. By default this will call validate_each to determine validity therefore subclasses should override validate_each with validation logic.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 148
+def validate(record)
+  attributes.each do |attribute|
+    value = record.read_attribute_for_validation(attribute)
+    next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank])
+    value = prepare_value_for_validation(value, record, attribute)
+    validate_each(record, attribute, value)
+  end
+end
+
+
+ +
+ +
+

+ + validate_each(record, attribute, value) + +

+ + +
+

Override this method in subclasses with the validation logic, adding errors to the records errors array where necessary.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 159
+def validate_each(record, attribute, value)
+  raise NotImplementedError, "Subclasses must implement a validate_each(record, attribute, value) method"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Error.html b/src/7.0/classes/ActiveModel/Error.html new file mode 100644 index 0000000000..284c8c1d8c --- /dev/null +++ b/src/7.0/classes/ActiveModel/Error.html @@ -0,0 +1,503 @@ +--- +title: ActiveModel::Error +layout: default +--- +
+ +
+
+ +
+ +

Active Model Error

+ +

Represents one single error

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CALLBACKS_OPTIONS=[:if, :unless, :on, :allow_nil, :allow_blank, :strict]
 
MESSAGE_OPTIONS=[:message]
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + attribute

The attribute of base which the error belongs to

+ [R] + base

The object which the error belongs to

+ [R] + options

The options provided when calling +errors#add+

+ [R] + raw_type

The raw value provided as the second parameter when calling +errors#add+

+ [R] + type

The type of error, defaults to :invalid unless specified

+ + + + +

Class Public methods

+ +
+

+ + new(base, attribute, type = :invalid, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 103
+def initialize(base, attribute, type = :invalid, **options)
+  @base = base
+  @attribute = attribute
+  @raw_type = type
+  @type = type || :invalid
+  @options = options
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + detail() + +

+ + +
+ +
+ + + + + +
+ Alias for: details +
+ + + +
+ +
+

+ + details() + +

+ + +
+

Returns the error details.

+ +
error = ActiveModel::Error.new(person, :name, :too_short, count: 5)
+error.details
+# => { error: :too_short, count: 5 }
+
+
+ + + +
+ Also aliased as: detail +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 148
+def details
+  { error: raw_type }.merge(options.except(*CALLBACKS_OPTIONS + MESSAGE_OPTIONS))
+end
+
+
+ +
+ +
+

+ + full_message() + +

+ + +
+

Returns the full error message.

+ +
error = ActiveModel::Error.new(person, :name, :too_short, count: 5)
+error.full_message
+# => "Name is too short (minimum is 5 characters)"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 158
+def full_message
+  self.class.full_message(attribute, message, @base)
+end
+
+
+ +
+ +
+

+ + match?(attribute, type = nil, **options) + +

+ + +
+

See if error matches provided attribute, type, and options.

+ +

Omitted params are not checked for a match.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 165
+def match?(attribute, type = nil, **options)
+  if @attribute != attribute || (type && @type != type)
+    return false
+  end
+
+  options.each do |key, value|
+    if @options[key] != value
+      return false
+    end
+  end
+
+  true
+end
+
+
+ +
+ +
+

+ + message() + +

+ + +
+

Returns the error message.

+ +
error = ActiveModel::Error.new(person, :name, :too_short, count: 5)
+error.message
+# => "is too short (minimum is 5 characters)"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 134
+def message
+  case raw_type
+  when Symbol
+    self.class.generate_message(attribute, raw_type, @base, options.except(*CALLBACKS_OPTIONS))
+  else
+    raw_type
+  end
+end
+
+
+ +
+ +
+

+ + strict_match?(attribute, type, **options) + +

+ + +
+

See if error matches provided attribute, type, and options exactly.

+ +

All params must be equal to Error’s own attributes to be considered a strict match.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 183
+def strict_match?(attribute, type, **options)
+  return false unless match?(attribute, type)
+
+  options == @options.except(*CALLBACKS_OPTIONS + MESSAGE_OPTIONS)
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + attributes_for_hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/error.rb, line 203
+def attributes_for_hash
+  [@base, @attribute, @raw_type, @options.except(*CALLBACKS_OPTIONS)]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Errors.html b/src/7.0/classes/ActiveModel/Errors.html new file mode 100644 index 0000000000..311a1048b0 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Errors.html @@ -0,0 +1,1309 @@ +--- +title: ActiveModel::Errors +layout: default +--- +
+ +
+
+ +
+ +

Active Model Errors

+ +

Provides error related functionalities you can include in your object for handling error messages and interacting with Action View helpers.

+ +

A minimal implementation could be:

+ +
class Person
+  # Required dependency for ActiveModel::Errors
+  extend ActiveModel::Naming
+
+  def initialize
+    @errors = ActiveModel::Errors.new(self)
+  end
+
+  attr_accessor :name
+  attr_reader   :errors
+
+  def validate!
+    errors.add(:name, :blank, message: "cannot be nil") if name.nil?
+  end
+
+  # The following methods are needed to be minimally implemented
+
+  def read_attribute_for_validation(attr)
+    send(attr)
+  end
+
+  def self.human_attribute_name(attr, options = {})
+    attr
+  end
+
+  def self.lookup_ancestors
+    [self]
+  end
+end
+
+ +

The last three methods are required in your object for Errors to be able to generate error messages correctly and also handle multiple languages. Of course, if you extend your object with ActiveModel::Translation you will not need to implement the last two. Likewise, using ActiveModel::Validations will handle the validation related methods for you.

+ +

The above allows you to do:

+ +
person = Person.new
+person.validate!            # => ["cannot be nil"]
+person.errors.full_messages # => ["name cannot be nil"]
+# etc..
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + errors

The actual array of Error objects This method is aliased to objects.

+ [R] + objects

The actual array of Error objects This method is aliased to objects.

+ + + + +

Class Public methods

+ +
+

+ + new(base) + +

+ + +
+

Pass in the instance of the object that is using the errors object.

+ +
class Person
+  def initialize
+    @errors = ActiveModel::Errors.new(self)
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 92
+def initialize(base)
+  @base = base
+  @errors = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](attribute) + +

+ + +
+

When passed a symbol or a name of a method, returns an array of errors for the method.

+ +
person.errors[:name]  # => ["cannot be nil"]
+person.errors['name'] # => ["cannot be nil"]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 204
+def [](attribute)
+  messages_for(attribute)
+end
+
+
+ +
+ +
+

+ + add(attribute, type = :invalid, **options) + +

+ + +
+

Adds a new error of type on attribute. More than one error can be added to the same attribute. If no type is supplied, :invalid is assumed.

+ +
person.errors.add(:name)
+# Adds <#ActiveModel::Error attribute=name, type=invalid>
+person.errors.add(:name, :not_implemented, message: "must be implemented")
+# Adds <#ActiveModel::Error attribute=name, type=not_implemented,
+                            options={:message=>"must be implemented"}>
+
+person.errors.messages
+# => {:name=>["is invalid", "must be implemented"]}
+
+ +

If type is a string, it will be used as error message.

+ +

If type is a symbol, it will be translated using the appropriate scope (see generate_message).

+ +
person.errors.add(:name, :blank)
+person.errors.messages
+# => {:name=>["can't be blank"]}
+
+person.errors.add(:name, :too_long, { count: 25 })
+person.errors.messages
+# => ["is too long (maximum is 25 characters)"]
+
+ +

If type is a proc, it will be called, allowing for things like Time.now to be used within an error.

+ +

If the :strict option is set to true, it will raise ActiveModel::StrictValidationFailed instead of adding the error. :strict option can also be set to any other exception.

+ +
person.errors.add(:name, :invalid, strict: true)
+# => ActiveModel::StrictValidationFailed: Name is invalid
+person.errors.add(:name, :invalid, strict: NameIsInvalid)
+# => NameIsInvalid: Name is invalid
+
+person.errors.messages # => {}
+
+ +

attribute should be set to :base if the error is not directly associated with a single attribute.

+ +
person.errors.add(:base, :name_or_email_blank,
+  message: "either name or email must be present")
+person.errors.messages
+# => {:base=>["either name or email must be present"]}
+person.errors.details
+# => {:base=>[{error: :name_or_email_blank}]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 317
+def add(attribute, type = :invalid, **options)
+  attribute, type, options = normalize_arguments(attribute, type, **options)
+  error = Error.new(@base, attribute, type, **options)
+
+  if exception = options[:strict]
+    exception = ActiveModel::StrictValidationFailed if exception == true
+    raise exception, error.full_message
+  end
+
+  @errors.append(error)
+
+  error
+end
+
+
+ +
+ +
+

+ + added?(attribute, type = :invalid, options = {}) + +

+ + +
+

Returns true if an error matches provided attribute and type, or false otherwise. type is treated the same as for add.

+ +
person.errors.add :name, :blank
+person.errors.added? :name, :blank           # => true
+person.errors.added? :name, "can't be blank" # => true
+
+ +

If the error requires options, then it returns true with the correct options, or false with incorrect or missing options.

+ +
person.errors.add :name, :too_long, { count: 25 }
+person.errors.added? :name, :too_long, count: 25                     # => true
+person.errors.added? :name, "is too long (maximum is 25 characters)" # => true
+person.errors.added? :name, :too_long, count: 24                     # => false
+person.errors.added? :name, :too_long                                # => false
+person.errors.added? :name, "is too long"                            # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 347
+def added?(attribute, type = :invalid, options = {})
+  attribute, type, options = normalize_arguments(attribute, type, **options)
+
+  if type.is_a? Symbol
+    @errors.any? { |error|
+      error.strict_match?(attribute, type, **options)
+    }
+  else
+    messages_for(attribute).include?(type)
+  end
+end
+
+
+ +
+ +
+

+ + as_json(options = nil) + +

+ + +
+

Returns a Hash that can be used as the JSON representation for this object. You can pass the :full_messages option. This determines if the json object should contain full messages or not (false by default).

+ +
person.errors.as_json                      # => {:name=>["cannot be nil"]}
+person.errors.as_json(full_messages: true) # => {:name=>["name cannot be nil"]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 222
+def as_json(options = nil)
+  to_hash(options && options[:full_messages])
+end
+
+
+ +
+ +
+

+ + attribute_names() + +

+ + +
+

Returns all error attribute names

+ +
person.errors.messages        # => {:name=>["cannot be nil", "must be specified"]}
+person.errors.attribute_names # => [:name]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 212
+def attribute_names
+  @errors.map(&:attribute).uniq.freeze
+end
+
+
+ +
+ +
+

+ + delete(attribute, type = nil, **options) + +

+ + +
+

Delete messages for key. Returns the deleted messages.

+ +
person.errors[:name]        # => ["cannot be nil"]
+person.errors.delete(:name) # => ["cannot be nil"]
+person.errors[:name]        # => []
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 190
+def delete(attribute, type = nil, **options)
+  attribute, type, options = normalize_arguments(attribute, type, **options)
+  matches = where(attribute, type, **options)
+  matches.each do |error|
+    @errors.delete(error)
+  end
+  matches.map(&:message).presence
+end
+
+
+ +
+ +
+

+ + details() + +

+ + +
+

Returns a Hash of attributes with an array of their error details.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 251
+def details
+  hash = group_by_attribute.transform_values do |errors|
+    errors.map(&:details)
+  end
+  hash.default = EMPTY_ARRAY
+  hash.freeze
+  hash
+end
+
+
+ +
+ +
+

+ + full_message(attribute, message) + +

+ + +
+

Returns a full message for a given attribute.

+ +
person.errors.full_message(:name, 'is invalid') # => "Name is invalid"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 426
+def full_message(attribute, message)
+  Error.full_message(attribute, message, @base)
+end
+
+
+ +
+ +
+

+ + full_messages() + +

+ + +
+

Returns all the full error messages in an array.

+ +
class Person
+  validates_presence_of :name, :address, :email
+  validates_length_of :name, in: 5..30
+end
+
+person = Person.create(address: '123 First St.')
+person.errors.full_messages
+# => ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
+
+
+ + + +
+ Also aliased as: to_a +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 390
+def full_messages
+  @errors.map(&:full_message)
+end
+
+
+ +
+ +
+

+ + full_messages_for(attribute) + +

+ + +
+

Returns all the full error messages for a given attribute in an array.

+ +
class Person
+  validates_presence_of :name, :email
+  validates_length_of :name, in: 5..30
+end
+
+person = Person.create()
+person.errors.full_messages_for(:name)
+# => ["Name is too short (minimum is 5 characters)", "Name can't be blank"]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 405
+def full_messages_for(attribute)
+  where(attribute).map(&:full_message).freeze
+end
+
+
+ +
+ +
+

+ + generate_message(attribute, type = :invalid, options = {}) + +

+ + +
+

Translates an error message in its default scope (activemodel.errors.messages).

+ +

Error messages are first looked up in activemodel.errors.models.MODEL.attributes.ATTRIBUTE.MESSAGE, if it’s not there, it’s looked up in activemodel.errors.models.MODEL.MESSAGE and if that is not there also, it returns the translation of the default message (e.g. activemodel.errors.messages.MESSAGE). The translated model name, translated attribute name, and the value are available for interpolation.

+ +

When using inheritance in your models, it will check all the inherited models too, but only if the model itself hasn’t been found. Say you have class Admin < User; end and you wanted the translation for the :blank error message for the title attribute, it looks for these translations:

+
  • +

    activemodel.errors.models.admin.attributes.title.blank

    +
  • +

    activemodel.errors.models.admin.blank

    +
  • +

    activemodel.errors.models.user.attributes.title.blank

    +
  • +

    activemodel.errors.models.user.blank

    +
  • +

    any default you provided through the options hash (in the activemodel.errors scope)

    +
  • +

    activemodel.errors.messages.blank

    +
  • +

    errors.attributes.title.blank

    +
  • +

    errors.messages.blank

    +
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 454
+def generate_message(attribute, type = :invalid, options = {})
+  Error.generate_message(attribute, type, @base, options)
+end
+
+
+ +
+ +
+

+ + group_by_attribute() + +

+ + +
+

Returns a Hash of attributes with an array of their Error objects.

+ +
person.errors.group_by_attribute
+# => {:name=>[<#ActiveModel::Error>, <#ActiveModel::Error>]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 264
+def group_by_attribute
+  @errors.group_by(&:attribute)
+end
+
+
+ +
+ +
+

+ + has_key?(attribute) + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + import(error, override_options = {}) + +

+ + +
+

Imports one error. Imported errors are wrapped as a NestedError, providing access to original error object. If attribute or type needs to be overridden, use override_options.

+ +

Options

+
  • +

    :attribute - Override the attribute the error belongs to.

    +
  • +

    :type - Override type of the error.

    +
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 129
+def import(error, override_options = {})
+  [:attribute, :type].each do |key|
+    if override_options.key?(key)
+      override_options[key] = override_options[key].to_sym
+    end
+  end
+  @errors.append(NestedError.new(@base, error, override_options))
+end
+
+
+ +
+ +
+

+ + include?(attribute) + +

+ + +
+

Returns true if the error messages include an error for the given key attribute, false otherwise.

+ +
person.errors.messages        # => {:name=>["cannot be nil"]}
+person.errors.include?(:name) # => true
+person.errors.include?(:age)  # => false
+
+
+ + + +
+ Also aliased as: has_key?, key? +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 177
+def include?(attribute)
+  @errors.any? { |error|
+    error.match?(attribute.to_sym)
+  }
+end
+
+
+ +
+ +
+

+ + key?(attribute) + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + merge!(other) + +

+ + +
+

Merges the errors from other, each Error wrapped as NestedError.

+ +

Parameters

+ + +

Examples

+ +
person.errors.merge!(other)
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 149
+def merge!(other)
+  return errors if equal?(other)
+
+  other.errors.each { |error|
+    import(error)
+  }
+end
+
+
+ +
+ +
+

+ + messages() + +

+ + +
+

Returns a Hash of attributes with an array of their error messages.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 243
+def messages
+  hash = to_hash
+  hash.default = EMPTY_ARRAY
+  hash.freeze
+  hash
+end
+
+
+ +
+ +
+

+ + messages_for(attribute) + +

+ + +
+

Returns all the error messages for a given attribute in an array.

+ +
class Person
+  validates_presence_of :name, :email
+  validates_length_of :name, in: 5..30
+end
+
+person = Person.create()
+person.errors.messages_for(:name)
+# => ["is too short (minimum is 5 characters)", "can't be blank"]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 419
+def messages_for(attribute)
+  where(attribute).map(&:message)
+end
+
+
+ +
+ +
+

+ + of_kind?(attribute, type = :invalid) + +

+ + +
+

Returns true if an error on the attribute with the given type is present, or false otherwise. type is treated the same as for add.

+ +
person.errors.add :age
+person.errors.add :name, :too_long, { count: 25 }
+person.errors.of_kind? :age                                            # => true
+person.errors.of_kind? :name                                           # => false
+person.errors.of_kind? :name, :too_long                                # => true
+person.errors.of_kind? :name, "is too long (maximum is 25 characters)" # => true
+person.errors.of_kind? :name, :not_too_long                            # => false
+person.errors.of_kind? :name, "is too long"                            # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 370
+def of_kind?(attribute, type = :invalid)
+  attribute, type = normalize_arguments(attribute, type)
+
+  if type.is_a? Symbol
+    !where(attribute, type).empty?
+  else
+    messages_for(attribute).include?(type)
+  end
+end
+
+
+ +
+ +
+

+ + to_a() + +

+ + +
+ +
+ + + + + +
+ Alias for: full_messages +
+ + + +
+ +
+

+ + to_hash(full_messages = false) + +

+ + +
+

Returns a Hash of attributes with their error messages. If full_messages is true, it will contain full messages (see full_message).

+ +
person.errors.to_hash       # => {:name=>["cannot be nil"]}
+person.errors.to_hash(true) # => {:name=>["name cannot be nil"]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 231
+def to_hash(full_messages = false)
+  message_method = full_messages ? :full_message : :message
+  group_by_attribute.transform_values do |errors|
+    errors.map(&message_method)
+  end
+end
+
+
+ +
+ +
+

+ + where(attribute, type = nil, **options) + +

+ + +
+

Search for errors matching attribute, type, or options.

+ +

Only supplied params will be matched.

+ +
person.errors.where(:name) # => all name errors.
+person.errors.where(:name, :too_short) # => all name errors being too short
+person.errors.where(:name, :too_short, minimum: 2) # => all name errors being too short and minimum is 2
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 164
+def where(attribute, type = nil, **options)
+  attribute, type, options = normalize_arguments(attribute, type, **options)
+  @errors.select { |error|
+    error.match?(attribute, type, **options)
+  }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/ForbiddenAttributesError.html b/src/7.0/classes/ActiveModel/ForbiddenAttributesError.html new file mode 100644 index 0000000000..876c6c6b80 --- /dev/null +++ b/src/7.0/classes/ActiveModel/ForbiddenAttributesError.html @@ -0,0 +1,78 @@ +--- +title: ActiveModel::ForbiddenAttributesError +layout: default +--- +
+ +
+
+ +
+ +

Raised when forbidden attributes are used for mass assignment.

+ +
class Person < ActiveRecord::Base
+end
+
+params = ActionController::Parameters.new(name: 'Bob')
+Person.new(params)
+# => ActiveModel::ForbiddenAttributesError
+
+params.permit!
+Person.new(params)
+# => #<Person id: nil, name: "Bob">
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Lint.html b/src/7.0/classes/ActiveModel/Lint.html new file mode 100644 index 0000000000..47c573bec4 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Lint.html @@ -0,0 +1,67 @@ +--- +title: ActiveModel::Lint +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Lint/Tests.html b/src/7.0/classes/ActiveModel/Lint/Tests.html new file mode 100644 index 0000000000..a0c4095a9e --- /dev/null +++ b/src/7.0/classes/ActiveModel/Lint/Tests.html @@ -0,0 +1,338 @@ +--- +title: ActiveModel::Lint::Tests +layout: default +--- +
+ +
+
+ +
+ +

Active Model Lint Tests

+ +

You can test whether an object is compliant with the Active Model API by including ActiveModel::Lint::Tests in your TestCase. It will include tests that tell you whether your object is fully compliant, or if not, which aspects of the API are not implemented.

+ +

Note an object is not required to implement all APIs in order to work with Action Pack. This module only intends to provide guidance in case you want all features out of the box.

+ +

These tests do not attempt to determine the semantic correctness of the returned values. For instance, you could implement valid? to always return true, and the tests would pass. It is up to you to ensure that the values are semantically meaningful.

+ +

Objects you pass in are expected to return a compliant object from a call to to_model. It is perfectly fine for to_model to return self.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + test_errors_aref() + +

+ + +
+

Passes if the object’s model responds to errors and if calling [](attribute) on the result of this method returns an array. Fails otherwise.

+ +

errors[attribute] is used to retrieve the errors of a model for a given attribute. If errors are present, the method should return an array of strings that are the errors for the attribute in question. If localization is used, the strings should be localized for the current locale. If no error is present, the method should return an empty array.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 102
+def test_errors_aref
+  assert_respond_to model, :errors
+  assert_equal [], model.errors[:hello], "errors#[] should return an empty Array"
+end
+
+
+ +
+ +
+

+ + test_model_naming() + +

+ + +
+

Passes if the object’s model responds to model_name both as an instance method and as a class method, and if calling this method returns a string with some convenience methods: :human, :singular and :plural.

+ +

Check ActiveModel::Naming for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 81
+def test_model_naming
+  assert_respond_to model.class, :model_name
+  model_name = model.class.model_name
+  assert_respond_to model_name, :to_str
+  assert_respond_to model_name.human, :to_str
+  assert_respond_to model_name.singular, :to_str
+  assert_respond_to model_name.plural, :to_str
+
+  assert_respond_to model, :model_name
+  assert_equal model.model_name, model.class.model_name
+end
+
+
+ +
+ +
+

+ + test_persisted?() + +

+ + +
+

Passes if the object’s model responds to persisted? and if calling this method returns either true or false. Fails otherwise.

+ +

persisted? is used when calculating the URL for an object. If the object is not persisted, a form for that object, for instance, will route to the create action. If it is persisted, a form for the object will route to the update action.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 70
+def test_persisted?
+  assert_respond_to model, :persisted?
+  assert_boolean model.persisted?, "persisted?"
+end
+
+
+ +
+ +
+

+ + test_to_key() + +

+ + +
+

Passes if the object’s model responds to to_key and if calling this method returns nil when the object is not persisted. Fails otherwise.

+ +

to_key returns an Enumerable of all (primary) key attributes of the model, and is used to a generate unique DOM id for the object.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 31
+def test_to_key
+  assert_respond_to model, :to_key
+  def model.persisted?() false end
+  assert model.to_key.nil?, "to_key should return nil when `persisted?` returns false"
+end
+
+
+ +
+ +
+

+ + test_to_param() + +

+ + +
+

Passes if the object’s model responds to to_param and if calling this method returns nil when the object is not persisted. Fails otherwise.

+ +

to_param is used to represent the object’s key in URLs. Implementers can decide to either raise an exception or provide a default in case the record uses a composite primary key. There are no tests for this behavior in lint because it doesn’t make sense to force any of the possible implementation strategies on the implementer.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 46
+def test_to_param
+  assert_respond_to model, :to_param
+  def model.to_key() [1] end
+  def model.persisted?() false end
+  assert model.to_param.nil?, "to_param should return nil when `persisted?` returns false"
+end
+
+
+ +
+ +
+

+ + test_to_partial_path() + +

+ + +
+

Passes if the object’s model responds to to_partial_path and if calling this method returns a string. Fails otherwise.

+ +

to_partial_path is used for looking up partials. For example, a BlogPost model might return “blog_posts/blog_post”.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/lint.rb, line 58
+def test_to_partial_path
+  assert_respond_to model, :to_partial_path
+  assert_kind_of String, model.to_partial_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/MissingAttributeError.html b/src/7.0/classes/ActiveModel/MissingAttributeError.html new file mode 100644 index 0000000000..baa3836a65 --- /dev/null +++ b/src/7.0/classes/ActiveModel/MissingAttributeError.html @@ -0,0 +1,75 @@ +--- +title: ActiveModel::MissingAttributeError +layout: default +--- +
+ +
+
+ +
+ +

Raised when an attribute is not defined.

+ +
class User < ActiveRecord::Base
+  has_many :pets
+end
+
+user = User.first
+user.pets.select(:id).first.user_id
+# => ActiveModel::MissingAttributeError: missing attribute: user_id
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Model.html b/src/7.0/classes/ActiveModel/Model.html new file mode 100644 index 0000000000..2236360866 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Model.html @@ -0,0 +1,106 @@ +--- +title: ActiveModel::Model +layout: default +--- +
+ +
+
+ +
+ +

Active Model Basic Model

+ +

Allows implementing models similar to ActiveRecord::Base. Includes ActiveModel::API for the required interface for an object to interact with Action Pack and Action View, but can be extended with other functionalities.

+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::Model
+  attr_accessor :name, :age
+end
+
+person = Person.new(name: 'bob', age: '18')
+person.name # => "bob"
+person.age  # => "18"
+
+ +

If for some reason you need to run code on initialize, make sure you call super if you want the attributes hash initialization to happen.

+ +
class Person
+  include ActiveModel::Model
+  attr_accessor :id, :name, :omg
+
+  def initialize(attributes={})
+    super
+    @omg ||= true
+  end
+end
+
+person = Person.new(id: 1, name: 'bob')
+person.omg # => true
+
+ +

For more detailed information on other functionalities available, please refer to the specific modules included in ActiveModel::Model (see below).

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Name.html b/src/7.0/classes/ActiveModel/Name.html new file mode 100644 index 0000000000..02b05d3583 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Name.html @@ -0,0 +1,740 @@ +--- +title: ActiveModel::Name +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Comparable + +
  • + +
+ + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + cache_key
+ [RW] + collection
+ [RW] + element
+ [RW] + i18n_key
+ [RW] + name
+ [RW] + param_key
+ [RW] + plural
+ [RW] + route_key
+ [RW] + singular
+ [RW] + singular_route_key
+ + + + +

Class Public methods

+ +
+

+ + new(klass, namespace = nil, name = nil, locale = :en) + +

+ + +
+

Returns a new ActiveModel::Name instance. By default, the namespace and name option will take the namespace and name of the given class respectively. Use locale argument for singularize and pluralize model name.

+ +
module Foo
+  class Bar
+  end
+end
+
+ActiveModel::Name.new(Foo::Bar).to_s
+# => "Foo::Bar"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 166
+def initialize(klass, namespace = nil, name = nil, locale = :en)
+  @name = name || klass.name
+
+  raise ArgumentError, "Class name cannot be blank. You need to supply a name argument when anonymous class given" if @name.blank?
+
+  @unnamespaced = @name.delete_prefix("#{namespace.name}::") if namespace
+  @klass        = klass
+  @singular     = _singularize(@name)
+  @plural       = ActiveSupport::Inflector.pluralize(@singular, locale)
+  @uncountable  = @plural == @singular
+  @element      = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(@name))
+  @human        = ActiveSupport::Inflector.humanize(@element)
+  @collection   = ActiveSupport::Inflector.tableize(@name)
+  @param_key    = (namespace ? _singularize(@unnamespaced) : @singular)
+  @i18n_key     = @name.underscore.to_sym
+
+  @route_key          = (namespace ? ActiveSupport::Inflector.pluralize(@param_key, locale) : @plural.dup)
+  @singular_route_key = ActiveSupport::Inflector.singularize(@route_key, locale)
+  @route_key << "_index" if @uncountable
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + !~(regexp) + + +

+ + +
+

Equivalent to String#!~. Match the class name against the given regexp. Returns true if there is no match, otherwise false.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name !~ /Post/ # => false
+BlogPost.model_name !~ /\d/   # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 83
+    
+
+
+ +
+ +
+

+ + <=>(other) + + +

+ + +
+

Equivalent to String#<=>.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name <=> 'BlogPost'  # => 0
+BlogPost.model_name <=> 'Blog'      # => 1
+BlogPost.model_name <=> 'BlogPosts' # => -1
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 50
+    
+
+
+ +
+ +
+

+ + ==(other) + + +

+ + +
+

Equivalent to String#==. Returns true if the class name and other are equal, otherwise false.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name == 'BlogPost'  # => true
+BlogPost.model_name == 'Blog Post' # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 19
+    
+
+
+ +
+ +
+

+ + ===(other) + + +

+ + +
+

Equivalent to #==.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name === 'BlogPost'  # => true
+BlogPost.model_name === 'Blog Post' # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 35
+    
+
+
+ +
+ +
+

+ + =~(regexp) + + +

+ + +
+

Equivalent to String#=~. Match the class name against the given regexp. Returns the position where the match starts or nil if there is no match.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name =~ /Post/ # => 4
+BlogPost.model_name =~ /\d/   # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 66
+    
+
+
+ +
+ +
+

+ + eql?(other) + + +

+ + +
+

Equivalent to String#eql?. Returns true if the class name and other have the same length and content, otherwise false.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name.eql?('BlogPost')  # => true
+BlogPost.model_name.eql?('Blog Post') # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 99
+    
+
+
+ +
+ +
+

+ + human(options = {}) + +

+ + +
+

Transform the model name into a more human format, using I18n. By default, it will underscore then humanize the class name.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name.human # => "Blog post"
+
+ +

Specify options with additional translating options.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 197
+def human(options = {})
+  return @human unless @klass.respond_to?(:lookup_ancestors) &&
+                       @klass.respond_to?(:i18n_scope)
+
+  defaults = @klass.lookup_ancestors.map do |klass|
+    klass.model_name.i18n_key
+  end
+
+  defaults << options[:default] if options[:default]
+  defaults << @human
+
+  options = { scope: [@klass.i18n_scope, :models], count: 1, default: defaults }.merge!(options.except(:default))
+  I18n.translate(defaults.shift, **options)
+end
+
+
+ +
+ +
+

+ + match?(regexp) + + +

+ + +
+

Equivalent to String#match?. Match the class name against the given regexp. Returns true if there is a match, otherwise false.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name.match?(/Post/) # => true
+BlogPost.model_name.match?(/\d/) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 115
+    
+
+
+ +
+ +
+

+ + to_s() + + +

+ + +
+

Returns the class name.

+ +
class BlogPost
+  extend ActiveModel::Naming
+end
+
+BlogPost.model_name.to_s # => "BlogPost"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 131
+    
+
+
+ +
+ +
+

+ + to_str() + + +

+ + +
+

Equivalent to to_s.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 151
+delegate :==, :===, :<=>, :=~, :"!~", :eql?, :match?, :to_s,
+         :to_str, :as_json, to: :name
+
+
+
+ +
+ +
+

+ + uncountable?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 212
+def uncountable?
+  @uncountable
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Naming.html b/src/7.0/classes/ActiveModel/Naming.html new file mode 100644 index 0000000000..af58d63ca9 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Naming.html @@ -0,0 +1,411 @@ +--- +title: ActiveModel::Naming +layout: default +--- +
+ +
+
+ +
+ +

Active Model Naming

+ +

Creates a model_name method on your object.

+ +

To implement, just extend ActiveModel::Naming in your object:

+ +
class BookCover
+  extend ActiveModel::Naming
+end
+
+BookCover.model_name.name   # => "BookCover"
+BookCover.model_name.human  # => "Book cover"
+
+BookCover.model_name.i18n_key              # => :book_cover
+BookModule::BookCover.model_name.i18n_key  # => :"book_module/book_cover"
+
+ +

Providing the functionality that ActiveModel::Naming provides in your object is required to pass the Active Model Lint test. So either extending the provided method below, or rolling your own is required.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + param_key(record_or_class) + +

+ + +
+

Returns string to use for params names. It differs for namespaced models regarding whether it’s inside isolated engine.

+ +
# For isolated engine:
+ActiveModel::Naming.param_key(Blog::Post) # => "post"
+
+# For shared engine:
+ActiveModel::Naming.param_key(Blog::Post) # => "blog_post"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 327
+def self.param_key(record_or_class)
+  model_name_from_record_or_class(record_or_class).param_key
+end
+
+
+ +
+ +
+

+ + plural(record_or_class) + +

+ + +
+

Returns the plural class name of a record or class.

+ +
ActiveModel::Naming.plural(post)             # => "posts"
+ActiveModel::Naming.plural(Highrise::Person) # => "highrise_people"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 272
+def self.plural(record_or_class)
+  model_name_from_record_or_class(record_or_class).plural
+end
+
+
+ +
+ +
+

+ + route_key(record_or_class) + +

+ + +
+

Returns string to use while generating route names. It differs for namespaced models regarding whether it’s inside isolated engine.

+ +
# For isolated engine:
+ActiveModel::Naming.route_key(Blog::Post) # => "posts"
+
+# For shared engine:
+ActiveModel::Naming.route_key(Blog::Post) # => "blog_posts"
+
+ +

The route key also considers if the noun is uncountable and, in such cases, automatically appends _index.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 315
+def self.route_key(record_or_class)
+  model_name_from_record_or_class(record_or_class).route_key
+end
+
+
+ +
+ +
+

+ + singular(record_or_class) + +

+ + +
+

Returns the singular class name of a record or class.

+ +
ActiveModel::Naming.singular(post)             # => "post"
+ActiveModel::Naming.singular(Highrise::Person) # => "highrise_person"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 280
+def self.singular(record_or_class)
+  model_name_from_record_or_class(record_or_class).singular
+end
+
+
+ +
+ +
+

+ + singular_route_key(record_or_class) + +

+ + +
+

Returns string to use while generating route names. It differs for namespaced models regarding whether it’s inside isolated engine.

+ +
# For isolated engine:
+ActiveModel::Naming.singular_route_key(Blog::Post) # => "post"
+
+# For shared engine:
+ActiveModel::Naming.singular_route_key(Blog::Post) # => "blog_post"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 300
+def self.singular_route_key(record_or_class)
+  model_name_from_record_or_class(record_or_class).singular_route_key
+end
+
+
+ +
+ +
+

+ + uncountable?(record_or_class) + +

+ + +
+

Identifies whether the class name of a record or class is uncountable.

+ +
ActiveModel::Naming.uncountable?(Sheep) # => true
+ActiveModel::Naming.uncountable?(Post)  # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 288
+def self.uncountable?(record_or_class)
+  model_name_from_record_or_class(record_or_class).uncountable?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + model_name() + +

+ + +
+

Returns an ActiveModel::Name object for module. It can be used to retrieve all kinds of naming-related information (See ActiveModel::Name for more information).

+ +
class Person
+  extend ActiveModel::Naming
+end
+
+Person.model_name.name     # => "Person"
+Person.model_name.class    # => ActiveModel::Name
+Person.model_name.singular # => "person"
+Person.model_name.plural   # => "people"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/naming.rb, line 259
+def model_name
+  @_model_name ||= begin
+    namespace = module_parents.detect do |n|
+      n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
+    end
+    ActiveModel::Name.new(self, namespace)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/NestedError.html b/src/7.0/classes/ActiveModel/NestedError.html new file mode 100644 index 0000000000..0d95d8f6c6 --- /dev/null +++ b/src/7.0/classes/ActiveModel/NestedError.html @@ -0,0 +1,126 @@ +--- +title: ActiveModel::NestedError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + inner_error
+ + + + +

Class Public methods

+ +
+

+ + new(base, inner_error, override_options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/nested_error.rb, line 8
+def initialize(base, inner_error, override_options = {})
+  @base = base
+  @inner_error = inner_error
+  @attribute = override_options.fetch(:attribute) { inner_error.attribute }
+  @type = override_options.fetch(:type) { inner_error.type }
+  @raw_type = inner_error.raw_type
+  @options = inner_error.options
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/RangeError.html b/src/7.0/classes/ActiveModel/RangeError.html new file mode 100644 index 0000000000..3f4b1a2b8d --- /dev/null +++ b/src/7.0/classes/ActiveModel/RangeError.html @@ -0,0 +1,66 @@ +--- +title: ActiveModel::RangeError +layout: default +--- +
+ +
+
+ +
+ +

Raised when attribute values are out of range.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/SecurePassword.html b/src/7.0/classes/ActiveModel/SecurePassword.html new file mode 100644 index 0000000000..be66887cbd --- /dev/null +++ b/src/7.0/classes/ActiveModel/SecurePassword.html @@ -0,0 +1,92 @@ +--- +title: ActiveModel::SecurePassword +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MAX_PASSWORD_LENGTH_ALLOWED=72
 

BCrypt hash function can handle maximum 72 bytes, and if we pass password of length more than 72 bytes it ignores extra characters. Hence need to put a restriction on password length.

+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/SecurePassword/ClassMethods.html b/src/7.0/classes/ActiveModel/SecurePassword/ClassMethods.html new file mode 100644 index 0000000000..569a6cdc21 --- /dev/null +++ b/src/7.0/classes/ActiveModel/SecurePassword/ClassMethods.html @@ -0,0 +1,205 @@ +--- +title: ActiveModel::SecurePassword::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + has_secure_password(attribute = :password, validations: true) + +

+ + +
+

Adds methods to set and authenticate against a BCrypt password. This mechanism requires you to have a XXX_digest attribute. Where XXX is the attribute name of your desired password.

+ +

The following validations are added automatically:

+
  • +

    Password must be present on creation

    +
  • +

    Password length should be less than or equal to 72 bytes

    +
  • +

    Confirmation of password (using a XXX_confirmation attribute)

    +
+ +

If confirmation validation is not needed, simply leave out the value for XXX_confirmation (i.e. don’t provide a form field for it). When this attribute has a nil value, the validation will not be triggered.

+ +

For further customizability, it is possible to suppress the default validations by passing validations: false as an argument.

+ +

Add bcrypt (~> 3.1.7) to Gemfile to use has_secure_password:

+ +
gem 'bcrypt', '~> 3.1.7'
+
+ +

Examples

+ +
Using Active Record (which automatically includes ActiveModel::SecurePassword)
+ +
# Schema: User(name:string, password_digest:string, recovery_password_digest:string)
+class User < ActiveRecord::Base
+  has_secure_password
+  has_secure_password :recovery_password, validations: false
+end
+
+user = User.new(name: 'david', password: '', password_confirmation: 'nomatch')
+user.save                                                  # => false, password required
+user.password = 'mUc3m00RsqyRe'
+user.save                                                  # => false, confirmation doesn't match
+user.password_confirmation = 'mUc3m00RsqyRe'
+user.save                                                  # => true
+user.recovery_password = "42password"
+user.recovery_password_digest                              # => "$2a$04$iOfhwahFymCs5weB3BNH/uXkTG65HR.qpW.bNhEjFP3ftli3o5DQC"
+user.save                                                  # => true
+user.authenticate('notright')                              # => false
+user.authenticate('mUc3m00RsqyRe')                         # => user
+user.authenticate_recovery_password('42password')          # => user
+User.find_by(name: 'david')&.authenticate('notright')      # => false
+User.find_by(name: 'david')&.authenticate('mUc3m00RsqyRe') # => user
+
+ +
Conditionally requiring a password
+ +
class Account
+  include ActiveModel::SecurePassword
+
+  attr_accessor :is_guest, :password_digest
+
+  has_secure_password
+
+  def errors
+    super.tap { |errors| errors.delete(:password, :blank) if is_guest }
+  end
+end
+
+account = Account.new
+account.valid? # => false, password required
+
+account.is_guest = true
+account.valid? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/secure_password.rb, line 84
+def has_secure_password(attribute = :password, validations: true)
+  # Load bcrypt gem only when has_secure_password is used.
+  # This is to avoid ActiveModel (and by extension the entire framework)
+  # being dependent on a binary library.
+  begin
+    require "bcrypt"
+  rescue LoadError
+    $stderr.puts "You don't have bcrypt installed in your application. Please add it to your Gemfile and run bundle install"
+    raise
+  end
+
+  include InstanceMethodsOnActivation.new(attribute)
+
+  if validations
+    include ActiveModel::Validations
+
+    # This ensures the model has a password by checking whether the password_digest
+    # is present, so that this works with both new and existing records. However,
+    # when there is an error, the message is added to the password attribute instead
+    # so that the error message will make sense to the end-user.
+    validate do |record|
+      record.errors.add(attribute, :blank) unless record.public_send("#{attribute}_digest").present?
+    end
+
+    validates_length_of attribute, maximum: ActiveModel::SecurePassword::MAX_PASSWORD_LENGTH_ALLOWED
+    validates_confirmation_of attribute, allow_blank: true
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/SecurePassword/InstanceMethodsOnActivation.html b/src/7.0/classes/ActiveModel/SecurePassword/InstanceMethodsOnActivation.html new file mode 100644 index 0000000000..ec2023b309 --- /dev/null +++ b/src/7.0/classes/ActiveModel/SecurePassword/InstanceMethodsOnActivation.html @@ -0,0 +1,139 @@ +--- +title: ActiveModel::SecurePassword::InstanceMethodsOnActivation +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(attribute) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/secure_password.rb, line 115
+def initialize(attribute)
+  attr_reader attribute
+
+  define_method("#{attribute}=") do |unencrypted_password|
+    if unencrypted_password.nil?
+      instance_variable_set("@#{attribute}", nil)
+      self.public_send("#{attribute}_digest=", nil)
+    elsif !unencrypted_password.empty?
+      instance_variable_set("@#{attribute}", unencrypted_password)
+      cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
+      self.public_send("#{attribute}_digest=", BCrypt::Password.create(unencrypted_password, cost: cost))
+    end
+  end
+
+  define_method("#{attribute}_confirmation=") do |unencrypted_password|
+    instance_variable_set("@#{attribute}_confirmation", unencrypted_password)
+  end
+
+  # Returns +self+ if the password is correct, otherwise +false+.
+  #
+  #   class User < ActiveRecord::Base
+  #     has_secure_password validations: false
+  #   end
+  #
+  #   user = User.new(name: 'david', password: 'mUc3m00RsqyRe')
+  #   user.save
+  #   user.authenticate_password('notright')      # => false
+  #   user.authenticate_password('mUc3m00RsqyRe') # => user
+  define_method("authenticate_#{attribute}") do |unencrypted_password|
+    attribute_digest = public_send("#{attribute}_digest")
+    attribute_digest.present? && BCrypt::Password.new(attribute_digest).is_password?(unencrypted_password) && self
+  end
+
+  alias_method :authenticate, :authenticate_password if attribute == :password
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Serialization.html b/src/7.0/classes/ActiveModel/Serialization.html new file mode 100644 index 0000000000..fbbf9d7546 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Serialization.html @@ -0,0 +1,245 @@ +--- +title: ActiveModel::Serialization +layout: default +--- +
+ +
+
+ +
+ +

Active Model Serialization

+ +

Provides a basic serialization to a serializable_hash for your objects.

+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::Serialization
+
+  attr_accessor :name
+
+  def attributes
+    {'name' => nil}
+  end
+end
+
+ +

Which would provide you with:

+ +
person = Person.new
+person.serializable_hash   # => {"name"=>nil}
+person.name = "Bob"
+person.serializable_hash   # => {"name"=>"Bob"}
+
+ +

An attributes hash must be defined and should contain any attributes you need to be serialized. Attributes must be strings, not symbols. When called, serializable hash will use instance methods that match the name of the attributes hash’s keys. In order to override this behavior, take a look at the private method read_attribute_for_serialization.

+ +

ActiveModel::Serializers::JSON module automatically includes the ActiveModel::Serialization module, so there is no need to explicitly include ActiveModel::Serialization.

+ +

A minimal implementation including JSON would be:

+ +
class Person
+  include ActiveModel::Serializers::JSON
+
+  attr_accessor :name
+
+  def attributes
+    {'name' => nil}
+  end
+end
+
+ +

Which would provide you with:

+ +
person = Person.new
+person.serializable_hash   # => {"name"=>nil}
+person.as_json             # => {"name"=>nil}
+person.to_json             # => "{\"name\":null}"
+
+person.name = "Bob"
+person.serializable_hash   # => {"name"=>"Bob"}
+person.as_json             # => {"name"=>"Bob"}
+person.to_json             # => "{\"name\":\"Bob\"}"
+
+ +

Valid options are :only, :except, :methods and :include. The following are all valid examples:

+ +
person.serializable_hash(only: 'name')
+person.serializable_hash(include: :address)
+person.serializable_hash(include: { address: { only: 'city' }})
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + serializable_hash(options = nil) + +

+ + +
+

Returns a serialized hash of your object.

+ +
class Person
+  include ActiveModel::Serialization
+
+  attr_accessor :name, :age
+
+  def attributes
+    {'name' => nil, 'age' => nil}
+  end
+
+  def capitalized_name
+    name.capitalize
+  end
+end
+
+person = Person.new
+person.name = 'bob'
+person.age  = 22
+person.serializable_hash                # => {"name"=>"bob", "age"=>22}
+person.serializable_hash(only: :name)   # => {"name"=>"bob"}
+person.serializable_hash(except: :name) # => {"age"=>22}
+person.serializable_hash(methods: :capitalized_name)
+# => {"name"=>"bob", "age"=>22, "capitalized_name"=>"Bob"}
+
+ +

Example with :include option

+ +
class User
+  include ActiveModel::Serializers::JSON
+  attr_accessor :name, :notes # Emulate has_many :notes
+  def attributes
+    {'name' => nil}
+  end
+end
+
+class Note
+  include ActiveModel::Serializers::JSON
+  attr_accessor :title, :text
+  def attributes
+    {'title' => nil, 'text' => nil}
+  end
+end
+
+note = Note.new
+note.title = 'Battle of Austerlitz'
+note.text = 'Some text here'
+
+user = User.new
+user.name = 'Napoleon'
+user.notes = [note]
+
+user.serializable_hash
+# => {"name" => "Napoleon"}
+user.serializable_hash(include: { notes: { only: 'title' }})
+# => {"name" => "Napoleon", "notes" => [{"title"=>"Battle of Austerlitz"}]}
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/serialization.rb, line 125
+def serializable_hash(options = nil)
+  attribute_names = attribute_names_for_serialization
+
+  return serializable_attributes(attribute_names) if options.blank?
+
+  if only = options[:only]
+    attribute_names &= Array(only).map(&:to_s)
+  elsif except = options[:except]
+    attribute_names -= Array(except).map(&:to_s)
+  end
+
+  hash = serializable_attributes(attribute_names)
+
+  Array(options[:methods]).each { |m| hash[m.to_s] = send(m) }
+
+  serializable_add_includes(options) do |association, records, opts|
+    hash[association.to_s] = if records.respond_to?(:to_ary)
+      records.to_ary.map { |a| a.serializable_hash(opts) }
+    else
+      records.serializable_hash(opts)
+    end
+  end
+
+  hash
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Serializers.html b/src/7.0/classes/ActiveModel/Serializers.html new file mode 100644 index 0000000000..7d42fe9207 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Serializers.html @@ -0,0 +1,67 @@ +--- +title: ActiveModel::Serializers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Serializers/JSON.html b/src/7.0/classes/ActiveModel/Serializers/JSON.html new file mode 100644 index 0000000000..31d1527dc2 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Serializers/JSON.html @@ -0,0 +1,287 @@ +--- +title: ActiveModel::Serializers::JSON +layout: default +--- +
+ +
+
+ +
+ +

Active Model JSON Serializer

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + as_json(options = nil) + +

+ + +
+

Returns a hash representing the model. Some configuration can be passed through options.

+ +

The option include_root_in_json controls the top-level behavior of as_json. If true, as_json will emit a single root node named after the object’s type. The default value for include_root_in_json option is false.

+ +
user = User.find(1)
+user.as_json
+# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#     "created_at" => "2006-08-01T17:27:133.000Z", "awesome" => true}
+
+ActiveRecord::Base.include_root_in_json = true
+
+user.as_json
+# => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#                  "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true } }
+
+ +

This behavior can also be achieved by setting the :root option to true as in:

+ +
user = User.find(1)
+user.as_json(root: true)
+# => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#                  "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true } }
+
+ +

If you prefer, :root may also be set to a custom string key instead as in:

+ +
user = User.find(1)
+user.as_json(root: "author")
+# => { "author" => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#                  "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true } }
+
+ +

Without any options, the returned Hash will include all the model’s attributes.

+ +
user = User.find(1)
+user.as_json
+# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true}
+
+ +

The :only and :except options can be used to limit the attributes included, and work similar to the attributes method.

+ +
user.as_json(only: [:id, :name])
+# => { "id" => 1, "name" => "Konata Izumi" }
+
+user.as_json(except: [:id, :created_at, :age])
+# => { "name" => "Konata Izumi", "awesome" => true }
+
+ +

To include the result of some method calls on the model use :methods:

+ +
user.as_json(methods: :permalink)
+# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true,
+#      "permalink" => "1-konata-izumi" }
+
+ +

To include associations use :include:

+ +
user.as_json(include: :posts)
+# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true,
+#      "posts" => [ { "id" => 1, "author_id" => 1, "title" => "Welcome to the weblog" },
+#                   { "id" => 2, "author_id" => 1, "title" => "So I was thinking" } ] }
+
+ +

Second level and higher order associations work as well:

+ +
user.as_json(include: { posts: {
+                           include: { comments: {
+                                          only: :body } },
+                           only: :title } })
+# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
+#      "created_at" => "2006-08-01T17:27:13.000Z", "awesome" => true,
+#      "posts" => [ { "comments" => [ { "body" => "1st post!" }, { "body" => "Second!" } ],
+#                     "title" => "Welcome to the weblog" },
+#                   { "comments" => [ { "body" => "Don't think too hard" } ],
+#                     "title" => "So I was thinking" } ] }
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/serializers/json.rb, line 96
+def as_json(options = nil)
+  root = if options && options.key?(:root)
+    options[:root]
+  else
+    include_root_in_json
+  end
+
+  hash = serializable_hash(options).as_json
+  if root
+    root = model_name.element if root == true
+    { root => hash }
+  else
+    hash
+  end
+end
+
+
+ +
+ +
+

+ + from_json(json, include_root = include_root_in_json) + +

+ + +
+

Sets the model attributes from a JSON string. Returns self.

+ +
class Person
+  include ActiveModel::Serializers::JSON
+
+  attr_accessor :name, :age, :awesome
+
+  def attributes=(hash)
+    hash.each do |key, value|
+      send("#{key}=", value)
+    end
+  end
+
+  def attributes
+    instance_values
+  end
+end
+
+json = { name: 'bob', age: 22, awesome:true }.to_json
+person = Person.new
+person.from_json(json) # => #<Person:0x007fec5e7a0088 @age=22, @awesome=true, @name="bob">
+person.name            # => "bob"
+person.age             # => 22
+person.awesome         # => true
+
+ +

The default value for include_root is false. You can change it to true if the given JSON string includes a single root node.

+ +
json = { person: { name: 'bob', age: 22, awesome:true } }.to_json
+person = Person.new
+person.from_json(json, true) # => #<Person:0x007fec5e7a0088 @age=22, @awesome=true, @name="bob">
+person.name                  # => "bob"
+person.age                   # => 22
+person.awesome               # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/serializers/json.rb, line 146
+def from_json(json, include_root = include_root_in_json)
+  hash = ActiveSupport::JSON.decode(json)
+  hash = hash.values.first if include_root
+  self.attributes = hash
+  self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/StrictValidationFailed.html b/src/7.0/classes/ActiveModel/StrictValidationFailed.html new file mode 100644 index 0000000000..63ca86c7a6 --- /dev/null +++ b/src/7.0/classes/ActiveModel/StrictValidationFailed.html @@ -0,0 +1,80 @@ +--- +title: ActiveModel::StrictValidationFailed +layout: default +--- +
+ +
+
+ +
+ +

Raised when a validation cannot be corrected by end users and are considered exceptional.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+
+  validates_presence_of :name, strict: true
+end
+
+person = Person.new
+person.name = nil
+person.valid?
+# => ActiveModel::StrictValidationFailed: Name can't be blank
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Translation.html b/src/7.0/classes/ActiveModel/Translation.html new file mode 100644 index 0000000000..f7fe4569b8 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Translation.html @@ -0,0 +1,240 @@ +--- +title: ActiveModel::Translation +layout: default +--- +
+ +
+
+ +
+ +

Active Model Translation

+ +

Provides integration between your object and the Rails internationalization (i18n) framework.

+ +

A minimal implementation could be:

+ +
class TranslatedPerson
+  extend ActiveModel::Translation
+end
+
+TranslatedPerson.human_attribute_name('my_attribute')
+# => "My attribute"
+
+ +

This also provides the required class methods for hooking into the Rails internationalization API, including being able to define a class-based i18n_scope and lookup_ancestors to find translations in parent classes.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + human_attribute_name(attribute, options = {}) + +

+ + +
+

Transforms attribute names into a more human format, such as “First name” instead of “first_name”.

+ +
Person.human_attribute_name("first_name") # => "First name"
+
+ +

Specify options with additional translating options.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/translation.rb, line 44
+def human_attribute_name(attribute, options = {})
+  options   = { count: 1 }.merge!(options)
+  parts     = attribute.to_s.split(".")
+  attribute = parts.pop
+  namespace = parts.join("/") unless parts.empty?
+  attributes_scope = "#{i18n_scope}.attributes"
+
+  if namespace
+    defaults = lookup_ancestors.map do |klass|
+      :"#{attributes_scope}.#{klass.model_name.i18n_key}/#{namespace}.#{attribute}"
+    end
+    defaults << :"#{attributes_scope}.#{namespace}.#{attribute}"
+  else
+    defaults = lookup_ancestors.map do |klass|
+      :"#{attributes_scope}.#{klass.model_name.i18n_key}.#{attribute}"
+    end
+  end
+
+  defaults << :"attributes.#{attribute}"
+  defaults << options.delete(:default) if options[:default]
+  defaults << attribute.humanize
+
+  options[:default] = defaults
+  I18n.translate(defaults.shift, **options)
+end
+
+
+ +
+ +
+

+ + i18n_scope() + +

+ + +
+

Returns the i18n_scope for the class. Override if you want custom lookup.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/translation.rb, line 26
+def i18n_scope
+  :activemodel
+end
+
+
+ +
+ +
+

+ + lookup_ancestors() + +

+ + +
+

When localizing a string, it goes through the lookup returned by this method, which is used in ActiveModel::Name#human, ActiveModel::Errors#full_messages and ActiveModel::Translation#human_attribute_name.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/translation.rb, line 34
+def lookup_ancestors
+  ancestors.select { |x| x.respond_to?(:model_name) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type.html b/src/7.0/classes/ActiveModel/Type.html new file mode 100644 index 0000000000..e0dfe609fc --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type.html @@ -0,0 +1,163 @@ +--- +title: ActiveModel::Type +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + register(type_name, klass = nil, &block) + +

+ + +
+

Add a new type to the registry, allowing it to be referenced as a symbol by attribute.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type.rb, line 29
+def register(type_name, klass = nil, &block)
+  registry.register(type_name, klass, &block)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/BigInteger.html b/src/7.0/classes/ActiveModel/Type/BigInteger.html new file mode 100644 index 0000000000..278fbcbb9a --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/BigInteger.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::BigInteger +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Binary.html b/src/7.0/classes/ActiveModel/Type/Binary.html new file mode 100644 index 0000000000..ff40bc18a1 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Binary.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::Type::Binary +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Boolean.html b/src/7.0/classes/ActiveModel/Type/Boolean.html new file mode 100644 index 0000000000..b07b62cd64 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Boolean.html @@ -0,0 +1,108 @@ +--- +title: ActiveRecord::Type::Boolean +layout: default +--- +
+ +
+
+ +
+ +

Active Model Type Boolean

+ +

A class that behaves like a boolean type, including rules for coercion of user input.

+ +

Coercion

+ +

Values set from user input will first be coerced into the appropriate ruby type. Coercion behavior is roughly mapped to Ruby’s boolean semantics.

+
  • +

    “false”, “f” , “0”, 0 or any other value in FALSE_VALUES will be coerced to false

    +
  • +

    Empty strings are coerced to nil

    +
  • +

    All other values will be coerced to true

    +
+ +
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
FALSE_VALUES=[ +false, 0, +"0", :"0", +"f", :f, +"F", :F, +"false", :false, +"FALSE", :FALSE, +"off", :off, +"OFF", :OFF, +].to_set.freeze
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Decimal.html b/src/7.0/classes/ActiveModel/Type/Decimal.html new file mode 100644 index 0000000000..79c591b0fe --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Decimal.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::Decimal +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Float.html b/src/7.0/classes/ActiveModel/Type/Float.html new file mode 100644 index 0000000000..d7d8065bb6 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Float.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::Float +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers.html b/src/7.0/classes/ActiveModel/Type/Helpers.html new file mode 100644 index 0000000000..ae8d3940db --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers.html @@ -0,0 +1,88 @@ +--- +title: ActiveModel::Type::Helpers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime.html b/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime.html new file mode 100644 index 0000000000..a4e5fbd89f --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime.html @@ -0,0 +1,73 @@ +--- +title: ActiveModel::Type::Helpers::AcceptsMultiparameterTime +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime/InstanceMethods.html b/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime/InstanceMethods.html new file mode 100644 index 0000000000..0066a99813 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/AcceptsMultiparameterTime/InstanceMethods.html @@ -0,0 +1,54 @@ +--- +title: ActiveModel::Type::Helpers::AcceptsMultiparameterTime::InstanceMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/Mutable.html b/src/7.0/classes/ActiveModel/Type/Helpers/Mutable.html new file mode 100644 index 0000000000..25a46500b4 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/Mutable.html @@ -0,0 +1,54 @@ +--- +title: ActiveModel::Type::Helpers::Mutable +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/Numeric.html b/src/7.0/classes/ActiveModel/Type/Helpers/Numeric.html new file mode 100644 index 0000000000..e660940a4c --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/Numeric.html @@ -0,0 +1,54 @@ +--- +title: ActiveModel::Type::Helpers::Numeric +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/TimeValue.html b/src/7.0/classes/ActiveModel/Type/Helpers/TimeValue.html new file mode 100644 index 0000000000..0ca3849f6f --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/TimeValue.html @@ -0,0 +1,54 @@ +--- +title: ActiveModel::Type::Helpers::TimeValue +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Helpers/Timezone.html b/src/7.0/classes/ActiveModel/Type/Helpers/Timezone.html new file mode 100644 index 0000000000..19970e8172 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Helpers/Timezone.html @@ -0,0 +1,54 @@ +--- +title: ActiveModel::Type::Helpers::Timezone +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/ImmutableString.html b/src/7.0/classes/ActiveModel/Type/ImmutableString.html new file mode 100644 index 0000000000..527bb76b7d --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/ImmutableString.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::ImmutableString +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Integer.html b/src/7.0/classes/ActiveModel/Type/Integer.html new file mode 100644 index 0000000000..35dc6cf6b0 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Integer.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::Integer +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/String.html b/src/7.0/classes/ActiveModel/Type/String.html new file mode 100644 index 0000000000..41ddb8f173 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/String.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Type::String +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Type/Value.html b/src/7.0/classes/ActiveModel/Type/Value.html new file mode 100644 index 0000000000..bd0c2763e2 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Type/Value.html @@ -0,0 +1,587 @@ +--- +title: ActiveRecord::Type::Value +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + limit
+ [R] + precision
+ [R] + scale
+ + + + +

Class Public methods

+ +
+

+ + new(precision: nil, limit: nil, scale: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 8
+def initialize(precision: nil, limit: nil, scale: nil)
+  @precision = precision
+  @scale = scale
+  @limit = limit
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other) + +

+ + +
+ +
+ + + +
+ Also aliased as: eql? +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 109
+def ==(other)
+  self.class == other.class &&
+    precision == other.precision &&
+    scale == other.scale &&
+    limit == other.limit
+end
+
+
+ +
+ +
+

+ + assert_valid_value(_) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 121
+def assert_valid_value(_)
+end
+
+
+ +
+ +
+

+ + cast(value) + +

+ + +
+

Type casts a value from user input (e.g. from a setter). This value may be a string from the form builder, or a ruby object passed to a setter. There is currently no way to differentiate between which source it came from.

+ +

The return value of this method will be returned from ActiveRecord::AttributeMethods::Read#read_attribute. See also: Value#cast_value.

+ +

value The raw input, as provided to the attribute setter.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 45
+def cast(value)
+  cast_value(value) unless value.nil?
+end
+
+
+ +
+ +
+

+ + changed?(old_value, new_value, _new_value_before_type_cast) + +

+ + +
+

Determines whether a value has changed for dirty checking. old_value and new_value will always be type-cast. Types should not need to override this method.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 72
+def changed?(old_value, new_value, _new_value_before_type_cast)
+  old_value != new_value
+end
+
+
+ +
+ +
+

+ + changed_in_place?(raw_old_value, new_value) + +

+ + +
+

Determines whether the mutable value has been modified since it was read. Returns false by default. If your type returns an object which could be mutated, you should override this method. You will need to either:

+ + +

or

+ + +

raw_old_value The original value, before being passed to deserialize.

+ +

new_value The current value, after type casting.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 93
+def changed_in_place?(raw_old_value, new_value)
+  false
+end
+
+
+ +
+ +
+

+ + deserialize(value) + +

+ + +
+

Converts a value from database input to the appropriate ruby type. The return value of this method will be returned from ActiveRecord::AttributeMethods::Read#read_attribute. The default implementation just calls Value#cast.

+ +

value The raw input, as provided from the database.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 31
+def deserialize(value)
+  cast(value)
+end
+
+
+ +
+ +
+

+ + eql?(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: == +
+ + + +
+ +
+

+ + hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 117
+def hash
+  [self.class, precision, scale, limit].hash
+end
+
+
+ +
+ +
+

+ + serializable?(value) + +

+ + +
+

Returns true if this type can convert value to a type that is usable by the database. For example a boolean type can return true if the value parameter is a Ruby boolean, but may return false if the value parameter is some other object.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 18
+def serializable?(value)
+  true
+end
+
+
+ +
+ +
+

+ + serialize(value) + +

+ + +
+

Casts a value from the ruby type to a type that the database knows how to understand. The returned value from this method should be a String, Numeric, Date, Time, Symbol, true, false, or nil.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 53
+def serialize(value)
+  value
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + cast_value(value) + +

+ + +
+

Convenience method for types which do not need separate type casting behavior for user and database inputs. Called by Value#cast for values except nil.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/type/value.rb, line 136
+def cast_value(value) # :doc:
+  value
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/UnknownAttributeError.html b/src/7.0/classes/ActiveModel/UnknownAttributeError.html new file mode 100644 index 0000000000..5c7b8c9218 --- /dev/null +++ b/src/7.0/classes/ActiveModel/UnknownAttributeError.html @@ -0,0 +1,147 @@ +--- +title: ActiveRecord::UnknownAttributeError +layout: default +--- +
+ +
+
+ +
+ +

Raised when unknown attributes are supplied via mass assignment.

+ +
class Person
+  include ActiveModel::AttributeAssignment
+  include ActiveModel::Validations
+end
+
+person = Person.new
+person.assign_attributes(name: 'Gorby')
+# => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person.
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + attribute
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(record, attribute) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/errors.rb, line 510
+def initialize(record, attribute)
+  @record = record
+  @attribute = attribute
+  super("unknown attribute '#{attribute}' for #{@record.class}.")
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/VERSION.html b/src/7.0/classes/ActiveModel/VERSION.html new file mode 100644 index 0000000000..8e0d85224b --- /dev/null +++ b/src/7.0/classes/ActiveModel/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActiveModel::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/ValidationError.html b/src/7.0/classes/ActiveModel/ValidationError.html new file mode 100644 index 0000000000..eb418e404f --- /dev/null +++ b/src/7.0/classes/ActiveModel/ValidationError.html @@ -0,0 +1,138 @@ +--- +title: ActiveModel::ValidationError +layout: default +--- +
+ +
+
+ +
+ +

Active Model ValidationError

+ +

Raised by validate! when the model is invalid. Use the model method to retrieve the record which did not validate.

+ +
begin
+  complex_operation_that_internally_calls_validate!
+rescue ActiveModel::ValidationError => invalid
+  puts invalid.model.errors
+end
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + model
+ + + + +

Class Public methods

+ +
+

+ + new(model) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 428
+def initialize(model)
+  @model = model
+  errors = @model.errors.full_messages.join(", ")
+  super(I18n.t(:"#{@model.class.i18n_scope}.errors.messages.model_invalid", errors: errors, default: :"errors.messages.model_invalid"))
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations.html b/src/7.0/classes/ActiveModel/Validations.html new file mode 100644 index 0000000000..f146d08a74 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations.html @@ -0,0 +1,560 @@ +--- +title: ActiveModel::Validations +layout: default +--- +
+ +
+
+ +
+ +

Active Model Validations

+ +

Provides a full validation framework to your objects.

+ +

A minimal implementation could be:

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :first_name, :last_name
+
+  validates_each :first_name, :last_name do |record, attr, value|
+    record.errors.add attr, "starts with z." if value.start_with?("z")
+  end
+end
+
+ +

Which provides you with the full standard validation stack that you know from Active Record:

+ +
person = Person.new
+person.valid?                   # => true
+person.invalid?                 # => false
+
+person.first_name = 'zoolander'
+person.valid?                   # => false
+person.invalid?                 # => true
+person.errors.messages          # => {first_name:["starts with z."]}
+
+ +

Note that ActiveModel::Validations automatically adds an errors method to your instances initialized with a new ActiveModel::Errors object, so there is no need for you to do this manually.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + validation_context
+ + + + + +

Instance Public methods

+ +
+

+ + errors() + +

+ + +
+

Returns the Errors object that holds all information about attribute error messages.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates_presence_of :name
+end
+
+person = Person.new
+person.valid? # => false
+person.errors # => #<ActiveModel::Errors:0x007fe603816640 @messages={name:["can't be blank"]}>
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 301
+def errors
+  @errors ||= Errors.new(self)
+end
+
+
+ +
+ +
+

+ + invalid?(context = nil) + +

+ + +
+

Performs the opposite of valid?. Returns true if errors were added, false otherwise.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates_presence_of :name
+end
+
+person = Person.new
+person.name = ''
+person.invalid? # => true
+person.name = 'david'
+person.invalid? # => false
+
+ +

Context can optionally be supplied to define which callbacks to test against (the context is defined on the validations using :on).

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates_presence_of :name, on: :new
+end
+
+person = Person.new
+person.invalid?       # => false
+person.invalid?(:new) # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 373
+def invalid?(context = nil)
+  !valid?(context)
+end
+
+
+ +
+ +
+

+ + valid?(context = nil) + +

+ + +
+

Runs all the specified validations and returns true if no errors were added otherwise false.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates_presence_of :name
+end
+
+person = Person.new
+person.name = ''
+person.valid? # => false
+person.name = 'david'
+person.valid? # => true
+
+ +

Context can optionally be supplied to define which callbacks to test against (the context is defined on the validations using :on).

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates_presence_of :name, on: :new
+end
+
+person = Person.new
+person.valid?       # => true
+person.valid?(:new) # => false
+
+
+ + + +
+ Also aliased as: validate +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 334
+def valid?(context = nil)
+  current_context, self.validation_context = validation_context, context
+  errors.clear
+  run_validations!
+ensure
+  self.validation_context = current_context
+end
+
+
+ +
+ +
+

+ + validate(context = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: valid? +
+ + + +
+ +
+

+ + validate!(context = nil) + +

+ + +
+

Runs all the validations within the specified context. Returns true if no errors are found, raises ValidationError otherwise.

+ +

Validations with no :on option will run no matter the context. Validations with some :on option will only run in the specified context.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 382
+def validate!(context = nil)
+  valid?(context) || raise_validation_error
+end
+
+
+ +
+ +
+

+ + validates_with(*args, &block) + +

+ + +
+

Passes the record off to the class or classes specified and allows them to add errors based on more complex conditions.

+ +
class Person
+  include ActiveModel::Validations
+
+  validate :instance_validations
+
+  def instance_validations
+    validates_with MyValidator
+  end
+end
+
+ +

Please consult the class method documentation for more information on creating your own validator.

+ +

You may also pass it multiple classes, like so:

+ +
class Person
+  include ActiveModel::Validations
+
+  validate :instance_validations, on: :create
+
+  def instance_validations
+    validates_with MyValidator, MyOtherValidator
+  end
+end
+
+ +

Standard configuration options (:on, :if and :unless), which are available on the class version of validates_with, should instead be placed on the validates method as these are applied and tested in the callback.

+ +

If you pass any additional configuration options, they will be passed to the class and available as options, please refer to the class version of this method for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/with.rb, line 137
+def validates_with(*args, &block)
+  options = args.extract_options!
+  options[:class] = self.class
+
+  args.each do |klass|
+    validator = klass.new(options, &block)
+    validator.validate(self)
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + raise_validation_error() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 410
+def raise_validation_error # :doc:
+  raise(ValidationError.new(self))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator.html b/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator.html new file mode 100644 index 0000000000..fc2f37dda7 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator.html @@ -0,0 +1,73 @@ +--- +title: ActiveModel::Validations::AcceptanceValidator +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator/LazilyDefineAttributes.html b/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator/LazilyDefineAttributes.html new file mode 100644 index 0000000000..59f33fef0f --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/AcceptanceValidator/LazilyDefineAttributes.html @@ -0,0 +1,309 @@ +--- +title: ActiveModel::Validations::AcceptanceValidator::LazilyDefineAttributes +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + attributes
+ + + + +

Class Public methods

+ +
+

+ + new(attributes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 28
+def initialize(attributes)
+  @attributes = attributes.map(&:to_s)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 73
+def ==(other)
+  self.class == other.class && attributes == other.attributes
+end
+
+
+ +
+ +
+

+ + define_on(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 56
+def define_on(klass)
+  @lock&.synchronize do
+    return unless @lock
+
+    attr_readers = attributes.reject { |name| klass.attribute_method?(name) }
+    attr_writers = attributes.reject { |name| klass.attribute_method?("#{name}=") }
+
+    attr_reader(*attr_readers)
+    attr_writer(*attr_writers)
+
+    remove_method :respond_to_missing?
+    remove_method :method_missing
+
+    @lock = nil
+  end
+end
+
+
+ +
+ +
+

+ + included(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 32
+def included(klass)
+  @lock = Mutex.new
+  mod = self
+
+  define_method(:respond_to_missing?) do |method_name, include_private = false|
+    mod.define_on(klass)
+    super(method_name, include_private) || mod.matches?(method_name)
+  end
+
+  define_method(:method_missing) do |method_name, *args, &block|
+    mod.define_on(klass)
+    if mod.matches?(method_name)
+      send(method_name, *args, &block)
+    else
+      super(method_name, *args, &block)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + matches?(method_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 51
+def matches?(method_name)
+  attr_name = method_name.to_s.chomp("=")
+  attributes.any? { |name| name == attr_name }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/Callbacks.html b/src/7.0/classes/ActiveModel/Validations/Callbacks.html new file mode 100644 index 0000000000..9ce7b309bc --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/Callbacks.html @@ -0,0 +1,101 @@ +--- +title: ActiveModel::Validations::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Active Model Validation Callbacks

+ +

Provides an interface for any class to have before_validation and after_validation callbacks.

+ +

First, include ActiveModel::Validations::Callbacks from the class you are creating:

+ +
class MyModel
+  include ActiveModel::Validations::Callbacks
+
+  before_validation :do_stuff_before_validation
+  after_validation  :do_stuff_after_validation
+end
+
+ +

Like other before_* callbacks if before_validation throws :abort then valid? will not be called.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/Callbacks/ClassMethods.html b/src/7.0/classes/ActiveModel/Validations/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..f094bcaa56 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/Callbacks/ClassMethods.html @@ -0,0 +1,197 @@ +--- +title: ActiveModel::Validations::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_validation(*args, &block) + +

+ + +
+

Defines a callback that will get called right after validation.

+ +
class Person
+  include ActiveModel::Validations
+  include ActiveModel::Validations::Callbacks
+
+  attr_accessor :name, :status
+
+  validates_presence_of :name
+
+  after_validation :set_status
+
+  private
+    def set_status
+      self.status = errors.empty?
+    end
+end
+
+person = Person.new
+person.name = ''
+person.valid? # => false
+person.status # => false
+person.name = 'bob'
+person.valid? # => true
+person.status # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/callbacks.rb, line 88
+def after_validation(*args, &block)
+  options = args.extract_options!
+  options = options.dup
+  options[:prepend] = true
+
+  set_options_for_callback(options)
+
+  set_callback(:validation, :after, *args, options, &block)
+end
+
+
+ +
+ +
+

+ + before_validation(*args, &block) + +

+ + +
+

Defines a callback that will get called right before validation.

+ +
class Person
+  include ActiveModel::Validations
+  include ActiveModel::Validations::Callbacks
+
+  attr_accessor :name
+
+  validates_length_of :name, maximum: 6
+
+  before_validation :remove_whitespaces
+
+  private
+    def remove_whitespaces
+      name.strip!
+    end
+end
+
+person = Person.new
+person.name = '  bob  '
+person.valid? # => true
+person.name   # => "bob"
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/callbacks.rb, line 55
+def before_validation(*args, &block)
+  options = args.extract_options!
+
+  set_options_for_callback(options)
+
+  set_callback(:validation, :before, *args, options, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/ClassMethods.html b/src/7.0/classes/ActiveModel/Validations/ClassMethods.html new file mode 100644 index 0000000000..bcf817aa66 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/ClassMethods.html @@ -0,0 +1,777 @@ +--- +title: ActiveModel::Validations::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attribute_method?(attribute) + +

+ + +
+

Returns true if attribute is an attribute method, false otherwise.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+end
+
+User.attribute_method?(:name) # => true
+User.attribute_method?(:age)  # => false
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 270
+def attribute_method?(attribute)
+  method_defined?(attribute)
+end
+
+
+ +
+ +
+

+ + clear_validators!() + +

+ + +
+

Clears all of the validators and validations.

+ +

Note that this will clear anything that is being used to validate the model for both the validates_with and validate methods. It clears the validators that are created with an invocation of validates_with and the callbacks that are set by an invocation of validate.

+ +
class Person
+  include ActiveModel::Validations
+
+  validates_with MyValidator
+  validates_with OtherValidator, on: :create
+  validates_with StrictValidator, strict: true
+  validate :cannot_be_robot
+
+  def cannot_be_robot
+    errors.add(:base, 'A person cannot be a robot') if person_is_robot
+  end
+end
+
+Person.validators
+# => [
+#      #<MyValidator:0x007fbff403e808 @options={}>,
+#      #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
+#      #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
+#    ]
+
+ +

If one runs Person.clear_validators! and then checks to see what validators this class has, you would obtain:

+ +
Person.validators # => []
+
+ +

Also, the callback set by validate :cannot_be_robot will be erased so that:

+ +
Person._validate_callbacks.empty?  # => true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 234
+def clear_validators!
+  reset_callbacks(:validate)
+  _validators.clear
+end
+
+
+ +
+ +
+

+ + validate(*args, &block) + +

+ + +
+

Adds a validation method or block to the class. This is useful when overriding the validate instance method becomes too unwieldy and you’re looking for more descriptive declaration of your validations.

+ +

This can be done with a symbol pointing to a method:

+ +
class Comment
+  include ActiveModel::Validations
+
+  validate :must_be_friends
+
+  def must_be_friends
+    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
+  end
+end
+
+ +

With a block which is passed with the current record to be validated:

+ +
class Comment
+  include ActiveModel::Validations
+
+  validate do |comment|
+    comment.must_be_friends
+  end
+
+  def must_be_friends
+    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
+  end
+end
+
+ +

Or with a block where self points to the current record to be validated:

+ +
class Comment
+  include ActiveModel::Validations
+
+  validate do
+    errors.add(:base, 'Must be friends to leave a comment') unless commenter.friend_of?(commentee)
+  end
+end
+
+ +

Note that the return value of validation methods is not relevant. It’s not possible to halt the validate callback chain.

+ +

Options:

+
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
+ +

NOTE: Calling validate multiple times on the same method will overwrite previous definitions.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 152
+def validate(*args, &block)
+  options = args.extract_options!
+
+  if args.all?(Symbol)
+    options.each_key do |k|
+      unless VALID_OPTIONS_FOR_VALIDATE.include?(k)
+        raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{VALID_OPTIONS_FOR_VALIDATE.map(&:inspect).join(', ')}. Perhaps you meant to call `validates` instead of `validate`?")
+      end
+    end
+  end
+
+  if options.key?(:on)
+    options = options.dup
+    options[:on] = Array(options[:on])
+    options[:if] = [
+      ->(o) { !(options[:on] & Array(o.validation_context)).empty? },
+      *options[:if]
+    ]
+  end
+
+  set_callback(:validate, *args, options, &block)
+end
+
+
+ +
+ +
+

+ + validates(*attributes) + +

+ + +
+

This method is a shortcut to all default validators and any custom validator classes ending in ‘Validator’. Note that Rails default validators can be overridden inside specific classes by creating custom validator classes in their place such as PresenceValidator.

+ +

Examples of using the default rails validators:

+ +
validates :username, absence: true
+validates :terms, acceptance: true
+validates :password, confirmation: true
+validates :username, exclusion: { in: %w(admin superuser) }
+validates :email, format: { with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create }
+validates :age, inclusion: { in: 0..9 }
+validates :first_name, length: { maximum: 30 }
+validates :age, numericality: true
+validates :username, presence: true
+
+ +

The power of the validates method comes when using custom validators and default validators in one call for a given attribute.

+ +
class EmailValidator < ActiveModel::EachValidator
+  def validate_each(record, attribute, value)
+    record.errors.add attribute, (options[:message] || "is not an email") unless
+      /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
+  end
+end
+
+class Person
+  include ActiveModel::Validations
+  attr_accessor :name, :email
+
+  validates :name, presence: true, length: { maximum: 100 }
+  validates :email, presence: true, email: true
+end
+
+ +

Validator classes may also exist within the class being validated allowing custom modules of validators to be included as needed.

+ +
class Film
+  include ActiveModel::Validations
+
+  class TitleValidator < ActiveModel::EachValidator
+    def validate_each(record, attribute, value)
+      record.errors.add attribute, "must start with 'the'" unless /\Athe/i.match?(value)
+    end
+  end
+
+  validates :name, title: true
+end
+
+ +

Additionally validator classes may be in another namespace and still used within any class.

+ +
validates :name, :'film/title' => true
+
+ +

The validators hash can also handle regular expressions, ranges, arrays and strings in shortcut form.

+ +
validates :email, format: /@/
+validates :role, inclusion: %w(admin contributor)
+validates :password, length: 6..20
+
+ +

When using shortcut form, ranges and arrays are passed to your validator’s initializer as options[:in] while other types including regular expressions and strings are passed as options[:with].

+ +

There is also a list of options that could be used along with validators:

+
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
  • +

    :allow_nil - Skip validation if the attribute is nil.

    +
  • +

    :allow_blank - Skip validation if the attribute is blank.

    +
  • +

    :strict - If the :strict option is set to true will raise ActiveModel::StrictValidationFailed instead of adding the error. :strict option can also be set to any other exception.

    +
+ +

Example:

+ +
validates :password, presence: true, confirmation: true, if: :password_required?
+validates :token, length: { is: 24 }, strict: TokenLengthException
+
+ +

Finally, the options :if, :unless, :on, :allow_blank, :allow_nil, :strict and :message can be given to one specific validator, as a hash:

+ +
validates :password, presence: { if: :password_required?, message: 'is forgotten.' }, confirmation: true
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/validates.rb, line 106
+def validates(*attributes)
+  defaults = attributes.extract_options!.dup
+  validations = defaults.slice!(*_validates_default_keys)
+
+  raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
+  raise ArgumentError, "You need to supply at least one validation" if validations.empty?
+
+  defaults[:attributes] = attributes
+
+  validations.each do |key, options|
+    key = "#{key.to_s.camelize}Validator"
+
+    begin
+      validator = key.include?("::") ? key.constantize : const_get(key)
+    rescue NameError
+      raise ArgumentError, "Unknown validator: '#{key}'"
+    end
+
+    next unless options
+
+    validates_with(validator, defaults.merge(_parse_validates_options(options)))
+  end
+end
+
+
+ +
+ +
+

+ + validates!(*attributes) + +

+ + +
+

This method is used to define validations that cannot be corrected by end users and are considered exceptional. So each validator defined with bang or :strict option set to true will always raise ActiveModel::StrictValidationFailed instead of adding error when validation fails. See validates for more information about the validation itself.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name
+  validates! :name, presence: true
+end
+
+person = Person.new
+person.name = ''
+person.valid?
+# => ActiveModel::StrictValidationFailed: Name can't be blank
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/validates.rb, line 148
+def validates!(*attributes)
+  options = attributes.extract_options!
+  options[:strict] = true
+  validates(*(attributes << options))
+end
+
+
+ +
+ +
+

+ + validates_each(*attr_names, &block) + +

+ + +
+

Validates each attribute against a block.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :first_name, :last_name
+
+  validates_each :first_name, :last_name, allow_blank: true do |record, attr, value|
+    record.errors.add attr, "starts with z." if value.start_with?("z")
+  end
+end
+
+ +

Options:

+
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :allow_nil - Skip validation if attribute is nil.

    +
  • +

    :allow_blank - Skip validation if attribute is blank.

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 85
+def validates_each(*attr_names, &block)
+  validates_with BlockValidator, _merge_attributes(attr_names), &block
+end
+
+
+ +
+ +
+

+ + validates_with(*args, &block) + +

+ + +
+

Passes the record off to the class or classes specified and allows them to add errors based on more complex conditions.

+ +
class Person
+  include ActiveModel::Validations
+  validates_with MyValidator
+end
+
+class MyValidator < ActiveModel::Validator
+  def validate(record)
+    if some_complex_logic
+      record.errors.add :base, 'This record is invalid'
+    end
+  end
+
+  private
+    def some_complex_logic
+      # ...
+    end
+end
+
+ +

You may also pass it multiple classes, like so:

+ +
class Person
+  include ActiveModel::Validations
+  validates_with MyValidator, MyOtherValidator, on: :create
+end
+
+ +

Configuration options:

+
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
  • +

    :strict - Specifies whether validation should be strict. See ActiveModel::Validations#validates! for more information.

    +
+ +

If you pass any additional configuration options, they will be passed to the class and available as options:

+ +
class Person
+  include ActiveModel::Validations
+  validates_with MyValidator, my_custom_key: 'my custom value'
+end
+
+class MyValidator < ActiveModel::Validator
+  def validate(record)
+    options[:my_custom_key] # => "my custom value"
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/with.rb, line 81
+def validates_with(*args, &block)
+  options = args.extract_options!
+  options[:class] = self
+
+  args.each do |klass|
+    validator = klass.new(options, &block)
+
+    if validator.respond_to?(:attributes) && !validator.attributes.empty?
+      validator.attributes.each do |attribute|
+        _validators[attribute.to_sym] << validator
+      end
+    else
+      _validators[nil] << validator
+    end
+
+    validate(validator, options)
+  end
+end
+
+
+ +
+ +
+

+ + validators() + +

+ + +
+

List all validators that are being used to validate the model using validates_with method.

+ +
class Person
+  include ActiveModel::Validations
+
+  validates_with MyValidator
+  validates_with OtherValidator, on: :create
+  validates_with StrictValidator, strict: true
+end
+
+Person.validators
+# => [
+#      #<MyValidator:0x007fbff403e808 @options={}>,
+#      #<OtherValidator:0x007fbff403d930 @options={on: :create}>,
+#      #<StrictValidator:0x007fbff3204a30 @options={strict:true}>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 192
+def validators
+  _validators.values.flatten.uniq
+end
+
+
+ +
+ +
+

+ + validators_on(*attributes) + +

+ + +
+

List all validators that are being used to validate a specific attribute.

+ +
class Person
+  include ActiveModel::Validations
+
+  attr_accessor :name, :age
+
+  validates_presence_of :name
+  validates_inclusion_of :age, in: 0..99
+end
+
+Person.validators_on(:name)
+# => [
+#       #<ActiveModel::Validations::PresenceValidator:0x007fe604914e60 @attributes=[:name], @options={}>,
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations.rb, line 254
+def validators_on(*attributes)
+  attributes.flat_map do |attribute|
+    _validators[attribute.to_sym]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validations/HelperMethods.html b/src/7.0/classes/ActiveModel/Validations/HelperMethods.html new file mode 100644 index 0000000000..44f566bf60 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validations/HelperMethods.html @@ -0,0 +1,815 @@ +--- +title: ActiveModel::Validations::HelperMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + validates_absence_of(*attr_names) + +

+ + +
+

Validates that the specified attributes are blank (as defined by Object#present?). Happens by default on save.

+ +
class Person < ActiveRecord::Base
+  validates_absence_of :first_name
+end
+
+ +

The first_name attribute must be in the object and it must be blank.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “must be blank”).

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/absence.rb, line 28
+def validates_absence_of(*attr_names)
+  validates_with AbsenceValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_acceptance_of(*attr_names) + +

+ + +
+

Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement).

+ +
class Person < ActiveRecord::Base
+  validates_acceptance_of :terms_of_service
+  validates_acceptance_of :eula, message: 'must be abided'
+end
+
+ +

If the database column does not exist, the terms_of_service attribute is entirely virtual. This check is performed only if terms_of_service is not nil and by default on save.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “must be accepted”).

    +
  • +

    :accept - Specifies a value that is considered accepted. Also accepts an array of possible values. The default value is an array [“1”, true], which makes it easy to relate to an HTML checkbox. This should be set to, or include, true if you are validating a database column, since the attribute is typecast from “1” to true before validation.

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/acceptance.rb, line 108
+def validates_acceptance_of(*attr_names)
+  validates_with AcceptanceValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_comparison_of(*attr_names) + +

+ + +
+

Validates the value of a specified attribute fulfills all defined comparisons with another value, proc, or attribute.

+ +
class Person < ActiveRecord::Base
+  validates_comparison_of :value, greater_than: 'the sum of its parts'
+end
+
+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “failed comparison”).

    +
  • +

    :greater_than - Specifies the value must be greater than the supplied value.

    +
  • +

    :greater_than_or_equal_to - Specifies the value must be greater than or equal to the supplied value.

    +
  • +

    :equal_to - Specifies the value must be equal to the supplied value.

    +
  • +

    :less_than - Specifies the value must be less than the supplied value.

    +
  • +

    :less_than_or_equal_to - Specifies the value must be less than or equal to the supplied value.

    +
  • +

    :other_than - Specifies the value must not be equal to the supplied value.

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict . See ActiveModel::Validations::ClassMethods#validates for more information.

+ +

The validator requires at least one of the following checks to be supplied. Each will accept a proc, value, or a symbol which corresponds to a method:

+
  • +

    :greater_than

    +
  • +

    :greater_than_or_equal_to

    +
  • +

    :equal_to

    +
  • +

    :less_than

    +
  • +

    :less_than_or_equal_to

    +
  • +

    :other_than

    +
+ +

For example:

+ +
class Person < ActiveRecord::Base
+  validates_comparison_of :birth_date, less_than_or_equal_to: -> { Date.today }
+  validates_comparison_of :preferred_name, other_than: :given_name, allow_nil: true
+end
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/comparison.rb, line 77
+def validates_comparison_of(*attr_names)
+  validates_with ComparisonValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_confirmation_of(*attr_names) + +

+ + +
+

Encapsulates the pattern of wanting to validate a password or email address field with a confirmation.

+ +
Model:
+  class Person < ActiveRecord::Base
+    validates_confirmation_of :user_name, :password
+    validates_confirmation_of :email_address,
+                              message: 'should match confirmation'
+  end
+
+View:
+  <%= password_field "person", "password" %>
+  <%= password_field "person", "password_confirmation" %>
+
+ +

The added password_confirmation attribute is virtual; it exists only as an in-memory attribute for validating the password. To achieve this, the validation adds accessors to the model for the confirmation attribute.

+ +

NOTE: This check is performed only if password_confirmation is not nil. To require confirmation, make sure to add a presence check for the confirmation attribute:

+ +
validates_presence_of :password_confirmation, if: :password_changed?
+
+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “doesn’t match %{translated_attribute_name}”).

    +
  • +

    :case_sensitive - Looks for an exact match. Ignored by non-text columns (true by default).

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/confirmation.rb, line 75
+def validates_confirmation_of(*attr_names)
+  validates_with ConfirmationValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_exclusion_of(*attr_names) + +

+ + +
+

Validates that the value of the specified attribute is not in a particular enumerable object.

+ +
class Person < ActiveRecord::Base
+  validates_exclusion_of :username, in: %w( admin superuser ), message: "You don't belong here"
+  validates_exclusion_of :age, in: 30..60, message: 'This site is only for under 30 and over 60'
+  validates_exclusion_of :format, in: %w( mov avi ), message: "extension %{value} is not allowed"
+  validates_exclusion_of :password, in: ->(person) { [person.username, person.first_name] },
+                         message: 'should not be the same as your username or first name'
+  validates_exclusion_of :karma, in: :reserved_karmas
+end
+
+ +

Configuration options:

+
  • +

    :in - An enumerable object of items that the value shouldn’t be part of. This can be supplied as a proc, lambda, or symbol which returns an enumerable. If the enumerable is a numerical, time, or datetime range the test is performed with Range#cover?, otherwise with include?. When using a proc or lambda the instance under validation is passed as an argument.

    +
  • +

    :within - A synonym(or alias) for :in Range#cover?, otherwise with include?.

    +
  • +

    :message - Specifies a custom error message (default is: “is reserved”).

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/exclusion.rb, line 44
+def validates_exclusion_of(*attr_names)
+  validates_with ExclusionValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_format_of(*attr_names) + +

+ + +
+

Validates whether the value of the specified attribute is of the correct form, going by the regular expression provided. You can require that the attribute matches the regular expression:

+ +
class Person < ActiveRecord::Base
+  validates_format_of :email, with: /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i, on: :create
+end
+
+ +

Alternatively, you can require that the specified attribute does not match the regular expression:

+ +
class Person < ActiveRecord::Base
+  validates_format_of :email, without: /NOSPAM/
+end
+
+ +

You can also provide a proc or lambda which will determine the regular expression that will be used to validate the attribute.

+ +
class Person < ActiveRecord::Base
+  # Admin can have number as a first letter in their screen name
+  validates_format_of :screen_name,
+                      with: ->(person) { person.admin? ? /\A[a-z0-9][a-z0-9_\-]*\z/i : /\A[a-z][a-z0-9_\-]*\z/i }
+end
+
+ +

Note: use \A and \z to match the start and end of the string, ^ and $ match the start/end of a line.

+ +

Due to frequent misuse of ^ and $, you need to pass the multiline: true option in case you use any of these two anchors in the provided regular expression. In most cases, you should be using \A and \z.

+ +

You must pass either :with or :without as an option. In addition, both must be a regular expression or a proc or lambda, or else an exception will be raised.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “is invalid”).

    +
  • +

    :with - Regular expression that if the attribute matches will result in a successful validation. This can be provided as a proc or lambda returning regular expression which will be called at runtime.

    +
  • +

    :without - Regular expression that if the attribute does not match will result in a successful validation. This can be provided as a proc or lambda returning regular expression which will be called at runtime.

    +
  • +

    :multiline - Set to true if your regular expression contains anchors that match the beginning or end of lines as opposed to the beginning or end of the string. These anchors are ^ and $.

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/format.rb, line 108
+def validates_format_of(*attr_names)
+  validates_with FormatValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_inclusion_of(*attr_names) + +

+ + +
+

Validates whether the value of the specified attribute is available in a particular enumerable object.

+ +
class Person < ActiveRecord::Base
+  validates_inclusion_of :role, in: %w( admin contributor )
+  validates_inclusion_of :age, in: 0..99
+  validates_inclusion_of :format, in: %w( jpg gif png ), message: "extension %{value} is not included in the list"
+  validates_inclusion_of :states, in: ->(person) { STATES[person.country] }
+  validates_inclusion_of :karma, in: :available_karmas
+end
+
+ +

Configuration options:

+
  • +

    :in - An enumerable object of available items. This can be supplied as a proc, lambda, or symbol which returns an enumerable. If the enumerable is a numerical, time, or datetime range the test is performed with Range#cover?, otherwise with include?. When using a proc or lambda the instance under validation is passed as an argument.

    +
  • +

    :within - A synonym(or alias) for :in

    +
  • +

    :message - Specifies a custom error message (default is: “is not included in the list”).

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/inclusion.rb, line 42
+def validates_inclusion_of(*attr_names)
+  validates_with InclusionValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_length_of(*attr_names) + +

+ + +
+

Validates that the specified attributes match the length restrictions supplied. Only one constraint option can be used at a time apart from :minimum and :maximum that can be combined together:

+ +
class Person < ActiveRecord::Base
+  validates_length_of :first_name, maximum: 30
+  validates_length_of :last_name, maximum: 30, message: "less than 30 if you don't mind"
+  validates_length_of :fax, in: 7..32, allow_nil: true
+  validates_length_of :phone, in: 7..32, allow_blank: true
+  validates_length_of :user_name, within: 6..20, too_long: 'pick a shorter name', too_short: 'pick a longer name'
+  validates_length_of :zip_code, minimum: 5, too_short: 'please enter at least 5 characters'
+  validates_length_of :smurf_leader, is: 4, message: "papa is spelled with 4 characters... don't play me."
+  validates_length_of :words_in_essay, minimum: 100, too_short: 'Your essay must be at least 100 words.'
+
+  private
+    def words_in_essay
+      essay.scan(/\w+/)
+    end
+end
+
+ +

Constraint options:

+
  • +

    :minimum - The minimum size of the attribute.

    +
  • +

    :maximum - The maximum size of the attribute. Allows nil by default if not used with :minimum.

    +
  • +

    :is - The exact size of the attribute.

    +
  • +

    :within - A range specifying the minimum and maximum size of the attribute.

    +
  • +

    :in - A synonym (or alias) for :within.

    +
+ +

Other options:

+
  • +

    :allow_nil - Attribute may be nil; skip validation.

    +
  • +

    :allow_blank - Attribute may be blank; skip validation.

    +
  • +

    :too_long - The error message if the attribute goes over the maximum (default is: “is too long (maximum is %{count} characters)”).

    +
  • +

    :too_short - The error message if the attribute goes under the minimum (default is: “is too short (minimum is %{count} characters)”).

    +
  • +

    :wrong_length - The error message if using the :is method and the attribute is the wrong size (default is: “is the wrong length (should be %{count} characters)”).

    +
  • +

    :message - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate too_long/too_short/wrong_length message.

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + +
+ Also aliased as: validates_size_of +
+ + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/length.rb, line 121
+def validates_length_of(*attr_names)
+  validates_with LengthValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_numericality_of(*attr_names) + +

+ + +
+

Validates whether the value of the specified attribute is numeric by trying to convert it to a float with Kernel.Float (if only_integer is false) or applying it to the regular expression /\A[+\-]?\d+\z/ (if only_integer is set to true). Precision of Kernel.Float values are guaranteed up to 15 digits.

+ +
class Person < ActiveRecord::Base
+  validates_numericality_of :value, on: :create
+end
+
+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “is not a number”).

    +
  • +

    :only_integer - Specifies whether the value has to be an integer (default is false).

    +
  • +

    :allow_nil - Skip validation if attribute is nil (default is false). Notice that for Integer and Float columns empty strings are converted to nil.

    +
  • +

    :greater_than - Specifies the value must be greater than the supplied value.

    +
  • +

    :greater_than_or_equal_to - Specifies the value must be greater than or equal the supplied value.

    +
  • +

    :equal_to - Specifies the value must be equal to the supplied value.

    +
  • +

    :less_than - Specifies the value must be less than the supplied value.

    +
  • +

    :less_than_or_equal_to - Specifies the value must be less than or equal the supplied value.

    +
  • +

    :other_than - Specifies the value must be other than the supplied value.

    +
  • +

    :odd - Specifies the value must be an odd number.

    +
  • +

    :even - Specifies the value must be an even number.

    +
  • +

    :in - Check that the value is within a range.

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict . See ActiveModel::Validations::ClassMethods#validates for more information.

+ +

The following checks can also be supplied with a proc or a symbol which corresponds to a method:

+
  • +

    :greater_than

    +
  • +

    :greater_than_or_equal_to

    +
  • +

    :equal_to

    +
  • +

    :less_than

    +
  • +

    :less_than_or_equal_to

    +
  • +

    :only_integer

    +
  • +

    :other_than

    +
+ +

For example:

+ +
class Person < ActiveRecord::Base
+  validates_numericality_of :width, less_than: ->(person) { person.height }
+  validates_numericality_of :width, greater_than: :minimum_weight
+end
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/numericality.rb, line 205
+def validates_numericality_of(*attr_names)
+  validates_with NumericalityValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_presence_of(*attr_names) + +

+ + +
+

Validates that the specified attributes are not blank (as defined by Object#blank?). Happens by default on save.

+ +
class Person < ActiveRecord::Base
+  validates_presence_of :first_name
+end
+
+ +

The first_name attribute must be in the object and it cannot be blank.

+ +

If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, in: [true, false].

+ +

This is due to the way Object#blank? handles boolean values: false.blank? # => true.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “can’t be blank”).

    +
+ +

There is also a list of default options supported by every validator: :if, :unless, :on, :allow_nil, :allow_blank, and :strict. See ActiveModel::Validations::ClassMethods#validates for more information.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validations/presence.rb, line 34
+def validates_presence_of(*attr_names)
+  validates_with PresenceValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_size_of(*attr_names) + +

+ + +
+ +
+ + + + + +
+ Alias for: validates_length_of +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveModel/Validator.html b/src/7.0/classes/ActiveModel/Validator.html new file mode 100644 index 0000000000..674475ab25 --- /dev/null +++ b/src/7.0/classes/ActiveModel/Validator.html @@ -0,0 +1,343 @@ +--- +title: ActiveModel::Validator +layout: default +--- +
+ +
+
+ +
+ +

Active Model Validator

+ +

A simple base class that can be used along with ActiveModel::Validations::ClassMethods.validates_with

+ +
class Person
+  include ActiveModel::Validations
+  validates_with MyValidator
+end
+
+class MyValidator < ActiveModel::Validator
+  def validate(record)
+    if some_complex_logic
+      record.errors.add(:base, "This record is invalid")
+    end
+  end
+
+  private
+    def some_complex_logic
+      # ...
+    end
+end
+
+ +

Any class that inherits from ActiveModel::Validator must implement a method called validate which accepts a record.

+ +
class Person
+  include ActiveModel::Validations
+  validates_with MyValidator
+end
+
+class MyValidator < ActiveModel::Validator
+  def validate(record)
+    record # => The person instance being validated
+    options # => Any non-standard options passed to validates_with
+  end
+end
+
+ +

To cause a validation error, you must add to the record‘s errors directly from within the validators message.

+ +
class MyValidator < ActiveModel::Validator
+  def validate(record)
+    record.errors.add :base, "This is some custom error message"
+    record.errors.add :first_name, "This is some complex validation"
+    # etc...
+  end
+end
+
+ +

To add behavior to the initialize method, use the following signature:

+ +
class MyValidator < ActiveModel::Validator
+  def initialize(options)
+    super
+    @my_custom_field = options[:field_name] || :first_name
+  end
+end
+
+ +

Note that the validator is initialized only once for the whole application life cycle, and not on each validation run.

+ +

The easiest way to add custom validators for validating individual attributes is with the convenient ActiveModel::EachValidator.

+ +
class TitleValidator < ActiveModel::EachValidator
+  def validate_each(record, attribute, value)
+    record.errors.add attribute, 'must be Mr., Mrs., or Dr.' unless %w(Mr. Mrs. Dr.).include?(value)
+  end
+end
+
+ +

This can now be used in combination with the validates method (see ActiveModel::Validations::ClassMethods#validates for more on this).

+ +
class Person
+  include ActiveModel::Validations
+  attr_accessor :title
+
+  validates :title, presence: true, title: true
+end
+
+ +

It can be useful to access the class that is using that validator when there are prerequisites such as an attr_accessor being present. This class is accessible via options[:class] in the constructor. To set up your validator override the constructor.

+ +
class MyValidator < ActiveModel::Validator
+  def initialize(options={})
+    super
+    options[:class].attr_accessor :custom_attribute
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + options
+ + + + +

Class Public methods

+ +
+

+ + kind() + +

+ + +
+

Returns the kind of the validator.

+ +
PresenceValidator.kind   # => :presence
+AcceptanceValidator.kind # => :acceptance
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 103
+def self.kind
+  @kind ||= name.split("::").last.underscore.chomp("_validator").to_sym unless anonymous?
+end
+
+
+ +
+ +
+

+ + new(options = {}) + +

+ + +
+

Accepts options that will be made available through the options reader.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 108
+def initialize(options = {})
+  @options = options.except(:class).freeze
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + kind() + +

+ + +
+

Returns the kind for this validator.

+ +
PresenceValidator.new(attributes: [:username]).kind # => :presence
+AcceptanceValidator.new(attributes: [:terms]).kind  # => :acceptance
+
+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 116
+def kind
+  self.class.kind
+end
+
+
+ +
+ +
+

+ + validate(record) + +

+ + +
+

Override this method in subclasses with validation logic, adding errors to the records errors array where necessary.

+
+ + + + + + + + +
+ + +
+
# File activemodel/lib/active_model/validator.rb, line 122
+def validate(record)
+  raise NotImplementedError, "Subclasses must implement a validate(record) method."
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord.html b/src/7.0/classes/ActiveRecord.html new file mode 100644 index 0000000000..ca4e24a730 --- /dev/null +++ b/src/7.0/classes/ActiveRecord.html @@ -0,0 +1,1061 @@ +--- +title: ActiveRecord +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MigrationProxy=Struct.new(:name, :version, :filename, :scope) do +def initialize(name, version, filename, scope) +super +@migration = nil +end + +def basename +File.basename(filename) +end + +delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration + +private +def migration +@migration ||= load_migration +end + +def load_migration +Object.send(:remove_const, name) rescue nil + +load(File.expand_path(filename)) +name.constantize.new(name, version) +end +end
 

MigrationProxy is used to defer loading of the actual migration classes until they are needed

Point=Struct.new(:x, :y)
 
UnknownAttributeError=ActiveModel::UnknownAttributeError
 

Raised when unknown attributes are supplied via mass assignment.

+ +
class Person
+  include ActiveModel::AttributeAssignment
+  include ActiveModel::Validations
+end
+
+person = Person.new
+person.assign_attributes(name: 'Gorby')
+# => ActiveModel::UnknownAttributeError: unknown attribute 'name' for Person.
+
+ + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Active Record as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Active Record as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ActiveJobRequiredError.html b/src/7.0/classes/ActiveRecord/ActiveJobRequiredError.html new file mode 100644 index 0000000000..13290bca27 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ActiveJobRequiredError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ActiveJobRequiredError +layout: default +--- +
+ +
+
+ +
+ +

Raised when trying to use a feature in Active Record which requires Active Job but the gem is not present.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ActiveRecordError.html b/src/7.0/classes/ActiveRecord/ActiveRecordError.html new file mode 100644 index 0000000000..7a421062c4 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ActiveRecordError.html @@ -0,0 +1,68 @@ +--- +title: ActiveRecord::ActiveRecordError +layout: default +--- +
+ +
+
+ +
+ +

Active Record Errors

+ +

Generic Active Record exception class.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AdapterNotFound.html b/src/7.0/classes/ActiveRecord/AdapterNotFound.html new file mode 100644 index 0000000000..efe527bd1d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AdapterNotFound.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::AdapterNotFound +layout: default +--- +
+ +
+
+ +
+ +

Raised when Active Record cannot find database adapter specified in config/database.yml or programmatically.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AdapterNotSpecified.html b/src/7.0/classes/ActiveRecord/AdapterNotSpecified.html new file mode 100644 index 0000000000..cd55c0d936 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AdapterNotSpecified.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::AdapterNotSpecified +layout: default +--- +
+ +
+
+ +
+ +

Raised when adapter not specified on connection (or configuration file config/database.yml misses adapter field).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AdapterTimeout.html b/src/7.0/classes/ActiveRecord/AdapterTimeout.html new file mode 100644 index 0000000000..6766f9161e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AdapterTimeout.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::AdapterTimeout +layout: default +--- +
+ +
+
+ +
+ +

AdapterTimeout will be raised when database clients times out while waiting from the server.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Aggregations.html b/src/7.0/classes/ActiveRecord/Aggregations.html new file mode 100644 index 0000000000..cb8a91dc99 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Aggregations.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::Aggregations +layout: default +--- +
+ +
+
+ +
+ +

See ActiveRecord::Aggregations::ClassMethods for documentation

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Aggregations/ClassMethods.html b/src/7.0/classes/ActiveRecord/Aggregations/ClassMethods.html new file mode 100644 index 0000000000..057100d400 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Aggregations/ClassMethods.html @@ -0,0 +1,294 @@ +--- +title: ActiveRecord::Aggregations::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Active Record implements aggregation through a macro-like class method called composed_of for representing attributes as value objects. It expresses relationships like “Account [is] composed of Money [among other things]” or “Person [is] composed of [an] address”. Each call to the macro adds a description of how the value objects are created from the attributes of the entity object (when the entity is initialized either as a new object or from finding an existing object) and how it can be turned back into attributes (when the entity is saved to the database).

+ +
class Customer < ActiveRecord::Base
+  composed_of :balance, class_name: "Money", mapping: %w(balance amount)
+  composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
+end
+
+ +

The customer class now has the following methods to manipulate the value objects:

+
  • +

    Customer#balance, Customer#balance=(money)

    +
  • +

    Customer#address, Customer#address=(address)

    +
+ +

These methods will operate with value objects like the ones described below:

+ +
class Money
+  include Comparable
+  attr_reader :amount, :currency
+  EXCHANGE_RATES = { "USD_TO_DKK" => 6 }
+
+  def initialize(amount, currency = "USD")
+    @amount, @currency = amount, currency
+  end
+
+  def exchange_to(other_currency)
+    exchanged_amount = (amount * EXCHANGE_RATES["#{currency}_TO_#{other_currency}"]).floor
+    Money.new(exchanged_amount, other_currency)
+  end
+
+  def ==(other_money)
+    amount == other_money.amount && currency == other_money.currency
+  end
+
+  def <=>(other_money)
+    if currency == other_money.currency
+      amount <=> other_money.amount
+    else
+      amount <=> other_money.exchange_to(currency).amount
+    end
+  end
+end
+
+class Address
+  attr_reader :street, :city
+  def initialize(street, city)
+    @street, @city = street, city
+  end
+
+  def close_to?(other_address)
+    city == other_address.city
+  end
+
+  def ==(other_address)
+    city == other_address.city && street == other_address.street
+  end
+end
+
+ +

Now it’s possible to access attributes from the database through the value objects instead. If you choose to name the composition the same as the attribute’s name, it will be the only way to access that attribute. That’s the case with our balance attribute. You interact with the value objects just like you would with any other attribute:

+ +
customer.balance = Money.new(20)     # sets the Money value object and the attribute
+customer.balance                     # => Money value object
+customer.balance.exchange_to("DKK")  # => Money.new(120, "DKK")
+customer.balance > Money.new(10)     # => true
+customer.balance == Money.new(20)    # => true
+customer.balance < Money.new(5)      # => false
+
+ +

Value objects can also be composed of multiple attributes, such as the case of Address. The order of the mappings will determine the order of the parameters.

+ +
customer.address_street = "Hyancintvej"
+customer.address_city   = "Copenhagen"
+customer.address        # => Address.new("Hyancintvej", "Copenhagen")
+
+customer.address = Address.new("May Street", "Chicago")
+customer.address_street # => "May Street"
+customer.address_city   # => "Chicago"
+
+ +

Writing value objects

+ +

Value objects are immutable and interchangeable objects that represent a given value, such as a Money object representing $5. Two Money objects both representing $5 should be equal (through methods such as == and <=> from Comparable if ranking makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as Customer can easily have two different objects that both have an address on Hyancintvej. Entity identity is determined by object or relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects.

+ +

It’s also important to treat the value objects as immutable. Don’t allow the Money object to have its amount changed after creation. Create a new Money object with the new value instead. The Money#exchange_to method is an example of this. It returns a new value object instead of changing its own values. Active Record won’t persist value objects that have been changed through means other than the writer method.

+ +

The immutable requirement is enforced by Active Record by freezing any object assigned as a value object. Attempting to change it afterwards will result in a RuntimeError.

+ +

Read more about value objects on c2.com/cgi/wiki?ValueObject and on the dangers of not keeping value objects immutable on c2.com/cgi/wiki?ValueObjectsShouldBeImmutable

+ +

Custom constructors and converters

+ +

By default value objects are initialized by calling the new constructor of the value class passing each of the mapped attributes, in the order specified by the :mapping option, as arguments. If the value class doesn’t support this convention then composed_of allows a custom constructor to be specified.

+ +

When a new value is assigned to the value object, the default assumption is that the new value is an instance of the value class. Specifying a custom converter allows the new value to be automatically converted to an instance of value class if necessary.

+ +

For example, the NetworkResource model has network_address and cidr_range attributes that should be aggregated using the NetAddr::CIDR value class (www.rubydoc.info/gems/netaddr/1.5.0/NetAddr/CIDR). The constructor for the value class is called create and it expects a CIDR address string as a parameter. New values can be assigned to the value object using either another NetAddr::CIDR object, a string or an array. The :constructor and :converter options can be used to meet these requirements:

+ +
class NetworkResource < ActiveRecord::Base
+  composed_of :cidr,
+              class_name: 'NetAddr::CIDR',
+              mapping: [ %w(network_address network), %w(cidr_range bits) ],
+              allow_nil: true,
+              constructor: Proc.new { |network_address, cidr_range| NetAddr::CIDR.create("#{network_address}/#{cidr_range}") },
+              converter: Proc.new { |value| NetAddr::CIDR.create(value.is_a?(Array) ? value.join('/') : value) }
+end
+
+# This calls the :constructor
+network_resource = NetworkResource.new(network_address: '192.168.0.1', cidr_range: 24)
+
+# These assignments will both use the :converter
+network_resource.cidr = [ '192.168.2.1', 8 ]
+network_resource.cidr = '192.168.0.1/24'
+
+# This assignment won't use the :converter as the value is already an instance of the value class
+network_resource.cidr = NetAddr::CIDR.create('192.168.2.1/8')
+
+# Saving and then reloading will use the :constructor on reload
+network_resource.save
+network_resource.reload
+
+ +

Finding records by a value object

+ +

Once a composed_of relationship is specified for a model, records can be loaded from the database by specifying an instance of the value object in the conditions hash. The following example finds all customers with address_street equal to “May Street” and address_city equal to “Chicago”:

+ +
Customer.where(address: Address.new("May Street", "Chicago"))
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + composed_of(part_id, options = {}) + +

+ + +
+

Adds reader and writer methods for manipulating a value object: composed_of :address adds address and address=(new_address) methods.

+ +

Options are:

+
  • +

    :class_name - Specifies the class name of the association. Use it only if that name can’t be inferred from the part id. So composed_of :address will by default be linked to the Address class, but if the real class name is CompanyAddress, you’ll have to specify it with this option.

    +
  • +

    :mapping - Specifies the mapping of entity attributes to attributes of the value object. Each mapping is represented as an array where the first item is the name of the entity attribute and the second item is the name of the attribute in the value object. The order in which mappings are defined determines the order in which attributes are sent to the value class constructor.

    +
  • +

    :allow_nil - Specifies that the value object will not be instantiated when all mapped attributes are nil. Setting the value object to nil has the effect of writing nil to all mapped attributes. This defaults to false.

    +
  • +

    :constructor - A symbol specifying the name of the constructor method or a Proc that is called to initialize the value object. The constructor is passed all of the mapped attributes, in the order that they are defined in the :mapping option, as arguments and uses them to instantiate a :class_name object. The default is :new.

    +
  • +

    :converter - A symbol specifying the name of a class method of :class_name or a Proc that is called when a new value is assigned to the value object. The converter is passed the single value that is used in the assignment and is only called if the new value is not an instance of :class_name. If :allow_nil is set to true, the converter can return nil to skip the assignment.

    +
+ +

Option examples:

+ +
composed_of :temperature, mapping: %w(reading celsius)
+composed_of :balance, class_name: "Money", mapping: %w(balance amount)
+composed_of :address, mapping: [ %w(address_street street), %w(address_city city) ]
+composed_of :gps_location
+composed_of :gps_location, allow_nil: true
+composed_of :ip_address,
+            class_name: 'IPAddr',
+            mapping: %w(ip to_i),
+            constructor: Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) },
+            converter: Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) }
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/aggregations.rb, line 222
+def composed_of(part_id, options = {})
+  options.assert_valid_keys(:class_name, :mapping, :allow_nil, :constructor, :converter)
+
+  unless self < Aggregations
+    include Aggregations
+  end
+
+  name        = part_id.id2name
+  class_name  = options[:class_name]  || name.camelize
+  mapping     = options[:mapping]     || [ name, name ]
+  mapping     = [ mapping ] unless mapping.first.is_a?(Array)
+  allow_nil   = options[:allow_nil]   || false
+  constructor = options[:constructor] || :new
+  converter   = options[:converter]
+
+  reader_method(name, class_name, mapping, allow_nil, constructor)
+  writer_method(name, class_name, mapping, allow_nil, converter)
+
+  reflection = ActiveRecord::Reflection.create(:composed_of, part_id, nil, options, self)
+  Reflection.add_aggregate_reflection self, part_id, reflection
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AssociationTypeMismatch.html b/src/7.0/classes/ActiveRecord/AssociationTypeMismatch.html new file mode 100644 index 0000000000..787feef7f7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AssociationTypeMismatch.html @@ -0,0 +1,78 @@ +--- +title: ActiveRecord::AssociationTypeMismatch +layout: default +--- +
+ +
+
+ +
+ +

Raised when an object assigned to an association has an incorrect type.

+ +
class Ticket < ActiveRecord::Base
+  has_many :patches
+end
+
+class Patch < ActiveRecord::Base
+  belongs_to :ticket
+end
+
+# Comments are not patches, this assignment raises AssociationTypeMismatch.
+@ticket.patches << Comment.new(content: "Please attach tests to your patch.")
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations.html b/src/7.0/classes/ActiveRecord/Associations.html new file mode 100644 index 0000000000..2f65d427b1 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations.html @@ -0,0 +1,150 @@ +--- +title: ActiveRecord::Associations +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/ClassMethods.html b/src/7.0/classes/ActiveRecord/Associations/ClassMethods.html new file mode 100644 index 0000000000..1e7339d6b4 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/ClassMethods.html @@ -0,0 +1,1711 @@ +--- +title: ActiveRecord::Associations::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Associations are a set of macro-like class methods for tying objects together through foreign keys. They express relationships like “Project has one Project Manager” or “Project belongs to a Portfolio”. Each macro adds a number of methods to the class which are specialized according to the collection or association symbol and the options hash. It works much the same way as Ruby’s own attr* methods.

+ +
class Project < ActiveRecord::Base
+  belongs_to              :portfolio
+  has_one                 :project_manager
+  has_many                :milestones
+  has_and_belongs_to_many :categories
+end
+
+ +

The project class now has the following methods (and more) to ease the traversal and manipulation of its relationships:

+
  • +

    Project#portfolio, Project#portfolio=(portfolio), Project#reload_portfolio

    +
  • +

    Project#project_manager, Project#project_manager=(project_manager), Project#reload_project_manager

    +
  • +

    Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone), Project#milestones.delete(milestone), Project#milestones.destroy(milestone), Project#milestones.find(milestone_id), Project#milestones.build, Project#milestones.create

    +
  • +

    Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1), Project#categories.delete(category1), Project#categories.destroy(category1)

    +
+ +

A word of warning

+ +

Don’t create associations that have the same name as instance methods of ActiveRecord::Base. Since the association adds a method with that name to its model, using an association with the same name as one provided by ActiveRecord::Base will override the method inherited through ActiveRecord::Base and will break things. For instance, attributes and connection would be bad choices for association names, because those names already exist in the list of ActiveRecord::Base instance methods.

+ +

Auto-generated methods

+ +

See also Instance Public methods below for more details.

+ +

Singular associations (one-to-one)

+ +
                                  |            |  belongs_to  |
+generated methods                 | belongs_to | :polymorphic | has_one
+----------------------------------+------------+--------------+---------
+other                             |     X      |      X       |    X
+other=(other)                     |     X      |      X       |    X
+build_other(attributes={})        |     X      |              |    X
+create_other(attributes={})       |     X      |              |    X
+create_other!(attributes={})      |     X      |              |    X
+reload_other                      |     X      |      X       |    X
+other_changed?                    |     X      |      X       |
+other_previously_changed?         |     X      |      X       |
+
+ +

Collection associations (one-to-many / many-to-many)

+ +
                                  |       |          | has_many
+generated methods                 | habtm | has_many | :through
+----------------------------------+-------+----------+----------
+others                            |   X   |    X     |    X
+others=(other,other,...)          |   X   |    X     |    X
+other_ids                         |   X   |    X     |    X
+other_ids=(id,id,...)             |   X   |    X     |    X
+others<<                          |   X   |    X     |    X
+others.push                       |   X   |    X     |    X
+others.concat                     |   X   |    X     |    X
+others.build(attributes={})       |   X   |    X     |    X
+others.create(attributes={})      |   X   |    X     |    X
+others.create!(attributes={})     |   X   |    X     |    X
+others.size                       |   X   |    X     |    X
+others.length                     |   X   |    X     |    X
+others.count                      |   X   |    X     |    X
+others.sum(*args)                 |   X   |    X     |    X
+others.empty?                     |   X   |    X     |    X
+others.clear                      |   X   |    X     |    X
+others.delete(other,other,...)    |   X   |    X     |    X
+others.delete_all                 |   X   |    X     |    X
+others.destroy(other,other,...)   |   X   |    X     |    X
+others.destroy_all                |   X   |    X     |    X
+others.find(*args)                |   X   |    X     |    X
+others.exists?                    |   X   |    X     |    X
+others.distinct                   |   X   |    X     |    X
+others.reset                      |   X   |    X     |    X
+others.reload                     |   X   |    X     |    X
+
+ +

Overriding generated methods

+ +

Association methods are generated in a module included into the model class, making overrides easy. The original generated method can thus be called with super:

+ +
class Car < ActiveRecord::Base
+  belongs_to :owner
+  belongs_to :old_owner
+
+  def owner=(new_owner)
+    self.old_owner = self.owner
+    super
+  end
+end
+
+ +

The association methods module is included immediately after the generated attributes methods module, meaning an association will override the methods for an attribute with the same name.

+ +

Cardinality and associations

+ +

Active Record associations can be used to describe one-to-one, one-to-many, and many-to-many relationships between models. Each model uses an association to describe its role in the relation. The belongs_to association is always used in the model that has the foreign key.

+ +

One-to-one

+ +

Use has_one in the base, and belongs_to in the associated model.

+ +
class Employee < ActiveRecord::Base
+  has_one :office
+end
+class Office < ActiveRecord::Base
+  belongs_to :employee    # foreign key - employee_id
+end
+
+ +

One-to-many

+ +

Use has_many in the base, and belongs_to in the associated model.

+ +
class Manager < ActiveRecord::Base
+  has_many :employees
+end
+class Employee < ActiveRecord::Base
+  belongs_to :manager     # foreign key - manager_id
+end
+
+ +

Many-to-many

+ +

There are two ways to build a many-to-many relationship.

+ +

The first way uses a has_many association with the :through option and a join model, so there are two stages of associations.

+ +
class Assignment < ActiveRecord::Base
+  belongs_to :programmer  # foreign key - programmer_id
+  belongs_to :project     # foreign key - project_id
+end
+class Programmer < ActiveRecord::Base
+  has_many :assignments
+  has_many :projects, through: :assignments
+end
+class Project < ActiveRecord::Base
+  has_many :assignments
+  has_many :programmers, through: :assignments
+end
+
+ +

For the second way, use has_and_belongs_to_many in both models. This requires a join table that has no corresponding model or primary key.

+ +
class Programmer < ActiveRecord::Base
+  has_and_belongs_to_many :projects       # foreign keys in the join table
+end
+class Project < ActiveRecord::Base
+  has_and_belongs_to_many :programmers    # foreign keys in the join table
+end
+
+ +

Choosing which way to build a many-to-many relationship is not always simple. If you need to work with the relationship model as its own entity, use has_many :through. Use has_and_belongs_to_many when working with legacy schemas or when you never work directly with the relationship itself.

+ +

Is it a belongs_to or has_one association?

+ +

Both express a 1-1 relationship. The difference is mostly where to place the foreign key, which goes on the table for the class declaring the belongs_to relationship.

+ +
class User < ActiveRecord::Base
+  # I reference an account.
+  belongs_to :account
+end
+
+class Account < ActiveRecord::Base
+  # One user references me.
+  has_one :user
+end
+
+ +

The tables for these classes could look something like:

+ +
CREATE TABLE users (
+  id bigint NOT NULL auto_increment,
+  account_id bigint default NULL,
+  name varchar default NULL,
+  PRIMARY KEY  (id)
+)
+
+CREATE TABLE accounts (
+  id bigint NOT NULL auto_increment,
+  name varchar default NULL,
+  PRIMARY KEY  (id)
+)
+
+ +

Unsaved objects and associations

+ +

You can manipulate objects and associations before they are saved to the database, but there is some special behavior you should be aware of, mostly involving the saving of associated objects.

+ +

You can set the :autosave option on a has_one, belongs_to, has_many, or has_and_belongs_to_many association. Setting it to true will always save the members, whereas setting it to false will never save the members. More details about :autosave option is available at AutosaveAssociation.

+ +

One-to-one associations

+
  • +

    Assigning an object to a has_one association automatically saves that object and the object being replaced (if there is one), in order to update their foreign keys - except if the parent object is unsaved (new_record? == true).

    +
  • +

    If either of these saves fail (due to one of the objects being invalid), an ActiveRecord::RecordNotSaved exception is raised and the assignment is cancelled.

    +
  • +

    If you wish to assign an object to a has_one association without saving it, use the #build_association method (documented below). The object being replaced will still be saved to update its foreign key.

    +
  • +

    Assigning an object to a belongs_to association does not save the object, since the foreign key field belongs on the parent. It does not save the parent either.

    +
+ +

Collections

+
  • +

    Adding an object to a collection (has_many or has_and_belongs_to_many) automatically saves that object, except if the parent object (the owner of the collection) is not yet stored in the database.

    +
  • +

    If saving any of the objects being added to a collection (via push or similar) fails, then push returns false.

    +
  • +

    If saving fails while replacing the collection (via association=), an ActiveRecord::RecordNotSaved exception is raised and the assignment is cancelled.

    +
  • +

    You can add an object to a collection without automatically saving it by using the collection.build method (documented below).

    +
  • +

    All unsaved (new_record? == true) members of the collection are automatically saved when the parent is saved.

    +
+ +

Customizing the query

+ +

Associations are built from Relation objects, and you can use the Relation syntax to customize them. For example, to add a condition:

+ +
class Blog < ActiveRecord::Base
+  has_many :published_posts, -> { where(published: true) }, class_name: 'Post'
+end
+
+ +

Inside the -> { ... } block you can use all of the usual Relation methods.

+ +

Accessing the owner object

+ +

Sometimes it is useful to have access to the owner object when building the query. The owner is passed as a parameter to the block. For example, the following association would find all events that occur on the user’s birthday:

+ +
class User < ActiveRecord::Base
+  has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
+end
+
+ +

Note: Joining or eager loading such associations is not possible because those operations happen before instance creation. Such associations can be preloaded, but doing so will perform N+1 queries because there will be a different scope for each record (similar to preloading polymorphic scopes).

+ +

Association callbacks

+ +

Similar to the normal callbacks that hook into the life cycle of an Active Record object, you can also define callbacks that get triggered when you add an object to or remove an object from an association collection.

+ +
class Firm < ActiveRecord::Base
+  has_many :clients,
+           dependent: :destroy,
+           after_add: :congratulate_client,
+           after_remove: :log_after_remove
+
+  def congratulate_client(record)
+    # ...
+  end
+
+  def log_after_remove(record)
+    # ...
+  end
+
+ +

It’s possible to stack callbacks by passing them as an array. Example:

+ +
class Firm < ActiveRecord::Base
+  has_many :clients,
+           dependent: :destroy,
+           after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
+           after_remove: :log_after_remove
+end
+
+ +

Possible callbacks are: before_add, after_add, before_remove, and after_remove.

+ +

If any of the before_add callbacks throw an exception, the object will not be added to the collection.

+ +

Similarly, if any of the before_remove callbacks throw an exception, the object will not be removed from the collection.

+ +

Note: To trigger remove callbacks, you must use destroy / destroy_all methods. For example:

+
  • +

    firm.clients.destroy(client)

    +
  • +

    firm.clients.destroy(*clients)

    +
  • +

    firm.clients.destroy_all

    +
+ +

delete / delete_all methods like the following do not trigger remove callbacks:

+
  • +

    firm.clients.delete(client)

    +
  • +

    firm.clients.delete(*clients)

    +
  • +

    firm.clients.delete_all

    +
+ +

Association extensions

+ +

The proxy objects that control the access to associations can be extended through anonymous modules. This is especially beneficial for adding new finders, creators, and other factory-type methods that are only used as part of this association.

+ +
class Account < ActiveRecord::Base
+  has_many :people do
+    def find_or_create_by_name(name)
+      first_name, last_name = name.split(" ", 2)
+      find_or_create_by(first_name: first_name, last_name: last_name)
+    end
+  end
+end
+
+person = Account.first.people.find_or_create_by_name("David Heinemeier Hansson")
+person.first_name # => "David"
+person.last_name  # => "Heinemeier Hansson"
+
+ +

If you need to share the same extensions between many associations, you can use a named extension module.

+ +
module FindOrCreateByNameExtension
+  def find_or_create_by_name(name)
+    first_name, last_name = name.split(" ", 2)
+    find_or_create_by(first_name: first_name, last_name: last_name)
+  end
+end
+
+class Account < ActiveRecord::Base
+  has_many :people, -> { extending FindOrCreateByNameExtension }
+end
+
+class Company < ActiveRecord::Base
+  has_many :people, -> { extending FindOrCreateByNameExtension }
+end
+
+ +

Some extensions can only be made to work with knowledge of the association’s internals. Extensions can access relevant state using the following methods (where items is the name of the association):

+
  • +

    record.association(:items).owner - Returns the object the association is part of.

    +
  • +

    record.association(:items).reflection - Returns the reflection object that describes the association.

    +
  • +

    record.association(:items).target - Returns the associated object for belongs_to and has_one, or the collection of associated objects for has_many and has_and_belongs_to_many.

    +
+ +

However, inside the actual extension code, you will not have access to the record as above. In this case, you can access proxy_association. For example, record.association(:items) and record.items.proxy_association will return the same object, allowing you to make calls like proxy_association.owner inside association extensions.

+ +

Association Join Models

+ +

Has Many associations can be configured with the :through option to use an explicit join model to retrieve the data. This operates similarly to a has_and_belongs_to_many association. The advantage is that you’re able to add validations, callbacks, and extra attributes on the join model. Consider the following schema:

+ +
class Author < ActiveRecord::Base
+  has_many :authorships
+  has_many :books, through: :authorships
+end
+
+class Authorship < ActiveRecord::Base
+  belongs_to :author
+  belongs_to :book
+end
+
+@author = Author.first
+@author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
+@author.books                              # selects all books by using the Authorship join model
+
+ +

You can also go through a has_many association on the join model:

+ +
class Firm < ActiveRecord::Base
+  has_many   :clients
+  has_many   :invoices, through: :clients
+end
+
+class Client < ActiveRecord::Base
+  belongs_to :firm
+  has_many   :invoices
+end
+
+class Invoice < ActiveRecord::Base
+  belongs_to :client
+end
+
+@firm = Firm.first
+@firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm
+@firm.invoices                            # selects all invoices by going through the Client join model
+
+ +

Similarly you can go through a has_one association on the join model:

+ +
class Group < ActiveRecord::Base
+  has_many   :users
+  has_many   :avatars, through: :users
+end
+
+class User < ActiveRecord::Base
+  belongs_to :group
+  has_one    :avatar
+end
+
+class Avatar < ActiveRecord::Base
+  belongs_to :user
+end
+
+@group = Group.first
+@group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
+@group.avatars                                # selects all avatars by going through the User join model.
+
+ +

An important caveat with going through has_one or has_many associations on the join model is that these associations are read-only. For example, the following would not work following the previous example:

+ +
@group.avatars << Avatar.new   # this would work if User belonged_to Avatar rather than the other way around
+@group.avatars.delete(@group.avatars.last)  # so would this
+
+ +

Setting Inverses

+ +

If you are using a belongs_to on the join model, it is a good idea to set the :inverse_of option on the belongs_to, which will mean that the following example works correctly (where tags is a has_many :through association):

+ +
@post = Post.first
+@tag = @post.tags.build name: "ruby"
+@tag.save
+
+ +

The last line ought to save the through record (a Tagging). This will only work if the :inverse_of is set:

+ +
class Tagging < ActiveRecord::Base
+  belongs_to :post
+  belongs_to :tag, inverse_of: :taggings
+end
+
+ +

If you do not set the :inverse_of record, the association will do its best to match itself up with the correct inverse. Automatic inverse detection only works on has_many, has_one, and belongs_to associations.

+ +

:foreign_key and :through options on the associations will also prevent the association’s inverse from being found automatically, as will a custom scopes in some cases. See further details in the Active Record Associations guide.

+ +

The automatic guessing of the inverse association uses a heuristic based on the name of the class, so it may not work for all associations, especially the ones with non-standard names.

+ +

You can turn off the automatic detection of inverse associations by setting the :inverse_of option to false like so:

+ +
class Tagging < ActiveRecord::Base
+  belongs_to :tag, inverse_of: false
+end
+
+ +

Nested Associations

+ +

You can actually specify any association with the :through option, including an association which has a :through option itself. For example:

+ +
class Author < ActiveRecord::Base
+  has_many :posts
+  has_many :comments, through: :posts
+  has_many :commenters, through: :comments
+end
+
+class Post < ActiveRecord::Base
+  has_many :comments
+end
+
+class Comment < ActiveRecord::Base
+  belongs_to :commenter
+end
+
+@author = Author.first
+@author.commenters # => People who commented on posts written by the author
+
+ +

An equivalent way of setting up this association this would be:

+ +
class Author < ActiveRecord::Base
+  has_many :posts
+  has_many :commenters, through: :posts
+end
+
+class Post < ActiveRecord::Base
+  has_many :comments
+  has_many :commenters, through: :comments
+end
+
+class Comment < ActiveRecord::Base
+  belongs_to :commenter
+end
+
+ +

When using a nested association, you will not be able to modify the association because there is not enough information to know what modification to make. For example, if you tried to add a Commenter in the example above, there would be no way to tell how to set up the intermediate Post and Comment objects.

+ +

Polymorphic Associations

+ +

Polymorphic associations on models are not restricted on what types of models they can be associated with. Rather, they specify an interface that a has_many association must adhere to.

+ +
class Asset < ActiveRecord::Base
+  belongs_to :attachable, polymorphic: true
+end
+
+class Post < ActiveRecord::Base
+  has_many :assets, as: :attachable         # The :as option specifies the polymorphic interface to use.
+end
+
+@asset.attachable = @post
+
+ +

This works by using a type column in addition to a foreign key to specify the associated record. In the Asset example, you’d need an attachable_id integer column and an attachable_type string column.

+ +

Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association. To continue with the asset example above, suppose there are guest posts and member posts that use the posts table for STI. In this case, there must be a type column in the posts table.

+ +

Note: The attachable_type= method is being called when assigning an attachable. The class_name of the attachable is passed as a String.

+ +
class Asset < ActiveRecord::Base
+  belongs_to :attachable, polymorphic: true
+
+  def attachable_type=(class_name)
+     super(class_name.constantize.base_class.to_s)
+  end
+end
+
+class Post < ActiveRecord::Base
+  # because we store "Post" in attachable_type now dependent: :destroy will work
+  has_many :assets, as: :attachable, dependent: :destroy
+end
+
+class GuestPost < Post
+end
+
+class MemberPost < Post
+end
+
+ +

Caching

+ +

All of the methods are built on a simple caching principle that will keep the result of the last query around unless specifically instructed not to. The cache is even shared across methods to make it even cheaper to use the macro-added methods without worrying too much about performance at the first go.

+ +
project.milestones             # fetches milestones from the database
+project.milestones.size        # uses the milestone cache
+project.milestones.empty?      # uses the milestone cache
+project.milestones.reload.size # fetches milestones from the database
+project.milestones             # uses the milestone cache
+
+ +

Eager loading of associations

+ +

Eager loading is a way to find objects of a certain class and a number of named associations. It is one of the easiest ways to prevent the dreaded N+1 problem in which fetching 100 posts that each need to display their author triggers 101 database queries. Through the use of eager loading, the number of queries will be reduced from 101 to 2.

+ +
class Post < ActiveRecord::Base
+  belongs_to :author
+  has_many   :comments
+end
+
+ +

Consider the following loop using the class above:

+ +
Post.all.each do |post|
+  puts "Post:            " + post.title
+  puts "Written by:      " + post.author.name
+  puts "Last comment on: " + post.comments.first.created_on
+end
+
+ +

To iterate over these one hundred posts, we’ll generate 201 database queries. Let’s first just optimize it for retrieving the author:

+ +
Post.includes(:author).each do |post|
+
+ +

This references the name of the belongs_to association that also used the :author symbol. After loading the posts, find will collect the author_id from each one and load all of the referenced authors with one query. Doing so will cut down the number of queries from 201 to 102.

+ +

We can improve upon the situation further by referencing both associations in the finder with:

+ +
Post.includes(:author, :comments).each do |post|
+
+ +

This will load all comments with a single query. This reduces the total number of queries to 3. In general, the number of queries will be 1 plus the number of associations named (except if some of the associations are polymorphic belongs_to - see below).

+ +

To include a deep hierarchy of associations, use a hash:

+ +
Post.includes(:author, { comments: { author: :gravatar } }).each do |post|
+
+ +

The above code will load all the comments and all of their associated authors and gravatars. You can mix and match any combination of symbols, arrays, and hashes to retrieve the associations you want to load.

+ +

All of this power shouldn’t fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you’ve reduced the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it’s no catch-all for performance problems, but it’s a great way to cut down on the number of queries in a situation as the one described above.

+ +

Since only one table is loaded at a time, conditions or orders cannot reference tables other than the main one. If this is the case, Active Record falls back to the previously used LEFT OUTER JOIN based strategy. For example:

+ +
Post.includes([:author, :comments]).where(['comments.approved = ?', true])
+
+ +

This will result in a single SQL query with joins along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id and LEFT OUTER JOIN authors ON authors.id = posts.author_id. Note that using conditions like this can have unintended consequences. In the above example, posts with no approved comments are not returned at all because the conditions apply to the SQL statement as a whole and not just to the association.

+ +

You must disambiguate column references for this fallback to happen, for example order: "author.name DESC" will work but order: "name DESC" will not.

+ +

If you want to load all posts (including posts with no approved comments), then write your own LEFT OUTER JOIN query using ON:

+ +
Post.joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id AND comments.approved = '1'")
+
+ +

In this case, it is usually more natural to include an association which has conditions defined on it:

+ +
class Post < ActiveRecord::Base
+  has_many :approved_comments, -> { where(approved: true) }, class_name: 'Comment'
+end
+
+Post.includes(:approved_comments)
+
+ +

This will load posts and eager load the approved_comments association, which contains only those comments that have been approved.

+ +

If you eager load an association with a specified :limit option, it will be ignored, returning all the associated objects:

+ +
class Picture < ActiveRecord::Base
+  has_many :most_recent_comments, -> { order('id DESC').limit(10) }, class_name: 'Comment'
+end
+
+Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
+
+ +

Eager loading is supported with polymorphic associations.

+ +
class Address < ActiveRecord::Base
+  belongs_to :addressable, polymorphic: true
+end
+
+ +

A call that tries to eager load the addressable model

+ +
Address.includes(:addressable)
+
+ +

This will execute one query to load the addresses and load the addressables with one query per addressable type. For example, if all the addressables are either of class Person or Company, then a total of 3 queries will be executed. The list of addressable types to load is determined on the back of the addresses loaded. This is not supported if Active Record has to fallback to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError. The reason is that the parent model’s type is a column value so its corresponding table name cannot be put in the FROM/JOIN clauses of that query.

+ +

Table Aliasing

+ +

Active Record uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, the standard table name is used. The second time, the table is aliased as #{reflection_name}_#{parent_table_name}. Indexes are appended for any more successive uses of the table name.

+ +
Post.joins(:comments)
+# => SELECT ... FROM posts INNER JOIN comments ON ...
+Post.joins(:special_comments) # STI
+# => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
+Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
+# => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
+
+ +

Acts as tree example:

+ +
TreeMixin.joins(:children)
+# => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
+TreeMixin.joins(children: :parent)
+# => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
+                            INNER JOIN parents_mixins ...
+TreeMixin.joins(children: {parent: :children})
+# => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
+                            INNER JOIN parents_mixins ...
+                            INNER JOIN mixins childrens_mixins_2
+
+ +

Has and Belongs to Many join tables use the same idea, but add a _join suffix:

+ +
Post.joins(:categories)
+# => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
+Post.joins(categories: :posts)
+# => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
+                           INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
+Post.joins(categories: {posts: :categories})
+# => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
+                           INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
+                           INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
+
+ +

If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table names will take precedence over the eager associations:

+ +
Post.joins(:comments).joins("inner join comments ...")
+# => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
+Post.joins(:comments, :special_comments).joins("inner join comments ...")
+# => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
+                           INNER JOIN comments special_comments_posts ...
+                           INNER JOIN comments ...
+
+ +

Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database.

+ +

Modules

+ +

By default, associations will look for objects within the current module scope. Consider:

+ +
module MyApplication
+  module Business
+    class Firm < ActiveRecord::Base
+      has_many :clients
+    end
+
+    class Client < ActiveRecord::Base; end
+  end
+end
+
+ +

When Firm#clients is called, it will in turn call MyApplication::Business::Client.find_all_by_firm_id(firm.id). If you want to associate with a class in another module scope, this can be done by specifying the complete class name.

+ +
module MyApplication
+  module Business
+    class Firm < ActiveRecord::Base; end
+  end
+
+  module Billing
+    class Account < ActiveRecord::Base
+      belongs_to :firm, class_name: "MyApplication::Business::Firm"
+    end
+  end
+end
+
+ +

Bi-directional associations

+ +

When you specify an association, there is usually an association on the associated model that specifies the same relationship in reverse. For example, with the following models:

+ +
class Dungeon < ActiveRecord::Base
+  has_many :traps
+  has_one :evil_wizard
+end
+
+class Trap < ActiveRecord::Base
+  belongs_to :dungeon
+end
+
+class EvilWizard < ActiveRecord::Base
+  belongs_to :dungeon
+end
+
+ +

The traps association on Dungeon and the dungeon association on Trap are the inverse of each other, and the inverse of the dungeon association on EvilWizard is the evil_wizard association on Dungeon (and vice-versa). By default, Active Record can guess the inverse of the association based on the name of the class. The result is the following:

+ +
d = Dungeon.first
+t = d.traps.first
+d.object_id == t.dungeon.object_id # => true
+
+ +

The Dungeon instances d and t.dungeon in the above example refer to the same in-memory instance since the association matches the name of the class. The result would be the same if we added :inverse_of to our model definitions:

+ +
class Dungeon < ActiveRecord::Base
+  has_many :traps, inverse_of: :dungeon
+  has_one :evil_wizard, inverse_of: :dungeon
+end
+
+class Trap < ActiveRecord::Base
+  belongs_to :dungeon, inverse_of: :traps
+end
+
+class EvilWizard < ActiveRecord::Base
+  belongs_to :dungeon, inverse_of: :evil_wizard
+end
+
+ +

For more information, see the documentation for the :inverse_of option.

+ +

Deleting from associations

+ +

Dependent associations

+ +

has_many, has_one, and belongs_to associations support the :dependent option. This allows you to specify that associated records should be deleted when the owner is deleted.

+ +

For example:

+ +
class Author
+  has_many :posts, dependent: :destroy
+end
+Author.find(1).destroy # => Will destroy all of the author's posts, too
+
+ +

The :dependent option can have different values which specify how the deletion is done. For more information, see the documentation for this option on the different specific association types. When no option is given, the behavior is to do nothing with the associated records when destroying a record.

+ +

Note that :dependent is implemented using Rails’ callback system, which works by processing callbacks in order. Therefore, other callbacks declared either before or after the :dependent option can affect what it does.

+ +

Note that :dependent option is ignored for has_one :through associations.

+ +

Delete or destroy?

+ +

has_many and has_and_belongs_to_many associations have the methods destroy, delete, destroy_all and delete_all.

+ +

For has_and_belongs_to_many, delete and destroy are the same: they cause the records in the join table to be removed.

+ +

For has_many, destroy and destroy_all will always call the destroy method of the record(s) being removed so that callbacks are run. However delete and delete_all will either do the deletion according to the strategy specified by the :dependent option, or if no :dependent option is given, then it will follow the default strategy. The default strategy is to do nothing (leave the foreign keys with the parent ids set), except for has_many :through, where the default strategy is delete_all (delete the join records, without running their callbacks).

+ +

There is also a clear method which is the same as delete_all, except that it returns the association rather than the records which have been deleted.

+ +

What gets deleted?

+ +

There is a potential pitfall here: has_and_belongs_to_many and has_many :through associations have records in join tables, as well as the associated records. So when we call one of these deletion methods, what exactly should be deleted?

+ +

The answer is that it is assumed that deletion on an association is about removing the link between the owner and the associated object(s), rather than necessarily the associated objects themselves. So with has_and_belongs_to_many and has_many :through, the join records will be deleted, but the associated records won’t.

+ +

This makes sense if you think about it: if you were to call post.tags.delete(Tag.find_by(name: 'food')) you would want the ‘food’ tag to be unlinked from the post, rather than for the tag itself to be removed from the database.

+ +

However, there are examples where this strategy doesn’t make sense. For example, suppose a person has many projects, and each project has many tasks. If we deleted one of a person’s tasks, we would probably not want the project to be deleted. In this scenario, the delete method won’t actually work: it can only be used if the association on the join model is a belongs_to. In other situations you are expected to perform operations directly on either the associated records or the :through association.

+ +

With a regular has_many there is no distinction between the “associated records” and the “link”, so there is only one choice for what gets deleted.

+ +

With has_and_belongs_to_many and has_many :through, if you want to delete the associated records themselves, you can always do something along the lines of person.tasks.each(&:destroy).

+ +

Type safety with ActiveRecord::AssociationTypeMismatch

+ +

If you attempt to assign an object to an association that doesn’t match the inferred or specified :class_name, you’ll get an ActiveRecord::AssociationTypeMismatch.

+ +

Options

+ +

All of the association macros can be specialized through options. This makes cases more complex than the simple and guessable ones possible.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + belongs_to(name, scope = nil, **options) + +

+ + +
+

Specifies a one-to-one association with another class. This method should only be used if this class contains the foreign key. If the other class contains the foreign key, then you should use has_one instead. See also ActiveRecord::Associations::ClassMethods‘s overview on when to use has_one and when to use belongs_to.

+ +

Methods will be added for retrieval and query for a single associated object, for which this object holds an id:

+ +

association is a placeholder for the symbol passed as the name argument, so belongs_to :author would add among others author.nil?.

+
association +
+

Returns the associated object. nil is returned if none is found.

+
association=(associate) +
+

Assigns the associate object, extracts the primary key, and sets it as the foreign key. No modification or deletion of existing records takes place.

+
build_association(attributes = {}) +
+

Returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key, but has not yet been saved.

+
create_association(attributes = {}) +
+

Returns a new object of the associated type that has been instantiated with attributes, linked to this object through a foreign key, and that has already been saved (if it passed the validation).

+
create_association!(attributes = {}) +
+

Does the same as create_association, but raises ActiveRecord::RecordInvalid if the record is invalid.

+
reload_association +
+

Returns the associated object, forcing a database read.

+
association_changed? +
+

Returns true if a new associate object has been assigned and the next save will update the foreign key.

+
association_previously_changed? +
+

Returns true if the previous save updated the association to reference a new associate object.

+
+ +

Example

+ +

A Post class declares belongs_to :author, which will add:

+
  • +

    Post#author (similar to Author.find(author_id))

    +
  • +

    Post#author=(author) (similar to post.author_id = author.id)

    +
  • +

    Post#build_author (similar to post.author = Author.new)

    +
  • +

    Post#create_author (similar to post.author = Author.new; post.author.save; post.author)

    +
  • +

    Post#create_author! (similar to post.author = Author.new; post.author.save!; post.author)

    +
  • +

    Post#reload_author

    +
  • +

    Post#author_changed?

    +
  • +

    Post#author_previously_changed?

    +
+ +

The declaration can also include an options hash to specialize the behavior of the association.

+ +

Scopes

+ +

You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific record or customize the generated query when you access the associated object.

+ +

Scope examples:

+ +
belongs_to :firm, -> { where(id: 2) }
+belongs_to :user, -> { joins(:friends) }
+belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
+
+ +

Options

+
:class_name +
+

Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So belongs_to :author will by default be linked to the Author class, but if the real class name is Person, you’ll have to specify it with this option.

+
:foreign_key +
+

Specify the foreign key used for the association. By default this is guessed to be the name of the association with an “_id” suffix. So a class that defines a belongs_to :person association will use “person_id” as the default :foreign_key. Similarly, belongs_to :favorite_person, class_name: "Person" will use a foreign key of “favorite_person_id”.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option.

+
:foreign_type +
+

Specify the column used to store the associated object’s type, if this is a polymorphic association. By default this is guessed to be the name of the association with a “_type” suffix. So a class that defines a belongs_to :taggable, polymorphic: true association will use “taggable_type” as the default :foreign_type.

+
:primary_key +
+

Specify the method that returns the primary key of associated object used for the association. By default this is id.

+
:dependent +
+

If set to :destroy, the associated object is destroyed when this object is. If set to :delete, the associated object is deleted without calling its destroy method. If set to :destroy_async, the associated object is scheduled to be destroyed in a background job. This option should not be specified when belongs_to is used in conjunction with a has_many relationship on another class because of the potential to leave orphaned records behind.

+
:counter_cache +
+

Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this class is created and decremented when it’s destroyed. This requires that a column named #{table_name}_count (such as comments_count for a belonging Comment class) is used on the associate class (such as a Post class) - that is the migration for #{table_name}_count is created on the associate class (such that Post.comments_count will return the count cached, see note below). You can also specify a custom counter cache column by providing a column name instead of a true/false value to this option (e.g., counter_cache: :my_custom_counter.) Note: Specifying a counter cache will add it to that model’s list of readonly attributes using attr_readonly.

+
:polymorphic +
+

Specify this association is a polymorphic association by passing true. Note: If you’ve enabled the counter cache, then you may want to add the counter cache attribute to the attr_readonly list in the associated classes (e.g. class Post; attr_readonly :comments_count; end).

+
:validate +
+

When set to true, validates new objects added to association when saving the parent object. false by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.

+
:autosave +
+

If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. If false, never save or destroy the associated object. By default, only save the associated object if it’s a new record.

+ +

Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.

+
:touch +
+

If true, the associated object will be touched (the updated_at / updated_on attributes set to current time) when this record is either saved or destroyed. If you specify a symbol, that attribute will be updated with the current time in addition to the updated_at / updated_on attribute. Please note that no validation will be performed when touching, and only the after_touch, after_commit, and after_rollback callbacks will be executed.

+
:inverse_of +
+

Specifies the name of the has_one or has_many association on the associated object that is the inverse of this belongs_to association. See ActiveRecord::Associations::ClassMethods‘s overview on Bi-directional associations for more detail.

+
:optional +
+

When set to true, the association will not have its presence validated.

+
:required +
+

When set to true, the association will also have its presence validated. This will validate the association itself, not the id. You can use :inverse_of to avoid an extra query during validation. NOTE: required is set to true by default and is deprecated. If you don’t want to have association presence validated, use optional: true.

+
:default +
+

Provide a callable (i.e. proc or lambda) to specify that the association should be initialized with a particular record before validation.

+
:strict_loading +
+

Enforces strict loading every time the associated record is loaded through this association.

+
:ensuring_owner_was +
+

Specifies an instance method to be called on the owner. The method must return true in order for the associated records to be deleted in a background job.

+
+ +

Option examples:

+ +
belongs_to :firm, foreign_key: "client_of"
+belongs_to :person, primary_key: "name", foreign_key: "person_name"
+belongs_to :author, class_name: "Person", foreign_key: "author_id"
+belongs_to :valid_coupon, ->(o) { where "discounts > ?", o.payments_count },
+                          class_name: "Coupon", foreign_key: "coupon_id"
+belongs_to :attachable, polymorphic: true
+belongs_to :project, -> { readonly }
+belongs_to :post, counter_cache: true
+belongs_to :comment, touch: true
+belongs_to :company, touch: :employees_last_updated_at
+belongs_to :user, optional: true
+belongs_to :account, default: -> { company.account }
+belongs_to :account, strict_loading: true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations.rb, line 1799
+def belongs_to(name, scope = nil, **options)
+  reflection = Builder::BelongsTo.build(self, name, scope, options)
+  Reflection.add_reflection self, name, reflection
+end
+
+
+ +
+ +
+

+ + has_and_belongs_to_many(name, scope = nil, **options, &extension) + +

+ + +
+

Specifies a many-to-many relationship with another class. This associates two classes via an intermediate join table. Unless the join table is explicitly specified as an option, it is guessed using the lexical order of the class names. So a join between Developer and Project will give the default join table name of “developers_projects” because “D” precedes “P” alphabetically. Note that this precedence is calculated using the < operator for String. This means that if the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered of higher lexical precedence than the shorter one. For example, one would expect the tables “paper_boxes” and “papers” to generate a join table name of “papers_paper_boxes” because of the length of the name “paper_boxes”, but it in fact generates a join table name of “paper_boxes_papers”. Be aware of this caveat, and use the custom :join_table option if you need to. If your tables share a common prefix, it will only appear once at the beginning. For example, the tables “catalog_categories” and “catalog_products” generate a join table name of “catalog_categories_products”.

+ +

The join table should not have a primary key or a model associated with it. You must manually generate the join table with a migration such as this:

+ +
class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.0]
+  def change
+    create_join_table :developers, :projects
+  end
+end
+
+ +

It’s also a good idea to add indexes to each of those columns to speed up the joins process. However, in MySQL it is advised to add a compound index for both of the columns as MySQL only uses one index per table during the lookup.

+ +

Adds the following methods for retrieval and query:

+ +

collection is a placeholder for the symbol passed as the name argument, so has_and_belongs_to_many :categories would add among others categories.empty?.

+
collection +
+

Returns a Relation of all the associated objects. An empty Relation is returned if none are found.

+
collection<<(object, …) +
+

Adds one or more objects to the collection by creating associations in the join table (collection.push and collection.concat are aliases to this method). Note that this operation instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record.

+
collection.delete(object, …) +
+

Removes one or more objects from the collection by removing their associations from the join table. This does not destroy the objects.

+
collection.destroy(object, …) +
+

Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option. This does not destroy the objects.

+
collection=objects +
+

Replaces the collection’s content by deleting and adding objects as appropriate.

+
collection_singular_ids +
+

Returns an array of the associated objects’ ids.

+
collection_singular_ids=ids +
+

Replace the collection by the objects identified by the primary keys in ids.

+
collection.clear +
+

Removes every object from the collection. This does not destroy the objects.

+
collection.empty? +
+

Returns true if there are no associated objects.

+
collection.size +
+

Returns the number of associated objects.

+
collection.find(id) +
+

Finds an associated object responding to the id and that meets the condition that it has to be associated with this object. Uses the same rules as ActiveRecord::FinderMethods#find.

+
collection.exists?(…) +
+

Checks whether an associated object with the given conditions exists. Uses the same rules as ActiveRecord::FinderMethods#exists?.

+
collection.build(attributes = {}) +
+

Returns a new object of the collection type that has been instantiated with attributes and linked to this object through the join table, but has not yet been saved.

+
collection.create(attributes = {}) +
+

Returns a new object of the collection type that has been instantiated with attributes, linked to this object through the join table, and that has already been saved (if it passed the validation).

+
collection.reload +
+

Returns a Relation of all of the associated objects, forcing a database read. An empty Relation is returned if none are found.

+
+ +

Example

+ +

A Developer class declares has_and_belongs_to_many :projects, which will add:

+
  • +

    Developer#projects

    +
  • +

    Developer#projects<<

    +
  • +

    Developer#projects.delete

    +
  • +

    Developer#projects.destroy

    +
  • +

    Developer#projects=

    +
  • +

    Developer#project_ids

    +
  • +

    Developer#project_ids=

    +
  • +

    Developer#projects.clear

    +
  • +

    Developer#projects.empty?

    +
  • +

    Developer#projects.size

    +
  • +

    Developer#projects.find(id)

    +
  • +

    Developer#projects.exists?(...)

    +
  • +

    Developer#projects.build (similar to Project.new(developer_id: id))

    +
  • +

    Developer#projects.create (similar to c = Project.new(developer_id: id); c.save; c)

    +
  • +

    Developer#projects.reload

    +
+ +

The declaration may include an options hash to specialize the behavior of the association.

+ +

Scopes

+ +

You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific set of records or customize the generated query when you access the associated collection.

+ +

Scope examples:

+ +
has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
+has_and_belongs_to_many :categories, ->(post) {
+  where("default_category = ?", post.default_category)
+}
+
+ +

Extensions

+ +

The extension argument allows you to pass a block into a has_and_belongs_to_many association. This is useful for adding new finders, creators, and other factory-type methods to be used as part of the association.

+ +

Extension examples:

+ +
has_and_belongs_to_many :contractors do
+  def find_or_create_by_name(name)
+    first_name, last_name = name.split(" ", 2)
+    find_or_create_by(first_name: first_name, last_name: last_name)
+  end
+end
+
+ +

Options

+
:class_name +
+

Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_and_belongs_to_many :projects will by default be linked to the Project class, but if the real class name is SuperProject, you’ll have to specify it with this option.

+
:join_table +
+

Specify the name of the join table if the default based on lexical order isn’t what you want. WARNING: If you’re overwriting the table name of either class, the table_name method MUST be declared underneath any has_and_belongs_to_many declaration in order to work.

+
:foreign_key +
+

Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and “_id” suffixed. So a Person class that makes a has_and_belongs_to_many association to Project will use “person_id” as the default :foreign_key.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option.

+
:association_foreign_key +
+

Specify the foreign key used for the association on the receiving side of the association. By default this is guessed to be the name of the associated class in lower-case and “_id” suffixed. So if a Person class makes a has_and_belongs_to_many association to Project, the association will use “project_id” as the default :association_foreign_key.

+
:validate +
+

When set to true, validates new objects added to association when saving the parent object. true by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.

+
:autosave +
+

If true, always save the associated objects or destroy them if marked for destruction, when saving the parent object. If false, never save or destroy the associated objects. By default, only save associated objects that are new records.

+ +

Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.

+
:strict_loading +
+

Enforces strict loading every time an associated record is loaded through this association.

+
+ +

Option examples:

+ +
has_and_belongs_to_many :projects
+has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
+has_and_belongs_to_many :nations, class_name: "Country"
+has_and_belongs_to_many :categories, join_table: "prods_cats"
+has_and_belongs_to_many :categories, -> { readonly }
+has_and_belongs_to_many :categories, strict_loading: true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations.rb, line 1971
+        def has_and_belongs_to_many(name, scope = nil, **options, &extension)
+          habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self)
+
+          builder = Builder::HasAndBelongsToMany.new name, self, options
+
+          join_model = builder.through_model
+
+          const_set join_model.name, join_model
+          private_constant join_model.name
+
+          middle_reflection = builder.middle_reflection join_model
+
+          Builder::HasMany.define_callbacks self, middle_reflection
+          Reflection.add_reflection self, middle_reflection.name, middle_reflection
+          middle_reflection.parent_reflection = habtm_reflection
+
+          include Module.new {
+            class_eval <<-RUBY, __FILE__, __LINE__ + 1
+              def destroy_associations
+                association(:#{middle_reflection.name}).delete_all(:delete_all)
+                association(:#{name}).reset
+                super
+              end
+            RUBY
+          }
+
+          hm_options = {}
+          hm_options[:through] = middle_reflection.name
+          hm_options[:source] = join_model.right_reflection.name
+
+          [:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name, :extend, :strict_loading].each do |k|
+            hm_options[k] = options[k] if options.key? k
+          end
+
+          has_many name, scope, **hm_options, &extension
+          _reflections[name.to_s].parent_reflection = habtm_reflection
+        end
+
+
+ +
+ +
+

+ + has_many(name, scope = nil, **options, &extension) + +

+ + +
+

Specifies a one-to-many association. The following methods for retrieval and query of collections of associated objects will be added:

+ +

collection is a placeholder for the symbol passed as the name argument, so has_many :clients would add among others clients.empty?.

+
collection +
+

Returns a Relation of all the associated objects. An empty Relation is returned if none are found.

+
collection<<(object, …) +
+

Adds one or more objects to the collection by setting their foreign keys to the collection’s primary key. Note that this operation instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record. This will also run validations and callbacks of associated object(s).

+
collection.delete(object, …) +
+

Removes one or more objects from the collection by setting their foreign keys to NULL. Objects will be in addition destroyed if they’re associated with dependent: :destroy, and deleted if they’re associated with dependent: :delete_all.

+ +

If the :through option is used, then the join records are deleted (rather than nullified) by default, but you can specify dependent: :destroy or dependent: :nullify to override this.

+
collection.destroy(object, …) +
+

Removes one or more objects from the collection by running destroy on each record, regardless of any dependent option, ensuring callbacks are run.

+ +

If the :through option is used, then the join records are destroyed instead, not the objects themselves.

+
collection=objects +
+

Replaces the collections content by deleting and adding objects as appropriate. If the :through option is true callbacks in the join models are triggered except destroy callbacks, since deletion is direct by default. You can specify dependent: :destroy or dependent: :nullify to override this.

+
collection_singular_ids +
+

Returns an array of the associated objects’ ids

+
collection_singular_ids=ids +
+

Replace the collection with the objects identified by the primary keys in ids. This method loads the models and calls collection=. See above.

+
collection.clear +
+

Removes every object from the collection. This destroys the associated objects if they are associated with dependent: :destroy, deletes them directly from the database if dependent: :delete_all, otherwise sets their foreign keys to NULL. If the :through option is true no destroy callbacks are invoked on the join models. Join models are directly deleted.

+
collection.empty? +
+

Returns true if there are no associated objects.

+
collection.size +
+

Returns the number of associated objects.

+
collection.find(…) +
+

Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.

+
collection.exists?(…) +
+

Checks whether an associated object with the given conditions exists. Uses the same rules as ActiveRecord::FinderMethods#exists?.

+
collection.build(attributes = {}, …) +
+

Returns one or more new objects of the collection type that have been instantiated with attributes and linked to this object through a foreign key, but have not yet been saved.

+
collection.create(attributes = {}) +
+

Returns a new object of the collection type that has been instantiated with attributes, linked to this object through a foreign key, and that has already been saved (if it passed the validation). Note: This only works if the base model already exists in the DB, not if it is a new (unsaved) record!

+
collection.create!(attributes = {}) +
+

Does the same as collection.create, but raises ActiveRecord::RecordInvalid if the record is invalid.

+
collection.reload +
+

Returns a Relation of all of the associated objects, forcing a database read. An empty Relation is returned if none are found.

+
+ +

Example

+ +

A Firm class declares has_many :clients, which will add:

+
  • +

    Firm#clients (similar to Client.where(firm_id: id))

    +
  • +

    Firm#clients<<

    +
  • +

    Firm#clients.delete

    +
  • +

    Firm#clients.destroy

    +
  • +

    Firm#clients=

    +
  • +

    Firm#client_ids

    +
  • +

    Firm#client_ids=

    +
  • +

    Firm#clients.clear

    +
  • +

    Firm#clients.empty? (similar to firm.clients.size == 0)

    +
  • +

    Firm#clients.size (similar to Client.count "firm_id = #{id}")

    +
  • +

    Firm#clients.find (similar to Client.where(firm_id: id).find(id))

    +
  • +

    Firm#clients.exists?(name: 'ACME') (similar to Client.exists?(name: 'ACME', firm_id: firm.id))

    +
  • +

    Firm#clients.build (similar to Client.new(firm_id: id))

    +
  • +

    Firm#clients.create (similar to c = Client.new(firm_id: id); c.save; c)

    +
  • +

    Firm#clients.create! (similar to c = Client.new(firm_id: id); c.save!)

    +
  • +

    Firm#clients.reload

    +
+ +

The declaration can also include an options hash to specialize the behavior of the association.

+ +

Scopes

+ +

You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific set of records or customize the generated query when you access the associated collection.

+ +

Scope examples:

+ +
has_many :comments, -> { where(author_id: 1) }
+has_many :employees, -> { joins(:address) }
+has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
+
+ +

Extensions

+ +

The extension argument allows you to pass a block into a has_many association. This is useful for adding new finders, creators, and other factory-type methods to be used as part of the association.

+ +

Extension examples:

+ +
has_many :employees do
+  def find_or_create_by_name(name)
+    first_name, last_name = name.split(" ", 2)
+    find_or_create_by(first_name: first_name, last_name: last_name)
+  end
+end
+
+ +

Options

+
:class_name +
+

Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_many :products will by default be linked to the Product class, but if the real class name is SpecialProduct, you’ll have to specify it with this option.

+
:foreign_key +
+

Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and “_id” suffixed. So a Person class that makes a has_many association will use “person_id” as the default :foreign_key.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option.

+
:foreign_type +
+

Specify the column used to store the associated object’s type, if this is a polymorphic association. By default this is guessed to be the name of the polymorphic association specified on “as” option with a “_type” suffix. So a class that defines a has_many :tags, as: :taggable association will use “taggable_type” as the default :foreign_type.

+
:primary_key +
+

Specify the name of the column to use as the primary key for the association. By default this is id.

+
:dependent +
+

Controls what happens to the associated objects when their owner is destroyed. Note that these are implemented as callbacks, and Rails executes callbacks in order. Therefore, other similar callbacks may affect the :dependent behavior, and the :dependent behavior may affect other callbacks.

+
  • +

    nil do nothing (default).

    +
  • +

    :destroy causes all the associated objects to also be destroyed.

    +
  • +

    :destroy_async destroys all the associated objects in a background job. WARNING: Do not use this option if the association is backed by foreign key constraints in your database. The foreign key constraint actions will occur inside the same transaction that deletes its owner.

    +
  • +

    :delete_all causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).

    +
  • +

    :nullify causes the foreign keys to be set to NULL. Polymorphic type will also be nullified on polymorphic associations. Callbacks are not executed.

    +
  • +

    :restrict_with_exception causes an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records.

    +
  • +

    :restrict_with_error causes an error to be added to the owner if there are any associated objects.

    +
+ +

If using with the :through option, the association on the join model must be a belongs_to, and the records which get deleted are the join records, rather than the associated records.

+ +

If using dependent: :destroy on a scoped association, only the scoped objects are destroyed. For example, if a Post model defines has_many :comments, -> { where published: true }, dependent: :destroy and destroy is called on a post, only published comments are destroyed. This means that any unpublished comments in the database would still contain a foreign key pointing to the now deleted post.

+
:counter_cache +
+

This option can be used to configure a custom named :counter_cache. You only need this option, when you customized the name of your :counter_cache on the belongs_to association.

+
:as +
+

Specifies a polymorphic interface (See belongs_to).

+
:through +
+

Specifies an association through which to perform the query. This can be any other type of association, including other :through associations. Options for :class_name, :primary_key and :foreign_key are ignored, as the association uses the source reflection.

+ +

If the association on the join model is a belongs_to, the collection can be modified and the records on the :through model will be automatically created and removed as appropriate. Otherwise, the collection is read-only, so you should manipulate the :through association directly.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option on the source association on the join model. This allows associated records to be built which will automatically create the appropriate join model records when they are saved. (See the ‘Association Join Models’ section above.)

+
:disable_joins +
+

Specifies whether joins should be skipped for an association. If set to true, two or more queries will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory due to database limitations. This option is only applicable on has_many :through associations as has_many alone do not perform a join.

+
:source +
+

Specifies the source association name used by has_many :through queries. Only use it if the name cannot be inferred from the association. has_many :subscribers, through: :subscriptions will look for either :subscribers or :subscriber on Subscription, unless a :source is given.

+
:source_type +
+

Specifies type of the source association used by has_many :through queries where the source association is a polymorphic belongs_to.

+
:validate +
+

When set to true, validates new objects added to association when saving the parent object. true by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.

+
:autosave +
+

If true, always save the associated objects or destroy them if marked for destruction, when saving the parent object. If false, never save or destroy the associated objects. By default, only save associated objects that are new records. This option is implemented as a before_save callback. Because callbacks are run in the order they are defined, associated objects may need to be explicitly saved in any user-defined before_save callbacks.

+ +

Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.

+
:inverse_of +
+

Specifies the name of the belongs_to association on the associated object that is the inverse of this has_many association. See ActiveRecord::Associations::ClassMethods‘s overview on Bi-directional associations for more detail.

+
:extend +
+

Specifies a module or array of modules that will be extended into the association object returned. Useful for defining methods on associations, especially when they should be shared between multiple association objects.

+
:strict_loading +
+

When set to true, enforces strict loading every time the associated record is loaded through this association.

+
:ensuring_owner_was +
+

Specifies an instance method to be called on the owner. The method must return true in order for the associated records to be deleted in a background job.

+
+ +

Option examples:

+ +
has_many :comments, -> { order("posted_on") }
+has_many :comments, -> { includes(:author) }
+has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
+has_many :tracks, -> { order("position") }, dependent: :destroy
+has_many :comments, dependent: :nullify
+has_many :tags, as: :taggable
+has_many :reports, -> { readonly }
+has_many :subscribers, through: :subscriptions, source: :user
+has_many :subscribers, through: :subscriptions, disable_joins: true
+has_many :comments, strict_loading: true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations.rb, line 1469
+def has_many(name, scope = nil, **options, &extension)
+  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
+  Reflection.add_reflection self, name, reflection
+end
+
+
+ +
+ +
+

+ + has_one(name, scope = nil, **options) + +

+ + +
+

Specifies a one-to-one association with another class. This method should only be used if the other class contains the foreign key. If the current class contains the foreign key, then you should use belongs_to instead. See also ActiveRecord::Associations::ClassMethods‘s overview on when to use has_one and when to use belongs_to.

+ +

The following methods for retrieval and query of a single associated object will be added:

+ +

association is a placeholder for the symbol passed as the name argument, so has_one :manager would add among others manager.nil?.

+
association +
+

Returns the associated object. nil is returned if none is found.

+
association=(associate) +
+

Assigns the associate object, extracts the primary key, sets it as the foreign key, and saves the associate object. To avoid database inconsistencies, permanently deletes an existing associated object when assigning a new one, even if the new one isn’t saved to database.

+
build_association(attributes = {}) +
+

Returns a new object of the associated type that has been instantiated with attributes and linked to this object through a foreign key, but has not yet been saved.

+
create_association(attributes = {}) +
+

Returns a new object of the associated type that has been instantiated with attributes, linked to this object through a foreign key, and that has already been saved (if it passed the validation).

+
create_association!(attributes = {}) +
+

Does the same as create_association, but raises ActiveRecord::RecordInvalid if the record is invalid.

+
reload_association +
+

Returns the associated object, forcing a database read.

+
+ +

Example

+ +

An Account class declares has_one :beneficiary, which will add:

+
  • +

    Account#beneficiary (similar to Beneficiary.where(account_id: id).first)

    +
  • +

    Account#beneficiary=(beneficiary) (similar to beneficiary.account_id = account.id; beneficiary.save)

    +
  • +

    Account#build_beneficiary (similar to Beneficiary.new(account_id: id))

    +
  • +

    Account#create_beneficiary (similar to b = Beneficiary.new(account_id: id); b.save; b)

    +
  • +

    Account#create_beneficiary! (similar to b = Beneficiary.new(account_id: id); b.save!; b)

    +
  • +

    Account#reload_beneficiary

    +
+ +

Scopes

+ +

You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific record or customize the generated query when you access the associated object.

+ +

Scope examples:

+ +
has_one :author, -> { where(comment_id: 1) }
+has_one :employer, -> { joins(:company) }
+has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
+
+ +

Options

+ +

The declaration can also include an options hash to specialize the behavior of the association.

+ +

Options are:

+
:class_name +
+

Specify the class name of the association. Use it only if that name can’t be inferred from the association name. So has_one :manager will by default be linked to the Manager class, but if the real class name is Person, you’ll have to specify it with this option.

+
:dependent +
+

Controls what happens to the associated object when its owner is destroyed:

+
  • +

    nil do nothing (default).

    +
  • +

    :destroy causes the associated object to also be destroyed

    +
  • +

    :destroy_async causes the associated object to be destroyed in a background job. WARNING: Do not use this option if the association is backed by foreign key constraints in your database. The foreign key constraint actions will occur inside the same transaction that deletes its owner.

    +
  • +

    :delete causes the associated object to be deleted directly from the database (so callbacks will not execute)

    +
  • +

    :nullify causes the foreign key to be set to NULL. Polymorphic type column is also nullified on polymorphic associations. Callbacks are not executed.

    +
  • +

    :restrict_with_exception causes an ActiveRecord::DeleteRestrictionError exception to be raised if there is an associated record

    +
  • +

    :restrict_with_error causes an error to be added to the owner if there is an associated object

    +
+ +

Note that :dependent option is ignored when using :through option.

+
:foreign_key +
+

Specify the foreign key used for the association. By default this is guessed to be the name of this class in lower-case and “_id” suffixed. So a Person class that makes a has_one association will use “person_id” as the default :foreign_key.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option.

+
:foreign_type +
+

Specify the column used to store the associated object’s type, if this is a polymorphic association. By default this is guessed to be the name of the polymorphic association specified on “as” option with a “_type” suffix. So a class that defines a has_one :tag, as: :taggable association will use “taggable_type” as the default :foreign_type.

+
:primary_key +
+

Specify the method that returns the primary key used for the association. By default this is id.

+
:as +
+

Specifies a polymorphic interface (See belongs_to).

+
:through +
+

Specifies a Join Model through which to perform the query. Options for :class_name, :primary_key, and :foreign_key are ignored, as the association uses the source reflection. You can only use a :through query through a has_one or belongs_to association on the join model.

+ +

If the association on the join model is a belongs_to, the collection can be modified and the records on the :through model will be automatically created and removed as appropriate. Otherwise, the collection is read-only, so you should manipulate the :through association directly.

+ +

If you are going to modify the association (rather than just read from it), then it is a good idea to set the :inverse_of option on the source association on the join model. This allows associated records to be built which will automatically create the appropriate join model records when they are saved. (See the ‘Association Join Models’ section above.)

+
:disable_joins +
+

Specifies whether joins should be skipped for an association. If set to true, two or more queries will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory due to database limitations. This option is only applicable on has_one :through associations as has_one alone does not perform a join.

+
:source +
+

Specifies the source association name used by has_one :through queries. Only use it if the name cannot be inferred from the association. has_one :favorite, through: :favorites will look for a :favorite on Favorite, unless a :source is given.

+
:source_type +
+

Specifies type of the source association used by has_one :through queries where the source association is a polymorphic belongs_to.

+
:validate +
+

When set to true, validates new objects added to association when saving the parent object. false by default. If you want to ensure associated objects are revalidated on every update, use validates_associated.

+
:autosave +
+

If true, always save the associated object or destroy it if marked for destruction, when saving the parent object. If false, never save or destroy the associated object. By default, only save the associated object if it’s a new record.

+ +

Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets :autosave to true.

+
:touch +
+

If true, the associated object will be touched (the updated_at / updated_on attributes set to current time) when this record is either saved or destroyed. If you specify a symbol, that attribute will be updated with the current time in addition to the updated_at / updated_on attribute. Please note that no validation will be performed when touching, and only the after_touch, after_commit, and after_rollback callbacks will be executed.

+
:inverse_of +
+

Specifies the name of the belongs_to association on the associated object that is the inverse of this has_one association. See ActiveRecord::Associations::ClassMethods‘s overview on Bi-directional associations for more detail.

+
:required +
+

When set to true, the association will also have its presence validated. This will validate the association itself, not the id. You can use :inverse_of to avoid an extra query during validation.

+
:strict_loading +
+

Enforces strict loading every time the associated record is loaded through this association.

+
:ensuring_owner_was +
+

Specifies an instance method to be called on the owner. The method must return true in order for the associated records to be deleted in a background job.

+
+ +

Option examples:

+ +
has_one :credit_card, dependent: :destroy  # destroys the associated credit card
+has_one :credit_card, dependent: :nullify  # updates the associated records foreign
+                                              # key value to NULL rather than destroying it
+has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
+has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
+has_one :attachment, as: :attachable
+has_one :boss, -> { readonly }
+has_one :club, through: :membership
+has_one :club, through: :membership, disable_joins: true
+has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
+has_one :credit_card, required: true
+has_one :credit_card, strict_loading: true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations.rb, line 1639
+def has_one(name, scope = nil, **options)
+  reflection = Builder::HasOne.build(self, name, scope, options)
+  Reflection.add_reflection self, name, reflection
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/CollectionProxy.html b/src/7.0/classes/ActiveRecord/Associations/CollectionProxy.html new file mode 100644 index 0000000000..ae1832a60a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/CollectionProxy.html @@ -0,0 +1,2483 @@ +--- +title: ActiveRecord::Associations::CollectionProxy +layout: default +--- +
+ +
+
+ +
+ +

Collection proxies in Active Record are middlemen between an association, and its target result set.

+ +

For example, given

+ +
class Blog < ActiveRecord::Base
+  has_many :posts
+end
+
+blog = Blog.first
+
+ +

The collection proxy returned by blog.posts is built from a :has_many association, and delegates to a collection of posts as the target.

+ +

This class delegates unknown methods to the association‘s relation class via a delegate cache.

+ +

The target result set is not loaded until needed. For example,

+ +
blog.posts.count
+
+ +

is computed directly through SQL and does not trigger by itself the instantiation of the actual post records.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + <<(*records) + +

+ + +
+

Adds one or more records to the collection by setting their foreign keys to the association’s primary key. Since << flattens its argument list and inserts each record, push and concat behave identically. Returns self so several appends may be chained together.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.size # => 0
+person.pets << Pet.new(name: 'Fancy-Fancy')
+person.pets << [Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo')]
+person.pets.size # => 3
+
+person.id # => 1
+person.pets
+# => [
+#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#      #<Pet id: 2, name: "Spook", person_id: 1>,
+#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + +
+ Also aliased as: push, append, concat +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1031
+def <<(*records)
+  proxy_association.concat(records) && self
+end
+
+
+ +
+ +
+

+ + ==(other) + +

+ + +
+

Equivalent to Array#==. Returns true if the two arrays contain the same number of elements and if each element is equal to the corresponding element in the other array, otherwise returns false.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#      #<Pet id: 2, name: "Spook", person_id: 1>
+#    ]
+
+other = person.pets.to_ary
+
+person.pets == other
+# => true
+
+other = [Pet.new(id: 1), Pet.new(id: 2)]
+
+person.pets == other
+# => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 962
+def ==(other)
+  load_target == other
+end
+
+
+ +
+ +
+

+ + any?() + + +

+ + +
+

Returns true if the collection is not empty.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.count # => 0
+person.pets.any?  # => false
+
+person.pets << Pet.new(name: 'Snoop')
+person.pets.count # => 1
+person.pets.any?  # => true
+
+ +

Calling it without a block when the collection is not yet loaded is equivalent to collection.exists?. If you’re going to load the collection anyway, it is better to call collection.load.any? to avoid an extra query.

+ +

You can also pass a block to define criteria. The behavior is the same, it returns true if the collection based on the criteria is not empty.

+ +
person.pets
+# => [#<Pet name: "Snoop", group: "dogs">]
+
+person.pets.any? do |pet|
+  pet.group == 'cats'
+end
+# => false
+
+person.pets.any? do |pet|
+  pet.group == 'dogs'
+end
+# => true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 834
+      
+
+
+ +
+ +
+

+ + append(*records) + +

+ + +
+ +
+ + + + + +
+ Alias for: << +
+ + + +
+ +
+

+ + build(attributes = {}, &block) + +

+ + +
+

Returns a new object of the collection type that has been instantiated with attributes and linked to this object, but have not yet been saved. You can pass an array of attributes hashes, this will return an array with the new objects.

+ +
class Person
+  has_many :pets
+end
+
+person.pets.build
+# => #<Pet id: nil, name: nil, person_id: 1>
+
+person.pets.build(name: 'Fancy-Fancy')
+# => #<Pet id: nil, name: "Fancy-Fancy", person_id: 1>
+
+person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}])
+# => [
+#      #<Pet id: nil, name: "Spook", person_id: 1>,
+#      #<Pet id: nil, name: "Choo-Choo", person_id: 1>,
+#      #<Pet id: nil, name: "Brain", person_id: 1>
+#    ]
+
+person.pets.size  # => 5 # size of the collection
+person.pets.count # => 0 # count from database
+
+
+ + + +
+ Also aliased as: new +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 316
+def build(attributes = {}, &block)
+  @association.build(attributes, &block)
+end
+
+
+ +
+ +
+

+ + calculate(operation, column_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 722
+def calculate(operation, column_name)
+  null_scope? ? scope.calculate(operation, column_name) : super
+end
+
+
+ +
+ +
+

+ + clear() + +

+ + +
+

Equivalent to delete_all. The difference is that returns self, instead of an array with the deleted objects, so methods can be chained. See delete_all for more information. Note that because delete_all removes records by directly running an SQL query into the database, the updated_at column of the object is not changed.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1048
+def clear
+  delete_all
+  self
+end
+
+
+ +
+ +
+

+ + concat(*records) + +

+ + +
+ +
+ + + + + +
+ Alias for: << +
+ + + +
+ +
+

+ + count(column_name = nil, &block) + + +

+ + +
+

Count all records.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+# This will perform the count using SQL.
+person.pets.count # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+ +

Passing a block will select all of a person’s pets in SQL and then perform the count using Ruby.

+ +
person.pets.count { |pet| pet.name.include?('-') } # => 2
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 731
+      
+
+
+ +
+ +
+

+ + create(attributes = {}, &block) + +

+ + +
+

Returns a new object of the collection type that has been instantiated with attributes, linked to this object and that has already been saved (if it passes the validations).

+ +
class Person
+  has_many :pets
+end
+
+person.pets.create(name: 'Fancy-Fancy')
+# => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+
+person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}])
+# => [
+#      #<Pet id: 2, name: "Spook", person_id: 1>,
+#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.size  # => 3
+person.pets.count # => 3
+
+person.pets.find(1, 2, 3)
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 347
+def create(attributes = {}, &block)
+  @association.create(attributes, &block)
+end
+
+
+ +
+ +
+

+ + create!(attributes = {}, &block) + +

+ + +
+

Like create, except that if the record is invalid, raises an exception.

+ +
class Person
+  has_many :pets
+end
+
+class Pet
+  validates :name, presence: true
+end
+
+person.pets.create!(name: nil)
+# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 363
+def create!(attributes = {}, &block)
+  @association.create!(attributes, &block)
+end
+
+
+ +
+ +
+

+ + delete(*records) + +

+ + +
+

Deletes the records supplied from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy. Returns an array with the deleted records.

+ +

For has_many :through associations, the default deletion strategy is :delete_all.

+ +

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.

+ +
class Person < ActiveRecord::Base
+  has_many :pets # dependent: :nullify option by default
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete(Pet.find(1))
+# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
+
+person.pets.size # => 2
+person.pets
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+Pet.find(1)
+# => #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>
+
+ +

If it is set to :destroy all the records are removed by calling their destroy method. See destroy for more information.

+ +
class Person < ActiveRecord::Base
+  has_many :pets, dependent: :destroy
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete(Pet.find(1), Pet.find(3))
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.size # => 1
+person.pets
+# => [#<Pet id: 2, name: "Spook", person_id: 1>]
+
+Pet.find(1, 3)
+# => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 3)
+
+ +

If it is set to :delete_all, all the records are deleted without calling their destroy method.

+ +
class Person < ActiveRecord::Base
+  has_many :pets, dependent: :delete_all
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete(Pet.find(1))
+# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
+
+person.pets.size # => 2
+person.pets
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+Pet.find(1)
+# => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=1
+
+ +

You can pass Integer or String values, it finds the records responding to the id and executes delete on them.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete("1")
+# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
+
+person.pets.delete(2, 3)
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 618
+def delete(*records)
+  @association.delete(*records).tap { reset_scope }
+end
+
+
+ +
+ +
+

+ + delete_all(dependent = nil) + +

+ + +
+

Deletes all the records from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy.

+ +

For has_many :through associations, the default deletion strategy is :delete_all.

+ +

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.

+ +
class Person < ActiveRecord::Base
+  has_many :pets # dependent: :nullify option by default
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete_all
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.size # => 0
+person.pets      # => []
+
+Pet.find(1, 2, 3)
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>,
+#       #<Pet id: 2, name: "Spook", person_id: nil>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: nil>
+#    ]
+
+ +

Both has_many and has_many :through dependencies default to the :delete_all strategy if the :dependent option is set to :destroy. Records are not instantiated and callbacks will not be fired.

+ +
class Person < ActiveRecord::Base
+  has_many :pets, dependent: :destroy
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete_all
+
+Pet.find(1, 2, 3)
+# => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
+
+ +

If it is set to :delete_all, all the objects are deleted without calling their destroy method.

+ +
class Person < ActiveRecord::Base
+  has_many :pets, dependent: :delete_all
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.delete_all
+
+Pet.find(1, 2, 3)
+# => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 472
+def delete_all(dependent = nil)
+  @association.delete_all(dependent).tap { reset_scope }
+end
+
+
+ +
+ +
+

+ + destroy(*records) + +

+ + +
+

Destroys the records supplied and removes them from the collection. This method will always remove record from the database ignoring the :dependent option. Returns an array with the removed records.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.destroy(Pet.find(1))
+# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]
+
+person.pets.size # => 2
+person.pets
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.destroy(Pet.find(2), Pet.find(3))
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.size  # => 0
+person.pets       # => []
+
+Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
+
+ +

You can pass Integer or String values, it finds the records responding to the id and then deletes them from the database.

+ +
person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 4, name: "Benny", person_id: 1>,
+#       #<Pet id: 5, name: "Brain", person_id: 1>,
+#       #<Pet id: 6, name: "Boss",  person_id: 1>
+#    ]
+
+person.pets.destroy("4")
+# => #<Pet id: 4, name: "Benny", person_id: 1>
+
+person.pets.size # => 2
+person.pets
+# => [
+#       #<Pet id: 5, name: "Brain", person_id: 1>,
+#       #<Pet id: 6, name: "Boss",  person_id: 1>
+#    ]
+
+person.pets.destroy(5, 6)
+# => [
+#       #<Pet id: 5, name: "Brain", person_id: 1>,
+#       #<Pet id: 6, name: "Boss",  person_id: 1>
+#    ]
+
+person.pets.size  # => 0
+person.pets       # => []
+
+Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 690
+def destroy(*records)
+  @association.destroy(*records).tap { reset_scope }
+end
+
+
+ +
+ +
+

+ + destroy_all() + +

+ + +
+

Deletes the records of the collection directly from the database ignoring the :dependent option. Records are instantiated and it invokes before_remove, after_remove, before_destroy, and after_destroy callbacks.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.size # => 3
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.destroy_all
+
+person.pets.size # => 0
+person.pets      # => []
+
+Pet.find(1) # => Couldn't find Pet with id=1
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 499
+def destroy_all
+  @association.destroy_all.tap { reset_scope }
+end
+
+
+ +
+ +
+

+ + distinct(value = true) + + +

+ + +
+

Specifies whether the records should be unique or not.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.select(:name)
+# => [
+#      #<Pet name: "Fancy-Fancy">,
+#      #<Pet name: "Fancy-Fancy">
+#    ]
+
+person.pets.select(:name).distinct
+# => [#<Pet name: "Fancy-Fancy">]
+
+person.pets.select(:name).distinct.distinct(false)
+# => [
+#      #<Pet name: "Fancy-Fancy">,
+#      #<Pet name: "Fancy-Fancy">
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 695
+      
+
+
+ +
+ +
+

+ + empty?() + +

+ + +
+

Returns true if the collection is empty. If the collection has been loaded it is equivalent to collection.size.zero?. If the collection has not been loaded, it is equivalent to !collection.exists?. If the collection has not already been loaded and you are going to fetch the records anyway it is better to check collection.load.empty?.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.count  # => 1
+person.pets.empty? # => false
+
+person.pets.delete_all
+
+person.pets.count  # => 0
+person.pets.empty? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 829
+def empty?
+  @association.empty?
+end
+
+
+ +
+ +
+

+ + fifth() + + +

+ + +
+

Same as first except returns only the fifth record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 199
+      
+
+
+ +
+ +
+

+ + find(*args) + +

+ + +
+

Finds an object in the collection responding to the id. Uses the same rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound error if the object cannot be found.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4
+
+person.pets.find(2) { |pet| pet.name.downcase! }
+# => #<Pet id: 2, name: "fancy-fancy", person_id: 1>
+
+person.pets.find(2, 3)
+# => [
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 136
+def find(*args)
+  return super if block_given?
+  @association.find(*args)
+end
+
+
+ +
+ +
+

+ + first(limit = nil) + + +

+ + +
+

Returns the first record, or the first n records, from the collection. If the collection is empty, the first form returns nil, and the second form returns an empty array.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.first # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+
+person.pets.first(2)
+# => [
+#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#      #<Pet id: 2, name: "Spook", person_id: 1>
+#    ]
+
+another_person_without.pets          # => []
+another_person_without.pets.first    # => nil
+another_person_without.pets.first(3) # => []
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 142
+      
+
+
+ +
+ +
+

+ + forty_two() + + +

+ + +
+

Same as first except returns only the forty second record. Also known as accessing “the reddit”.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 207
+      
+
+
+ +
+ +
+

+ + fourth() + + +

+ + +
+

Same as first except returns only the fourth record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 191
+      
+
+
+ +
+ +
+

+ + include?(record) + +

+ + +
+

Returns true if the given record is present in the collection.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets # => [#<Pet id: 20, name: "Snoop">]
+
+person.pets.include?(Pet.find(20)) # => true
+person.pets.include?(Pet.find(21)) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 925
+def include?(record)
+  !!@association.include?(record)
+end
+
+
+ +
+ +
+

+ + last(limit = nil) + +

+ + +
+

Returns the last record, or the last n records, from the collection. If the collection is empty, the first form returns nil, and the second form returns an empty array.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.last # => #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+
+person.pets.last(2)
+# => [
+#      #<Pet id: 2, name: "Spook", person_id: 1>,
+#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+another_person_without.pets         # => []
+another_person_without.pets.last    # => nil
+another_person_without.pets.last(3) # => []
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 257
+def last(limit = nil)
+  load_target if find_from_target?
+  super
+end
+
+
+ +
+ +
+

+ + length() + + +

+ + +
+

Returns the size of the collection calling size on the target. If the collection has been already loaded, length and size are equivalent. If not and you are going to need the records anyway this method will take one less query. Otherwise size is more efficient.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.length # => 3
+# executes something like SELECT "pets".* FROM "pets" WHERE "pets"."person_id" = 1
+
+# Because the collection is loaded, you can
+# call the collection with no additional queries:
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 785
+      
+
+
+ +
+ +
+

+ + load_target() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 42
+def load_target
+  @association.load_target
+end
+
+
+ +
+ +
+

+ + loaded() + +

+ + +
+ +
+ + + + + +
+ Alias for: loaded? +
+ + + +
+ +
+

+ + loaded?() + +

+ + +
+

Returns true if the association has been loaded, otherwise false.

+ +
person.pets.loaded? # => false
+person.pets.records
+person.pets.loaded? # => true
+
+
+ + + +
+ Also aliased as: loaded +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 51
+def loaded?
+  @association.loaded?
+end
+
+
+ +
+ +
+

+ + many?() + + +

+ + +
+

Returns true if the collection has more than one record. Equivalent to collection.size > 1.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.count # => 1
+person.pets.many? # => false
+
+person.pets << Pet.new(name: 'Snoopy')
+person.pets.count # => 2
+person.pets.many? # => true
+
+ +

You can also pass a block to define criteria. The behavior is the same, it returns true if the collection based on the criteria has more than one record.

+ +
person.pets
+# => [
+#      #<Pet name: "Gorby", group: "cats">,
+#      #<Pet name: "Puff", group: "cats">,
+#      #<Pet name: "Snoop", group: "dogs">
+#    ]
+
+person.pets.many? do |pet|
+  pet.group == 'dogs'
+end
+# => false
+
+person.pets.many? do |pet|
+  pet.group == 'cats'
+end
+# => true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 875
+      
+
+
+ +
+ +
+

+ + new(attributes = {}, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: build +
+ + + +
+ +
+

+ + pluck(*column_names) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 726
+def pluck(*column_names)
+  null_scope? ? scope.pluck(*column_names) : super
+end
+
+
+ +
+ +
+

+ + push(*records) + +

+ + +
+ +
+ + + + + +
+ Alias for: << +
+ + + +
+ +
+

+ + reload() + +

+ + +
+

Reloads the collection from the database. Returns self.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets # fetches pets from the database
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+person.pets # uses the pets cache
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+person.pets.reload # fetches pets from the database
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1067
+def reload
+  proxy_association.reload(true)
+  reset_scope
+end
+
+
+ +
+ +
+

+ + replace(other_array) + +

+ + +
+

Replaces this collection with other_array. This will perform a diff and delete/add only records that have changed.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]
+
+other_pets = [Pet.new(name: 'Puff', group: 'celebrities')]
+
+person.pets.replace(other_pets)
+
+person.pets
+# => [#<Pet id: 2, name: "Puff", group: "celebrities", person_id: 1>]
+
+ +

If the supplied array has an incorrect association type, it raises an ActiveRecord::AssociationTypeMismatch error:

+ +
person.pets.replace(["doo", "ggie", "gaga"])
+# => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 389
+def replace(other_array)
+  @association.replace(other_array)
+end
+
+
+ +
+ +
+

+ + reset() + +

+ + +
+

Unloads the association. Returns self.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets # fetches pets from the database
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+person.pets # uses the pets cache
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+person.pets.reset # clears the pets cache
+
+person.pets  # fetches pets from the database
+# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1088
+def reset
+  proxy_association.reset
+  proxy_association.reset_scope
+  reset_scope
+end
+
+
+ +
+ +
+

+ + scope() + +

+ + +
+

Returns a Relation object for the records in this association

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 934
+def scope
+  @scope ||= @association.scope
+end
+
+
+ +
+ +
+

+ + second() + + +

+ + +
+

Same as first except returns only the second record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 175
+      
+
+
+ +
+ +
+

+ + second_to_last() + + +

+ + +
+

Same as first except returns only the second-to-last record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 224
+      
+
+
+ +
+ +
+

+ + select(*fields, &block) + + +

+ + +
+

Works in two ways.

+ +

First: Specify a subset of fields to be selected from the result set.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.select(:name)
+# => [
+#      #<Pet id: nil, name: "Fancy-Fancy">,
+#      #<Pet id: nil, name: "Spook">,
+#      #<Pet id: nil, name: "Choo-Choo">
+#    ]
+
+person.pets.select(:id, :name)
+# => [
+#      #<Pet id: 1, name: "Fancy-Fancy">,
+#      #<Pet id: 2, name: "Spook">,
+#      #<Pet id: 3, name: "Choo-Choo">
+#    ]
+
+ +

Be careful because this also means you’re initializing a model object with only the fields that you’ve selected. If you attempt to access a field except id that is not in the initialized record you’ll receive:

+ +
person.pets.select(:name).first.person_id
+# => ActiveModel::MissingAttributeError: missing attribute: person_id
+
+ +

Second: You can pass a block so it can be used just like Array#select. This builds an array of objects from the database for the scope, converting them into an array and iterating through them using Array#select.

+ +
person.pets.select { |pet| /oo/.match?(pet.name) }
+# => [
+#      #<Pet id: 2, name: "Spook", person_id: 1>,
+#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 57
+      
+
+
+ +
+ +
+

+ + size() + +

+ + +
+

Returns the size of the collection. If the collection hasn’t been loaded, it executes a SELECT COUNT(*) query. Else it calls collection.size.

+ +

If the collection has been already loaded size and length are equivalent. If not and you are going to need the records anyway length will take one less query. Otherwise size is more efficient.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets.size # => 3
+# executes something like SELECT COUNT(*) FROM "pets" WHERE "pets"."person_id" = 1
+
+person.pets # This will execute a SELECT * FROM query
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.size # => 3
+# Because the collection is already loaded, this will behave like
+# collection.size and no SQL count query is executed.
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 780
+def size
+  @association.size
+end
+
+
+ +
+ +
+

+ + take(limit = nil) + +

+ + +
+

Gives a record (or N records if a parameter is supplied) from the collection using the same rules as ActiveRecord::Base.take.

+ +
class Person < ActiveRecord::Base
+  has_many :pets
+end
+
+person.pets
+# => [
+#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#       #<Pet id: 2, name: "Spook", person_id: 1>,
+#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
+#    ]
+
+person.pets.take # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
+
+person.pets.take(2)
+# => [
+#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
+#      #<Pet id: 2, name: "Spook", person_id: 1>
+#    ]
+
+another_person_without.pets         # => []
+another_person_without.pets.take    # => nil
+another_person_without.pets.take(2) # => []
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 287
+def take(limit = nil)
+  load_target if find_from_target?
+  super
+end
+
+
+ +
+ +
+

+ + target() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 38
+def target
+  @association.target
+end
+
+
+ +
+ +
+

+ + third() + + +

+ + +
+

Same as first except returns only the third record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 183
+      
+
+
+ +
+ +
+

+ + third_to_last() + + +

+ + +
+

Same as first except returns only the third-to-last record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 216
+      
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/Preloader.html b/src/7.0/classes/ActiveRecord/Associations/Preloader.html new file mode 100644 index 0000000000..31aee4d4d0 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/Preloader.html @@ -0,0 +1,81 @@ +--- +title: ActiveRecord::Associations::Preloader +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/Preloader/Association.html b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association.html new file mode 100644 index 0000000000..dd756f742d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::Associations::Preloader::Association +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderQuery.html b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderQuery.html new file mode 100644 index 0000000000..9d5dff8682 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderQuery.html @@ -0,0 +1,335 @@ +--- +title: ActiveRecord::Associations::Preloader::Association::LoaderQuery +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + association_key_name
+ [R] + scope
+ + + + +

Class Public methods

+ +
+

+ + new(scope, association_key_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 10
+def initialize(scope, association_key_name)
+  @scope = scope
+  @association_key_name = association_key_name
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + eql?(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 15
+def eql?(other)
+  association_key_name == other.association_key_name &&
+    scope.table_name == other.scope.table_name &&
+    scope.values_for_queries == other.scope.values_for_queries
+end
+
+
+ +
+ +
+

+ + hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 21
+def hash
+  [association_key_name, scope.table_name, scope.values_for_queries].hash
+end
+
+
+ +
+ +
+

+ + load_records_for_keys(keys, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 38
+def load_records_for_keys(keys, &block)
+  scope.where(association_key_name => keys).load(&block)
+end
+
+
+ +
+ +
+

+ + load_records_in_batch(loaders) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 29
+def load_records_in_batch(loaders)
+  raw_records = records_for(loaders)
+
+  loaders.each do |loader|
+    loader.load_records(raw_records)
+    loader.run
+  end
+end
+
+
+ +
+ +
+

+ + records_for(loaders) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 25
+def records_for(loaders)
+  LoaderRecords.new(loaders, self).records
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderRecords.html b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderRecords.html new file mode 100644 index 0000000000..e017cc7c7c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Associations/Preloader/Association/LoaderRecords.html @@ -0,0 +1,154 @@ +--- +title: ActiveRecord::Associations::Preloader::Association::LoaderRecords +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(loaders, loader_query) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 44
+def initialize(loaders, loader_query)
+  @loader_query = loader_query
+  @loaders = loaders
+  @keys_to_load = Set.new
+  @already_loaded_records_by_key = {}
+
+  populate_keys_to_load_and_already_loaded_records
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + records() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations/preloader/association.rb, line 53
+def records
+  load_records + already_loaded_records
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AsynchronousQueryInsideTransactionError.html b/src/7.0/classes/ActiveRecord/AsynchronousQueryInsideTransactionError.html new file mode 100644 index 0000000000..3a2b86c442 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AsynchronousQueryInsideTransactionError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::AsynchronousQueryInsideTransactionError +layout: default +--- +
+ +
+
+ +
+ +

AsynchronousQueryInsideTransactionError will be raised when attempting to perform an asynchronous query from inside a transaction

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeAssignment.html b/src/7.0/classes/ActiveRecord/AttributeAssignment.html new file mode 100644 index 0000000000..da9a0982a6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeAssignment.html @@ -0,0 +1,68 @@ +--- +title: ActiveRecord::AttributeAssignment +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeAssignmentError.html b/src/7.0/classes/ActiveRecord/AttributeAssignmentError.html new file mode 100644 index 0000000000..73e801cc7b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeAssignmentError.html @@ -0,0 +1,137 @@ +--- +title: ActiveRecord::AttributeAssignmentError +layout: default +--- +
+ +
+
+ +
+ +

Raised when an error occurred while doing a mass assignment to an attribute through the ActiveRecord::Base#attributes= method. The exception has an attribute property that is the name of the offending attribute.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + attribute
+ [R] + exception
+ + + + +

Class Public methods

+ +
+

+ + new(message = nil, exception = nil, attribute = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 355
+def initialize(message = nil, exception = nil, attribute = nil)
+  super(message)
+  @exception = exception
+  @attribute = attribute
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods.html b/src/7.0/classes/ActiveRecord/AttributeMethods.html new file mode 100644 index 0000000000..e6b58e8e37 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods.html @@ -0,0 +1,693 @@ +--- +title: ActiveRecord::AttributeMethods +layout: default +--- +
+ +
+
+ +
+ +

Active Record Attribute Methods

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RESTRICTED_CLASS_METHODS=%w(private public protected allocate new name parent superclass)
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + [](attr_name) + +

+ + +
+

Returns the value of the attribute identified by attr_name after it has been typecast (for example, “2004-12-12” in a date column is cast to a date object, like Date.new(2004, 12, 12)). It raises ActiveModel::MissingAttributeError if the identified attribute is missing.

+ +

Note: :id is always present.

+ +
class Person < ActiveRecord::Base
+  belongs_to :organization
+end
+
+person = Person.new(name: 'Francesco', age: '22')
+person[:name] # => "Francesco"
+person[:age]  # => 22
+
+person = Person.select('id').first
+person[:name]            # => ActiveModel::MissingAttributeError: missing attribute: name
+person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 329
+def [](attr_name)
+  read_attribute(attr_name) { |n| missing_attribute(n, caller) }
+end
+
+
+ +
+ +
+

+ + []=(attr_name, value) + +

+ + +
+

Updates the attribute identified by attr_name with the specified value.

+ +
class Person < ActiveRecord::Base
+end
+
+person = Person.new
+person[:age] = '22'
+person[:age] # => 22
+person[:age].class # => Integer
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 342
+def []=(attr_name, value)
+  write_attribute(attr_name, value)
+end
+
+
+ +
+ +
+

+ + accessed_fields() + +

+ + +
+

Returns the name of all database fields which have been read from this model. This can be useful in development mode to determine which fields need to be selected. For performance critical pages, selecting only the required fields can be an easy performance win (assuming you aren’t using all of the fields on the model).

+ +

For example:

+ +
class PostsController < ActionController::Base
+  after_action :print_accessed_fields, only: :index
+
+  def index
+    @posts = Post.all
+  end
+
+  private
+    def print_accessed_fields
+      p @posts.first.accessed_fields
+    end
+end
+
+ +

Which allows you to quickly change your code to:

+ +
class PostsController < ActionController::Base
+  def index
+    @posts = Post.select(:id, :title, :author_id, :updated_at)
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 374
+def accessed_fields
+  @attributes.accessed
+end
+
+
+ +
+ +
+

+ + attribute_for_inspect(attr_name) + +

+ + +
+

Returns an #inspect-like string for the value of the attribute attr_name. String attributes are truncated up to 50 characters. Other attributes return the value of #inspect without modification.

+ +
person = Person.create!(name: 'David Heinemeier Hansson ' * 3)
+
+person.attribute_for_inspect(:name)
+# => "\"David Heinemeier Hansson David Heinemeier Hansson ...\""
+
+person.attribute_for_inspect(:created_at)
+# => "\"2012-10-22 00:15:07.000000000 +0000\""
+
+person.attribute_for_inspect(:tag_ids)
+# => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 283
+def attribute_for_inspect(attr_name)
+  attr_name = attr_name.to_s
+  attr_name = self.class.attribute_aliases[attr_name] || attr_name
+  value = _read_attribute(attr_name)
+  format_for_inspect(attr_name, value)
+end
+
+
+ +
+ +
+

+ + attribute_names() + +

+ + +
+

Returns an array of names for the attributes available on this object.

+ +
class Person < ActiveRecord::Base
+end
+
+person = Person.new
+person.attribute_names
+# => ["id", "created_at", "updated_at", "name", "age"]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 252
+def attribute_names
+  @attributes.keys
+end
+
+
+ +
+ +
+

+ + attribute_present?(attr_name) + +

+ + +
+

Returns true if the specified attribute has been set by the user or by a database load and is neither nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings). Otherwise, false. Note that it always returns true with boolean attributes.

+ +
class Task < ActiveRecord::Base
+end
+
+task = Task.new(title: '', is_done: false)
+task.attribute_present?(:title)   # => false
+task.attribute_present?(:is_done) # => true
+task.title = 'Buy milk'
+task.is_done = true
+task.attribute_present?(:title)   # => true
+task.attribute_present?(:is_done) # => true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 305
+def attribute_present?(attr_name)
+  attr_name = attr_name.to_s
+  attr_name = self.class.attribute_aliases[attr_name] || attr_name
+  value = _read_attribute(attr_name)
+  !value.nil? && !(value.respond_to?(:empty?) && value.empty?)
+end
+
+
+ +
+ +
+

+ + attributes() + +

+ + +
+

Returns a hash of all the attributes with their names as keys and the values of the attributes as values.

+ +
class Person < ActiveRecord::Base
+end
+
+person = Person.create(name: 'Francesco', age: 22)
+person.attributes
+# => {"id"=>3, "created_at"=>Sun, 21 Oct 2012 04:53:04, "updated_at"=>Sun, 21 Oct 2012 04:53:04, "name"=>"Francesco", "age"=>22}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 264
+def attributes
+  @attributes.to_hash
+end
+
+
+ +
+ +
+

+ + has_attribute?(attr_name) + +

+ + +
+

Returns true if the given attribute is in the attributes hash, otherwise false.

+ +
class Person < ActiveRecord::Base
+  alias_attribute :new_name, :name
+end
+
+person = Person.new
+person.has_attribute?(:name)     # => true
+person.has_attribute?(:new_name) # => true
+person.has_attribute?('age')     # => true
+person.has_attribute?(:nothing)  # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 234
+def has_attribute?(attr_name)
+  attr_name = attr_name.to_s
+  attr_name = self.class.attribute_aliases[attr_name] || attr_name
+  @attributes.key?(attr_name)
+end
+
+
+ +
+ +
+

+ + respond_to?(name, include_private = false) + +

+ + +
+

A Person object with a name attribute can ask person.respond_to?(:name), person.respond_to?(:name=), and person.respond_to?(:name?) which will all return true. It also defines the attribute methods if they have not been generated.

+ +
class Person < ActiveRecord::Base
+end
+
+person = Person.new
+person.respond_to?(:name)    # => true
+person.respond_to?(:name=)   # => true
+person.respond_to?(:name?)   # => true
+person.respond_to?('age')    # => true
+person.respond_to?('age=')   # => true
+person.respond_to?('age?')   # => true
+person.respond_to?(:nothing) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 207
+def respond_to?(name, include_private = false)
+  return false unless super
+
+  # If the result is true then check for the select case.
+  # For queries selecting a subset of columns, return false for unselected columns.
+  # We check defined?(@attributes) not to issue warnings if called on objects that
+  # have been allocated but not yet initialized.
+  if defined?(@attributes)
+    if name = self.class.symbol_column_to_string(name.to_sym)
+      return _has_attribute?(name)
+    end
+  end
+
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html b/src/7.0/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html new file mode 100644 index 0000000000..0623833fb5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/BeforeTypeCast.html @@ -0,0 +1,230 @@ +--- +title: ActiveRecord::AttributeMethods::BeforeTypeCast +layout: default +--- +
+ +
+
+ +
+ +

Active Record Attribute Methods Before Type Cast

+ +

ActiveRecord::AttributeMethods::BeforeTypeCast provides a way to read the value of the attributes before typecasting and deserialization.

+ +
class Task < ActiveRecord::Base
+end
+
+task = Task.new(id: '1', completed_on: '2012-10-21')
+task.id           # => 1
+task.completed_on # => Sun, 21 Oct 2012
+
+task.attributes_before_type_cast
+# => {"id"=>"1", "completed_on"=>"2012-10-21", ... }
+task.read_attribute_before_type_cast('id')           # => "1"
+task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
+
+ +

In addition to read_attribute_before_type_cast and attributes_before_type_cast, it declares a method for all attributes with the *_before_type_cast suffix.

+ +
task.id_before_type_cast           # => "1"
+task.completed_on_before_type_cast # => "2012-10-21"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attributes_before_type_cast() + +

+ + +
+

Returns a hash of attributes before typecasting and deserialization.

+ +
class Task < ActiveRecord::Base
+end
+
+task = Task.new(title: nil, is_done: true, completed_on: '2012-10-21')
+task.attributes
+# => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>Sun, 21 Oct 2012, "created_at"=>nil, "updated_at"=>nil}
+task.attributes_before_type_cast
+# => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/before_type_cast.rb, line 65
+def attributes_before_type_cast
+  @attributes.values_before_type_cast
+end
+
+
+ +
+ +
+

+ + attributes_for_database() + +

+ + +
+

Returns a hash of attributes for assignment to the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/before_type_cast.rb, line 70
+def attributes_for_database
+  @attributes.values_for_database
+end
+
+
+ +
+ +
+

+ + read_attribute_before_type_cast(attr_name) + +

+ + +
+

Returns the value of the attribute identified by attr_name before typecasting and deserialization.

+ +
class Task < ActiveRecord::Base
+end
+
+task = Task.new(id: '1', completed_on: '2012-10-21')
+task.read_attribute('id')                            # => 1
+task.read_attribute_before_type_cast('id')           # => '1'
+task.read_attribute('completed_on')                  # => Sun, 21 Oct 2012
+task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
+task.read_attribute_before_type_cast(:completed_on)  # => "2012-10-21"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/before_type_cast.rb, line 48
+def read_attribute_before_type_cast(attr_name)
+  name = attr_name.to_s
+  name = self.class.attribute_aliases[name] || name
+
+  attribute_before_type_cast(name)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/ClassMethods.html b/src/7.0/classes/ActiveRecord/AttributeMethods/ClassMethods.html new file mode 100644 index 0000000000..3ed1c90ec1 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/ClassMethods.html @@ -0,0 +1,323 @@ +--- +title: ActiveRecord::AttributeMethods::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attribute_method?(attribute) + +

+ + +
+

Returns true if attribute is an attribute method and table exists, false otherwise.

+ +
class Person < ActiveRecord::Base
+end
+
+Person.attribute_method?('name')   # => true
+Person.attribute_method?(:age=)    # => true
+Person.attribute_method?(:nothing) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 150
+def attribute_method?(attribute)
+  super || (table_exists? && column_names.include?(attribute.to_s.delete_suffix("=")))
+end
+
+
+ +
+ +
+

+ + attribute_names() + +

+ + +
+

Returns an array of column names as strings if it’s not an abstract class and table exists. Otherwise it returns an empty array.

+ +
class Person < ActiveRecord::Base
+end
+
+Person.attribute_names
+# => ["id", "created_at", "updated_at", "name", "age"]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 162
+def attribute_names
+  @attribute_names ||= if !abstract_class? && table_exists?
+    attribute_types.keys
+  else
+    []
+  end.freeze
+end
+
+
+ +
+ +
+

+ + dangerous_class_method?(method_name) + +

+ + +
+

A class method is ‘dangerous’ if it is already (re)defined by Active Record, but not by any ancestors. (So ‘puts’ is not dangerous but ‘new’ is.)

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 127
+def dangerous_class_method?(method_name)
+  return true if RESTRICTED_CLASS_METHODS.include?(method_name.to_s)
+
+  if Base.respond_to?(method_name, true)
+    if Object.respond_to?(method_name, true)
+      Base.method(method_name).owner != Object.method(method_name).owner
+    else
+      true
+    end
+  else
+    false
+  end
+end
+
+
+ +
+ +
+

+ + has_attribute?(attr_name) + +

+ + +
+

Returns true if the given attribute exists, otherwise false.

+ +
class Person < ActiveRecord::Base
+  alias_attribute :new_name, :name
+end
+
+Person.has_attribute?('name')     # => true
+Person.has_attribute?('new_name') # => true
+Person.has_attribute?(:age)       # => true
+Person.has_attribute?(:nothing)   # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 180
+def has_attribute?(attr_name)
+  attr_name = attr_name.to_s
+  attr_name = attribute_aliases[attr_name] || attr_name
+  attribute_types.key?(attr_name)
+end
+
+
+ +
+ +
+

+ + instance_method_already_implemented?(method_name) + +

+ + +
+

Raises an ActiveRecord::DangerousAttributeError exception when an Active Record method is defined in the model, otherwise false.

+ +
class Person < ActiveRecord::Base
+  def save
+    'already defined by Active Record'
+  end
+end
+
+Person.instance_method_already_implemented?(:save)
+# => ActiveRecord::DangerousAttributeError: save is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name.
+
+Person.instance_method_already_implemented?(:name)
+# => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods.rb, line 91
+def instance_method_already_implemented?(method_name)
+  if dangerous_attribute_method?(method_name)
+    raise DangerousAttributeError, "#{method_name} is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name."
+  end
+
+  if superclass == Base
+    super
+  else
+    # If ThisClass < ... < SomeSuperClass < ... < Base and SomeSuperClass
+    # defines its own attribute method, then we don't want to override that.
+    defined = method_defined_within?(method_name, superclass, Base) &&
+      ! superclass.instance_method(method_name).owner.is_a?(GeneratedAttributeMethods)
+    defined || super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty.html new file mode 100644 index 0000000000..63defcc261 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty.html @@ -0,0 +1,627 @@ +--- +title: ActiveRecord::AttributeMethods::Dirty +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attribute_before_last_save(attr_name) + +

+ + +
+

Returns the original value of an attribute before the last save.

+ +

This method is useful in after callbacks to get the original value of an attribute before the save that triggered the callbacks to run. It can be invoked as name_before_last_save instead of attribute_before_last_save("name").

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 100
+def attribute_before_last_save(attr_name)
+  mutations_before_last_save.original_value(attr_name.to_s)
+end
+
+
+ +
+ +
+

+ + attribute_change_to_be_saved(attr_name) + +

+ + +
+

Returns the change to an attribute that will be persisted during the next save.

+ +

This method is useful in validations and before callbacks, to see the change to an attribute that will occur when the record is saved. It can be invoked as name_change_to_be_saved instead of attribute_change_to_be_saved("name").

+ +

If the attribute will change, the result will be an array containing the original value and the new value about to be saved.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 142
+def attribute_change_to_be_saved(attr_name)
+  mutations_from_database.change_to_attribute(attr_name.to_s)
+end
+
+
+ +
+ +
+

+ + attribute_in_database(attr_name) + +

+ + +
+

Returns the value of an attribute in the database, as opposed to the in-memory value that will be persisted the next time the record is saved.

+ +

This method is useful in validations and before callbacks, to see the original value of an attribute prior to any changes about to be saved. It can be invoked as name_in_database instead of attribute_in_database("name").

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 154
+def attribute_in_database(attr_name)
+  mutations_from_database.original_value(attr_name.to_s)
+end
+
+
+ +
+ +
+

+ + attributes_in_database() + +

+ + +
+

Returns a hash of the attributes that will change when the record is next saved.

+ +

The hash keys are the attribute names, and the hash values are the original attribute values in the database (as opposed to the in-memory values about to be saved).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 181
+def attributes_in_database
+  mutations_from_database.changed_values
+end
+
+
+ +
+ +
+

+ + changed_attribute_names_to_save() + +

+ + +
+

Returns an array of the names of any attributes that will change when the record is next saved.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 171
+def changed_attribute_names_to_save
+  mutations_from_database.changed_attribute_names
+end
+
+
+ +
+ +
+

+ + changes_to_save() + +

+ + +
+

Returns a hash containing all the changes that will be persisted during the next save.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 165
+def changes_to_save
+  mutations_from_database.changes
+end
+
+
+ +
+ +
+

+ + has_changes_to_save?() + +

+ + +
+

Will the next call to save have any changes to persist?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 159
+def has_changes_to_save?
+  mutations_from_database.any_changes?
+end
+
+
+ +
+ +
+

+ + reload(*) + +

+ + +
+

reload the record and clears changed attributes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 57
+def reload(*)
+  super.tap do
+    @mutations_before_last_save = nil
+    @mutations_from_database = nil
+  end
+end
+
+
+ +
+ +
+

+ + saved_change_to_attribute(attr_name) + +

+ + +
+

Returns the change to an attribute during the last save. If the attribute was changed, the result will be an array containing the original value and the saved value.

+ +

This method is useful in after callbacks, to see the change in an attribute during the save that triggered the callbacks to run. It can be invoked as saved_change_to_name instead of saved_change_to_attribute("name").

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 90
+def saved_change_to_attribute(attr_name)
+  mutations_before_last_save.change_to_attribute(attr_name.to_s)
+end
+
+
+ +
+ +
+

+ + saved_change_to_attribute?(attr_name, **options) + +

+ + +
+

Did this attribute change when we last saved?

+ +

This method is useful in after callbacks to determine if an attribute was changed during the save that triggered the callbacks to run. It can be invoked as saved_change_to_name? instead of saved_change_to_attribute?("name").

+ +

Options

+ +

from When passed, this method will return false unless the original value is equal to the given option

+ +

to When passed, this method will return false unless the value was changed to the given value

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 78
+def saved_change_to_attribute?(attr_name, **options)
+  mutations_before_last_save.changed?(attr_name.to_s, **options)
+end
+
+
+ +
+ +
+

+ + saved_changes() + +

+ + +
+

Returns a hash containing all the changes that were just saved.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 110
+def saved_changes
+  mutations_before_last_save.changes
+end
+
+
+ +
+ +
+

+ + saved_changes?() + +

+ + +
+

Did the last call to save have any changes to change?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 105
+def saved_changes?
+  mutations_before_last_save.any_changes?
+end
+
+
+ +
+ +
+

+ + will_save_change_to_attribute?(attr_name, **options) + +

+ + +
+

Will this attribute change the next time we save?

+ +

This method is useful in validations and before callbacks to determine if the next call to save will change a particular attribute. It can be invoked as will_save_change_to_name? instead of will_save_change_to_attribute?("name").

+ +

Options

+ +

from When passed, this method will return false unless the original value is equal to the given option

+ +

to When passed, this method will return false unless the value will be changed to the given value

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 128
+def will_save_change_to_attribute?(attr_name, **options)
+  mutations_from_database.changed?(attr_name.to_s, **options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty/ClassMethods.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty/ClassMethods.html new file mode 100644 index 0000000000..2073df31cb --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Dirty/ClassMethods.html @@ -0,0 +1,191 @@ +--- +title: ActiveRecord::AttributeMethods::Dirty::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + partial_writes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 31
+        def partial_writes
+          ActiveSupport::Deprecation.warn(<<-MSG.squish)
+            ActiveRecord::Base.partial_writes is deprecated and will be removed in Rails 7.1.
+            Use `partial_updates` and `partial_inserts` instead.
+          MSG
+          partial_updates && partial_inserts
+        end
+
+
+ +
+ +
+

+ + partial_writes=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 47
+        def partial_writes=(value)
+          ActiveSupport::Deprecation.warn(<<-MSG.squish)
+            `ActiveRecord::Base.partial_writes=` is deprecated and will be removed in Rails 7.1.
+            Use `partial_updates=` and `partial_inserts=` instead.
+          MSG
+          self.partial_updates = self.partial_inserts = value
+        end
+
+
+ +
+ +
+

+ + partial_writes?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/dirty.rb, line 39
+        def partial_writes?
+          ActiveSupport::Deprecation.warn(<<-MSG.squish)
+            `ActiveRecord::Base.partial_writes?` is deprecated and will be removed in Rails 7.1.
+            Use `partial_updates?` and `partial_inserts?` instead.
+          MSG
+          partial_updates? && partial_inserts?
+        end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey.html b/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey.html new file mode 100644 index 0000000000..9066208354 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey.html @@ -0,0 +1,349 @@ +--- +title: ActiveRecord::AttributeMethods::PrimaryKey +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + id() + +

+ + +
+

Returns the primary key column’s value.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 18
+def id
+  _read_attribute(@primary_key)
+end
+
+
+ +
+ +
+

+ + id=(value) + +

+ + +
+

Sets the primary key column’s value.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 23
+def id=(value)
+  _write_attribute(@primary_key, value)
+end
+
+
+ +
+ +
+

+ + id?() + +

+ + +
+

Queries the primary key column’s value.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 28
+def id?
+  query_attribute(@primary_key)
+end
+
+
+ +
+ +
+

+ + id_before_type_cast() + +

+ + +
+

Returns the primary key column’s value before type cast.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 33
+def id_before_type_cast
+  attribute_before_type_cast(@primary_key)
+end
+
+
+ +
+ +
+

+ + id_in_database() + +

+ + +
+

Returns the primary key column’s value from the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 43
+def id_in_database
+  attribute_in_database(@primary_key)
+end
+
+
+ +
+ +
+

+ + id_was() + +

+ + +
+

Returns the primary key column’s previous value.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 38
+def id_was
+  attribute_was(@primary_key)
+end
+
+
+ +
+ +
+

+ + to_key() + +

+ + +
+

Returns this record’s primary key value wrapped in an array if one is available.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 12
+def to_key
+  key = id
+  [key] if key
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html b/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html new file mode 100644 index 0000000000..55e2c0edd3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/PrimaryKey/ClassMethods.html @@ -0,0 +1,294 @@ +--- +title: ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ID_ATTRIBUTE_METHODS=%w(id id= id? id_before_type_cast id_was id_in_database id_for_database).to_set
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + dangerous_attribute_method?(method_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 63
+def dangerous_attribute_method?(method_name)
+  super && !ID_ATTRIBUTE_METHODS.include?(method_name)
+end
+
+
+ +
+ +
+

+ + instance_method_already_implemented?(method_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 59
+def instance_method_already_implemented?(method_name)
+  super || primary_key && ID_ATTRIBUTE_METHODS.include?(method_name)
+end
+
+
+ +
+ +
+

+ + primary_key() + +

+ + +
+

Defines the primary key field – can be overridden in subclasses. Overwriting will negate any effect of the primary_key_prefix_type setting, though.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 70
+def primary_key
+  @primary_key = reset_primary_key unless defined? @primary_key
+  @primary_key
+end
+
+
+ +
+ +
+

+ + primary_key=(value) + +

+ + +
+

Sets the name of the primary key column.

+ +
class Project < ActiveRecord::Base
+  self.primary_key = 'sysid'
+end
+
+ +

You can also define the primary_key method yourself:

+ +
class Project < ActiveRecord::Base
+  def self.primary_key
+    'foo_' + super
+  end
+end
+
+Project.primary_key # => "foo_id"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 119
+def primary_key=(value)
+  @primary_key        = value && -value.to_s
+  @quoted_primary_key = nil
+  @attributes_builder = nil
+end
+
+
+ +
+ +
+

+ + quoted_primary_key() + +

+ + +
+

Returns a quoted version of the primary key name, used to construct SQL statements.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/primary_key.rb, line 77
+def quoted_primary_key
+  @quoted_primary_key ||= connection.quote_column_name(primary_key)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Query.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Query.html new file mode 100644 index 0000000000..7e4b6714b7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Query.html @@ -0,0 +1,123 @@ +--- +title: ActiveRecord::AttributeMethods::Query +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + query_attribute(attr_name) + +

+ + +
+ +
+ + + +
+ Also aliased as: attribute? +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/query.rb, line 12
+def query_attribute(attr_name)
+  value = self.public_send(attr_name)
+
+  case value
+  when true        then true
+  when false, nil  then false
+  else
+    if !type_for_attribute(attr_name) { false }
+      if Numeric === value || !value.match?(/[^0-9]/)
+        !value.to_i.zero?
+      else
+        return false if ActiveModel::Type::Boolean::FALSE_VALUES.include?(value)
+        !value.blank?
+      end
+    elsif value.respond_to?(:zero?)
+      !value.zero?
+    else
+      !value.blank?
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Read.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Read.html new file mode 100644 index 0000000000..1b417be3cf --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Read.html @@ -0,0 +1,105 @@ +--- +title: ActiveRecord::AttributeMethods::Read +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + read_attribute(attr_name, &block) + +

+ + +
+

Returns the value of the attribute identified by attr_name after it has been typecast (for example, “2004-12-12” in a date column is cast to a date object, like Date.new(2004, 12, 12)).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/read.rb, line 27
+def read_attribute(attr_name, &block)
+  name = attr_name.to_s
+  name = self.class.attribute_aliases[name] || name
+
+  name = @primary_key if name == "id" && @primary_key
+  @attributes.fetch_value(name, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization.html new file mode 100644 index 0000000000..33f2bc1a13 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::AttributeMethods::Serialization +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html new file mode 100644 index 0000000000..a8b5190247 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ClassMethods.html @@ -0,0 +1,194 @@ +--- +title: ActiveRecord::AttributeMethods::Serialization::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + serialize(attr_name, class_name_or_coder = Object, **options) + +

+ + +
+

If you have an attribute that needs to be saved to the database as a serialized object, and retrieved by deserializing into the same object, then specify the name of that attribute using this method and serialization will be handled automatically.

+ +

The serialization format may be YAML, JSON, or any custom format using a custom coder class.

+ +

Keep in mind that database adapters handle certain serialization tasks for you. For instance: json and jsonb types in PostgreSQL will be converted between JSON object/array syntax and Ruby Hash or Array objects transparently. There is no need to use serialize in this case.

+ +

For more complex cases, such as conversion to or from your application domain objects, consider using the ActiveRecord::Attributes API.

+ +

Parameters

+
  • +

    attr_name - The name of the attribute to serialize.

    +
  • +

    class_name_or_coder - Optional. May be one of the following:

    +
    • +

      default - The attribute value will be serialized as YAML. The attribute value must respond to to_yaml.

      +
    • +

      Array - The attribute value will be serialized as YAML, but an empty Array will be serialized as NULL. The attribute value must be an Array.

      +
    • +

      Hash - The attribute value will be serialized as YAML, but an empty Hash will be serialized as NULL. The attribute value must be a Hash.

      +
    • +

      JSON - The attribute value will be serialized as JSON. The attribute value must respond to to_json.

      +
    • +

      custom coder - The attribute value will be serialized using the coder’s dump(value) method, and will be deserialized using the coder’s load(string) method. The dump method may return nil to serialize the value as NULL.

      +
    +
+ +

Options

+
  • +

    :default - The default value to use when no value is provided. If this option is not passed, the previous default value (if any) will be used. Otherwise, the default will be nil.

    +
+ +

Examples

+ +
Serialize the preferences attribute using YAML
+ +
class User < ActiveRecord::Base
+  serialize :preferences
+end
+
+ +
Serialize the preferences attribute using JSON
+ +
class User < ActiveRecord::Base
+  serialize :preferences, JSON
+end
+
+ +
Serialize the preferences Hash using YAML
+ +
class User < ActiveRecord::Base
+  serialize :preferences, Hash
+end
+
+ +
Serialize the preferences attribute using a custom coder
+ +
class Rot13JSON
+  def self.rot13(string)
+    string.tr("a-zA-Z", "n-za-mN-ZA-M")
+  end
+
+  # Serializes an attribute value to a string that will be stored in the database.
+  def self.dump(value)
+    rot13(ActiveSupport::JSON.dump(value))
+  end
+
+  # Deserializes a string from the database to an attribute value.
+  def self.load(string)
+    ActiveSupport::JSON.load(rot13(string))
+  end
+end
+
+class User < ActiveRecord::Base
+  serialize :preferences, Rot13JSON
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/serialization.rb, line 103
+def serialize(attr_name, class_name_or_coder = Object, **options)
+  # When ::JSON is used, force it to go through the Active Support JSON encoder
+  # to ensure special objects (e.g. Active Record models) are dumped correctly
+  # using the #as_json hook.
+  coder = if class_name_or_coder == ::JSON
+    Coders::JSON
+  elsif [:load, :dump].all? { |x| class_name_or_coder.respond_to?(x) }
+    class_name_or_coder
+  else
+    Coders::YAMLColumn.new(attr_name, class_name_or_coder)
+  end
+
+  attribute(attr_name, **options) do |cast_type|
+    if type_incompatible_with_serialize?(cast_type, class_name_or_coder)
+      raise ColumnNotSerializableError.new(attr_name, cast_type)
+    end
+
+    cast_type = cast_type.subtype if Type::Serialized === cast_type
+    Type::Serialized.new(cast_type, coder)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ColumnNotSerializableError.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ColumnNotSerializableError.html new file mode 100644 index 0000000000..b7d675d9db --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Serialization/ColumnNotSerializableError.html @@ -0,0 +1,111 @@ +--- +title: ActiveRecord::AttributeMethods::Serialization::ColumnNotSerializableError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(name, type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/serialization.rb, line 9
+        def initialize(name, type)
+          super <<~EOS
+            Column `#{name}` of type #{type.class} does not support `serialize` feature.
+            Usually it means that you are trying to use `serialize`
+            on a column that already implements serialization natively.
+          EOS
+        end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/TimeZoneConversion.html b/src/7.0/classes/ActiveRecord/AttributeMethods/TimeZoneConversion.html new file mode 100644 index 0000000000..6237fedcae --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/TimeZoneConversion.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::AttributeMethods::TimeZoneConversion +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AttributeMethods/Write.html b/src/7.0/classes/ActiveRecord/AttributeMethods/Write.html new file mode 100644 index 0000000000..252607611d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AttributeMethods/Write.html @@ -0,0 +1,105 @@ +--- +title: ActiveRecord::AttributeMethods::Write +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + write_attribute(attr_name, value) + +

+ + +
+

Updates the attribute identified by attr_name with the specified value. Empty strings for Integer and Float columns are turned into nil.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attribute_methods/write.rb, line 31
+def write_attribute(attr_name, value)
+  name = attr_name.to_s
+  name = self.class.attribute_aliases[name] || name
+
+  name = @primary_key if name == "id" && @primary_key
+  @attributes.write_from_user(name, value)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Attributes.html b/src/7.0/classes/ActiveRecord/Attributes.html new file mode 100644 index 0000000000..23f706c6fb --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Attributes.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::Attributes +layout: default +--- +
+ +
+
+ +
+ +

See ActiveRecord::Attributes::ClassMethods for documentation

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Attributes/ClassMethods.html b/src/7.0/classes/ActiveRecord/Attributes/ClassMethods.html new file mode 100644 index 0000000000..a91fb837da --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Attributes/ClassMethods.html @@ -0,0 +1,348 @@ +--- +title: ActiveRecord::Attributes::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options) + +

+ + +
+

Defines an attribute with a type on this model. It will override the type of existing attributes if needed. This allows control over how values are converted to and from SQL when assigned to a model. It also changes the behavior of values passed to ActiveRecord::Base.where. This will let you use your domain objects across much of Active Record, without having to rely on implementation details or monkey patching.

+ +

name The name of the methods to define attribute methods for, and the column which this will persist to.

+ +

cast_type A symbol such as :string or :integer, or a type object to be used for this attribute. See the examples below for more information about providing custom type objects.

+ +

Options

+ +

The following options are accepted:

+ +

default The default value to use when no value is provided. If this option is not passed, the previous default value (if any) will be used. Otherwise, the default will be nil.

+ +

array (PostgreSQL only) specifies that the type should be an array (see the examples below).

+ +

range (PostgreSQL only) specifies that the type should be a range (see the examples below).

+ +

When using a symbol for cast_type, extra options are forwarded to the constructor of the type object.

+ +

Examples

+ +

The type detected by Active Record can be overridden.

+ +
# db/schema.rb
+create_table :store_listings, force: true do |t|
+  t.decimal :price_in_cents
+end
+
+# app/models/store_listing.rb
+class StoreListing < ActiveRecord::Base
+end
+
+store_listing = StoreListing.new(price_in_cents: '10.1')
+
+# before
+store_listing.price_in_cents # => BigDecimal(10.1)
+
+class StoreListing < ActiveRecord::Base
+  attribute :price_in_cents, :integer
+end
+
+# after
+store_listing.price_in_cents # => 10
+
+ +

A default can also be provided.

+ +
# db/schema.rb
+create_table :store_listings, force: true do |t|
+  t.string :my_string, default: "original default"
+end
+
+StoreListing.new.my_string # => "original default"
+
+# app/models/store_listing.rb
+class StoreListing < ActiveRecord::Base
+  attribute :my_string, :string, default: "new default"
+end
+
+StoreListing.new.my_string # => "new default"
+
+class Product < ActiveRecord::Base
+  attribute :my_default_proc, :datetime, default: -> { Time.now }
+end
+
+Product.new.my_default_proc # => 2015-05-30 11:04:48 -0600
+sleep 1
+Product.new.my_default_proc # => 2015-05-30 11:04:49 -0600
+
+ +

Attributes do not need to be backed by a database column.

+ +
# app/models/my_model.rb
+class MyModel < ActiveRecord::Base
+  attribute :my_string, :string
+  attribute :my_int_array, :integer, array: true
+  attribute :my_float_range, :float, range: true
+end
+
+model = MyModel.new(
+  my_string: "string",
+  my_int_array: ["1", "2", "3"],
+  my_float_range: "[1,3.5]",
+)
+model.attributes
+# =>
+  {
+    my_string: "string",
+    my_int_array: [1, 2, 3],
+    my_float_range: 1.0..3.5
+  }
+
+ +

Passing options to the type constructor

+ +
# app/models/my_model.rb
+class MyModel < ActiveRecord::Base
+  attribute :small_int, :integer, limit: 2
+end
+
+MyModel.create(small_int: 65537)
+# => Error: 65537 is out of range for the limit of two bytes
+
+ +

Creating Custom Types

+ +

Users may also define their own custom types, as long as they respond to the methods defined on the value type. The method deserialize or cast will be called on your type object, with raw input from the database or from your controllers. See ActiveModel::Type::Value for the expected API. It is recommended that your type objects inherit from an existing type, or from ActiveRecord::Type::Value

+ +
class MoneyType < ActiveRecord::Type::Integer
+  def cast(value)
+    if !value.kind_of?(Numeric) && value.include?('$')
+      price_in_dollars = value.gsub(/\$/, '').to_f
+      super(price_in_dollars * 100)
+    else
+      super
+    end
+  end
+end
+
+# config/initializers/types.rb
+ActiveRecord::Type.register(:money, MoneyType)
+
+# app/models/store_listing.rb
+class StoreListing < ActiveRecord::Base
+  attribute :price_in_cents, :money
+end
+
+store_listing = StoreListing.new(price_in_cents: '$10.00')
+store_listing.price_in_cents # => 1000
+
+ +

For more details on creating custom types, see the documentation for ActiveModel::Type::Value. For more details on registering your types to be referenced by a symbol, see ActiveRecord::Type.register. You can also pass a type object directly, in place of a symbol.

+ +

Querying

+ +

When ActiveRecord::Base.where is called, it will use the type defined by the model class to convert the value to SQL, calling serialize on your type object. For example:

+ +
class Money < Struct.new(:amount, :currency)
+end
+
+class MoneyType < ActiveRecord::Type::Value
+  def initialize(currency_converter:)
+    @currency_converter = currency_converter
+  end
+
+  # value will be the result of +deserialize+ or
+  # +cast+. Assumed to be an instance of +Money+ in
+  # this case.
+  def serialize(value)
+    value_in_bitcoins = @currency_converter.convert_to_bitcoins(value)
+    value_in_bitcoins.amount
+  end
+end
+
+# config/initializers/types.rb
+ActiveRecord::Type.register(:money, MoneyType)
+
+# app/models/product.rb
+class Product < ActiveRecord::Base
+  currency_converter = ConversionRatesFromTheInternet.new
+  attribute :price_in_bitcoins, :money, currency_converter: currency_converter
+end
+
+Product.where(price_in_bitcoins: Money.new(5, "USD"))
+# => SELECT * FROM products WHERE price_in_bitcoins = 0.02230
+
+Product.where(price_in_bitcoins: Money.new(5, "GBP"))
+# => SELECT * FROM products WHERE price_in_bitcoins = 0.03412
+
+ +

Dirty Tracking

+ +

The type of an attribute is given the opportunity to change how dirty tracking is performed. The methods changed? and changed_in_place? will be called from ActiveModel::Dirty. See the documentation for those methods in ActiveModel::Type::Value for more details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attributes.rb, line 208
+def attribute(name, cast_type = nil, default: NO_DEFAULT_PROVIDED, **options)
+  name = name.to_s
+  name = attribute_aliases[name] || name
+
+  reload_schema_from_cache
+
+  case cast_type
+  when Symbol
+    cast_type = Type.lookup(cast_type, **options, adapter: Type.adapter_name_from(self))
+  when nil
+    if (prev_cast_type, prev_default = attributes_to_define_after_schema_loads[name])
+      default = prev_default if default == NO_DEFAULT_PROVIDED
+    else
+      prev_cast_type = -> subtype { subtype }
+    end
+
+    cast_type = if block_given?
+      -> subtype { yield Proc === prev_cast_type ? prev_cast_type[subtype] : prev_cast_type }
+    else
+      prev_cast_type
+    end
+  end
+
+  self.attributes_to_define_after_schema_loads =
+    attributes_to_define_after_schema_loads.merge(name => [cast_type, default])
+end
+
+
+ +
+ +
+

+ + define_attribute( name, cast_type, default: NO_DEFAULT_PROVIDED, user_provided_default: true ) + +

+ + +
+

This is the low level API which sits beneath attribute. It only accepts type objects, and will do its work immediately instead of waiting for the schema to load. Automatic schema detection and ClassMethods#attribute both call this under the hood. While this method is provided so it can be used by plugin authors, application code should probably use ClassMethods#attribute.

+ +

name The name of the attribute being defined. Expected to be a String.

+ +

cast_type The type object to use for this attribute.

+ +

default The default value to use when no value is provided. If this option is not passed, the previous default value (if any) will be used. Otherwise, the default will be nil. A proc can also be passed, and will be called once each time a new value is needed.

+ +

user_provided_default Whether the default value should be cast using cast or deserialize.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/attributes.rb, line 253
+def define_attribute(
+  name,
+  cast_type,
+  default: NO_DEFAULT_PROVIDED,
+  user_provided_default: true
+)
+  attribute_types[name] = cast_type
+  define_default_attribute(name, default, cast_type, from_user: user_provided_default)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/AutosaveAssociation.html b/src/7.0/classes/ActiveRecord/AutosaveAssociation.html new file mode 100644 index 0000000000..3da528d278 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/AutosaveAssociation.html @@ -0,0 +1,431 @@ +--- +title: ActiveRecord::AutosaveAssociation +layout: default +--- +
+ +
+
+ +
+ +

Active Record Autosave Association

+ +

AutosaveAssociation is a module that takes care of automatically saving associated records when their parent is saved. In addition to saving, it also destroys any associated records that were marked for destruction. (See mark_for_destruction and marked_for_destruction?).

+ +

Saving of the parent, its associations, and the destruction of marked associations, all happen inside a transaction. This should never leave the database in an inconsistent state.

+ +

If validations for any of the associations fail, their error messages will be applied to the parent.

+ +

Note that it also means that associations marked for destruction won’t be destroyed directly. They will however still be marked for destruction.

+ +

Note that autosave: false is not same as not declaring :autosave. When the :autosave option is not present then new association records are saved but the updated association records are not saved.

+ +

Validation

+ +

Child records are validated unless :validate is false.

+ +

Callbacks

+ +

Association with autosave option defines several callbacks on your model (around_save, before_save, after_create, after_update). Please note that callbacks are executed in the order they were defined in model. You should avoid modifying the association content before autosave callbacks are executed. Placing your callbacks after associations is usually a good practice.

+ +

One-to-one Example

+ +
class Post < ActiveRecord::Base
+  has_one :author, autosave: true
+end
+
+ +

Saving changes to the parent and its associated model can now be performed automatically and atomically:

+ +
post = Post.find(1)
+post.title       # => "The current global position of migrating ducks"
+post.author.name # => "alloy"
+
+post.title = "On the migration of ducks"
+post.author.name = "Eloy Duran"
+
+post.save
+post.reload
+post.title       # => "On the migration of ducks"
+post.author.name # => "Eloy Duran"
+
+ +

Destroying an associated model, as part of the parent’s save action, is as simple as marking it for destruction:

+ +
post.author.mark_for_destruction
+post.author.marked_for_destruction? # => true
+
+ +

Note that the model is not yet removed from the database:

+ +
id = post.author.id
+Author.find_by(id: id).nil? # => false
+
+post.save
+post.reload.author # => nil
+
+ +

Now it is removed from the database:

+ +
Author.find_by(id: id).nil? # => true
+
+ +

One-to-many Example

+ +

When :autosave is not declared new children are saved when their parent is saved:

+ +
class Post < ActiveRecord::Base
+  has_many :comments # :autosave option is not declared
+end
+
+post = Post.new(title: 'ruby rocks')
+post.comments.build(body: 'hello world')
+post.save # => saves both post and comment
+
+post = Post.create(title: 'ruby rocks')
+post.comments.build(body: 'hello world')
+post.save # => saves both post and comment
+
+post = Post.create(title: 'ruby rocks')
+comment = post.comments.create(body: 'hello world')
+comment.body = 'hi everyone'
+post.save # => saves post, but not comment
+
+ +

When :autosave is true all children are saved, no matter whether they are new records or not:

+ +
class Post < ActiveRecord::Base
+  has_many :comments, autosave: true
+end
+
+post = Post.create(title: 'ruby rocks')
+comment = post.comments.create(body: 'hello world')
+comment.body = 'hi everyone'
+post.comments.build(body: "good morning.")
+post.save # => saves post and both comments.
+
+ +

Destroying one of the associated models as part of the parent’s save action is as simple as marking it for destruction:

+ +
post.comments # => [#<Comment id: 1, ...>, #<Comment id: 2, ...]>
+post.comments[1].mark_for_destruction
+post.comments[1].marked_for_destruction? # => true
+post.comments.length # => 2
+
+ +

Note that the model is not yet removed from the database:

+ +
id = post.comments.last.id
+Comment.find_by(id: id).nil? # => false
+
+post.save
+post.reload.comments.length # => 1
+
+ +

Now it is removed from the database:

+ +
Comment.find_by(id: id).nil? # => true
+
+ +

Caveats

+ +

Note that autosave will only trigger for already-persisted association records if the records themselves have been changed. This is to protect against SystemStackError caused by circular association validations. The one exception is if a custom validation context is used, in which case the validations will always fire on the associated records.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + changed_for_autosave?() + +

+ + +
+

Returns whether or not this record has been changed in any way (including whether any of its nested autosave associations are likewise changed)

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 271
+def changed_for_autosave?
+  new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
+end
+
+
+ +
+ +
+

+ + destroyed_by_association() + +

+ + +
+

Returns the association for the parent being destroyed.

+ +

Used to avoid updating the counter cache unnecessarily.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 265
+def destroyed_by_association
+  @destroyed_by_association
+end
+
+
+ +
+ +
+

+ + destroyed_by_association=(reflection) + +

+ + +
+

Records the association that is being destroyed and destroying this record in the process.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 258
+def destroyed_by_association=(reflection)
+  @destroyed_by_association = reflection
+end
+
+
+ +
+ +
+

+ + mark_for_destruction() + +

+ + +
+

Marks this record to be destroyed as part of the parent’s save transaction. This does not actually destroy the record instantly, rather child record will be destroyed when parent.save is called.

+ +

Only useful if the :autosave option on the parent is enabled for this associated model.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 245
+def mark_for_destruction
+  @marked_for_destruction = true
+end
+
+
+ +
+ +
+

+ + marked_for_destruction?() + +

+ + +
+

Returns whether or not this record will be destroyed as part of the parent’s save transaction.

+ +

Only useful if the :autosave option on the parent is enabled for this associated model.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 252
+def marked_for_destruction?
+  @marked_for_destruction
+end
+
+
+ +
+ +
+

+ + reload(options = nil) + +

+ + +
+

Reloads the attributes of the object as usual and clears marked_for_destruction flag.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/autosave_association.rb, line 234
+def reload(options = nil)
+  @marked_for_destruction = false
+  @destroyed_by_association = nil
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Base.html b/src/7.0/classes/ActiveRecord/Base.html new file mode 100644 index 0000000000..a11e792462 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Base.html @@ -0,0 +1,538 @@ +--- +title: ActiveRecord::Base +layout: default +--- +
+ +
+
+ +
+ +

Active Record

+ +

Active Record objects don’t specify their attributes directly, but rather infer them from the table definition with which they’re linked. Adding, removing, and changing attributes and their type is done directly in the database. Any change is instantly reflected in the Active Record objects. The mapping that binds a given Active Record class to a certain database table will happen automatically in most common cases, but can be overwritten for the uncommon ones.

+ +

See the mapping rules in table_name and the full example in files/activerecord/README_rdoc.html for more insight.

+ +

Creation

+ +

Active Records accept constructor parameters either in a hash or as a block. The hash method is especially useful when you’re receiving the data from somewhere else, like an HTTP request. It works like this:

+ +
user = User.new(name: "David", occupation: "Code Artist")
+user.name # => "David"
+
+ +

You can also use block initialization:

+ +
user = User.new do |u|
+  u.name = "David"
+  u.occupation = "Code Artist"
+end
+
+ +

And of course you can just create a bare object and specify the attributes after the fact:

+ +
user = User.new
+user.name = "David"
+user.occupation = "Code Artist"
+
+ +

Conditions

+ +

Conditions can either be specified as a string, array, or hash representing the WHERE-part of an SQL statement. The array form is to be used when the condition input is tainted and requires sanitization. The string form can be used for statements that don’t involve tainted data. The hash form works much like the array form, except only equality and range is possible. Examples:

+ +
class User < ActiveRecord::Base
+  def self.authenticate_unsafely(user_name, password)
+    where("user_name = '#{user_name}' AND password = '#{password}'").first
+  end
+
+  def self.authenticate_safely(user_name, password)
+    where("user_name = ? AND password = ?", user_name, password).first
+  end
+
+  def self.authenticate_safely_simply(user_name, password)
+    where(user_name: user_name, password: password).first
+  end
+end
+
+ +

The authenticate_unsafely method inserts the parameters directly into the query and is thus susceptible to SQL-injection attacks if the user_name and password parameters come directly from an HTTP request. The authenticate_safely and authenticate_safely_simply both will sanitize the user_name and password before inserting them in the query, which will ensure that an attacker can’t escape the query and fake the login (or worse).

+ +

When using multiple parameters in the conditions, it can easily become hard to read exactly what the fourth or fifth question mark is supposed to represent. In those cases, you can resort to named bind variables instead. That’s done by replacing the question marks with symbols and supplying a hash with values for the matching symbol keys:

+ +
Company.where(
+  "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
+  { id: 3, name: "37signals", division: "First", accounting_date: '2005-01-01' }
+).first
+
+ +

Similarly, a simple hash without a statement will generate conditions based on equality with the SQL AND operator. For instance:

+ +
Student.where(first_name: "Harvey", status: 1)
+Student.where(params[:student])
+
+ +

A range may be used in the hash to use the SQL BETWEEN operator:

+ +
Student.where(grade: 9..12)
+
+ +

An array may be used in the hash to use the SQL IN operator:

+ +
Student.where(grade: [9,11,12])
+
+ +

When joining tables, nested hashes or keys written in the form ‘table_name.column_name’ can be used to qualify the table name of a particular condition. For instance:

+ +
Student.joins(:schools).where(schools: { category: 'public' })
+Student.joins(:schools).where('schools.category' => 'public' )
+
+ +

Overwriting default accessors

+ +

All column values are automatically available through basic accessors on the Active Record object, but sometimes you want to specialize this behavior. This can be done by overwriting the default accessors (using the same name as the attribute) and calling super to actually change things.

+ +
class Song < ActiveRecord::Base
+  # Uses an integer of seconds to hold the length of the song
+
+  def length=(minutes)
+    super(minutes.to_i * 60)
+  end
+
+  def length
+    super / 60
+  end
+end
+
+ +

Attribute query methods

+ +

In addition to the basic accessors, query methods are also automatically available on the Active Record object. Query methods allow you to test whether an attribute value is present. Additionally, when dealing with numeric values, a query method will return false if the value is zero.

+ +

For example, an Active Record User with the name attribute has a name? method that you can call to determine whether the user has a name:

+ +
user = User.new(name: "David")
+user.name? # => true
+
+anonymous = User.new(name: "")
+anonymous.name? # => false
+
+ +

Query methods will also respect any overrides of default accessors:

+ +
class User
+  # Has admin boolean column
+  def admin
+    false
+  end
+end
+
+user.update(admin: true)
+
+user.read_attribute(:admin)  # => true, gets the column value
+user[:admin] # => true, also gets the column value
+
+user.admin   # => false, due to the getter override
+user.admin?  # => false, due to the getter override
+
+ +

Accessing attributes before they have been typecasted

+ +

Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first. That can be done by using the <attribute>_before_type_cast accessors that all attributes have. For example, if your Account model has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast.

+ +

This is especially useful in validation situations where the user might supply a string for an integer field and you want to display the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn’t what you want.

+ +

Dynamic attribute-based finders

+ +

Dynamic attribute-based finders are a mildly deprecated way of getting (and/or creating) objects by simple queries without turning to SQL. They work by appending the name of an attribute to find_by_ like Person.find_by_user_name. Instead of writing Person.find_by(user_name: user_name), you can use Person.find_by_user_name(user_name).

+ +

It’s possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an ActiveRecord::RecordNotFound error if they do not return any records, like Person.find_by_last_name!.

+ +

It’s also possible to use multiple attributes in the same find_by_ by separating them with “and”.

+ +
Person.find_by(user_name: user_name, password: password)
+Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
+
+ +

It’s even possible to call these dynamic finder methods on relations and named scopes.

+ +
Payment.order("created_on").find_by_amount(50)
+
+ +

Saving arrays, hashes, and other non-mappable objects in text columns

+ +

Active Record can serialize any object in text columns using YAML. To do so, you must specify this with a call to the class method serialize. This makes it possible to store arrays, hashes, and other non-mappable objects without doing any additional work.

+ +
class User < ActiveRecord::Base
+  serialize :preferences
+end
+
+user = User.create(preferences: { "background" => "black", "display" => large })
+User.find(user.id).preferences # => { "background" => "black", "display" => large }
+
+ +

You can also specify a class option as the second parameter that’ll raise an exception if a serialized object is retrieved as a descendant of a class not in the hierarchy.

+ +
class User < ActiveRecord::Base
+  serialize :preferences, Hash
+end
+
+user = User.create(preferences: %w( one two three ))
+User.find(user.id).preferences    # raises SerializationTypeMismatch
+
+ +

When you specify a class option, the default value for that attribute will be a new instance of that class.

+ +
class User < ActiveRecord::Base
+  serialize :preferences, OpenStruct
+end
+
+user = User.new
+user.preferences.theme_color = "red"
+
+ +

Single table inheritance

+ +

Active Record allows inheritance by storing the name of the class in a column that is named “type” by default. See ActiveRecord::Inheritance for more details.

+ +

Connection to multiple databases in different models

+ +

Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection. For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection and Course and all of its subclasses will use this connection instead.

+ +

This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a hash indexed by the class. If a connection is requested, the ActiveRecord::Base.retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool.

+ +

Exceptions

+ + +

Note: The attributes listed are class-level attributes (accessible from both the class and instance level). So it’s possible to assign a logger to the class through Base.logger= which will then be used by all instances in the current object space.

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Batches.html b/src/7.0/classes/ActiveRecord/Batches.html new file mode 100644 index 0000000000..ea054bd432 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Batches.html @@ -0,0 +1,447 @@ +--- +title: ActiveRecord::Batches +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ORDER_IGNORE_MESSAGE="Scoped order is ignored, it's forced to be batch order."
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + find_each(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc, &block) + +

+ + +
+

Looping through a collection of records from the database (using the Scoping::Named::ClassMethods.all method, for example) is very inefficient since it will try to instantiate all the objects at once.

+ +

In that case, batch processing methods allow you to work with the records in batches, thereby greatly reducing memory consumption.

+ +

The find_each method uses find_in_batches with a batch size of 1000 (or as specified by the :batch_size option).

+ +
Person.find_each do |person|
+  person.do_awesome_stuff
+end
+
+Person.where("age > 21").find_each do |person|
+  person.party_all_night!
+end
+
+ +

If you do not provide a block to find_each, it will return an Enumerator for chaining with other methods:

+ +
Person.find_each.with_index do |person, index|
+  person.award_trophy(index + 1)
+end
+
+ +

Options

+
  • +

    :batch_size - Specifies the size of the batch. Defaults to 1000.

    +
  • +

    :start - Specifies the primary key value to start from, inclusive of the value.

    +
  • +

    :finish - Specifies the primary key value to end at, inclusive of the value.

    +
  • +

    :error_on_ignore - Overrides the application config to specify if an error should be raised when an order is present in the relation.

    +
  • +

    :order - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.

    +
+ +

Limits are honored, and if present there is no requirement for the batch size: it can be less than, equal to, or greater than the limit.

+ +

The options start and finish are especially useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the records between id 1 and 9999 and worker 2 handle from 10000 and beyond by setting the :start and :finish option on each worker.

+ +
# In worker 1, let's process until 9999 records.
+Person.find_each(finish: 9_999) do |person|
+  person.party_all_night!
+end
+
+# In worker 2, let's process from record 10_000 and onwards.
+Person.find_each(start: 10_000) do |person|
+  person.party_all_night!
+end
+
+ +

NOTE: Order can be ascending (:asc) or descending (:desc). It is automatically set to ascending on the primary key (“id ASC”). This also means that this method only works when the primary key is orderable (e.g. an integer or string).

+ +

NOTE: By its nature, batch processing is subject to race conditions if other processes are modifying the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches.rb, line 68
+def find_each(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc, &block)
+  if block_given?
+    find_in_batches(start: start, finish: finish, batch_size: batch_size, error_on_ignore: error_on_ignore, order: order) do |records|
+      records.each(&block)
+    end
+  else
+    enum_for(:find_each, start: start, finish: finish, batch_size: batch_size, error_on_ignore: error_on_ignore, order: order) do
+      relation = self
+      apply_limits(relation, start, finish, order).size
+    end
+  end
+end
+
+
+ +
+ +
+

+ + find_in_batches(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc) + +

+ + +
+

Yields each batch of records that was found by the find options as an array.

+ +
Person.where("age > 21").find_in_batches do |group|
+  sleep(50) # Make sure it doesn't get too crowded in there!
+  group.each { |person| person.party_all_night! }
+end
+
+ +

If you do not provide a block to find_in_batches, it will return an Enumerator for chaining with other methods:

+ +
Person.find_in_batches.with_index do |group, batch|
+  puts "Processing group ##{batch}"
+  group.each(&:recover_from_last_night!)
+end
+
+ +

To be yielded each record one by one, use find_each instead.

+ +

Options

+
  • +

    :batch_size - Specifies the size of the batch. Defaults to 1000.

    +
  • +

    :start - Specifies the primary key value to start from, inclusive of the value.

    +
  • +

    :finish - Specifies the primary key value to end at, inclusive of the value.

    +
  • +

    :error_on_ignore - Overrides the application config to specify if an error should be raised when an order is present in the relation.

    +
  • +

    :order - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.

    +
+ +

Limits are honored, and if present there is no requirement for the batch size: it can be less than, equal to, or greater than the limit.

+ +

The options start and finish are especially useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the records between id 1 and 9999 and worker 2 handle from 10000 and beyond by setting the :start and :finish option on each worker.

+ +
# Let's process from record 10_000 on.
+Person.find_in_batches(start: 10_000) do |group|
+  group.each { |person| person.party_all_night! }
+end
+
+ +

NOTE: Order can be ascending (:asc) or descending (:desc). It is automatically set to ascending on the primary key (“id ASC”). This also means that this method only works when the primary key is orderable (e.g. an integer or string).

+ +

NOTE: By its nature, batch processing is subject to race conditions if other processes are modifying the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches.rb, line 128
+def find_in_batches(start: nil, finish: nil, batch_size: 1000, error_on_ignore: nil, order: :asc)
+  relation = self
+  unless block_given?
+    return to_enum(:find_in_batches, start: start, finish: finish, batch_size: batch_size, error_on_ignore: error_on_ignore, order: order) do
+      total = apply_limits(relation, start, finish, order).size
+      (total - 1).div(batch_size) + 1
+    end
+  end
+
+  in_batches(of: batch_size, start: start, finish: finish, load: true, error_on_ignore: error_on_ignore, order: order) do |batch|
+    yield batch.to_a
+  end
+end
+
+
+ +
+ +
+

+ + in_batches(of: 1000, start: nil, finish: nil, load: false, error_on_ignore: nil, order: :asc) + +

+ + +
+

Yields ActiveRecord::Relation objects to work with a batch of records.

+ +
Person.where("age > 21").in_batches do |relation|
+  relation.delete_all
+  sleep(10) # Throttle the delete queries
+end
+
+ +

If you do not provide a block to in_batches, it will return a BatchEnumerator which is enumerable.

+ +
Person.in_batches.each_with_index do |relation, batch_index|
+  puts "Processing relation ##{batch_index}"
+  relation.delete_all
+end
+
+ +

Examples of calling methods on the returned BatchEnumerator object:

+ +
Person.in_batches.delete_all
+Person.in_batches.update_all(awesome: true)
+Person.in_batches.each_record(&:party_all_night!)
+
+ +

Options

+
  • +

    :of - Specifies the size of the batch. Defaults to 1000.

    +
  • +

    :load - Specifies if the relation should be loaded. Defaults to false.

    +
  • +

    :start - Specifies the primary key value to start from, inclusive of the value.

    +
  • +

    :finish - Specifies the primary key value to end at, inclusive of the value.

    +
  • +

    :error_on_ignore - Overrides the application config to specify if an error should be raised when an order is present in the relation.

    +
  • +

    :order - Specifies the primary key order (can be :asc or :desc). Defaults to :asc.

    +
+ +

Limits are honored, and if present there is no requirement for the batch size, it can be less than, equal, or greater than the limit.

+ +

The options start and finish are especially useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the records between id 1 and 9999 and worker 2 handle from 10000 and beyond by setting the :start and :finish option on each worker.

+ +
# Let's process from record 10_000 on.
+Person.in_batches(start: 10_000).update_all(awesome: true)
+
+ +

An example of calling where query method on the relation:

+ +
Person.in_batches.each do |relation|
+  relation.update_all('age = age + 1')
+  relation.where('age > 21').update_all(should_party: true)
+  relation.where('age <= 21').delete_all
+end
+
+ +

NOTE: If you are going to iterate through each record, you should call each_record on the yielded BatchEnumerator:

+ +
Person.in_batches.each_record(&:party_all_night!)
+
+ +

NOTE: Order can be ascending (:asc) or descending (:desc). It is automatically set to ascending on the primary key (“id ASC”). This also means that this method only works when the primary key is orderable (e.g. an integer or string).

+ +

NOTE: By its nature, batch processing is subject to race conditions if other processes are modifying the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches.rb, line 204
+def in_batches(of: 1000, start: nil, finish: nil, load: false, error_on_ignore: nil, order: :asc)
+  relation = self
+  unless block_given?
+    return BatchEnumerator.new(of: of, start: start, finish: finish, relation: self)
+  end
+
+  unless [:asc, :desc].include?(order)
+    raise ArgumentError, ":order must be :asc or :desc, got #{order.inspect}"
+  end
+
+  if arel.orders.present?
+    act_on_ignored_order(error_on_ignore)
+  end
+
+  batch_limit = of
+  if limit_value
+    remaining   = limit_value
+    batch_limit = remaining if remaining < batch_limit
+  end
+
+  relation = relation.reorder(batch_order(order)).limit(batch_limit)
+  relation = apply_limits(relation, start, finish, order)
+  relation.skip_query_cache! # Retaining the results in the query cache would undermine the point of batching
+  batch_relation = relation
+
+  loop do
+    if load
+      records = batch_relation.records
+      ids = records.map(&:id)
+      yielded_relation = where(primary_key => ids)
+      yielded_relation.load_records(records)
+    else
+      ids = batch_relation.pluck(primary_key)
+      yielded_relation = where(primary_key => ids)
+    end
+
+    break if ids.empty?
+
+    primary_key_offset = ids.last
+    raise ArgumentError.new("Primary key not included in the custom select clause") unless primary_key_offset
+
+    yield yielded_relation
+
+    break if ids.length < batch_limit
+
+    if limit_value
+      remaining -= ids.length
+
+      if remaining == 0
+        # Saves a useless iteration when the limit is a multiple of the
+        # batch size.
+        break
+      elsif remaining < batch_limit
+        relation = relation.limit(remaining)
+      end
+    end
+
+    batch_relation = relation.where(
+      predicate_builder[primary_key, primary_key_offset, order == :desc ? :lt : :gt]
+    )
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Batches/BatchEnumerator.html b/src/7.0/classes/ActiveRecord/Batches/BatchEnumerator.html new file mode 100644 index 0000000000..2f8cbaa927 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Batches/BatchEnumerator.html @@ -0,0 +1,392 @@ +--- +title: ActiveRecord::Batches::BatchEnumerator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + finish

The primary key value at which the BatchEnumerator ends, inclusive of the value.

+ [R] + relation

The relation from which the BatchEnumerator yields batches.

+ [R] + start

The primary key value from which the BatchEnumerator starts, inclusive of the value.

+ + + + + +

Instance Public methods

+ +
+

+ + batch_size() + +

+ + +
+

The size of the batches yielded by the BatchEnumerator.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 25
+def batch_size
+  @of
+end
+
+
+ +
+ +
+

+ + delete_all() + +

+ + +
+

Deletes records in batches. Returns the total number of rows affected.

+ +
Person.in_batches.delete_all
+
+ +

See Relation#delete_all for details of how each batch is deleted.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 63
+def delete_all
+  sum(&:delete_all)
+end
+
+
+ +
+ +
+

+ + destroy_all() + +

+ + +
+

Destroys records in batches.

+ +
Person.where("age < 10").in_batches.destroy_all
+
+ +

See Relation#destroy_all for details of how each batch is destroyed.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 83
+def destroy_all
+  each(&:destroy_all)
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+

Yields an ActiveRecord::Relation object for each batch of records.

+ +
Person.in_batches.each do |relation|
+  relation.update_all(awesome: true)
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 92
+def each(&block)
+  enum = @relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: false)
+  return enum.each(&block) if block_given?
+  enum
+end
+
+
+ +
+ +
+

+ + each_record(&block) + +

+ + +
+

Looping through a collection of records from the database (using the all method, for example) is very inefficient since it will try to instantiate all the objects at once.

+ +

In that case, batch processing methods allow you to work with the records in batches, thereby greatly reducing memory consumption.

+ +
Person.in_batches.each_record do |person|
+  person.do_awesome_stuff
+end
+
+Person.where("age > 21").in_batches(of: 10).each_record do |person|
+  person.party_all_night!
+end
+
+ +

If you do not provide a block to each_record, it will return an Enumerator for chaining with other methods:

+ +
Person.in_batches.each_record.with_index do |person, index|
+  person.award_trophy(index + 1)
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 50
+def each_record(&block)
+  return to_enum(:each_record) unless block_given?
+
+  @relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: true).each do |relation|
+    relation.records.each(&block)
+  end
+end
+
+
+ +
+ +
+

+ + update_all(updates) + +

+ + +
+

Updates records in batches. Returns the total number of rows affected.

+ +
Person.in_batches.update_all("age = age + 1")
+
+ +

See Relation#update_all for details of how each batch is updated.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/batches/batch_enumerator.rb, line 72
+def update_all(updates)
+  sum do |relation|
+    relation.update_all(updates)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Calculations.html b/src/7.0/classes/ActiveRecord/Calculations.html new file mode 100644 index 0000000000..9c1b3e5d80 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Calculations.html @@ -0,0 +1,601 @@ +--- +title: ActiveRecord::Calculations +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + average(column_name) + +

+ + +
+

Calculates the average value on a given column. Returns nil if there’s no row. See calculate for examples with options.

+ +
Person.average(:age) # => 35.8
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 100
+def average(column_name)
+  calculate(:average, column_name)
+end
+
+
+ +
+ +
+

+ + calculate(operation, column_name) + +

+ + +
+

This calculates aggregate values in the given column. Methods for count, sum, average, minimum, and maximum have been added as shortcuts.

+ +
Person.calculate(:count, :all) # The same as Person.count
+Person.average(:age) # SELECT AVG(age) FROM people...
+
+# Selects the minimum age for any family without any minors
+Person.group(:last_name).having("min(age) > 17").minimum(:age)
+
+Person.sum("2 * age")
+
+ +

There are two basic forms of output:

+
  • +

    Single aggregate value: The single value is type cast to Integer for COUNT, Float for AVG, and the given column’s type for everything else.

    +
  • +

    Grouped values: This returns an ordered hash of the values and groups them. It takes either a column name, or the name of a belongs_to association.

    + +
    values = Person.group('last_name').maximum(:age)
    +puts values["Drake"]
    +# => 43
    +
    +drake  = Family.find_by(last_name: 'Drake')
    +values = Person.group(:family).maximum(:age) # Person belongs_to :family
    +puts values[drake]
    +# => 43
    +
    +values.each do |family, max_age|
    +  ...
    +end
    +
    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 179
+def calculate(operation, column_name)
+  if has_include?(column_name)
+    relation = apply_join_dependency
+
+    if operation.to_s.downcase == "count"
+      unless distinct_value || distinct_select?(column_name || select_for_count)
+        relation.distinct!
+        relation.select_values = [ klass.primary_key || table[Arel.star] ]
+      end
+      # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
+      relation.order_values = [] if group_values.empty?
+    end
+
+    relation.calculate(operation, column_name)
+  else
+    perform_calculation(operation, column_name)
+  end
+end
+
+
+ +
+ +
+

+ + count(column_name = nil) + +

+ + +
+

Count the records.

+ +
Person.count
+# => the total count of all people
+
+Person.count(:age)
+# => returns the total count of all people whose age is present in database
+
+Person.count(:all)
+# => performs a COUNT(*) (:all is an alias for '*')
+
+Person.distinct.count(:age)
+# => counts the number of different age values
+
+ +

If count is used with Relation#group, it returns a Hash whose keys represent the aggregated column, and the values are the respective amounts:

+ +
Person.group(:city).count
+# => { 'Rome' => 5, 'Paris' => 3 }
+
+ +

If count is used with Relation#group for multiple columns, it returns a Hash whose keys are an array containing the individual values of each column and the value of each key would be the count.

+ +
Article.group(:status, :category).count
+# =>  {["draft", "business"]=>10, ["draft", "technology"]=>4,
+#      ["published", "business"]=>0, ["published", "technology"]=>2}
+
+ +

If count is used with Relation#select, it will count the selected columns:

+ +
Person.select(:age).count
+# => counts the number of different age values
+
+ +

Note: not all valid Relation#select expressions are valid count expressions. The specifics differ between databases. In invalid cases, an error from the database is thrown.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 84
+def count(column_name = nil)
+  if block_given?
+    unless column_name.nil?
+      raise ArgumentError, "Column name argument is not supported when a block is passed."
+    end
+
+    super()
+  else
+    calculate(:count, column_name)
+  end
+end
+
+
+ +
+ +
+

+ + ids() + +

+ + +
+

Pluck all the ID’s for the relation using the table’s primary key

+ +
Person.ids # SELECT people.id FROM people
+Person.joins(:companies).ids # SELECT people.id FROM people INNER JOIN companies ON companies.person_id = people.id
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 283
+def ids
+  pluck primary_key
+end
+
+
+ +
+ +
+

+ + maximum(column_name) + +

+ + +
+

Calculates the maximum value on a given column. The value is returned with the same data type of the column, or nil if there’s no row. See calculate for examples with options.

+ +
Person.maximum(:age) # => 93
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 118
+def maximum(column_name)
+  calculate(:maximum, column_name)
+end
+
+
+ +
+ +
+

+ + minimum(column_name) + +

+ + +
+

Calculates the minimum value on a given column. The value is returned with the same data type of the column, or nil if there’s no row. See calculate for examples with options.

+ +
Person.minimum(:age) # => 7
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 109
+def minimum(column_name)
+  calculate(:minimum, column_name)
+end
+
+
+ +
+ +
+

+ + pick(*column_names) + +

+ + +
+

Pick the value(s) from the named column(s) in the current relation. This is short-hand for relation.limit(1).pluck(*column_names).first, and is primarily useful when you have a relation that’s already narrowed down to a single row.

+ +

Just like pluck, pick will only load the actual value, not the entire record object, so it’s also more efficient. The value is, again like with pluck, typecast by the column type.

+ +
Person.where(id: 1).pick(:name)
+# SELECT people.name FROM people WHERE id = 1 LIMIT 1
+# => 'David'
+
+Person.where(id: 1).pick(:name, :email_address)
+# SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1
+# => [ 'David', 'david@loudthinking.com' ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 271
+def pick(*column_names)
+  if loaded? && all_attributes?(column_names)
+    return records.pick(*column_names)
+  end
+
+  limit(1).pluck(*column_names).first
+end
+
+
+ +
+ +
+

+ + pluck(*column_names) + +

+ + +
+

Use pluck as a shortcut to select one or more attributes without loading an entire record object per row.

+ +
Person.pluck(:name)
+
+ +

instead of

+ +
Person.all.map(&:name)
+
+ +

Pluck returns an Array of attribute values type-casted to match the plucked column names, if they can be deduced. Plucking an SQL fragment returns String values by default.

+ +
Person.pluck(:name)
+# SELECT people.name FROM people
+# => ['David', 'Jeremy', 'Jose']
+
+Person.pluck(:id, :name)
+# SELECT people.id, people.name FROM people
+# => [[1, 'David'], [2, 'Jeremy'], [3, 'Jose']]
+
+Person.distinct.pluck(:role)
+# SELECT DISTINCT role FROM people
+# => ['admin', 'member', 'guest']
+
+Person.where(age: 21).limit(5).pluck(:id)
+# SELECT people.id FROM people WHERE people.age = 21 LIMIT 5
+# => [2, 3]
+
+Person.pluck(Arel.sql('DATEDIFF(updated_at, created_at)'))
+# SELECT DATEDIFF(updated_at, created_at) FROM people
+# => ['0', '27761', '173']
+
+ +

See also ids.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 233
+def pluck(*column_names)
+  if loaded? && all_attributes?(column_names)
+    return records.pluck(*column_names)
+  end
+
+  if has_include?(column_names.first)
+    relation = apply_join_dependency
+    relation.pluck(*column_names)
+  else
+    klass.disallow_raw_sql!(column_names)
+    columns = arel_columns(column_names)
+    relation = spawn
+    relation.select_values = columns
+    result = skip_query_cache_if_necessary do
+      if where_clause.contradiction?
+        ActiveRecord::Result.empty
+      else
+        klass.connection.select_all(relation.arel, "#{klass.name} Pluck")
+      end
+    end
+    type_cast_pluck_values(result, columns)
+  end
+end
+
+
+ +
+ +
+

+ + sum(identity_or_column = nil, &block) + +

+ + +
+

Calculates the sum of values on a given column. The value is returned with the same data type of the column, 0 if there’s no row. See calculate for examples with options.

+ +
Person.sum(:age) # => 4562
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/calculations.rb, line 127
+    def sum(identity_or_column = nil, &block)
+      if block_given?
+        values = map(&block)
+        if identity_or_column.nil? && (values.first.is_a?(Numeric) || values.first(1) == [] || values.first.respond_to?(:coerce))
+          identity_or_column = 0
+        end
+
+        if identity_or_column.nil?
+          ActiveSupport::Deprecation.warn(<<-MSG.squish)
+            Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
+            Sum of non-numeric elements requires an initial argument.
+          MSG
+          values.inject(:+) || 0
+        else
+          values.sum(identity_or_column)
+        end
+      else
+        calculate(:sum, identity_or_column)
+      end
+    end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Callbacks.html b/src/7.0/classes/ActiveRecord/Callbacks.html new file mode 100644 index 0000000000..14f864e391 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Callbacks.html @@ -0,0 +1,378 @@ +--- +title: ActiveRecord::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Active Record Callbacks

+ +

Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic before or after a change in the object state. This can be used to make sure that associated and dependent objects are deleted when ActiveRecord::Base#destroy is called (by overwriting before_destroy) or to massage attributes before they’re validated (by overwriting before_validation). As an example of the callbacks initiated, consider the ActiveRecord::Base#save call for a new record:

+
  • +

    (-) save

    +
  • +

    (-) valid

    +
  • +

    (1) before_validation

    +
  • +

    (-) validate

    +
  • +

    (2) after_validation

    +
  • +

    (3) before_save

    +
  • +

    (4) before_create

    +
  • +

    (-) create

    +
  • +

    (5) after_create

    +
  • +

    (6) after_save

    +
  • +

    (7) after_commit

    +
+ +

Also, an after_rollback callback can be configured to be triggered whenever a rollback is issued. Check out ActiveRecord::Transactions for more details about after_commit and after_rollback.

+ +

Additionally, an after_touch callback is triggered whenever an object is touched.

+ +

Lastly an after_find and after_initialize callback is triggered for each object that is found and instantiated by a finder, with after_initialize being triggered after new objects are instantiated as well.

+ +

There are nineteen callbacks in total, which give a lot of control over how to react and prepare for each state in the Active Record life cycle. The sequence for calling ActiveRecord::Base#save for an existing record is similar, except that each _create callback is replaced by the corresponding _update callback.

+ +

Examples:

+ +
class CreditCard < ActiveRecord::Base
+  # Strip everything but digits, so the user can specify "555 234 34" or
+  # "5552-3434" and both will mean "55523434"
+  before_validation(on: :create) do
+    self.number = number.gsub(/[^0-9]/, "") if attribute_present?("number")
+  end
+end
+
+class Subscription < ActiveRecord::Base
+  before_create :record_signup
+
+  private
+    def record_signup
+      self.signed_up_on = Date.today
+    end
+end
+
+class Firm < ActiveRecord::Base
+  # Disables access to the system, for associated clients and people when the firm is destroyed
+  before_destroy { |record| Person.where(firm_id: record.id).update_all(access: 'disabled')   }
+  before_destroy { |record| Client.where(client_of: record.id).update_all(access: 'disabled') }
+end
+
+ +

Inheritable callback queues

+ +

Besides the overwritable callback methods, it’s also possible to register callbacks through the use of the callback macros. Their main advantage is that the macros add behavior into a callback queue that is kept intact through an inheritance hierarchy.

+ +
class Topic < ActiveRecord::Base
+  before_destroy :destroy_author
+end
+
+class Reply < Topic
+  before_destroy :destroy_readers
+end
+
+ +

When Topic#destroy is run only destroy_author is called. When Reply#destroy is run, both destroy_author and destroy_readers are called.

+ +

IMPORTANT: In order for inheritance to work for the callback queues, you must specify the callbacks before specifying the associations. Otherwise, you might trigger the loading of a child before the parent has registered the callbacks and they won’t be inherited.

+ +

Types of callbacks

+ +

There are three types of callbacks accepted by the callback macros: method references (symbol), callback objects, inline methods (using a proc). Method references and callback objects are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for creating mix-ins).

+ +

The method reference callbacks work by specifying a protected or private method available in the object, like this:

+ +
class Topic < ActiveRecord::Base
+  before_destroy :delete_parents
+
+  private
+    def delete_parents
+      self.class.delete_by(parent_id: id)
+    end
+end
+
+ +

The callback objects have methods named after the callback called with the record as the only parameter, such as:

+ +
class BankAccount < ActiveRecord::Base
+  before_save      EncryptionWrapper.new
+  after_save       EncryptionWrapper.new
+  after_initialize EncryptionWrapper.new
+end
+
+class EncryptionWrapper
+  def before_save(record)
+    record.credit_card_number = encrypt(record.credit_card_number)
+  end
+
+  def after_save(record)
+    record.credit_card_number = decrypt(record.credit_card_number)
+  end
+
+  alias_method :after_initialize, :after_save
+
+  private
+    def encrypt(value)
+      # Secrecy is committed
+    end
+
+    def decrypt(value)
+      # Secrecy is unveiled
+    end
+end
+
+ +

So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other initialization data such as the name of the attribute to work with:

+ +
class BankAccount < ActiveRecord::Base
+  before_save      EncryptionWrapper.new("credit_card_number")
+  after_save       EncryptionWrapper.new("credit_card_number")
+  after_initialize EncryptionWrapper.new("credit_card_number")
+end
+
+class EncryptionWrapper
+  def initialize(attribute)
+    @attribute = attribute
+  end
+
+  def before_save(record)
+    record.send("#{@attribute}=", encrypt(record.send("#{@attribute}")))
+  end
+
+  def after_save(record)
+    record.send("#{@attribute}=", decrypt(record.send("#{@attribute}")))
+  end
+
+  alias_method :after_initialize, :after_save
+
+  private
+    def encrypt(value)
+      # Secrecy is committed
+    end
+
+    def decrypt(value)
+      # Secrecy is unveiled
+    end
+end
+
+ +

before_validation* returning statements

+ +

If the before_validation callback throws :abort, the process will be aborted and ActiveRecord::Base#save will return false. If ActiveRecord::Base#save! is called it will raise an ActiveRecord::RecordInvalid exception. Nothing will be appended to the errors object.

+ +

Canceling callbacks

+ +

If a before_* callback throws :abort, all the later callbacks and the associated action are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last.

+ +

Ordering callbacks

+ +

Sometimes application code requires that callbacks execute in a specific order. For example, a before_destroy callback (log_children in this case) should be executed before records in the children association are destroyed by the dependent: :destroy option.

+ +

Let’s look at the code below:

+ +
class Topic < ActiveRecord::Base
+  has_many :children, dependent: :destroy
+
+  before_destroy :log_children
+
+  private
+    def log_children
+      # Child processing
+    end
+end
+
+ +

In this case, the problem is that when the before_destroy callback is executed, records in the children association no longer exist because the ActiveRecord::Base#destroy callback was executed first. You can use the prepend option on the before_destroy callback to avoid this.

+ +
class Topic < ActiveRecord::Base
+  has_many :children, dependent: :destroy
+
+  before_destroy :log_children, prepend: true
+
+  private
+    def log_children
+      # Child processing
+    end
+end
+
+ +

This way, the before_destroy is executed before the dependent: :destroy is called, and the data is still available.

+ +

Also, there are cases when you want several callbacks of the same type to be executed in order.

+ +

For example:

+ +
class Topic < ActiveRecord::Base
+  has_many :children
+
+  after_save :log_children
+  after_save :do_something_else
+
+  private
+    def log_children
+      # Child processing
+    end
+
+    def do_something_else
+      # Something else
+    end
+end
+
+ +

In this case the log_children is executed before do_something_else. The same applies to all non-transactional callbacks.

+ +

As seen below, in case there are multiple transactional callbacks the order is reversed.

+ +

For example:

+ +
class Topic < ActiveRecord::Base
+  has_many :children
+
+  after_commit :log_children
+  after_commit :do_something_else
+
+  private
+    def log_children
+      # Child processing
+    end
+
+    def do_something_else
+      # Something else
+    end
+end
+
+ +

In this case the do_something_else is executed before log_children.

+ +

Transactions

+ +

The entire callback chain of a #save, #save!, or #destroy call runs within a transaction. That includes after_* hooks. If everything goes fine a COMMIT is executed once the chain has been completed.

+ +

If a before_* callback cancels the action a ROLLBACK is issued. You can also trigger a ROLLBACK raising an exception in any of the callbacks, including after_* hooks. Note, however, that in that case the client needs to be aware of it because an ordinary #save will raise such exception instead of quietly returning false.

+ +

Debugging callbacks

+ +

The callback chain is accessible via the _*_callbacks method on an object. Active Model Callbacks support :before, :after and :around as values for the kind property. The kind property defines what part of the chain the callback runs in.

+ +

To find all callbacks in the before_save callback chain:

+ +
Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }
+
+ +

Returns an array of callback objects that form the before_save chain.

+ +

To further check if the before_save chain contains a proc defined as rest_when_dead use the filter property of the callback object:

+ +
Topic._save_callbacks.select { |cb| cb.kind.eql?(:before) }.collect(&:filter).include?(:rest_when_dead)
+
+ +

Returns true or false depending on whether the proc is contained in the before_save callback chain on a Topic model.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
CALLBACKS=[ +:after_initialize, :after_find, :after_touch, :before_validation, :after_validation, +:before_save, :around_save, :after_save, :before_create, :around_create, +:after_create, :before_update, :around_update, :after_update, +:before_destroy, :around_destroy, :after_destroy, :after_commit, :after_rollback +]
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Callbacks/ClassMethods.html b/src/7.0/classes/ActiveRecord/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..ee9d9dd84b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Callbacks/ClassMethods.html @@ -0,0 +1,646 @@ +--- +title: ActiveRecord::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_create(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is created. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 370
+      
+
+
+ +
+ +
+

+ + after_destroy(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is destroyed. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 418
+    
+
+
+ +
+ +
+

+ + after_find(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is instantiated via a finder. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 314
+      
+
+
+ +
+ +
+

+ + after_initialize(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is instantiated. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 306
+      
+
+
+ +
+ +
+

+ + after_save(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is saved. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 346
+      
+
+
+ +
+ +
+

+ + after_touch(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is touched. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 322
+      
+
+
+ +
+ +
+

+ + after_update(*args, &block) + + +

+ + +
+

Registers a callback to be called after a record is updated. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 394
+      
+
+
+ +
+ +
+

+ + around_create(*args, &block) + + +

+ + +
+

Registers a callback to be called around the creation of a record. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 362
+      
+
+
+ +
+ +
+

+ + around_destroy(*args, &block) + + +

+ + +
+

Registers a callback to be called around the destruction of a record. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 410
+      
+
+
+ +
+ +
+

+ + around_save(*args, &block) + + +

+ + +
+

Registers a callback to be called around the save of a record. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 338
+      
+
+
+ +
+ +
+

+ + around_update(*args, &block) + + +

+ + +
+

Registers a callback to be called around the update of a record. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 386
+      
+
+
+ +
+ +
+

+ + before_create(*args, &block) + + +

+ + +
+

Registers a callback to be called before a record is created. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 354
+      
+
+
+ +
+ +
+

+ + before_destroy(*args, &block) + + +

+ + +
+

Registers a callback to be called before a record is destroyed. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 402
+      
+
+
+ +
+ +
+

+ + before_save(*args, &block) + + +

+ + +
+

Registers a callback to be called before a record is saved. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 330
+      
+
+
+ +
+ +
+

+ + before_update(*args, &block) + + +

+ + +
+

Registers a callback to be called before a record is updated. See ActiveRecord::Callbacks for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/callbacks.rb, line 378
+      
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConfigurationError.html b/src/7.0/classes/ActiveRecord/ConfigurationError.html new file mode 100644 index 0000000000..9f2feefff3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConfigurationError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ConfigurationError +layout: default +--- +
+ +
+
+ +
+ +

Raised when association is being configured improperly or user tries to use offset and limit together with ActiveRecord::Base.has_many or ActiveRecord::Base.has_and_belongs_to_many associations.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters.html new file mode 100644 index 0000000000..68d8da0e94 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters.html @@ -0,0 +1,300 @@ +--- +title: ActiveRecord::ConnectionAdapters +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter.html new file mode 100644 index 0000000000..1dfd545a42 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter.html @@ -0,0 +1,2961 @@ +--- +title: ActiveRecord::ConnectionAdapters::AbstractAdapter +layout: default +--- +
+ +
+
+ +
+ +

Active Record supports multiple database systems. AbstractAdapter and related classes form the abstraction layer which makes this possible. An AbstractAdapter represents a connection to a database, and provides an abstract interface for database-specific functionality such as establishing a connection, escaping values, building the right SQL fragments for :offset and :limit options, etc.

+ +

All the concrete database adapters follow the interface laid down in this class. ActiveRecord::Base.connection returns an AbstractAdapter object, which you can use.

+ +

Most of the methods in the adapter are useful during migrations. Most notably, the instance methods provided by SchemaStatements are very useful.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ADAPTER_NAME="Abstract"
 
COMMENT_REGEX=%r{(?:--.*\n)|/\*(?:[^*]|\*[^/])*\*/}m
 
SIMPLE_INT=/\A\d+\z/
 
TYPE_MAP=Type::TypeMap.new.tap { |m| initialize_type_map(m) }
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + in_use?
+ [R] + lock
+ [R] + logger
+ [R] + owner
+ [RW] + pool
+ [R] + visitor
+ + + + +

Class Public methods

+ +
+

+ + database_exists?(config) + +

+ + +
+

Does the database for this adapter exist?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 289
+def self.database_exists?(config)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + type_cast_config_to_boolean(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 57
+def self.type_cast_config_to_boolean(config)
+  if config == "false"
+    false
+  else
+    config
+  end
+end
+
+
+ +
+ +
+

+ + type_cast_config_to_integer(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 47
+def self.type_cast_config_to_integer(config)
+  if config.is_a?(Integer)
+    config
+  elsif SIMPLE_INT.match?(config)
+    config.to_i
+  else
+    config
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active?() + +

+ + +
+

Checks whether the connection to the database is still active. This includes checking whether the database is actually capable of responding, i.e. whether the connection isn’t stale.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 515
+def active?
+end
+
+
+ +
+ +
+

+ + adapter_name() + +

+ + +
+

Returns the human-readable name of the adapter. Use mixed case - one can always use downcase if needed.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 284
+def adapter_name
+  self.class::ADAPTER_NAME
+end
+
+
+ +
+ +
+

+ + all_foreign_keys_valid?() + +

+ + +
+

Override to check all foreign key constraints in a database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 506
+def all_foreign_keys_valid?
+  true
+end
+
+
+ +
+ +
+

+ + clear_cache!() + +

+ + +
+

Clear any caching the database adapter may be doing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 566
+def clear_cache!
+  @lock.synchronize { @statements.clear } if @statements
+end
+
+
+ +
+ +
+

+ + close() + +

+ + +
+

Check the connection back in to the connection pool

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 621
+def close
+  pool.checkin self
+end
+
+
+ +
+ +
+

+ + disable_extension(name) + +

+ + +
+

This is meant to be implemented by the adapters that support extensions

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 459
+def disable_extension(name)
+end
+
+
+ +
+ +
+

+ + disable_referential_integrity() + +

+ + +
+

Override to turn off referential integrity while executing &block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 501
+def disable_referential_integrity
+  yield
+end
+
+
+ +
+ +
+

+ + discard!() + +

+ + +
+

Immediately forget this connection ever existed. Unlike disconnect!, this will not communicate with the server.

+ +

After calling this method, the behavior of all other methods becomes undefined. This is called internally just before a forked process gets rid of a connection that belonged to its parent.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 539
+def discard!
+  # This should be overridden by concrete adapters.
+  #
+  # Prevent @connection's finalizer from touching the socket, or
+  # otherwise communicating with its server, when it is collected.
+  if schema_cache.connection == self
+    schema_cache.connection = nil
+  end
+end
+
+
+ +
+ +
+

+ + disconnect!() + +

+ + +
+

Disconnects from the database if already connected. Otherwise, this method does nothing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 528
+def disconnect!
+  clear_cache!
+  reset_transaction
+end
+
+
+ +
+ +
+

+ + enable_extension(name) + +

+ + +
+

This is meant to be implemented by the adapters that support extensions

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 463
+def enable_extension(name)
+end
+
+
+ +
+ +
+

+ + expire() + +

+ + +
+

this method must only be called while holding connection pool’s mutex

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 241
+def expire
+  if in_use?
+    if @owner != Thread.current
+      raise ActiveRecordError, "Cannot expire connection, " \
+        "it is owned by a different thread: #{@owner}. " \
+        "Current thread: #{Thread.current}."
+    end
+
+    @idle_since = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+    @owner = nil
+  else
+    raise ActiveRecordError, "Cannot expire connection, it is not currently leased."
+  end
+end
+
+
+ +
+ +
+

+ + extensions() + +

+ + +
+

A list of extensions, to be filled in by adapters that support them.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 489
+def extensions
+  []
+end
+
+
+ +
+ +
+

+ + index_algorithms() + +

+ + +
+

A list of index algorithms, to be filled by adapters that support them.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 494
+def index_algorithms
+  {}
+end
+
+
+ +
+ +
+

+ + lease() + +

+ + +
+

this method must only be called while holding connection pool’s mutex

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 200
+def lease
+  if in_use?
+    msg = +"Cannot lease connection, "
+    if @owner == Thread.current
+      msg << "it is already leased by the current thread."
+    else
+      msg << "it is already in use by a different thread: #{@owner}. " \
+             "Current thread: #{Thread.current}."
+    end
+    raise ActiveRecordError, msg
+  end
+
+  @owner = Thread.current
+end
+
+
+ +
+ +
+

+ + prefetch_primary_key?(table_name = nil) + +

+ + +
+

Should primary key values be selected from their corresponding sequence before the insert statement? If true, next_sequence_value is called before each insert to set the record’s primary key.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 316
+def prefetch_primary_key?(table_name = nil)
+  false
+end
+
+
+ +
+ +
+

+ + prepared_statements() + +

+ + +
+ +
+ + + + + +
+ Alias for: prepared_statements? +
+ + + +
+ +
+

+ + prepared_statements?() + +

+ + +
+ +
+ + + +
+ Also aliased as: prepared_statements +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 167
+def prepared_statements?
+  @prepared_statements && !prepared_statements_disabled_cache.include?(object_id)
+end
+
+
+ +
+ +
+

+ + preventing_writes?() + +

+ + +
+

Determines whether writes are currently being prevented.

+ +

Returns true if the connection is a replica.

+ +

If the application is using legacy handling, returns true if connection_handler.prevent_writes is set.

+ +

If the application is using the new connection handling will return true based on current_preventing_writes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 133
+def preventing_writes?
+  return true if replica?
+  return ActiveRecord::Base.connection_handler.prevent_writes if ActiveRecord.legacy_connection_handling
+  return false if connection_class.nil?
+
+  connection_class.current_preventing_writes
+end
+
+
+ +
+ +
+

+ + raw_connection() + +

+ + +
+

Provides access to the underlying database driver for this adapter. For example, this method returns a Mysql2::Client object in case of Mysql2Adapter, and a PG::Connection object in case of PostgreSQLAdapter.

+ +

This is useful for when you need to call a proprietary method such as PostgreSQL’s lo_* methods.

+ +

Active Record cannot track if the database is getting modified using this client. If that is the case, generally you’ll want to invalidate the query cache using ActiveRecord::Base.clear_query_cache.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 592
+def raw_connection
+  disable_lazy_transactions!
+  @connection
+end
+
+
+ +
+ +
+

+ + reconnect!() + +

+ + +
+

Disconnects from the database if already connected, and establishes a new connection with the database. Implementors should call super if they override the default implementation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 521
+def reconnect!
+  clear_cache!
+  reset_transaction
+end
+
+
+ +
+ +
+

+ + replica?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 116
+def replica?
+  @config[:replica] || false
+end
+
+
+ +
+ +
+

+ + requires_reloading?() + +

+ + +
+

Returns true if its required to reload the connection between requests for development mode.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 571
+def requires_reloading?
+  false
+end
+
+
+ +
+ +
+

+ + reset!() + +

+ + +
+

Reset the state of this connection, directing the DBMS to clear transactions and other connection-related server-side state. Usually a database-dependent operation.

+ +

The default implementation does nothing; the implementation should be overridden by concrete adapters.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 555
+def reset!
+  # this should be overridden by concrete adapters
+end
+
+
+ +
+ +
+

+ + role() + +

+ + +
+

The role (e.g. :writing) for the current connection. In a non-multi role application, :writing is returned.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 221
+def role
+  @pool.role
+end
+
+
+ +
+ +
+

+ + schema_cache() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 231
+def schema_cache
+  @pool.get_schema_cache(self)
+end
+
+
+ +
+ +
+

+ + schema_cache=(cache) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 235
+def schema_cache=(cache)
+  cache.connection = self
+  @pool.set_schema_cache(cache)
+end
+
+
+ +
+ +
+

+ + schema_version() + +

+ + +
+

Returns the version identifier of the schema currently available in the database. This is generally equal to the number of the highest- numbered migration that has been executed, or 0 if no schema information is present / the database is empty.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 656
+def schema_version
+  migration_context.current_version
+end
+
+
+ +
+ +
+

+ + shard() + +

+ + +
+

The shard (e.g. :default) for the current connection. In a non-sharded application, :default is returned.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 227
+def shard
+  @pool.shard
+end
+
+
+ +
+ +
+

+ + supports_advisory_locks?() + +

+ + +
+

Does this adapter support application-enforced advisory locking?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 309
+def supports_advisory_locks?
+  false
+end
+
+
+ +
+ +
+

+ + supports_bulk_alter?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 299
+def supports_bulk_alter?
+  false
+end
+
+
+ +
+ +
+

+ + supports_check_constraints?() + +

+ + +
+

Does this adapter support creating check constraints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 376
+def supports_check_constraints?
+  false
+end
+
+
+ +
+ +
+

+ + supports_comments?() + +

+ + +
+

Does this adapter support metadata comments on database objects (tables, columns, indexes)?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 401
+def supports_comments?
+  false
+end
+
+
+ +
+ +
+

+ + supports_comments_in_create?() + +

+ + +
+

Can comments for tables, columns, and indexes be specified in create/alter table statements?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 406
+def supports_comments_in_create?
+  false
+end
+
+
+ +
+ +
+

+ + supports_common_table_expressions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 425
+def supports_common_table_expressions?
+  false
+end
+
+
+ +
+ +
+

+ + supports_concurrent_connections?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 449
+def supports_concurrent_connections?
+  true
+end
+
+
+ +
+ +
+

+ + supports_datetime_with_precision?() + +

+ + +
+

Does this adapter support datetime with precision?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 391
+def supports_datetime_with_precision?
+  false
+end
+
+
+ +
+ +
+

+ + supports_ddl_transactions?() + +

+ + +
+

Does this adapter support DDL rollbacks in transactions? That is, would CREATE TABLE or ALTER TABLE get rolled back by a transaction?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 295
+def supports_ddl_transactions?
+  false
+end
+
+
+ +
+ +
+

+ + supports_deferrable_constraints?() + +

+ + +
+

Does this adapter support creating deferrable constraints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 371
+def supports_deferrable_constraints?
+  false
+end
+
+
+ +
+ +
+

+ + supports_explain?() + +

+ + +
+

Does this adapter support explain?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 340
+def supports_explain?
+  false
+end
+
+
+ +
+ +
+

+ + supports_expression_index?() + +

+ + +
+

Does this adapter support expression indices?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 335
+def supports_expression_index?
+  false
+end
+
+
+ +
+ +
+

+ + supports_extensions?() + +

+ + +
+

Does this adapter support database extensions?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 350
+def supports_extensions?
+  false
+end
+
+
+ +
+ +
+

+ + supports_foreign_keys?() + +

+ + +
+

Does this adapter support creating foreign key constraints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 361
+def supports_foreign_keys?
+  false
+end
+
+
+ +
+ +
+

+ + supports_foreign_tables?() + +

+ + +
+

Does this adapter support foreign/external tables?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 416
+def supports_foreign_tables?
+  false
+end
+
+
+ +
+ +
+

+ + supports_index_sort_order?() + +

+ + +
+

Does this adapter support index sort order?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 325
+def supports_index_sort_order?
+  false
+end
+
+
+ +
+ +
+

+ + supports_indexes_in_create?() + +

+ + +
+

Does this adapter support creating indexes in the same statement as creating the table?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 356
+def supports_indexes_in_create?
+  false
+end
+
+
+ +
+ +
+

+ + supports_insert_conflict_target?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 445
+def supports_insert_conflict_target?
+  false
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_skip?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 437
+def supports_insert_on_duplicate_skip?
+  false
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_update?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 441
+def supports_insert_on_duplicate_update?
+  false
+end
+
+
+ +
+ +
+

+ + supports_insert_returning?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 433
+def supports_insert_returning?
+  false
+end
+
+
+ +
+ +
+

+ + supports_json?() + +

+ + +
+

Does this adapter support json data type?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 396
+def supports_json?
+  false
+end
+
+
+ +
+ +
+

+ + supports_lazy_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 429
+def supports_lazy_transactions?
+  false
+end
+
+
+ +
+ +
+

+ + supports_materialized_views?() + +

+ + +
+

Does this adapter support materialized views?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 386
+def supports_materialized_views?
+  false
+end
+
+
+ +
+ +
+

+ + supports_optimizer_hints?() + +

+ + +
+

Does this adapter support optimizer hints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 421
+def supports_optimizer_hints?
+  false
+end
+
+
+ +
+ +
+

+ + supports_partial_index?() + +

+ + +
+

Does this adapter support partial indices?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 330
+def supports_partial_index?
+  false
+end
+
+
+ +
+ +
+

+ + supports_partitioned_indexes?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 320
+def supports_partitioned_indexes?
+  false
+end
+
+
+ +
+ +
+

+ + supports_savepoints?() + +

+ + +
+

Does this adapter support savepoints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 304
+def supports_savepoints?
+  false
+end
+
+
+ +
+ +
+

+ + supports_transaction_isolation?() + +

+ + +
+

Does this adapter support setting the isolation level for a transaction?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 345
+def supports_transaction_isolation?
+  false
+end
+
+
+ +
+ +
+

+ + supports_validate_constraints?() + +

+ + +
+

Does this adapter support creating invalid constraints?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 366
+def supports_validate_constraints?
+  false
+end
+
+
+ +
+ +
+

+ + supports_views?() + +

+ + +
+

Does this adapter support views?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 381
+def supports_views?
+  false
+end
+
+
+ +
+ +
+

+ + supports_virtual_columns?() + +

+ + +
+

Does this adapter support virtual columns?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 411
+def supports_virtual_columns?
+  false
+end
+
+
+ +
+ +
+

+ + throw_away!() + +

+ + +
+

Removes the connection from the pool and disconnect it.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 560
+def throw_away!
+  pool.remove self
+  disconnect!
+end
+
+
+ +
+ +
+

+ + unprepared_statement() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 275
+def unprepared_statement
+  cache = prepared_statements_disabled_cache.add?(object_id) if @prepared_statements
+  yield
+ensure
+  cache&.delete(object_id)
+end
+
+
+ +
+ +
+

+ + use_metadata_table?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 120
+def use_metadata_table?
+  @config.fetch(:use_metadata_table, true)
+end
+
+
+ +
+ +
+

+ + verify!() + +

+ + +
+

Checks whether the connection to the database is still active (i.e. not stale). This is done under the hood by calling active?. If the connection is no longer active, then this method will reconnect to the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 578
+def verify!
+  reconnect! unless active?
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 742
+def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil, async: false, &block) # :doc:
+  @instrumenter.instrument(
+    "sql.active_record",
+    sql:               sql,
+    name:              name,
+    binds:             binds,
+    type_casted_binds: type_casted_binds,
+    statement_name:    statement_name,
+    async:             async,
+    connection:        self) do
+    @lock.synchronize(&block)
+  rescue => e
+    raise translate_exception_class(e, sql, binds)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter/Version.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter/Version.html new file mode 100644 index 0000000000..a50af86f6f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractAdapter/Version.html @@ -0,0 +1,215 @@ +--- +title: ActiveRecord::ConnectionAdapters::AbstractAdapter::Version +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Comparable + +
  • + +
+ + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + full_version_string
+ + + + +

Class Public methods

+ +
+

+ + new(version_string, full_version_string = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 181
+def initialize(version_string, full_version_string = nil)
+  @version = version_string.split(".").map(&:to_i)
+  @full_version_string = full_version_string
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(version_string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 186
+def <=>(version_string)
+  @version <=> version_string.split(".").map(&:to_i)
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_adapter.rb, line 190
+def to_s
+  @version.join(".")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractMysqlAdapter.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractMysqlAdapter.html new file mode 100644 index 0000000000..75ef7db316 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/AbstractMysqlAdapter.html @@ -0,0 +1,1756 @@ +--- +title: ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ER_CANNOT_ADD_FOREIGN=1215
 
ER_CANNOT_CREATE_TABLE=1005
 
ER_DATA_TOO_LONG=1406
 
ER_DB_CREATE_EXISTS=1007
 

See dev.mysql.com/doc/mysql-errors/en/server-error-reference.html

ER_DO_NOT_HAVE_DEFAULT=1364
 
ER_DUP_ENTRY=1062
 
ER_FILSORT_ABORT=1028
 
ER_FK_INCOMPATIBLE_COLUMNS=3780
 
ER_LOCK_DEADLOCK=1213
 
ER_LOCK_WAIT_TIMEOUT=1205
 
ER_NOT_NULL_VIOLATION=1048
 
ER_NO_REFERENCED_ROW=1216
 
ER_NO_REFERENCED_ROW_2=1452
 
ER_OUT_OF_RANGE=1264
 
ER_QUERY_INTERRUPTED=1317
 
ER_QUERY_TIMEOUT=3024
 
ER_ROW_IS_REFERENCED=1217
 
ER_ROW_IS_REFERENCED_2=1451
 
NATIVE_DATABASE_TYPES={ +primary_key: "bigint auto_increment PRIMARY KEY", +string: { name: "varchar", limit: 255 }, +text: { name: "text" }, +integer: { name: "int", limit: 4 }, +bigint: { name: "bigint" }, +float: { name: "float", limit: 24 }, +decimal: { name: "decimal" }, +datetime: { name: "datetime" }, +timestamp: { name: "timestamp" }, +time: { name: "time" }, +date: { name: "date" }, +binary: { name: "blob" }, +blob: { name: "blob" }, +boolean: { name: "tinyint", limit: 1 }, +json: { name: "json" }, +}
 
TYPE_MAP=Type::TypeMap.new.tap { |m| initialize_type_map(m) }
 
TYPE_MAP_WITH_BOOLEAN=Type::TypeMap.new(TYPE_MAP).tap do |m| +m.register_type %r(^tinyint\(1\))i, Type::Boolean.new +end
 
+ + + + + + +

Class Public methods

+ +
+

+ + emulate_booleans + +

+ + +
+

By default, the Mysql2Adapter will consider all columns of type tinyint(1) as boolean. If you wish to disable this emulation you can add the following line to your application.rb file:

+ +
ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans = false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 27
+class_attribute :emulate_booleans, default: true
+
+
+
+ +
+ +
+

+ + new(connection, logger, connection_options, config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 54
+def initialize(connection, logger, connection_options, config)
+  super(connection, logger, config)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + charset() + +

+ + +
+

Returns the database character set.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 269
+def charset
+  show_variable "character_set_database"
+end
+
+
+ +
+ +
+

+ + check_constraints(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 413
+      def check_constraints(table_name)
+        if supports_check_constraints?
+          scope = quoted_scope(table_name)
+
+          sql = <<~SQL
+            SELECT cc.constraint_name AS 'name',
+                  cc.check_clause AS 'expression'
+            FROM information_schema.check_constraints cc
+            JOIN information_schema.table_constraints tc
+            USING (constraint_schema, constraint_name)
+            WHERE tc.table_schema = #{scope[:schema]}
+              AND tc.table_name = #{scope[:name]}
+              AND cc.constraint_schema = #{scope[:schema]}
+          SQL
+          sql += " AND cc.table_name = #{scope[:name]}" if mariadb?
+
+          chk_info = exec_query(sql, "SCHEMA")
+
+          chk_info.map do |row|
+            options = {
+              name: row["name"]
+            }
+            expression = row["expression"]
+            expression = expression[1..-2] if expression.start_with?("(") && expression.end_with?(")")
+            expression = strip_whitespace_characters(expression)
+            CheckConstraintDefinition.new(table_name, expression, options)
+          end
+        else
+          raise NotImplementedError
+        end
+      end
+
+
+ +
+ +
+

+ + collation() + +

+ + +
+

Returns the database collation strategy.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 274
+def collation
+  show_variable "collation_database"
+end
+
+
+ +
+ +
+

+ + create_database(name, options = {}) + +

+ + +
+

Create a new MySQL database with optional :charset and :collation. Charset defaults to utf8mb4.

+ +

Example:

+ +
create_database 'charset_test', charset: 'latin1', collation: 'latin1_bin'
+create_database 'matt_development'
+create_database 'matt_development', charset: :big5
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 244
+def create_database(name, options = {})
+  if options[:collation]
+    execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT COLLATE #{quote_table_name(options[:collation])}"
+  elsif options[:charset]
+    execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET #{quote_table_name(options[:charset])}"
+  elsif row_format_dynamic_by_default?
+    execute "CREATE DATABASE #{quote_table_name(name)} DEFAULT CHARACTER SET `utf8mb4`"
+  else
+    raise "Configure a supported :charset and ensure innodb_large_prefix is enabled to support indexes on varchar(255) string columns."
+  end
+end
+
+
+ +
+ +
+

+ + current_database() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 264
+def current_database
+  query_value("SELECT database()", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + drop_table(table_name, **options) + +

+ + +
+

Drops a table from the database.

+
:force +
+

Set to :cascade to drop dependent objects as well. Defaults to false.

+
:if_exists +
+

Set to true to only drop the table if it exists. Defaults to false.

+
:temporary +
+

Set to true to drop temporary table. Defaults to false.

+
+ +

Although this command ignores most options and the block if one is given, it can be helpful to provide these in a migration’s change method so it can be reverted. In that case, options and the block will be used by create_table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 321
+def drop_table(table_name, **options)
+  schema_cache.clear_data_source_cache!(table_name.to_s)
+  execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}"
+end
+
+
+ +
+ +
+

+ + execute(sql, name = nil, async: false) + +

+ + +
+

Executes the SQL statement in the context of this connection.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 194
+def execute(sql, name = nil, async: false)
+  raw_execute(sql, name, async: async)
+end
+
+
+ +
+ +
+

+ + foreign_keys(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 377
+      def foreign_keys(table_name)
+        raise ArgumentError unless table_name.present?
+
+        scope = quoted_scope(table_name)
+
+        fk_info = exec_query(<<~SQL, "SCHEMA")
+          SELECT fk.referenced_table_name AS 'to_table',
+                 fk.referenced_column_name AS 'primary_key',
+                 fk.column_name AS 'column',
+                 fk.constraint_name AS 'name',
+                 rc.update_rule AS 'on_update',
+                 rc.delete_rule AS 'on_delete'
+          FROM information_schema.referential_constraints rc
+          JOIN information_schema.key_column_usage fk
+          USING (constraint_schema, constraint_name)
+          WHERE fk.referenced_column_name IS NOT NULL
+            AND fk.table_schema = #{scope[:schema]}
+            AND fk.table_name = #{scope[:name]}
+            AND rc.constraint_schema = #{scope[:schema]}
+            AND rc.table_name = #{scope[:name]}
+        SQL
+
+        fk_info.map do |row|
+          options = {
+            column: unquote_identifier(row["column"]),
+            name: row["name"],
+            primary_key: row["primary_key"]
+          }
+
+          options[:on_update] = extract_foreign_key_action(row["on_update"])
+          options[:on_delete] = extract_foreign_key_action(row["on_delete"])
+
+          ForeignKeyDefinition.new(table_name, unquote_identifier(row["to_table"]), options)
+        end
+      end
+
+
+ +
+ +
+

+ + index_algorithms() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 153
+def index_algorithms
+  {
+    default: "ALGORITHM = DEFAULT",
+    copy:    "ALGORITHM = COPY",
+    inplace: "ALGORITHM = INPLACE",
+    instant: "ALGORITHM = INSTANT",
+  }
+end
+
+
+ +
+ +
+

+ + native_database_types() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 149
+def native_database_types
+  NATIVE_DATABASE_TYPES
+end
+
+
+ +
+ +
+

+ + recreate_database(name, options = {}) + +

+ + +
+

Drops the database specified on the name attribute and creates it again using the provided options.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 230
+def recreate_database(name, options = {})
+  drop_database(name)
+  sql = create_database(name, options)
+  reconnect!
+  sql
+end
+
+
+ +
+ +
+

+ + rename_index(table_name, old_name, new_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 326
+def rename_index(table_name, old_name, new_name)
+  if supports_rename_index?
+    validate_index_length!(table_name, new_name)
+
+    execute "ALTER TABLE #{quote_table_name(table_name)} RENAME INDEX #{quote_table_name(old_name)} TO #{quote_table_name(new_name)}"
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + rename_table(table_name, new_name) + +

+ + +
+

Renames a table.

+ +

Example:

+ +
rename_table('octopuses', 'octopi')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 299
+def rename_table(table_name, new_name)
+  schema_cache.clear_data_source_cache!(table_name.to_s)
+  schema_cache.clear_data_source_cache!(new_name.to_s)
+  execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
+  rename_table_indexes(table_name, new_name)
+end
+
+
+ +
+ +
+

+ + show_variable(name) + +

+ + +
+

SHOW VARIABLES LIKE ‘name’

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 475
+def show_variable(name)
+  query_value("SELECT @@#{name}", "SCHEMA")
+rescue ActiveRecord::StatementInvalid
+  nil
+end
+
+
+ +
+ +
+

+ + strict_mode?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 526
+def strict_mode?
+  self.class.type_cast_config_to_boolean(@config.fetch(:strict, true))
+end
+
+
+ +
+ +
+

+ + supports_advisory_locks?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 129
+def supports_advisory_locks?
+  true
+end
+
+
+ +
+ +
+

+ + supports_bulk_alter?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 68
+def supports_bulk_alter?
+  true
+end
+
+
+ +
+ +
+

+ + supports_check_constraints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 96
+def supports_check_constraints?
+  if mariadb?
+    database_version >= "10.2.1"
+  else
+    database_version >= "8.0.16"
+  end
+end
+
+
+ +
+ +
+

+ + supports_common_table_expressions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 121
+def supports_common_table_expressions?
+  if mariadb?
+    database_version >= "10.2.1"
+  else
+    database_version >= "8.0.1"
+  end
+end
+
+
+ +
+ +
+

+ + supports_datetime_with_precision?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 108
+def supports_datetime_with_precision?
+  mariadb? || database_version >= "5.6.4"
+end
+
+
+ +
+ +
+

+ + supports_explain?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 84
+def supports_explain?
+  true
+end
+
+
+ +
+ +
+

+ + supports_expression_index?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 76
+def supports_expression_index?
+  !mariadb? && database_version >= "8.0.13"
+end
+
+
+ +
+ +
+

+ + supports_foreign_keys?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 92
+def supports_foreign_keys?
+  true
+end
+
+
+ +
+ +
+

+ + supports_index_sort_order?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 72
+def supports_index_sort_order?
+  !mariadb? && database_version >= "8.0.1"
+end
+
+
+ +
+ +
+

+ + supports_indexes_in_create?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 88
+def supports_indexes_in_create?
+  true
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_skip?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 133
+def supports_insert_on_duplicate_skip?
+  true
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_update?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 137
+def supports_insert_on_duplicate_update?
+  true
+end
+
+
+ +
+ +
+

+ + supports_optimizer_hints?() + +

+ + + + + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 117
+def supports_optimizer_hints?
+  !mariadb? && database_version >= "5.7.7"
+end
+
+
+ +
+ +
+

+ + supports_transaction_isolation?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 80
+def supports_transaction_isolation?
+  true
+end
+
+
+ +
+ +
+

+ + supports_views?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 104
+def supports_views?
+  true
+end
+
+
+ +
+ +
+

+ + supports_virtual_columns?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb, line 112
+def supports_virtual_columns?
+  mariadb? || database_version >= "5.7.5"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Column.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Column.html new file mode 100644 index 0000000000..50d5182bcf --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Column.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::ConnectionAdapters::Column +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/ColumnMethods.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ColumnMethods.html new file mode 100644 index 0000000000..89827de9d9 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ColumnMethods.html @@ -0,0 +1,151 @@ +--- +title: ActiveRecord::ConnectionAdapters::ColumnMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + column(name, type, **options) + + +

+ + +
+

Appends a column or columns of a specified type.

+ +
t.string(:goat)
+t.string(:goat, :sheep)
+
+ +

See TableDefinition#column

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 260
+included do
+  define_column_methods :bigint, :binary, :boolean, :date, :datetime, :decimal,
+    :float, :integer, :json, :string, :text, :time, :timestamp, :virtual
+
+  alias :blob :binary
+  alias :numeric :decimal
+end
+
+
+ +
+ +
+

+ + primary_key(name, type = :primary_key, **options) + +

+ + +
+

Appends a primary key definition to the table definition. Can be called multiple times, but this is probably not a good idea.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 245
+def primary_key(name, type = :primary_key, **options)
+  column(name, type, **options.merge(primary_key: true))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html new file mode 100644 index 0000000000..4f01be6cb2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionHandler.html @@ -0,0 +1,713 @@ +--- +title: ActiveRecord::ConnectionAdapters::ConnectionHandler +layout: default +--- +
+ +
+
+ +
+ +

ConnectionHandler is a collection of ConnectionPool objects. It is used for keeping separate connection pools that connect to different databases.

+ +

For example, suppose that you have 5 models, with the following hierarchy:

+ +
class Author < ActiveRecord::Base
+end
+
+class BankAccount < ActiveRecord::Base
+end
+
+class Book < ActiveRecord::Base
+  establish_connection :library_db
+end
+
+class ScaryBook < Book
+end
+
+class GoodBook < Book
+end
+
+ +

And a database.yml that looked like this:

+ +
development:
+  database: my_application
+  host: localhost
+
+library_db:
+  database: library
+  host: some.library.org
+
+ +

Your primary database in the development environment is “my_application” but the Book model connects to a separate database called “library_db” (this can even be a database on a different machine).

+ +

Book, ScaryBook, and GoodBook will all use the same connection pool to “library_db” while Author, BankAccount, and any other models you create will use the default connection pool to “my_application”.

+ +

The various connection pools are managed by a single instance of ConnectionHandler accessible via ActiveRecord::Base.connection_handler. All Active Record models use this handler to determine the connection pool that they should use.

+ +

The ConnectionHandler class is not coupled with the Active models, as it has no knowledge about the model. The model needs to pass a connection specification name to the handler, in order to look up the correct connection pool.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 75
+def initialize
+  # These caches are keyed by pool_config.connection_specification_name (PoolConfig#connection_specification_name).
+  @owner_to_pool_manager = Concurrent::Map.new(initial_capacity: 2)
+
+  # Backup finalizer: if the forked child skipped Kernel#fork the early discard has not occurred
+  ObjectSpace.define_finalizer self, FINALIZER
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active_connections?(role = ActiveRecord::Base.current_role) + +

+ + +
+

Returns true if there are any active connections among the connection pools that the ConnectionHandler is managing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 161
+def active_connections?(role = ActiveRecord::Base.current_role)
+  connection_pool_list(role).any?(&:active_connection?)
+end
+
+
+ +
+ +
+

+ + all_connection_pools() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 117
+def all_connection_pools
+  owner_to_pool_manager.values.flat_map { |m| m.pool_configs.map(&:pool) }
+end
+
+
+ +
+ +
+

+ + clear_active_connections!(role = ActiveRecord::Base.current_role) + +

+ + +
+

Returns any connections in use by the current thread back to the pool, and also returns connections to the pool cached by threads that are no longer alive.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 168
+def clear_active_connections!(role = ActiveRecord::Base.current_role)
+  connection_pool_list(role).each(&:release_connection)
+end
+
+
+ +
+ +
+

+ + clear_all_connections!(role = ActiveRecord::Base.current_role) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 179
+def clear_all_connections!(role = ActiveRecord::Base.current_role)
+  connection_pool_list(role).each(&:disconnect!)
+end
+
+
+ +
+ +
+

+ + clear_reloadable_connections!(role = ActiveRecord::Base.current_role) + +

+ + +
+

Clears the cache which maps classes.

+ +

See ConnectionPool#clear_reloadable_connections! for details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 175
+def clear_reloadable_connections!(role = ActiveRecord::Base.current_role)
+  connection_pool_list(role).each(&:clear_reloadable_connections!)
+end
+
+
+ +
+ +
+

+ + connected?(spec_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) + +

+ + +
+

Returns true if a connection that’s accessible to this class has already been opened.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 216
+def connected?(spec_name, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
+  pool = retrieve_connection_pool(spec_name, role: role, shard: shard)
+  pool && pool.connected?
+end
+
+
+ +
+ +
+

+ + connection_pool_list(role = ActiveRecord::Base.current_role) + +

+ + +
+ +
+ + + +
+ Also aliased as: connection_pools +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 121
+def connection_pool_list(role = ActiveRecord::Base.current_role)
+  owner_to_pool_manager.values.flat_map { |m| m.pool_configs(role).map(&:pool) }
+end
+
+
+ +
+ +
+

+ + connection_pools(role = ActiveRecord::Base.current_role) + +

+ + +
+ +
+ + + + + +
+ Alias for: connection_pool_list +
+ + + +
+ +
+

+ + establish_connection(config, owner_name: Base, role: ActiveRecord::Base.current_role, shard: Base.current_shard) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 126
+def establish_connection(config, owner_name: Base, role: ActiveRecord::Base.current_role, shard: Base.current_shard)
+  owner_name = StringConnectionOwner.new(config.to_s) if config.is_a?(Symbol)
+
+  pool_config = resolve_pool_config(config, owner_name, role, shard)
+  db_config = pool_config.db_config
+
+  # Protects the connection named `ActiveRecord::Base` from being removed
+  # if the user calls `establish_connection :primary`.
+  if owner_to_pool_manager.key?(pool_config.connection_specification_name)
+    remove_connection_pool(pool_config.connection_specification_name, role: role, shard: shard)
+  end
+
+  message_bus = ActiveSupport::Notifications.instrumenter
+  payload = {}
+  if pool_config
+    payload[:spec_name] = pool_config.connection_specification_name
+    payload[:shard] = shard
+    payload[:config] = db_config.configuration_hash
+  end
+
+  if ActiveRecord.legacy_connection_handling
+    owner_to_pool_manager[pool_config.connection_specification_name] ||= LegacyPoolManager.new
+  else
+    owner_to_pool_manager[pool_config.connection_specification_name] ||= PoolManager.new
+  end
+  pool_manager = get_pool_manager(pool_config.connection_specification_name)
+  pool_manager.set_pool_config(role, shard, pool_config)
+
+  message_bus.instrument("!connection.active_record", payload) do
+    pool_config.pool
+  end
+end
+
+
+ +
+ +
+

+ + flush_idle_connections!(role = ActiveRecord::Base.current_role) + +

+ + +
+

Disconnects all currently idle connections.

+ +

See ConnectionPool#flush! for details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 186
+def flush_idle_connections!(role = ActiveRecord::Base.current_role)
+  connection_pool_list(role).each(&:flush!)
+end
+
+
+ +
+ +
+

+ + remove_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 221
+def remove_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
+  if pool_manager = get_pool_manager(owner)
+    pool_config = pool_manager.remove_pool_config(role, shard)
+
+    if pool_config
+      pool_config.disconnect!
+      pool_config.db_config
+    end
+  end
+end
+
+
+ +
+ +
+

+ + retrieve_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard) + +

+ + +
+

Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool_manager. This makes retrieving the connection pool O(1) once the process is warm. When a connection is established or removed, we invalidate the cache.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 235
+def retrieve_connection_pool(owner, role: ActiveRecord::Base.current_role, shard: ActiveRecord::Base.current_shard)
+  pool_config = get_pool_manager(owner)&.get_pool_config(role, shard)
+  pool_config&.pool
+end
+
+
+ +
+ +
+

+ + while_preventing_writes(enabled = true) + +

+ + +
+

Prevent writing to the database regardless of role.

+ +

In some cases you may want to prevent writes to the database even if you are on a database that can write. while_preventing_writes will prevent writes to the database for the duration of the block.

+ +

This method does not provide the same protection as a readonly user and is meant to be a safeguard against accidental writes.

+ +

See READ_QUERY for the queries that are blocked by this method.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_handler.rb, line 102
+def while_preventing_writes(enabled = true)
+  unless ActiveRecord.legacy_connection_handling
+    raise NotImplementedError, "`while_preventing_writes` is only available on the connection_handler with legacy_connection_handling"
+  end
+
+  original, self.prevent_writes = self.prevent_writes, enabled
+  yield
+ensure
+  self.prevent_writes = original
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html new file mode 100644 index 0000000000..89944972b4 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html @@ -0,0 +1,1178 @@ +--- +title: ActiveRecord::ConnectionAdapters::ConnectionPool +layout: default +--- +
+ +
+
+ +
+ +

Connection pool base class for managing Active Record database connections.

+ +

Introduction

+ +

A connection pool synchronizes thread access to a limited number of database connections. The basic idea is that each thread checks out a database connection from the pool, uses that connection, and checks the connection back in. ConnectionPool is completely thread-safe, and will ensure that a connection cannot be used by two threads at the same time, as long as ConnectionPool’s contract is correctly followed. It will also handle cases in which there are more threads than connections: if all connections have been checked out, and a thread tries to checkout a connection anyway, then ConnectionPool will wait until some other thread has checked in a connection.

+ +

Obtaining (checking out) a connection

+ +

Connections can be obtained and used from a connection pool in several ways:

+
  1. +

    Simply use ActiveRecord::Base.connection as with Active Record 2.1 and earlier (pre-connection-pooling). Eventually, when you’re done with the connection(s) and wish it to be returned to the pool, you call ActiveRecord::Base.clear_active_connections!. This will be the default behavior for Active Record when used in conjunction with Action Pack’s request handling cycle.

    +
  2. +

    Manually check out a connection from the pool with ActiveRecord::Base.connection_pool.checkout. You are responsible for returning this connection to the pool when finished by calling ActiveRecord::Base.connection_pool.checkin(connection).

    +
  3. +

    Use ActiveRecord::Base.connection_pool.with_connection(&block), which obtains a connection, yields it as the sole argument to the block, and returns it to the pool after the block completes.

    +
+ +

Connections in the pool are actually AbstractAdapter objects (or objects compatible with AbstractAdapter’s interface).

+ +

Options

+ +

There are several connection-pooling-related options that you can add to your database connection configuration:

+
  • +

    pool: maximum number of connections the pool may manage (default 5).

    +
  • +

    idle_timeout: number of seconds that a connection will be kept unused in the pool before it is automatically disconnected (default 300 seconds). Set this to zero to keep connections forever.

    +
  • +

    checkout_timeout: number of seconds to wait for a connection to become available before giving up and raising a timeout error (default 5 seconds).

    +
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + async_executor
+ [RW] + automatic_reconnect
+ [RW] + checkout_timeout
+ [R] + connection_class
+ [R] + connection_klass
+ [R] + db_config
+ [R] + pool_config
+ [R] + reaper
+ [R] + role
+ [R] + shard
+ [R] + size
+ + + + +

Class Public methods

+ +
+

+ + new(pool_config) + +

+ + +
+

Creates a new ConnectionPool object. pool_config is a PoolConfig object which describes database connection information (e.g. adapter, host name, username, password, etc), as well as the maximum size for this ConnectionPool.

+ +

The default ConnectionPool maximum size is 5.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 120
+def initialize(pool_config)
+  super()
+
+  @pool_config = pool_config
+  @db_config = pool_config.db_config
+  @connection_class = pool_config.connection_class
+  @role = pool_config.role
+  @shard = pool_config.shard
+
+  @checkout_timeout = db_config.checkout_timeout
+  @idle_timeout = db_config.idle_timeout
+  @size = db_config.pool
+
+  # This variable tracks the cache of threads mapped to reserved connections, with the
+  # sole purpose of speeding up the +connection+ method. It is not the authoritative
+  # registry of which thread owns which connection. Connection ownership is tracked by
+  # the +connection.owner+ attr on each +connection+ instance.
+  # The invariant works like this: if there is mapping of <tt>thread => conn</tt>,
+  # then that +thread+ does indeed own that +conn+. However, an absence of such
+  # mapping does not mean that the +thread+ doesn't own the said connection. In
+  # that case +conn.owner+ attr should be consulted.
+  # Access and modification of <tt>@thread_cached_conns</tt> does not require
+  # synchronization.
+  @thread_cached_conns = Concurrent::Map.new(initial_capacity: @size)
+
+  @connections         = []
+  @automatic_reconnect = true
+
+  # Connection pool allows for concurrent (outside the main +synchronize+ section)
+  # establishment of new connections. This variable tracks the number of threads
+  # currently in the process of independently establishing connections to the DB.
+  @now_connecting = 0
+
+  @threads_blocking_new_connections = 0
+
+  @available = ConnectionLeasingQueue.new self
+
+  @lock_thread = false
+
+  @async_executor = build_async_executor
+
+  lazily_set_schema_cache
+
+  @reaper = Reaper.new(self, db_config.reaping_frequency)
+  @reaper.run
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active_connection?() + +

+ + +
+

Returns true if there is an open connection being used for the current thread.

+ +

This method only works for connections that have been obtained through connection or with_connection methods. Connections obtained through checkout will not be detected by active_connection?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 189
+def active_connection?
+  @thread_cached_conns[connection_cache_key(current_thread)]
+end
+
+
+ +
+ +
+

+ + checkin(conn) + +

+ + +
+

Check-in a database connection back into the pool, indicating that you no longer need this connection.

+ +

conn: an AbstractAdapter object, which was obtained by earlier by calling checkout on this pool.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 349
+def checkin(conn)
+  conn.lock.synchronize do
+    synchronize do
+      remove_connection_from_thread_cache conn
+
+      conn._run_checkin_callbacks do
+        conn.expire
+      end
+
+      @available.add conn
+    end
+  end
+end
+
+
+ +
+ +
+

+ + checkout(checkout_timeout = @checkout_timeout) + +

+ + +
+

Check-out a database connection from the pool, indicating that you want to use it. You should call checkin when you no longer need this.

+ +

This is done by either returning and leasing existing connection, or by creating a new connection and leasing it.

+ +

If all connections are leased and the pool is at capacity (meaning the number of currently leased connections is greater than or equal to the size limit set), an ActiveRecord::ConnectionTimeoutError exception will be raised.

+ +

Returns: an AbstractAdapter object.

+ +

Raises:

+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 340
+def checkout(checkout_timeout = @checkout_timeout)
+  checkout_and_verify(acquire_connection(checkout_timeout))
+end
+
+
+ +
+ +
+

+ + clear_reloadable_connections(raise_on_acquisition_timeout = true) + +

+ + +
+

Clears the cache which maps classes and re-connects connections that require reloading.

+ +

Raises:

+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 298
+def clear_reloadable_connections(raise_on_acquisition_timeout = true)
+  with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do
+    synchronize do
+      @connections.each do |conn|
+        if conn.in_use?
+          conn.steal!
+          checkin conn
+        end
+        conn.disconnect! if conn.requires_reloading?
+      end
+      @connections.delete_if(&:requires_reloading?)
+      @available.clear
+    end
+  end
+end
+
+
+ +
+ +
+

+ + clear_reloadable_connections!() + +

+ + +
+

Clears the cache which maps classes and re-connects connections that require reloading.

+ +

The pool first tries to gain ownership of all connections. If unable to do so within a timeout interval (default duration is spec.db_config.checkout_timeout * 2 seconds), then the pool forcefully clears the cache and reloads connections without any regard for other connection owning threads.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 322
+def clear_reloadable_connections!
+  clear_reloadable_connections(false)
+end
+
+
+ +
+ +
+

+ + connected?() + +

+ + +
+

Returns true if a connection has already been opened.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 221
+def connected?
+  synchronize { @connections.any? }
+end
+
+
+ +
+ +
+

+ + connection() + +

+ + +
+

Retrieve the connection associated with the current thread, or call checkout to obtain one if necessary.

+ +

connection can be called any number of times; the connection is held in a cache keyed by a thread.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 180
+def connection
+  @thread_cached_conns[connection_cache_key(current_thread)] ||= checkout
+end
+
+
+ +
+ +
+

+ + connections() + +

+ + +
+

Returns an array containing the connections currently in the pool. Access to the array does not require synchronization on the pool because the array is newly created and not retained by the pool.

+ +

However; this method bypasses the ConnectionPool’s thread-safe connection access pattern. A returned connection may be owned by another thread, unowned, or by happen-stance owned by the calling thread.

+ +

Calling methods on a connection without ownership is subject to the thread-safety guarantees of the underlying method. Many of the methods on connection adapter classes are inherently multi-thread unsafe.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 236
+def connections
+  synchronize { @connections.dup }
+end
+
+
+ +
+ +
+

+ + disconnect(raise_on_acquisition_timeout = true) + +

+ + +
+

Disconnects all connections in the pool, and clears the pool.

+ +

Raises:

+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 246
+def disconnect(raise_on_acquisition_timeout = true)
+  with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do
+    synchronize do
+      @connections.each do |conn|
+        if conn.in_use?
+          conn.steal!
+          checkin conn
+        end
+        conn.disconnect!
+      end
+      @connections = []
+      @available.clear
+    end
+  end
+end
+
+
+ +
+ +
+

+ + disconnect!() + +

+ + +
+

Disconnects all connections in the pool, and clears the pool.

+ +

The pool first tries to gain ownership of all connections. If unable to do so within a timeout interval (default duration is spec.db_config.checkout_timeout * 2 seconds), then the pool is forcefully disconnected without any regard for other connection owning threads.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 268
+def disconnect!
+  disconnect(false)
+end
+
+
+ +
+ +
+

+ + flush(minimum_idle = @idle_timeout) + +

+ + +
+

Disconnect all connections that have been idle for at least minimum_idle seconds. Connections currently checked out, or that were checked in less than minimum_idle seconds ago, are unaffected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 420
+def flush(minimum_idle = @idle_timeout)
+  return if minimum_idle.nil?
+
+  idle_connections = synchronize do
+    return if self.discarded?
+    @connections.select do |conn|
+      !conn.in_use? && conn.seconds_idle >= minimum_idle
+    end.each do |conn|
+      conn.lease
+
+      @available.delete conn
+      @connections.delete conn
+    end
+  end
+
+  idle_connections.each do |conn|
+    conn.disconnect!
+  end
+end
+
+
+ +
+ +
+

+ + flush!() + +

+ + +
+

Disconnect all currently idle connections. Connections currently checked out are unaffected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 442
+def flush!
+  reap
+  flush(-1)
+end
+
+
+ +
+ +
+

+ + lock_thread=(lock_thread) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 167
+def lock_thread=(lock_thread)
+  if lock_thread
+    @lock_thread = Thread.current
+  else
+    @lock_thread = nil
+  end
+end
+
+
+ +
+ +
+

+ + reap() + +

+ + +
+

Recover lost connections for the pool. A lost connection can occur if a programmer forgets to checkin a connection at the end of a thread or a thread dies unexpectedly.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 397
+def reap
+  stale_connections = synchronize do
+    return if self.discarded?
+    @connections.select do |conn|
+      conn.in_use? && !conn.owner.alive?
+    end.each do |conn|
+      conn.steal!
+    end
+  end
+
+  stale_connections.each do |conn|
+    if conn.active?
+      conn.reset!
+      checkin conn
+    else
+      remove conn
+    end
+  end
+end
+
+
+ +
+ +
+

+ + release_connection(owner_thread = Thread.current) + +

+ + +
+

Signal that the thread is finished with the current connection. release_connection releases the connection-thread association and returns the connection to the pool.

+ +

This method only works for connections that have been obtained through connection or with_connection methods, connections obtained through checkout will not be automatically released.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 200
+def release_connection(owner_thread = Thread.current)
+  if conn = @thread_cached_conns.delete(connection_cache_key(owner_thread))
+    checkin conn
+  end
+end
+
+
+ +
+ +
+

+ + remove(conn) + +

+ + +
+

Remove a connection from the connection pool. The connection will remain open and active but will no longer be managed by this pool.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 365
+def remove(conn)
+  needs_new_connection = false
+
+  synchronize do
+    remove_connection_from_thread_cache conn
+
+    @connections.delete conn
+    @available.delete conn
+
+    # @available.any_waiting? => true means that prior to removing this
+    # conn, the pool was at its max size (@connections.size == @size).
+    # This would mean that any threads stuck waiting in the queue wouldn't
+    # know they could checkout_new_connection, so let's do it for them.
+    # Because condition-wait loop is encapsulated in the Queue class
+    # (that in turn is oblivious to ConnectionPool implementation), threads
+    # that are "stuck" there are helpless. They have no way of creating
+    # new connections and are completely reliant on us feeding available
+    # connections into the Queue.
+    needs_new_connection = @available.any_waiting?
+  end
+
+  # This is intentionally done outside of the synchronized section as we
+  # would like not to hold the main mutex while checking out new connections.
+  # Thus there is some chance that needs_new_connection information is now
+  # stale, we can live with that (bulk_make_new_connections will make
+  # sure not to exceed the pool's @size limit).
+  bulk_make_new_connections(1) if needs_new_connection
+end
+
+
+ +
+ +
+

+ + stat() + +

+ + +
+

Return connection pool’s usage statistic Example:

+ +
ActiveRecord::Base.connection_pool.stat # => { size: 15, connections: 1, busy: 1, dead: 0, idle: 0, waiting: 0, checkout_timeout: 5 }
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 455
+def stat
+  synchronize do
+    {
+      size: size,
+      connections: @connections.size,
+      busy: @connections.count { |c| c.in_use? && c.owner.alive? },
+      dead: @connections.count { |c| c.in_use? && !c.owner.alive? },
+      idle: @connections.count { |c| !c.in_use? },
+      waiting: num_waiting_in_queue,
+      checkout_timeout: checkout_timeout
+    }
+  end
+end
+
+
+ +
+ +
+

+ + with_connection() + +

+ + +
+

If a connection obtained through connection or with_connection methods already exists yield it to the block. If no such connection exists checkout a connection, yield it to the block, and checkin the connection when finished.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb, line 210
+def with_connection
+  unless conn = @thread_cached_conns[connection_cache_key(Thread.current)]
+    conn = connection
+    fresh_connection = true
+  end
+  yield conn
+ensure
+  release_connection if fresh_connection
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Queue.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Queue.html new file mode 100644 index 0000000000..c681cc64eb --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Queue.html @@ -0,0 +1,375 @@ +--- +title: ActiveRecord::ConnectionAdapters::ConnectionPool::Queue +layout: default +--- +
+ +
+
+ +
+ +

Threadsafe, fair, LIFO queue. Meant to be used by ConnectionPool with which it shares a Monitor.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(lock = Monitor.new) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 12
+def initialize(lock = Monitor.new)
+  @lock = lock
+  @cond = @lock.new_cond
+  @num_waiting = 0
+  @queue = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add(element) + +

+ + +
+

Add element to the queue. Never blocks.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 35
+def add(element)
+  synchronize do
+    @queue.push element
+    @cond.signal
+  end
+end
+
+
+ +
+ +
+

+ + any_waiting?() + +

+ + +
+

Test if any threads are currently waiting on the queue.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 20
+def any_waiting?
+  synchronize do
+    @num_waiting > 0
+  end
+end
+
+
+ +
+ +
+

+ + clear() + +

+ + +
+

Remove all elements from the queue.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 50
+def clear
+  synchronize do
+    @queue.clear
+  end
+end
+
+
+ +
+ +
+

+ + delete(element) + +

+ + +
+

If element is in the queue, remove and return it, or nil.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 43
+def delete(element)
+  synchronize do
+    @queue.delete(element)
+  end
+end
+
+
+ +
+ +
+

+ + num_waiting() + +

+ + +
+

Returns the number of threads currently waiting on this queue.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 28
+def num_waiting
+  synchronize do
+    @num_waiting
+  end
+end
+
+
+ +
+ +
+

+ + poll(timeout = nil) + +

+ + +
+

Remove the head of the queue.

+ +

If timeout is not given, remove and return the head of the queue if the number of available elements is strictly greater than the number of threads currently waiting (that is, don’t jump ahead in line). Otherwise, return nil.

+ +

If timeout is given, block if there is no element available, waiting up to timeout seconds for an element to become available.

+ +

Raises:

+ + +

becomes available within timeout seconds,

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb, line 70
+def poll(timeout = nil)
+  synchronize { internal_poll(timeout) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Reaper.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Reaper.html new file mode 100644 index 0000000000..73e118e4a5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool/Reaper.html @@ -0,0 +1,181 @@ +--- +title: ActiveRecord::ConnectionAdapters::ConnectionPool::Reaper +layout: default +--- +
+ +
+
+ +
+ +

Every frequency seconds, the reaper will call reap and flush on pool. A reaper instantiated with a zero frequency will never reap the connection pool.

+ +

Configure the frequency by setting reaping_frequency in your database yaml file (default 60 seconds).

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + frequency
+ [R] + pool
+ + + + +

Class Public methods

+ +
+

+ + new(pool, frequency) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb, line 18
+def initialize(pool, frequency)
+  @pool      = pool
+  @frequency = frequency
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + run() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb, line 69
+def run
+  return unless frequency && frequency > 0
+  self.class.register_pool(pool, frequency)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseLimits.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseLimits.html new file mode 100644 index 0000000000..8b4c53f5a3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseLimits.html @@ -0,0 +1,140 @@ +--- +title: ActiveRecord::ConnectionAdapters::DatabaseLimits +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + index_name_length() + +

+ + +
+

Returns the maximum length of an index name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb, line 16
+def index_name_length
+  max_identifier_length
+end
+
+
+ +
+ +
+

+ + table_alias_length() + +

+ + +
+

Returns the maximum length of a table alias.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_limits.rb, line 11
+def table_alias_length
+  max_identifier_length
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html new file mode 100644 index 0000000000..814fc75509 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html @@ -0,0 +1,1526 @@ +--- +title: ActiveRecord::ConnectionAdapters::DatabaseStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 6
+def initialize
+  super
+  reset_transaction
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_transaction_record(record, ensure_finalize = true) + +

+ + +
+

Register a record with the current transaction so that its after_commit and after_rollback callbacks can be called.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 345
+def add_transaction_record(record, ensure_finalize = true)
+  current_transaction.add_record(record, ensure_finalize)
+end
+
+
+ +
+ +
+

+ + begin_db_transaction() + +

+ + +
+

Begins the transaction (and turns off auto-committing).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 350
+def begin_db_transaction()    end
+
+
+ +
+ +
+

+ + begin_isolated_db_transaction(isolation) + +

+ + +
+

Begins the transaction with the isolation level set. Raises an error by default; adapters that support setting the isolation level should implement this method.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 364
+def begin_isolated_db_transaction(isolation)
+  raise ActiveRecord::TransactionIsolationError, "adapter does not support setting transaction isolation"
+end
+
+
+ +
+ +
+

+ + commit_db_transaction() + +

+ + +
+

Commits the transaction (and turns on auto-committing).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 369
+def commit_db_transaction()   end
+
+
+ +
+ +
+

+ + create(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) + +

+ + +
+ +
+ + + + + +
+ Alias for: insert +
+ + + +
+ +
+

+ + default_sequence_name(table, column) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 383
+def default_sequence_name(table, column)
+  nil
+end
+
+
+ +
+ +
+

+ + delete(arel, name = nil, binds = []) + +

+ + +
+

Executes the delete statement and returns the number of rows affected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 179
+def delete(arel, name = nil, binds = [])
+  sql, binds = to_sql_and_binds(arel, binds)
+  exec_delete(sql, name, binds)
+end
+
+
+ +
+ +
+

+ + empty_insert_statement_value(primary_key = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 415
+def empty_insert_statement_value(primary_key = nil)
+  "DEFAULT VALUES"
+end
+
+
+ +
+ +
+

+ + exec_delete(sql, name = nil, binds = []) + +

+ + +
+

Executes delete sql statement in the context of this connection using binds as the bind substitutes. name is logged along with the executed sql statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 138
+def exec_delete(sql, name = nil, binds = [])
+  exec_query(sql, name, binds)
+end
+
+
+ +
+ +
+

+ + exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil) + +

+ + +
+

Executes insert sql statement in the context of this connection using binds as the bind substitutes. name is logged along with the executed sql statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 130
+def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
+  sql, binds = sql_for_insert(sql, pk, binds)
+  exec_query(sql, name, binds)
+end
+
+
+ +
+ +
+

+ + exec_query(sql, name = "SQL", binds = [], prepare: false) + +

+ + +
+

Executes sql statement in the context of this connection using binds as the bind substitutes. name is logged along with the executed sql statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 123
+def exec_query(sql, name = "SQL", binds = [], prepare: false)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + exec_update(sql, name = nil, binds = []) + +

+ + +
+

Executes update sql statement in the context of this connection using binds as the bind substitutes. name is logged along with the executed sql statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 145
+def exec_update(sql, name = nil, binds = [])
+  exec_query(sql, name, binds)
+end
+
+
+ +
+ +
+

+ + execute(sql, name = nil) + +

+ + +
+

Executes the SQL statement in the context of this connection and returns the raw result from the connection adapter. Note: depending on your database connector, the result returned by this method may be manually memory managed. Consider using the exec_query wrapper instead.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 116
+def execute(sql, name = nil)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + high_precision_current_timestamp() + +

+ + +
+

Returns an Arel SQL literal for the CURRENT_TIMESTAMP for usage with arbitrary precision date/time columns.

+ +

Adapters supporting datetime with precision should override this to provide as much precision as is available.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 453
+def high_precision_current_timestamp
+  HIGH_PRECISION_CURRENT_TIMESTAMP
+end
+
+
+ +
+ +
+

+ + insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) + +

+ + +
+

Executes an INSERT query and returns the new record’s ID

+ +

id_value will be returned unless the value is nil, in which case the database will attempt to calculate the last inserted id and return that value.

+ +

If the next id was calculated in advance (as in Oracle), it should be passed in as id_value.

+
+ + + +
+ Also aliased as: create +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 165
+def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
+  sql, binds = to_sql_and_binds(arel, binds)
+  value = exec_insert(sql, name, binds, pk, sequence_name)
+  id_value || last_inserted_id(value)
+end
+
+
+ +
+ +
+

+ + insert_fixture(fixture, table_name) + +

+ + +
+

Inserts the given fixture into the table. Overridden in adapters that require something beyond a simple insert (e.g. Oracle). Most of adapters should implement insert_fixtures_set that leverages bulk SQL insert. We keep this method to provide fallback for databases like sqlite that do not support bulk inserts.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 397
+def insert_fixture(fixture, table_name)
+  execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
+end
+
+
+ +
+ +
+

+ + insert_fixtures_set(fixture_set, tables_to_delete = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 401
+def insert_fixtures_set(fixture_set, tables_to_delete = [])
+  fixture_inserts = build_fixture_statements(fixture_set)
+  table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
+  statements = table_deletes + fixture_inserts
+
+  with_multi_statements do
+    disable_referential_integrity do
+      transaction(requires_new: true) do
+        execute_batch(statements, "Fixtures Load")
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + reset_sequence!(table, column, sequence = nil) + +

+ + +
+

Set the sequence to the max value of the table’s column.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 388
+def reset_sequence!(table, column, sequence = nil)
+  # Do nothing by default. Implement for PostgreSQL, Oracle, ...
+end
+
+
+ +
+ +
+

+ + rollback_db_transaction() + +

+ + +
+

Rolls back the transaction (and turns on auto-committing). Must be done if the transaction block raises an exception or returns false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 373
+def rollback_db_transaction
+  exec_rollback_db_transaction
+end
+
+
+ +
+ +
+

+ + rollback_to_savepoint(name = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 379
+def rollback_to_savepoint(name = nil)
+  exec_rollback_to_savepoint(name)
+end
+
+
+ +
+ +
+

+ + sanitize_limit(limit) + +

+ + +
+

Sanitizes the given LIMIT parameter in order to prevent SQL injection.

+ +

The limit may be anything that can evaluate to a string via to_s. It should look like an integer, or an Arel SQL literal.

+ +

Returns Integer and Arel::Nodes::SqlLiteral limits as is.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 425
+def sanitize_limit(limit)
+  if limit.is_a?(Integer) || limit.is_a?(Arel::Nodes::SqlLiteral)
+    limit
+  else
+    Integer(limit)
+  end
+end
+
+
+ +
+ +
+

+ + select_all(arel, name = nil, binds = [], preparable: nil, async: false) + +

+ + +
+

Returns an ActiveRecord::Result instance.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 62
+def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
+  arel = arel_from_relation(arel)
+  sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
+
+  select(sql, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
+rescue ::RangeError
+  ActiveRecord::Result.empty
+end
+
+
+ +
+ +
+

+ + select_one(arel, name = nil, binds = []) + +

+ + +
+

Returns a record hash with the column names as keys and column values as values.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 73
+def select_one(arel, name = nil, binds = [])
+  select_all(arel, name, binds).first
+end
+
+
+ +
+ +
+

+ + select_rows(arel, name = nil, binds = []) + +

+ + +
+

Returns an array of arrays containing the field values. Order is the same as that returned by columns.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 90
+def select_rows(arel, name = nil, binds = [])
+  select_all(arel, name, binds).rows
+end
+
+
+ +
+ +
+

+ + select_value(arel, name = nil, binds = []) + +

+ + +
+

Returns a single value from a record

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 78
+def select_value(arel, name = nil, binds = [])
+  single_value_from_rows(select_rows(arel, name, binds))
+end
+
+
+ +
+ +
+

+ + select_values(arel, name = nil, binds = []) + +

+ + +
+

Returns an array of the values of the first column in a select:

+ +
select_values("SELECT id FROM companies LIMIT 3") => [1,2,3]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 84
+def select_values(arel, name = nil, binds = [])
+  select_rows(arel, name, binds).map(&:first)
+end
+
+
+ +
+ +
+

+ + to_sql(arel_or_sql_string, binds = []) + +

+ + +
+

Converts an arel AST to SQL

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 12
+def to_sql(arel_or_sql_string, binds = [])
+  sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
+  sql
+end
+
+
+ +
+ +
+

+ + transaction(requires_new: nil, isolation: nil, joinable: true, &block) + +

+ + +
+

Runs the given block in a database transaction, and returns the result of the block.

+ +

Nested transactions support

+ +

transaction calls can be nested. By default, this makes all database statements in the nested transaction block become part of the parent transaction. For example, the following behavior may be surprising:

+ +
ActiveRecord::Base.transaction do
+  Post.create(title: 'first')
+  ActiveRecord::Base.transaction do
+    Post.create(title: 'second')
+    raise ActiveRecord::Rollback
+  end
+end
+
+ +

This creates both “first” and “second” posts. Reason is the ActiveRecord::Rollback exception in the nested block does not issue a ROLLBACK. Since these exceptions are captured in transaction blocks, the parent block does not see it and the real transaction is committed.

+ +

Most databases don’t support true nested transactions. At the time of writing, the only database that supports true nested transactions that we’re aware of, is MS-SQL.

+ +

In order to get around this problem, transaction will emulate the effect of nested transactions, by using savepoints: dev.mysql.com/doc/refman/en/savepoint.html.

+ +

It is safe to call this method if a database transaction is already open, i.e. if transaction is called within another transaction block. In case of a nested call, transaction will behave as follows:

+
  • +

    The block will be run without doing anything. All database statements that happen within the block are effectively appended to the already open database transaction.

    +
  • +

    However, if :requires_new is set, the block will be wrapped in a database savepoint acting as a sub-transaction.

    +
+ +

In order to get a ROLLBACK for the nested transaction you may ask for a real sub-transaction by passing requires_new: true. If anything goes wrong, the database rolls back to the beginning of the sub-transaction without rolling back the parent transaction. If we add it to the previous example:

+ +
ActiveRecord::Base.transaction do
+  Post.create(title: 'first')
+  ActiveRecord::Base.transaction(requires_new: true) do
+    Post.create(title: 'second')
+    raise ActiveRecord::Rollback
+  end
+end
+
+ +

only post with title “first” is created.

+ +

See ActiveRecord::Transactions to learn more.

+ +

Caveats

+ +

MySQL doesn’t support DDL transactions. If you perform a DDL operation, then any created savepoints will be automatically released. For example, if you’ve created a savepoint, then you execute a CREATE TABLE statement, then the savepoint that was created will be automatically released.

+ +

This means that, on MySQL, you shouldn’t execute DDL operations inside a transaction call that you know might create a savepoint. Otherwise, transaction will raise exceptions when it tries to release the already-automatically-released savepoints:

+ +
Model.connection.transaction do  # BEGIN
+  Model.connection.transaction(requires_new: true) do  # CREATE SAVEPOINT active_record_1
+    Model.connection.create_table(...)
+    # active_record_1 now automatically released
+  end  # RELEASE SAVEPOINT active_record_1  <--- BOOM! database error!
+end
+
+ +

Transaction isolation

+ +

If your database supports setting the isolation level for a transaction, you can set it like so:

+ +
Post.transaction(isolation: :serializable) do
+  # ...
+end
+
+ +

Valid isolation levels are:

+
  • +

    :read_uncommitted

    +
  • +

    :read_committed

    +
  • +

    :repeatable_read

    +
  • +

    :serializable

    +
+ +

You should consult the documentation for your database to understand the semantics of these different levels:

+ + +

An ActiveRecord::TransactionIsolationError will be raised if:

+
  • +

    The adapter does not support setting the isolation level

    +
  • +

    You are joining an existing open transaction

    +
  • +

    You are creating a nested (savepoint) transaction

    +
+ +

The mysql2 and postgresql adapters support setting the transaction isolation level.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 309
+def transaction(requires_new: nil, isolation: nil, joinable: true, &block)
+  if !requires_new && current_transaction.joinable?
+    if isolation
+      raise ActiveRecord::TransactionIsolationError, "cannot set isolation when joining a transaction"
+    end
+    yield
+  else
+    transaction_manager.within_new_transaction(isolation: isolation, joinable: joinable, &block)
+  end
+rescue ActiveRecord::Rollback
+  # rollbacks are silently swallowed
+end
+
+
+ +
+ +
+

+ + transaction_isolation_levels() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 352
+def transaction_isolation_levels
+  {
+    read_uncommitted: "READ UNCOMMITTED",
+    read_committed:   "READ COMMITTED",
+    repeatable_read:  "REPEATABLE READ",
+    serializable:     "SERIALIZABLE"
+  }
+end
+
+
+ +
+ +
+

+ + transaction_open?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 335
+def transaction_open?
+  current_transaction.open?
+end
+
+
+ +
+ +
+

+ + truncate(table_name, name = nil) + +

+ + +
+

Executes the truncate statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 185
+def truncate(table_name, name = nil)
+  execute(build_truncate_statement(table_name), name)
+end
+
+
+ +
+ +
+

+ + update(arel, name = nil, binds = []) + +

+ + +
+

Executes the update statement and returns the number of rows affected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 173
+def update(arel, name = nil, binds = [])
+  sql, binds = to_sql_and_binds(arel, binds)
+  exec_update(sql, name, binds)
+end
+
+
+ +
+ +
+

+ + write_query?(sql) + +

+ + +
+

Determines whether the SQL statement is a write query.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 107
+def write_query?(sql)
+  raise NotImplementedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable.html new file mode 100644 index 0000000000..c9d29912ae --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable.html @@ -0,0 +1,146 @@ +--- +title: ActiveRecord::ConnectionAdapters::Deduplicable +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + -@() + +

+ + +
+ +
+ + + + + +
+ Alias for: deduplicate +
+ + + +
+ +
+

+ + deduplicate() + +

+ + +
+ +
+ + + +
+ Also aliased as: -@ +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/deduplicable.rb, line 18
+def deduplicate
+  self.class.registry[self] ||= deduplicated
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable/ClassMethods.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable/ClassMethods.html new file mode 100644 index 0000000000..7bb7df2041 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Deduplicable/ClassMethods.html @@ -0,0 +1,140 @@ +--- +title: ActiveRecord::ConnectionAdapters::Deduplicable::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + new(*, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/deduplicable.rb, line 13
+def new(*, **)
+  super.deduplicate
+end
+
+
+ +
+ +
+

+ + registry() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/deduplicable.rb, line 9
+def registry
+  @registry ||= {}
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL.html new file mode 100644 index 0000000000..214800a5f5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL.html @@ -0,0 +1,94 @@ +--- +title: ActiveRecord::ConnectionAdapters::MySQL +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/ColumnMethods.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/ColumnMethods.html new file mode 100644 index 0000000000..74134cfa71 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/ColumnMethods.html @@ -0,0 +1,473 @@ +--- +title: ActiveRecord::ConnectionAdapters::MySQL::ColumnMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + blob(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 10
+        
+
+
+ +
+ +
+

+ + longblob(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 22
+        
+
+
+ +
+ +
+

+ + longtext(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 34
+        
+
+
+ +
+ +
+

+ + mediumblob(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 18
+        
+
+
+ +
+ +
+

+ + mediumtext(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 30
+        
+
+
+ +
+ +
+

+ + tinyblob(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 14
+        
+
+
+ +
+ +
+

+ + tinytext(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 26
+        
+
+
+ +
+ +
+

+ + unsigned_bigint(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 42
+        
+
+
+ +
+ +
+

+ + unsigned_decimal(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 53
+included do
+  define_column_methods :blob, :tinyblob, :mediumblob, :longblob,
+    :tinytext, :mediumtext, :longtext, :unsigned_integer, :unsigned_bigint,
+    :unsigned_float, :unsigned_decimal
+end
+
+
+ +
+ +
+

+ + unsigned_float(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 46
+        
+
+
+ +
+ +
+

+ + unsigned_integer(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 38
+        
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/DatabaseStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/DatabaseStatements.html new file mode 100644 index 0000000000..d6056375dc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/DatabaseStatements.html @@ -0,0 +1,187 @@ +--- +title: ActiveRecord::ConnectionAdapters::MySQL::DatabaseStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + execute(sql, name = nil, async: false) + +

+ + +
+

Executes the SQL statement in the context of this connection.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb, line 43
+def execute(sql, name = nil, async: false)
+  sql = transform_query(sql)
+  check_if_write_query(sql)
+
+  raw_execute(sql, name, async: async)
+end
+
+
+ +
+ +
+

+ + explain(arel, binds = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb, line 33
+def explain(arel, binds = [])
+  sql     = "EXPLAIN #{to_sql(arel, binds)}"
+  start   = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+  result  = exec_query(sql, "EXPLAIN", binds)
+  elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
+
+  MySQL::ExplainPrettyPrinter.new.pp(result, elapsed)
+end
+
+
+ +
+ +
+

+ + high_precision_current_timestamp() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb, line 86
+def high_precision_current_timestamp
+  HIGH_PRECISION_CURRENT_TIMESTAMP
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/Table.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/Table.html new file mode 100644 index 0000000000..52e9c2e523 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/Table.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::ConnectionAdapters::MySQL::Table +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/TableDefinition.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/TableDefinition.html new file mode 100644 index 0000000000..ce8f66c4c9 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/MySQL/TableDefinition.html @@ -0,0 +1,145 @@ +--- +title: ActiveRecord::ConnectionAdapters::MySQL::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + charset
+ [R] + collation
+ + + + +

Class Public methods

+ +
+

+ + new(conn, name, charset: nil, collation: nil, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql/schema_definitions.rb, line 65
+def initialize(conn, name, charset: nil, collation: nil, **)
+  super
+  @charset = charset
+  @collation = collation
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html new file mode 100644 index 0000000000..712880922b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Mysql2Adapter.html @@ -0,0 +1,709 @@ +--- +title: ActiveRecord::ConnectionAdapters::Mysql2Adapter +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ADAPTER_NAME="Mysql2"
 
ER_ACCESS_DENIED_ERROR=1045
 
ER_BAD_DB_ERROR=1049
 
ER_CONN_HOST_ERROR=2003
 
ER_UNKNOWN_HOST_ERROR=2005
 
+ + + + + + +

Class Public methods

+ +
+

+ + database_exists?(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 64
+def self.database_exists?(config)
+  !!ActiveRecord::Base.mysql2_connection(config)
+rescue ActiveRecord::NoDatabaseError
+  false
+end
+
+
+ +
+ +
+

+ + new(connection, logger, connection_options, config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 58
+def initialize(connection, logger, connection_options, config)
+  superclass_config = config.reverse_merge(prepared_statements: false)
+  super(connection, logger, connection_options, superclass_config)
+  configure_connection
+end
+
+
+ +
+ +
+

+ + new_client(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 43
+def new_client(config)
+  Mysql2::Client.new(config)
+rescue Mysql2::Error => error
+  if error.error_number == ConnectionAdapters::Mysql2Adapter::ER_BAD_DB_ERROR
+    raise ActiveRecord::NoDatabaseError.db_error(config[:database])
+  elsif error.error_number == ConnectionAdapters::Mysql2Adapter::ER_ACCESS_DENIED_ERROR
+    raise ActiveRecord::DatabaseConnectionError.username_error(config[:username])
+  elsif [ConnectionAdapters::Mysql2Adapter::ER_CONN_HOST_ERROR, ConnectionAdapters::Mysql2Adapter::ER_UNKNOWN_HOST_ERROR].include?(error.error_number)
+    raise ActiveRecord::DatabaseConnectionError.hostname_error(config[:host])
+  else
+    raise ActiveRecord::ConnectionNotEstablished, error.message
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 118
+def active?
+  @connection.ping
+end
+
+
+ +
+ +
+

+ + disconnect!() + +

+ + +
+

Disconnects from the database if already connected. Otherwise, this method does nothing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 131
+def disconnect!
+  super
+  @connection.close
+end
+
+
+ +
+ +
+

+ + error_number(exception) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 100
+def error_number(exception)
+  exception.error_number if exception.respond_to?(:error_number)
+end
+
+
+ +
+ +
+

+ + quote_string(string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 108
+def quote_string(string)
+  @connection.escape(string)
+rescue Mysql2::Error => error
+  raise translate_exception(error, message: error.message, sql: "<escape>", binds: [])
+end
+
+
+ +
+ +
+

+ + reconnect!() + +

+ + +
+ +
+ + + +
+ Also aliased as: reset! +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 122
+def reconnect!
+  super
+  disconnect!
+  connect
+end
+
+
+ +
+ +
+

+ + reset!() + +

+ + +
+ +
+ + + + + +
+ Alias for: reconnect! +
+ + + +
+ +
+

+ + supports_comments?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 74
+def supports_comments?
+  true
+end
+
+
+ +
+ +
+

+ + supports_comments_in_create?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 78
+def supports_comments_in_create?
+  true
+end
+
+
+ +
+ +
+

+ + supports_json?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 70
+def supports_json?
+  !mariadb? && database_version >= "5.7.8"
+end
+
+
+ +
+ +
+

+ + supports_lazy_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 86
+def supports_lazy_transactions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_savepoints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb, line 82
+def supports_savepoints?
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/NullColumn.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/NullColumn.html new file mode 100644 index 0000000000..6543b67b4c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/NullColumn.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::ConnectionAdapters::NullColumn +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL.html new file mode 100644 index 0000000000..dfa82e45f3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL.html @@ -0,0 +1,162 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/AlterTable.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/AlterTable.html new file mode 100644 index 0000000000..3d6abd1307 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/AlterTable.html @@ -0,0 +1,164 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::AlterTable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + constraint_validations
+ + + + +

Class Public methods

+ +
+

+ + new(td) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 232
+def initialize(td)
+  super
+  @constraint_validations = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + validate_constraint(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 237
+def validate_constraint(name)
+  @constraint_validations << name
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/ColumnMethods.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/ColumnMethods.html new file mode 100644 index 0000000000..65731fdd66 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/ColumnMethods.html @@ -0,0 +1,1324 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + bigserial(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 57
+        
+
+
+ +
+ +
+

+ + bit(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 61
+        
+
+
+ +
+ +
+

+ + bit_varying(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 65
+        
+
+
+ +
+ +
+

+ + box(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 137
+        
+
+
+ +
+ +
+

+ + cidr(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 69
+        
+
+
+ +
+ +
+

+ + circle(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 149
+        
+
+
+ +
+ +
+

+ + citext(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 73
+        
+
+
+ +
+ +
+

+ + daterange(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 77
+        
+
+
+ +
+ +
+

+ + enum(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 184
+included do
+  define_column_methods :bigserial, :bit, :bit_varying, :cidr, :citext, :daterange,
+    :hstore, :inet, :interval, :int4range, :int8range, :jsonb, :ltree, :macaddr,
+    :money, :numrange, :oid, :point, :line, :lseg, :box, :path, :polygon, :circle,
+    :serial, :tsrange, :tstzrange, :tsvector, :uuid, :xml, :timestamptz, :enum
+end
+
+
+ +
+ +
+

+ + hstore(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 81
+        
+
+
+ +
+ +
+

+ + inet(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 85
+        
+
+
+ +
+ +
+

+ + int4range(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 93
+        
+
+
+ +
+ +
+

+ + int8range(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 97
+        
+
+
+ +
+ +
+

+ + interval(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 89
+        
+
+
+ +
+ +
+

+ + jsonb(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 101
+        
+
+
+ +
+ +
+

+ + line(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 129
+        
+
+
+ +
+ +
+

+ + lseg(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 133
+        
+
+
+ +
+ +
+

+ + ltree(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 105
+        
+
+
+ +
+ +
+

+ + macaddr(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 109
+        
+
+
+ +
+ +
+

+ + money(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 113
+        
+
+
+ +
+ +
+

+ + numrange(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 117
+        
+
+
+ +
+ +
+

+ + oid(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 121
+        
+
+
+ +
+ +
+

+ + path(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 141
+        
+
+
+ +
+ +
+

+ + point(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 125
+        
+
+
+ +
+ +
+

+ + polygon(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 145
+        
+
+
+ +
+ +
+

+ + primary_key(name, type = :primary_key, **options) + +

+ + +
+

Defines the primary key field. Use of the native PostgreSQL UUID type is supported, and can be used by defining your tables as such:

+ +
create_table :stuffs, id: :uuid do |t|
+  t.string :content
+  t.timestamps
+end
+
+ +

By default, this will use the gen_random_uuid() function from the pgcrypto extension. As that extension is only available in PostgreSQL 9.4+, for earlier versions an explicit default can be set to use uuid_generate_v4() from the uuid-ossp extension instead:

+ +
create_table :stuffs, id: false do |t|
+  t.primary_key :id, :uuid, default: "uuid_generate_v4()"
+  t.uuid :foo_id
+  t.timestamps
+end
+
+ +

To enable the appropriate extension, which is a requirement, use the enable_extension method in your migrations.

+ +

To use a UUID primary key without any of the extensions, set the :default option to nil:

+ +
create_table :stuffs, id: false do |t|
+  t.primary_key :id, :uuid, default: nil
+  t.uuid :foo_id
+  t.timestamps
+end
+
+ +

You may also pass a custom stored procedure that returns a UUID or use a different UUID generation function from another library.

+ +

Note that setting the UUID primary key default value to nil will require you to assure that you always provide a UUID value before saving a record (as primary keys cannot be nil). This might be done via the SecureRandom.uuid method and a before_save callback, for instance.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 48
+def primary_key(name, type = :primary_key, **options)
+  if type == :uuid
+    options[:default] = options.fetch(:default, "gen_random_uuid()")
+  end
+
+  super
+end
+
+
+ +
+ +
+

+ + serial(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 153
+        
+
+
+ +
+ +
+

+ + timestamptz(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 177
+        
+
+
+ +
+ +
+

+ + tsrange(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 157
+        
+
+
+ +
+ +
+

+ + tstzrange(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 161
+        
+
+
+ +
+ +
+

+ + tsvector(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 165
+        
+
+
+ +
+ +
+

+ + uuid(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 169
+        
+
+
+ +
+ +
+

+ + xml(*names, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 173
+        
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/DatabaseStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/DatabaseStatements.html new file mode 100644 index 0000000000..7dfb5484c8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/DatabaseStatements.html @@ -0,0 +1,190 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + execute(sql, name = nil) + +

+ + +
+

Executes an SQL statement, returning a PG::Result object on success or raising a PG::Error exception otherwise. Note: the PG::Result object is manually memory managed; if you don’t need it specifically, you may want consider the exec_query wrapper.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb, line 39
+def execute(sql, name = nil)
+  sql = transform_query(sql)
+  check_if_write_query(sql)
+
+  materialize_transactions
+  mark_transaction_written_if_write(sql)
+
+  log(sql, name) do
+    ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
+      @connection.async_exec(sql)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + explain(arel, binds = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb, line 7
+def explain(arel, binds = [])
+  sql = "EXPLAIN #{to_sql(arel, binds)}"
+  PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
+end
+
+
+ +
+ +
+

+ + high_precision_current_timestamp() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb, line 128
+def high_precision_current_timestamp
+  HIGH_PRECISION_CURRENT_TIMESTAMP
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID.html new file mode 100644 index 0000000000..d291f4a484 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID.html @@ -0,0 +1,121 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::OID +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit.html new file mode 100644 index 0000000000..ba37482d95 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bit +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit/Data.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit/Data.html new file mode 100644 index 0000000000..e53e9cbb9b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/OID/Bit/Data.html @@ -0,0 +1,227 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Bit::Data +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb, line 30
+def initialize(value)
+  @value = value
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + binary?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb, line 38
+def binary?
+  /\A[01]*\Z/.match?(value)
+end
+
+
+ +
+ +
+

+ + hex?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb, line 42
+def hex?
+  /\A[0-9A-F]*\Z/i.match?(value)
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb, line 34
+def to_s
+  value
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting.html new file mode 100644 index 0000000000..366c14dc14 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting.html @@ -0,0 +1,360 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + check_int_in_range(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 28
+        def check_int_in_range(value)
+          if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
+            exception = <<~ERROR
+              Provided value outside of the range of a signed 64bit integer.
+
+              PostgreSQL will treat the column type in question as a numeric.
+              This may result in a slow sequential scan due to a comparison
+              being performed between an integer or bigint value and a numeric value.
+
+              To allow for this potentially unwanted behavior, set
+              ActiveRecord.raise_int_wider_than_64bit to false.
+            ERROR
+            raise IntegerOutOf64BitRange.new exception
+          end
+        end
+
+
+ +
+ +
+

+ + column_name_matcher() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 153
+def column_name_matcher
+  COLUMN_NAME
+end
+
+
+ +
+ +
+

+ + column_name_with_order_matcher() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 157
+def column_name_with_order_matcher
+  COLUMN_NAME_WITH_ORDER
+end
+
+
+ +
+ +
+

+ + escape_bytea(value) + +

+ + +
+

Escapes binary strings for bytea input to the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 17
+def escape_bytea(value)
+  @connection.escape_bytea(value) if value
+end
+
+
+ +
+ +
+

+ + quote_schema_name(name) + +

+ + +
+

Quotes schema names for use in SQL queries.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 91
+def quote_schema_name(name)
+  PG::Connection.quote_ident(name)
+end
+
+
+ +
+ +
+

+ + quote_table_name_for_assignment(table, attr) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 95
+def quote_table_name_for_assignment(table, attr)
+  quote_column_name(attr)
+end
+
+
+ +
+ +
+

+ + unescape_bytea(value) + +

+ + +
+

Unescapes bytea output from a database to the binary string it represents. NOTE: This is NOT an inverse of escape_bytea! This is only to be used on escaped binary output from database drive.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 24
+def unescape_bytea(value)
+  @connection.unescape_bytea(value) if value
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting/IntegerOutOf64BitRange.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting/IntegerOutOf64BitRange.html new file mode 100644 index 0000000000..3303fbbf3f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Quoting/IntegerOutOf64BitRange.html @@ -0,0 +1,107 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting::IntegerOutOf64BitRange +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(msg) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb, line 11
+def initialize(msg)
+  super(msg)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/SchemaStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/SchemaStatements.html new file mode 100644 index 0000000000..623155c606 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/SchemaStatements.html @@ -0,0 +1,1136 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::SchemaStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + client_min_messages() + +

+ + +
+

Returns the current client message level.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 237
+def client_min_messages
+  query_value("SHOW client_min_messages", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + client_min_messages=(level) + +

+ + +
+

Set the client message level.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 242
+def client_min_messages=(level)
+  execute("SET client_min_messages TO '#{level}'", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + collation() + +

+ + +
+

Returns the current database collation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 189
+def collation
+  query_value("SELECT datcollate FROM pg_database WHERE datname = current_database()", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + create_database(name, options = {}) + +

+ + +
+

Create a new PostgreSQL database. Options include :owner, :template, :encoding (defaults to utf8), :collation, :ctype, :tablespace, and :connection_limit (note that MySQL uses :charset while PostgreSQL uses :encoding).

+ +

Example:

+ +
create_database config[:database], config
+create_database 'foo_development', encoding: 'unicode'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 22
+def create_database(name, options = {})
+  options = { encoding: "utf8" }.merge!(options.symbolize_keys)
+
+  option_string = options.each_with_object(+"") do |(key, value), memo|
+    memo << case key
+            when :owner
+              " OWNER = \"#{value}\""
+            when :template
+              " TEMPLATE = \"#{value}\""
+            when :encoding
+              " ENCODING = '#{value}'"
+            when :collation
+              " LC_COLLATE = '#{value}'"
+            when :ctype
+              " LC_CTYPE = '#{value}'"
+            when :tablespace
+              " TABLESPACE = \"#{value}\""
+            when :connection_limit
+              " CONNECTION LIMIT = #{value}"
+            else
+              ""
+    end
+  end
+
+  execute "CREATE DATABASE #{quote_table_name(name)}#{option_string}"
+end
+
+
+ +
+ +
+

+ + create_schema(schema_name) + +

+ + +
+

Creates a schema for the given schema name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 210
+def create_schema(schema_name)
+  execute "CREATE SCHEMA #{quote_schema_name(schema_name)}"
+end
+
+
+ +
+ +
+

+ + ctype() + +

+ + +
+

Returns the current database ctype.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 194
+def ctype
+  query_value("SELECT datctype FROM pg_database WHERE datname = current_database()", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + current_database() + +

+ + +
+

Returns the current database name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 174
+def current_database
+  query_value("SELECT current_database()", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + current_schema() + +

+ + +
+

Returns the current schema name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 179
+def current_schema
+  query_value("SELECT current_schema", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + drop_schema(schema_name, **options) + +

+ + +
+

Drops the schema for the given schema name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 215
+def drop_schema(schema_name, **options)
+  execute "DROP SCHEMA#{' IF EXISTS' if options[:if_exists]} #{quote_schema_name(schema_name)} CASCADE"
+end
+
+
+ +
+ +
+

+ + encoding() + +

+ + +
+

Returns the current database encoding format.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 184
+def encoding
+  query_value("SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database()", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + foreign_keys(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 483
+        def foreign_keys(table_name)
+          scope = quoted_scope(table_name)
+          fk_info = exec_query(<<~SQL, "SCHEMA")
+            SELECT t2.oid::regclass::text AS to_table, a1.attname AS column, a2.attname AS primary_key, c.conname AS name, c.confupdtype AS on_update, c.confdeltype AS on_delete, c.convalidated AS valid, c.condeferrable AS deferrable, c.condeferred AS deferred
+            FROM pg_constraint c
+            JOIN pg_class t1 ON c.conrelid = t1.oid
+            JOIN pg_class t2 ON c.confrelid = t2.oid
+            JOIN pg_attribute a1 ON a1.attnum = c.conkey[1] AND a1.attrelid = t1.oid
+            JOIN pg_attribute a2 ON a2.attnum = c.confkey[1] AND a2.attrelid = t2.oid
+            JOIN pg_namespace t3 ON c.connamespace = t3.oid
+            WHERE c.contype = 'f'
+              AND t1.relname = #{scope[:name]}
+              AND t3.nspname = #{scope[:schema]}
+            ORDER BY c.conname
+          SQL
+
+          fk_info.map do |row|
+            options = {
+              column: Utils.unquote_identifier(row["column"]),
+              name: row["name"],
+              primary_key: row["primary_key"]
+            }
+
+            options[:on_delete] = extract_foreign_key_action(row["on_delete"])
+            options[:on_update] = extract_foreign_key_action(row["on_update"])
+            options[:deferrable] = extract_foreign_key_deferrable(row["deferrable"], row["deferred"])
+
+            options[:validate] = row["valid"]
+            to_table = Utils.unquote_identifier(row["to_table"])
+
+            ForeignKeyDefinition.new(table_name, to_table, options)
+          end
+        end
+
+
+ +
+ +
+

+ + foreign_table_exists?(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 521
+def foreign_table_exists?(table_name)
+  query_values(data_source_sql(table_name, type: "FOREIGN TABLE"), "SCHEMA").any? if table_name.present?
+end
+
+
+ +
+ +
+

+ + foreign_tables() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 517
+def foreign_tables
+  query_values(data_source_sql(type: "FOREIGN TABLE"), "SCHEMA")
+end
+
+
+ +
+ +
+

+ + index_name_exists?(table_name, index_name) + +

+ + +
+

Verifies existence of an index with a given name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 68
+        def index_name_exists?(table_name, index_name)
+          table = quoted_scope(table_name)
+          index = quoted_scope(index_name)
+
+          query_value(<<~SQL, "SCHEMA").to_i > 0
+            SELECT COUNT(*)
+            FROM pg_class t
+            INNER JOIN pg_index d ON t.oid = d.indrelid
+            INNER JOIN pg_class i ON d.indexrelid = i.oid
+            LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
+            WHERE i.relkind IN ('i', 'I')
+              AND i.relname = #{index[:name]}
+              AND t.relname = #{table[:name]}
+              AND n.nspname = #{index[:schema]}
+          SQL
+        end
+
+
+ +
+ +
+

+ + rename_index(table_name, old_name, new_name) + +

+ + +
+

Renames an index of a table. Raises error if length of new index name is greater than allowed limit.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 477
+def rename_index(table_name, old_name, new_name)
+  validate_index_length!(table_name, new_name)
+
+  execute "ALTER INDEX #{quote_column_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
+end
+
+
+ +
+ +
+

+ + rename_table(table_name, new_name) + +

+ + +
+

Renames a table. Also renames a table’s primary key sequence if the sequence name exists and matches the Active Record default.

+ +

Example:

+ +
rename_table('octopuses', 'octopi')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 378
+def rename_table(table_name, new_name)
+  clear_cache!
+  schema_cache.clear_data_source_cache!(table_name.to_s)
+  schema_cache.clear_data_source_cache!(new_name.to_s)
+  execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
+  pk, seq = pk_and_sequence_for(new_name)
+  if pk
+    idx = "#{table_name}_pkey"
+    new_idx = "#{new_name}_pkey"
+    execute "ALTER INDEX #{quote_table_name(idx)} RENAME TO #{quote_table_name(new_idx)}"
+    if seq && seq.identifier == "#{table_name}_#{pk}_seq"
+      new_seq = "#{new_name}_#{pk}_seq"
+      execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
+    end
+  end
+  rename_table_indexes(table_name, new_name)
+end
+
+
+ +
+ +
+

+ + schema_exists?(name) + +

+ + +
+

Returns true if schema exists.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 63
+def schema_exists?(name)
+  query_value("SELECT COUNT(*) FROM pg_namespace WHERE nspname = #{quote(name)}", "SCHEMA").to_i > 0
+end
+
+
+ +
+ +
+

+ + schema_names() + +

+ + +
+

Returns an array of schema names.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 199
+        def schema_names
+          query_values(<<~SQL, "SCHEMA")
+            SELECT nspname
+              FROM pg_namespace
+             WHERE nspname !~ '^pg_.*'
+               AND nspname NOT IN ('information_schema')
+             ORDER by nspname;
+          SQL
+        end
+
+
+ +
+ +
+

+ + schema_search_path() + +

+ + +
+

Returns the active schema search path.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 232
+def schema_search_path
+  @schema_search_path ||= query_value("SHOW search_path", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + schema_search_path=(schema_csv) + +

+ + +
+

Sets the schema search path to a string of comma-separated schema names. Names beginning with $ have to be quoted (e.g. $user => ‘$user’). See: www.postgresql.org/docs/current/static/ddl-schemas.html

+ +

This should be not be called manually but set in database.yml.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 224
+def schema_search_path=(schema_csv)
+  if schema_csv
+    execute("SET search_path TO #{schema_csv}", "SCHEMA")
+    @schema_search_path = schema_csv
+  end
+end
+
+
+ +
+ +
+

+ + serial_sequence(table, column) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 255
+def serial_sequence(table, column)
+  query_value("SELECT pg_get_serial_sequence(#{quote(table)}, #{quote(column)})", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + validate_check_constraint(table_name, **options) + +

+ + +
+

Validates the given check constraint.

+ +
validate_check_constraint :products, name: "price_check"
+
+ +

The options hash accepts the same keys as add_check_constraint[rdoc-ref:ConnectionAdapters::SchemaStatements#add_check_constraint].

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 646
+def validate_check_constraint(table_name, **options)
+  chk_name_to_validate = check_constraint_for!(table_name, **options).name
+
+  validate_constraint table_name, chk_name_to_validate
+end
+
+
+ +
+ +
+

+ + validate_constraint(table_name, constraint_name) + +

+ + +
+

Validates the given constraint.

+ +

Validates the constraint named constraint_name on accounts.

+ +
validate_constraint :accounts, :constraint_name
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 613
+def validate_constraint(table_name, constraint_name)
+  at = create_alter_table table_name
+  at.validate_constraint constraint_name
+
+  execute schema_creation.accept(at)
+end
+
+
+ +
+ +
+

+ + validate_foreign_key(from_table, to_table = nil, **options) + +

+ + +
+

Validates the given foreign key.

+ +

Validates the foreign key on accounts.branch_id.

+ +
validate_foreign_key :accounts, :branches
+
+ +

Validates the foreign key on accounts.owner_id.

+ +
validate_foreign_key :accounts, column: :owner_id
+
+ +

Validates the foreign key named special_fk_name on the accounts table.

+ +
validate_foreign_key :accounts, name: :special_fk_name
+
+ +

The options hash accepts the same keys as SchemaStatements#add_foreign_key.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb, line 635
+def validate_foreign_key(from_table, to_table = nil, **options)
+  fk_name_to_validate = foreign_key_for!(from_table, to_table: to_table, **options).name
+
+  validate_constraint from_table, fk_name_to_validate
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Table.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Table.html new file mode 100644 index 0000000000..67f7b36a4d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/Table.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::Table +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TableDefinition.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TableDefinition.html new file mode 100644 index 0000000000..6f9da8c37c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TableDefinition.html @@ -0,0 +1,136 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + unlogged
+ + + + +

Class Public methods

+ +
+

+ + new(*, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb, line 197
+def initialize(*, **)
+  super
+  @unlogged = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TypeMetadata.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TypeMetadata.html new file mode 100644 index 0000000000..f68bbdae54 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQL/TypeMetadata.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQL::TypeMetadata +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html new file mode 100644 index 0000000000..3bccc10177 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/PostgreSQLAdapter.html @@ -0,0 +1,2420 @@ +--- +title: ActiveRecord::ConnectionAdapters::PostgreSQLAdapter +layout: default +--- +
+ +
+
+ +
+ +

The PostgreSQL adapter works with the native C (github.com/ged/ruby-pg) driver.

+ +

Options:

+
  • +

    :host - Defaults to a Unix-domain socket in /tmp. On machines without Unix-domain sockets, the default is to connect to localhost.

    +
  • +

    :port - Defaults to 5432.

    +
  • +

    :username - Defaults to be the same as the operating system name of the user running the application.

    +
  • +

    :password - Password to be used if the server demands password authentication.

    +
  • +

    :database - Defaults to be the same as the username.

    +
  • +

    :schema_search_path - An optional schema search path for the connection given as a string of comma-separated schema names. This is backward-compatible with the :schema_order option.

    +
  • +

    :encoding - An optional client encoding that is used in a SET client_encoding TO <encoding> call on the connection.

    +
  • +

    :min_messages - An optional client min messages that is used in a SET client_min_messages TO <min_messages> call on the connection.

    +
  • +

    :variables - An optional hash of additional parameters that will be used in SET SESSION key = val calls on the connection.

    +
  • +

    :insert_returning - An optional boolean to control the use of RETURNING for INSERT statements defaults to true.

    +
+ +

Any further options are used as connection parameters to libpq. See www.postgresql.org/docs/current/static/libpq-connect.html for the list of parameters.

+ +

In addition, default connection parameters of libpq can be set per environment variables. See www.postgresql.org/docs/current/static/libpq-envars.html .

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ADAPTER_NAME="PostgreSQL"
 
DEADLOCK_DETECTED="40P01"
 
DUPLICATE_DATABASE="42P04"
 
FOREIGN_KEY_VIOLATION="23503"
 
LOCK_NOT_AVAILABLE="55P03"
 
NATIVE_DATABASE_TYPES={ +primary_key: "bigserial primary key", +string: { name: "character varying" }, +text: { name: "text" }, +integer: { name: "integer", limit: 4 }, +bigint: { name: "bigint" }, +float: { name: "float" }, +decimal: { name: "decimal" }, +datetime: {}, # set dynamically based on datetime_type +timestamp: { name: "timestamp" }, +timestamptz: { name: "timestamptz" }, +time: { name: "time" }, +date: { name: "date" }, +daterange: { name: "daterange" }, +numrange: { name: "numrange" }, +tsrange: { name: "tsrange" }, +tstzrange: { name: "tstzrange" }, +int4range: { name: "int4range" }, +int8range: { name: "int8range" }, +binary: { name: "bytea" }, +boolean: { name: "boolean" }, +xml: { name: "xml" }, +tsvector: { name: "tsvector" }, +hstore: { name: "hstore" }, +inet: { name: "inet" }, +cidr: { name: "cidr" }, +macaddr: { name: "macaddr" }, +uuid: { name: "uuid" }, +json: { name: "json" }, +jsonb: { name: "jsonb" }, +ltree: { name: "ltree" }, +citext: { name: "citext" }, +point: { name: "point" }, +line: { name: "line" }, +lseg: { name: "lseg" }, +box: { name: "box" }, +path: { name: "path" }, +polygon: { name: "polygon" }, +circle: { name: "circle" }, +bit: { name: "bit" }, +bit_varying: { name: "bit varying" }, +money: { name: "money" }, +interval: { name: "interval" }, +oid: { name: "oid" }, +enum: {} # special type https://www.postgresql.org/docs/current/datatype-enum.html +}
 
NOT_NULL_VIOLATION="23502"
 
NUMERIC_VALUE_OUT_OF_RANGE="22003"
 
QUERY_CANCELED="57014"
 
SERIALIZATION_FAILURE="40001"
 
UNIQUE_VIOLATION="23505"
 
VALUE_LIMIT_VIOLATION="22001"
 

See www.postgresql.org/docs/current/static/errcodes-appendix.html

+ + + + + + +

Class Public methods

+ +
+

+ + create_unlogged_tables + +

+ + +
+

PostgreSQL allows the creation of “unlogged” tables, which do not record data in the PostgreSQL Write-Ahead Log. This can make the tables faster, but significantly increases the risk of data loss if the database crashes. As a result, this should not be used in production environments. If you would like all created tables to be unlogged in the test environment you can add the following line to your test.rb file:

+ +
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables = true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 103
+class_attribute :create_unlogged_tables, default: false
+
+
+
+ +
+ +
+

+ + database_exists?(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 300
+def self.database_exists?(config)
+  !!ActiveRecord::Base.postgresql_connection(config)
+rescue ActiveRecord::NoDatabaseError
+  false
+end
+
+
+ +
+ +
+

+ + datetime_type + +

+ + +
+

PostgreSQL supports multiple types for DateTimes. By default, if you use datetime in migrations, Rails will translate this to a PostgreSQL “timestamp without time zone”. Change this in an initializer to use another NATIVE_DATABASE_TYPES. For example, to store DateTimes as “timestamp with time zone”:

+ +
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type = :timestamptz
+
+ +

Or if you are adding a custom type:

+ +
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:my_custom_type] = { name: "my_custom_type_name" }
+ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type = :my_custom_type
+
+ +

If you’re using :ruby as your config.active_record.schema_format and you change this setting, you should immediately run bin/rails db:migrate to update the types in your schema.rb.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 121
+class_attribute :datetime_type, default: :timestamp
+
+
+
+ +
+ +
+

+ + new(connection, logger, connection_parameters, config) + +

+ + +
+

Initializes and connects a PostgreSQL adapter.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 281
+def initialize(connection, logger, connection_parameters, config)
+  super(connection, logger, config)
+
+  @connection_parameters = connection_parameters || {}
+
+  # @local_tz is initialized as nil to avoid warnings when connect tries to use it
+  @local_tz = nil
+  @max_identifier_length = nil
+
+  configure_connection
+  add_pg_encoders
+  add_pg_decoders
+
+  @type_map = Type::HashLookupTypeMap.new
+  initialize_type_map
+  @local_tz = execute("SHOW TIME ZONE", "SCHEMA").first["TimeZone"]
+  @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
+end
+
+
+ +
+ +
+

+ + new_client(conn_params) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 77
+def new_client(conn_params)
+  PG.connect(**conn_params)
+rescue ::PG::Error => error
+  if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
+    raise ActiveRecord::NoDatabaseError.db_error(conn_params[:dbname])
+  elsif conn_params && conn_params[:user] && error.message.include?(conn_params[:user])
+    raise ActiveRecord::DatabaseConnectionError.username_error(conn_params[:user])
+  elsif conn_params && conn_params[:hostname] && error.message.include?(conn_params[:hostname])
+    raise ActiveRecord::DatabaseConnectionError.hostname_error(conn_params[:hostname])
+  else
+    raise ActiveRecord::ConnectionNotEstablished, error.message
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active?() + +

+ + +
+

Is this connection alive and ready for queries?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 307
+def active?
+  @lock.synchronize do
+    @connection.query ";"
+  end
+  true
+rescue PG::Error
+  false
+end
+
+
+ +
+ +
+

+ + create_enum(name, values) + +

+ + +
+

Given a name and an array of values, creates an enum type.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 472
+      def create_enum(name, values)
+        sql_values = values.map { |s| "'#{s}'" }.join(", ")
+        query = <<~SQL
+          DO $$
+          BEGIN
+              IF NOT EXISTS (
+                SELECT 1 FROM pg_type t
+                WHERE t.typname = '#{name}'
+              ) THEN
+                  CREATE TYPE \"#{name}\" AS ENUM (#{sql_values});
+              END IF;
+          END
+          $$;
+        SQL
+        exec_query(query)
+      end
+
+
+ +
+ +
+

+ + disable_extension(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 439
+def disable_extension(name)
+  exec_query("DROP EXTENSION IF EXISTS \"#{name}\" CASCADE").tap {
+    reload_type_map
+  }
+end
+
+
+ +
+ +
+

+ + disconnect!() + +

+ + +
+

Disconnects from the database if already connected. Otherwise, this method does nothing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 347
+def disconnect!
+  @lock.synchronize do
+    super
+    @connection.close rescue nil
+  end
+end
+
+
+ +
+ +
+

+ + enable_extension(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 433
+def enable_extension(name)
+  exec_query("CREATE EXTENSION IF NOT EXISTS \"#{name}\"").tap {
+    reload_type_map
+  }
+end
+
+
+ +
+ +
+

+ + enum_types() + +

+ + +
+

Returns a list of defined enum types, and their values.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 458
+      def enum_types
+        query = <<~SQL
+          SELECT
+            type.typname AS name,
+            string_agg(enum.enumlabel, ',' ORDER BY enum.enumsortorder) AS value
+          FROM pg_enum AS enum
+          JOIN pg_type AS type
+            ON (type.oid = enum.enumtypid)
+          GROUP BY type.typname;
+        SQL
+        exec_query(query, "SCHEMA").cast_values
+      end
+
+
+ +
+ +
+

+ + extension_available?(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 445
+def extension_available?(name)
+  query_value("SELECT true FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + extension_enabled?(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 449
+def extension_enabled?(name)
+  query_value("SELECT installed_version IS NOT NULL FROM pg_available_extensions WHERE name = #{quote(name)}", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + extensions() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 453
+def extensions
+  exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
+end
+
+
+ +
+ +
+

+ + index_algorithms() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 252
+def index_algorithms
+  { concurrently: "CONCURRENTLY" }
+end
+
+
+ +
+ +
+

+ + max_identifier_length() + +

+ + +
+

Returns the configured supported identifier length supported by PostgreSQL

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 490
+def max_identifier_length
+  @max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
+end
+
+
+ +
+ +
+

+ + reconnect!() + +

+ + +
+

Close then reopen the connection.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 322
+def reconnect!
+  @lock.synchronize do
+    super
+    @connection.reset
+    configure_connection
+    reload_type_map
+  rescue PG::ConnectionBad
+    connect
+  end
+end
+
+
+ +
+ +
+

+ + reset!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 333
+def reset!
+  @lock.synchronize do
+    clear_cache!
+    reset_transaction
+    unless @connection.transaction_status == ::PG::PQTRANS_IDLE
+      @connection.query "ROLLBACK"
+    end
+    @connection.query "DISCARD ALL"
+    configure_connection
+  end
+end
+
+
+ +
+ +
+

+ + session_auth=(user) + +

+ + +
+

Set the authorized user for this session

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 495
+def session_auth=(user)
+  clear_cache!
+  execute("SET SESSION AUTHORIZATION #{user}")
+end
+
+
+ +
+ +
+

+ + set_standard_conforming_strings() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 372
+def set_standard_conforming_strings
+  execute("SET standard_conforming_strings = on", "SCHEMA")
+end
+
+
+ +
+ +
+

+ + supports_advisory_locks?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 380
+def supports_advisory_locks?
+  true
+end
+
+
+ +
+ +
+

+ + supports_bulk_alter?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 177
+def supports_bulk_alter?
+  true
+end
+
+
+ +
+ +
+

+ + supports_check_constraints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 205
+def supports_check_constraints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_comments?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 229
+def supports_comments?
+  true
+end
+
+
+ +
+ +
+

+ + supports_common_table_expressions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 411
+def supports_common_table_expressions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_datetime_with_precision?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 221
+def supports_datetime_with_precision?
+  true
+end
+
+
+ +
+ +
+

+ + supports_ddl_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 376
+def supports_ddl_transactions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_deferrable_constraints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 213
+def supports_deferrable_constraints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_explain?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 384
+def supports_explain?
+  true
+end
+
+
+ +
+ +
+

+ + supports_expression_index?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 193
+def supports_expression_index?
+  true
+end
+
+
+ +
+ +
+

+ + supports_extensions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 388
+def supports_extensions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_foreign_keys?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 201
+def supports_foreign_keys?
+  true
+end
+
+
+ +
+ +
+

+ + supports_foreign_tables?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 396
+def supports_foreign_tables?
+  true
+end
+
+
+ +
+ +
+

+ + supports_index_sort_order?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 181
+def supports_index_sort_order?
+  true
+end
+
+
+ +
+ +
+

+ + supports_insert_conflict_target?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_insert_on_conflict?() + +

+ + +
+ +
+ + + + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 241
+def supports_insert_on_conflict?
+  database_version >= 90500 # >= 9.5
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_skip?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_insert_on_duplicate_update?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_insert_returning?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 237
+def supports_insert_returning?
+  true
+end
+
+
+ +
+ +
+

+ + supports_json?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 225
+def supports_json?
+  true
+end
+
+
+ +
+ +
+

+ + supports_lazy_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 415
+def supports_lazy_transactions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_materialized_views?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 392
+def supports_materialized_views?
+  true
+end
+
+
+ +
+ +
+

+ + supports_optimizer_hints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 404
+def supports_optimizer_hints?
+  unless defined?(@has_pg_hint_plan)
+    @has_pg_hint_plan = extension_available?("pg_hint_plan")
+  end
+  @has_pg_hint_plan
+end
+
+
+ +
+ +
+

+ + supports_partial_index?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 189
+def supports_partial_index?
+  true
+end
+
+
+ +
+ +
+

+ + supports_partitioned_indexes?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 185
+def supports_partitioned_indexes?
+  database_version >= 110_000 # >= 11.0
+end
+
+
+ +
+ +
+

+ + supports_pgcrypto_uuid?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 400
+def supports_pgcrypto_uuid?
+  database_version >= 90400 # >= 9.4
+end
+
+
+ +
+ +
+

+ + supports_savepoints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 233
+def supports_savepoints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_transaction_isolation?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 197
+def supports_transaction_isolation?
+  true
+end
+
+
+ +
+ +
+

+ + supports_validate_constraints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 209
+def supports_validate_constraints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_views?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 217
+def supports_views?
+  true
+end
+
+
+ +
+ +
+

+ + supports_virtual_columns?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 248
+def supports_virtual_columns?
+  database_version >= 120_000 # >= 12.0
+end
+
+
+ +
+ +
+

+ + use_insert_returning?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb, line 500
+def use_insert_returning?
+  @use_insert_returning
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache.html new file mode 100644 index 0000000000..e8da4c4be8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache.html @@ -0,0 +1,447 @@ +--- +title: ActiveRecord::ConnectionAdapters::QueryCache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + query_cache
+ [R] + query_cache_enabled
+ + + + +

Class Public methods

+ +
+

+ + dirties_query_cache(base, *method_names) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 17
+        def dirties_query_cache(base, *method_names)
+          method_names.each do |method_name|
+            base.class_eval <<-end_code, __FILE__, __LINE__ + 1
+              def #{method_name}(*)
+                ActiveRecord::Base.clear_query_caches_for_current_thread
+                super
+              end
+            end_code
+          end
+        end
+
+
+ +
+ +
+

+ + new(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 52
+def initialize(*)
+  super
+  @query_cache         = Hash.new { |h, sql| h[sql] = {} }
+  @query_cache_enabled = false
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cache() + +

+ + +
+

Enable the query cache within the block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 59
+def cache
+  old, @query_cache_enabled = @query_cache_enabled, true
+  yield
+ensure
+  @query_cache_enabled = old
+  clear_query_cache unless @query_cache_enabled
+end
+
+
+ +
+ +
+

+ + clear_query_cache() + +

+ + +
+

Clears the query cache.

+ +

One reason you may wish to call this method explicitly is between queries that ask the database to randomize results. Otherwise the cache would see the same SQL query and repeatedly return the same result each time, silently undermining the randomness you were expecting.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 90
+def clear_query_cache
+  @lock.synchronize do
+    @query_cache.clear
+  end
+end
+
+
+ +
+ +
+

+ + disable_query_cache!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 71
+def disable_query_cache!
+  @query_cache_enabled = false
+  clear_query_cache
+end
+
+
+ +
+ +
+

+ + enable_query_cache!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 67
+def enable_query_cache!
+  @query_cache_enabled = true
+end
+
+
+ +
+ +
+

+ + select_all(arel, name = nil, binds = [], preparable: nil, async: false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 96
+def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
+  arel = arel_from_relation(arel)
+
+  # If arel is locked this is a SELECT ... FOR UPDATE or somesuch.
+  # Such queries should not be cached.
+  if @query_cache_enabled && !(arel.respond_to?(:locked) && arel.locked)
+    sql, binds, preparable = to_sql_and_binds(arel, binds, preparable)
+
+    if async
+      lookup_sql_cache(sql, name, binds) || super(sql, name, binds, preparable: preparable, async: async)
+    else
+      cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable, async: async) }
+    end
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + uncached() + +

+ + +
+

Disable the query cache within the block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 77
+def uncached
+  old, @query_cache_enabled = @query_cache_enabled, false
+  yield
+ensure
+  @query_cache_enabled = old
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache/ConnectionPoolConfiguration.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache/ConnectionPoolConfiguration.html new file mode 100644 index 0000000000..7d723f6b19 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/QueryCache/ConnectionPoolConfiguration.html @@ -0,0 +1,224 @@ +--- +title: ActiveRecord::ConnectionAdapters::QueryCache::ConnectionPoolConfiguration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 30
+def initialize(*)
+  super
+  @query_cache_enabled = Concurrent::Map.new { false }
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + disable_query_cache!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 40
+def disable_query_cache!
+  @query_cache_enabled.delete connection_cache_key(current_thread)
+  connection.disable_query_cache! if active_connection?
+end
+
+
+ +
+ +
+

+ + enable_query_cache!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 35
+def enable_query_cache!
+  @query_cache_enabled[connection_cache_key(current_thread)] = true
+  connection.enable_query_cache! if active_connection?
+end
+
+
+ +
+ +
+

+ + query_cache_enabled() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb, line 45
+def query_cache_enabled
+  @query_cache_enabled[connection_cache_key(current_thread)]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Quoting.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Quoting.html new file mode 100644 index 0000000000..d7018f23de --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Quoting.html @@ -0,0 +1,572 @@ +--- +title: ActiveRecord::ConnectionAdapters::Quoting +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + quote(value) + +

+ + +
+

Quotes the column value to help prevent SQL injection attacks.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 11
+def quote(value)
+  case value
+  when String, Symbol, ActiveSupport::Multibyte::Chars
+    "'#{quote_string(value.to_s)}'"
+  when true       then quoted_true
+  when false      then quoted_false
+  when nil        then "NULL"
+  # BigDecimals need to be put in a non-normalized form and quoted.
+  when BigDecimal then value.to_s("F")
+  when Numeric, ActiveSupport::Duration then value.to_s
+  when Type::Binary::Data then quoted_binary(value)
+  when Type::Time::Value then "'#{quoted_time(value)}'"
+  when Date, Time then "'#{quoted_date(value)}'"
+  when Class      then "'#{value}'"
+  else raise TypeError, "can't quote #{value.class.name}"
+  end
+end
+
+
+ +
+ +
+

+ + quote_bound_value(value) + +

+ + +
+

Quote a value to be used as a bound parameter of unknown type. For example, MySQL might perform dangerous castings when comparing a string to a number, so this method will cast numbers to string.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 50
+def quote_bound_value(value)
+  quote(value)
+end
+
+
+ +
+ +
+

+ + quote_column_name(column_name) + +

+ + +
+

Quotes the column name. Defaults to no quoting.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 74
+def quote_column_name(column_name)
+  column_name.to_s
+end
+
+
+ +
+ +
+

+ + quote_string(s) + +

+ + +
+

Quotes a string, escaping any ‘ (single quote) and \ (backslash) characters.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 69
+def quote_string(s)
+  s.gsub("\\", '\&\&').gsub("'", "''") # ' (for ruby-mode)
+end
+
+
+ +
+ +
+

+ + quote_table_name(table_name) + +

+ + +
+

Quotes the table name. Defaults to column name quoting.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 79
+def quote_table_name(table_name)
+  quote_column_name(table_name)
+end
+
+
+ +
+ +
+

+ + quote_table_name_for_assignment(table, attr) + +

+ + +
+

Override to return the quoted table name for assignment. Defaults to table quoting.

+ +

This works for mysql2 where table.column can be used to resolve ambiguity.

+ +

We override this in the sqlite3 and postgresql adapters to use only the column name (as per syntax requirements).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 91
+def quote_table_name_for_assignment(table, attr)
+  quote_table_name("#{table}.#{attr}")
+end
+
+
+ +
+ +
+

+ + quoted_date(value) + +

+ + +
+

Quote date/time values for use in SQL input. Includes microseconds if the value is a Time responding to usec.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 122
+def quoted_date(value)
+  if value.acts_like?(:time)
+    if ActiveRecord.default_timezone == :utc
+      value = value.getutc if !value.utc?
+    else
+      value = value.getlocal
+    end
+  end
+
+  result = value.to_fs(:db)
+  if value.respond_to?(:usec) && value.usec > 0
+    result << "." << sprintf("%06d", value.usec)
+  else
+    result
+  end
+end
+
+
+ +
+ +
+

+ + quoted_false() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 112
+def quoted_false
+  "FALSE"
+end
+
+
+ +
+ +
+

+ + quoted_true() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 104
+def quoted_true
+  "TRUE"
+end
+
+
+ +
+ +
+

+ + type_cast(value) + +

+ + +
+

Cast a value to a type that the database understands. For example, SQLite does not understand dates, so this method will convert a Date to a String.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 32
+def type_cast(value)
+  case value
+  when Symbol, ActiveSupport::Multibyte::Chars, Type::Binary::Data
+    value.to_s
+  when true       then unquoted_true
+  when false      then unquoted_false
+  # BigDecimals need to be put in a non-normalized form and quoted.
+  when BigDecimal then value.to_s("F")
+  when nil, Numeric, String then value
+  when Type::Time::Value then quoted_time(value)
+  when Date, Time then quoted_date(value)
+  else raise TypeError, "can't cast #{value.class.name}"
+  end
+end
+
+
+ +
+ +
+

+ + unquoted_false() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 116
+def unquoted_false
+  false
+end
+
+
+ +
+ +
+

+ + unquoted_true() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/quoting.rb, line 108
+def unquoted_true
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/RealTransaction.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/RealTransaction.html new file mode 100644 index 0000000000..6f499b38de --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/RealTransaction.html @@ -0,0 +1,193 @@ +--- +title: ActiveRecord::ConnectionAdapters::RealTransaction +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + commit() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 218
+def commit
+  connection.commit_db_transaction if materialized?
+  @state.full_commit!
+end
+
+
+ +
+ +
+

+ + materialize!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 203
+def materialize!
+  if isolation_level
+    connection.begin_isolated_db_transaction(isolation_level)
+  else
+    connection.begin_db_transaction
+  end
+
+  super
+end
+
+
+ +
+ +
+

+ + rollback() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 213
+def rollback
+  connection.rollback_db_transaction if materialized?
+  @state.full_rollback!
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3.html new file mode 100644 index 0000000000..fd5f19d4a5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3.html @@ -0,0 +1,88 @@ +--- +title: ActiveRecord::ConnectionAdapters::SQLite3 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/DatabaseStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/DatabaseStatements.html new file mode 100644 index 0000000000..5055738d13 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/DatabaseStatements.html @@ -0,0 +1,141 @@ +--- +title: ActiveRecord::ConnectionAdapters::SQLite3::DatabaseStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + explain(arel, binds = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb, line 18
+def explain(arel, binds = [])
+  sql = "EXPLAIN QUERY PLAN #{to_sql(arel, binds)}"
+  SQLite3::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", []))
+end
+
+
+ +
+ +
+

+ + high_precision_current_timestamp() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3/database_statements.rb, line 107
+def high_precision_current_timestamp
+  HIGH_PRECISION_CURRENT_TIMESTAMP
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/TableDefinition.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/TableDefinition.html new file mode 100644 index 0000000000..202d5fd693 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3/TableDefinition.html @@ -0,0 +1,180 @@ +--- +title: ActiveRecord::ConnectionAdapters::SQLite3::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + belongs_to(*args, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: references +
+ + + +
+ +
+

+ + change_column(column_name, type, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb, line 7
+def change_column(column_name, type, **options)
+  name = column_name.to_s
+  @columns_hash[name] = nil
+  column(name, type, **options)
+end
+
+
+ +
+ +
+

+ + references(*args, **options) + +

+ + +
+ +
+ + + +
+ Also aliased as: belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb, line 13
+def references(*args, **options)
+  super(*args, type: :integer, **options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html new file mode 100644 index 0000000000..5cb73a3ff9 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html @@ -0,0 +1,1253 @@ +--- +title: ActiveRecord::ConnectionAdapters::SQLite3Adapter +layout: default +--- +
+ +
+
+ +
+ +

The SQLite3 adapter works with the sqlite3-ruby drivers (available as gem from rubygems.org/gems/sqlite3).

+ +

Options:

+
  • +

    :database - Path to the database file.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ADAPTER_NAME="SQLite"
 
COLLATE_REGEX=/.*"(\w+)".*collate\s+"(\w+)".*/i.freeze
 
NATIVE_DATABASE_TYPES={ +primary_key: "integer PRIMARY KEY AUTOINCREMENT NOT NULL", +string: { name: "varchar" }, +text: { name: "text" }, +integer: { name: "integer" }, +float: { name: "float" }, +decimal: { name: "decimal" }, +datetime: { name: "datetime" }, +time: { name: "time" }, +date: { name: "date" }, +binary: { name: "blob" }, +boolean: { name: "boolean" }, +json: { name: "json" }, +}
 
TYPE_MAP=Type::TypeMap.new.tap { |m| initialize_type_map(m) }
 
+ + + + + + +

Class Public methods

+ +
+

+ + database_exists?(config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 92
+def self.database_exists?(config)
+  config = config.symbolize_keys
+  if config[:database] == ":memory:"
+    true
+  else
+    database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
+    File.exist?(database_file)
+  end
+end
+
+
+ +
+ +
+

+ + new(connection, logger, connection_options, config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 86
+def initialize(connection, logger, connection_options, config)
+  @memory_database = config[:database] == ":memory:"
+  super(connection, logger, config)
+  configure_connection
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + active?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 161
+def active?
+  !@connection.closed?
+end
+
+
+ +
+ +
+

+ + disconnect!() + +

+ + +
+

Disconnects from the database if already connected. Otherwise, this method does nothing.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 172
+def disconnect!
+  super
+  @connection.close rescue nil
+end
+
+
+ +
+ +
+

+ + encoding() + +

+ + +
+

Returns the current database encoding format as a string, e.g. ‘UTF-8’

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 186
+def encoding
+  @connection.encoding.to_s
+end
+
+
+ +
+ +
+

+ + foreign_keys(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 305
+def foreign_keys(table_name)
+  fk_info = exec_query("PRAGMA foreign_key_list(#{quote(table_name)})", "SCHEMA")
+  fk_info.map do |row|
+    options = {
+      column: row["from"],
+      primary_key: row["to"],
+      on_delete: extract_foreign_key_action(row["on_delete"]),
+      on_update: extract_foreign_key_action(row["on_update"])
+    }
+    ForeignKeyDefinition.new(table_name, row["table"], options)
+  end
+end
+
+
+ +
+ +
+

+ + reconnect!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 165
+def reconnect!
+  super
+  connect if @connection.closed?
+end
+
+
+ +
+ +
+

+ + rename_table(table_name, new_name) + +

+ + +
+

Renames a table.

+ +

Example:

+ +
rename_table('octopuses', 'octopi')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 237
+def rename_table(table_name, new_name)
+  schema_cache.clear_data_source_cache!(table_name.to_s)
+  schema_cache.clear_data_source_cache!(new_name.to_s)
+  exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
+  rename_table_indexes(table_name, new_name)
+end
+
+
+ +
+ +
+

+ + requires_reloading?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 122
+def requires_reloading?
+  true
+end
+
+
+ +
+ +
+

+ + supports_check_constraints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 130
+def supports_check_constraints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_common_table_expressions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 146
+def supports_common_table_expressions?
+  database_version >= "3.8.3"
+end
+
+
+ +
+ +
+

+ + supports_concurrent_connections?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 157
+def supports_concurrent_connections?
+  !@memory_database
+end
+
+
+ +
+ +
+

+ + supports_datetime_with_precision?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 138
+def supports_datetime_with_precision?
+  true
+end
+
+
+ +
+ +
+

+ + supports_ddl_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 102
+def supports_ddl_transactions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_explain?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 190
+def supports_explain?
+  true
+end
+
+
+ +
+ +
+

+ + supports_expression_index?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 118
+def supports_expression_index?
+  database_version >= "3.9.0"
+end
+
+
+ +
+ +
+

+ + supports_foreign_keys?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 126
+def supports_foreign_keys?
+  true
+end
+
+
+ +
+ +
+

+ + supports_index_sort_order?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 177
+def supports_index_sort_order?
+  true
+end
+
+
+ +
+ +
+

+ + supports_insert_conflict_target?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_insert_on_conflict?() + +

+ + +
+ +
+ + + + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 150
+def supports_insert_on_conflict?
+  database_version >= "3.24.0"
+end
+
+
+ +
+ +
+

+ + supports_insert_on_duplicate_skip?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_insert_on_duplicate_update?() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + supports_json?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 142
+def supports_json?
+  true
+end
+
+
+ +
+ +
+

+ + supports_lazy_transactions?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 194
+def supports_lazy_transactions?
+  true
+end
+
+
+ +
+ +
+

+ + supports_partial_index?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 114
+def supports_partial_index?
+  true
+end
+
+
+ +
+ +
+

+ + supports_savepoints?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 106
+def supports_savepoints?
+  true
+end
+
+
+ +
+ +
+

+ + supports_transaction_isolation?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 110
+def supports_transaction_isolation?
+  true
+end
+
+
+ +
+ +
+

+ + supports_views?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb, line 134
+def supports_views?
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SavepointTransaction.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SavepointTransaction.html new file mode 100644 index 0000000000..310e94f2f8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SavepointTransaction.html @@ -0,0 +1,275 @@ +--- +title: ActiveRecord::ConnectionAdapters::SavepointTransaction +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(connection, savepoint_name, parent_transaction, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 172
+def initialize(connection, savepoint_name, parent_transaction, **options)
+  super(connection, **options)
+
+  parent_transaction.state.add_child(@state)
+
+  if isolation_level
+    raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
+  end
+
+  @savepoint_name = savepoint_name
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + commit() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 194
+def commit
+  connection.release_savepoint(savepoint_name) if materialized?
+  @state.commit!
+end
+
+
+ +
+ +
+

+ + full_rollback?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 199
+def full_rollback?; false; end
+
+
+ +
+ +
+

+ + materialize!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 184
+def materialize!
+  connection.create_savepoint(savepoint_name)
+  super
+end
+
+
+ +
+ +
+

+ + rollback() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 189
+def rollback
+  connection.rollback_to_savepoint(savepoint_name) if materialized?
+  @state.rollback!
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Savepoints.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Savepoints.html new file mode 100644 index 0000000000..47cf3086a6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Savepoints.html @@ -0,0 +1,218 @@ +--- +title: ActiveRecord::ConnectionAdapters::Savepoints +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create_savepoint(name = current_savepoint_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb, line 10
+def create_savepoint(name = current_savepoint_name)
+  execute("SAVEPOINT #{name}", "TRANSACTION")
+end
+
+
+ +
+ +
+

+ + current_savepoint_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb, line 6
+def current_savepoint_name
+  current_transaction.savepoint_name
+end
+
+
+ +
+ +
+

+ + exec_rollback_to_savepoint(name = current_savepoint_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb, line 14
+def exec_rollback_to_savepoint(name = current_savepoint_name)
+  execute("ROLLBACK TO SAVEPOINT #{name}", "TRANSACTION")
+end
+
+
+ +
+ +
+

+ + release_savepoint(name = current_savepoint_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/savepoints.rb, line 18
+def release_savepoint(name = current_savepoint_name)
+  execute("RELEASE SAVEPOINT #{name}", "TRANSACTION")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaCache.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaCache.html new file mode 100644 index 0000000000..3e3101dd1e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaCache.html @@ -0,0 +1,921 @@ +--- +title: ActiveRecord::ConnectionAdapters::SchemaCache +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + connection
+ [R] + version
+ + + + +

Class Public methods

+ +
+

+ + load_from(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 8
+def self.load_from(filename)
+  return unless File.file?(filename)
+
+  read(filename) do |file|
+    if filename.include?(".dump")
+      Marshal.load(file)
+    else
+      if YAML.respond_to?(:unsafe_load)
+        YAML.unsafe_load(file)
+      else
+        YAML.load(file)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + new(conn) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 38
+def initialize(conn)
+  @connection = conn
+
+  @columns      = {}
+  @columns_hash = {}
+  @primary_keys = {}
+  @data_sources = {}
+  @indexes      = {}
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add(table_name) + +

+ + +
+

Add internal cache for table with table_name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 97
+def add(table_name)
+  if data_source_exists?(table_name)
+    primary_keys(table_name)
+    columns(table_name)
+    columns_hash(table_name)
+    indexes(table_name)
+  end
+end
+
+
+ +
+ +
+

+ + clear!() + +

+ + +
+

Clears out internal caches

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 149
+def clear!
+  @columns.clear
+  @columns_hash.clear
+  @primary_keys.clear
+  @data_sources.clear
+  @indexes.clear
+  @version = nil
+  @database_version = nil
+end
+
+
+ +
+ +
+

+ + clear_data_source_cache!(name) + +

+ + +
+

Clear out internal caches for the data source name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 164
+def clear_data_source_cache!(name)
+  @columns.delete name
+  @columns_hash.delete name
+  @primary_keys.delete name
+  @data_sources.delete name
+  @indexes.delete name
+end
+
+
+ +
+ +
+

+ + columns(table_name) + +

+ + +
+

Get the columns for a table

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 111
+def columns(table_name)
+  if ignored_table?(table_name)
+    raise ActiveRecord::StatementInvalid, "Table '#{table_name}' doesn't exist"
+  end
+
+  @columns.fetch(table_name) do
+    @columns[deep_deduplicate(table_name)] = deep_deduplicate(connection.columns(table_name))
+  end
+end
+
+
+ +
+ +
+

+ + columns_hash(table_name) + +

+ + +
+

Get the columns for a table as a hash, key is the column name value is the column object.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 123
+def columns_hash(table_name)
+  @columns_hash.fetch(table_name) do
+    @columns_hash[deep_deduplicate(table_name)] = columns(table_name).index_by(&:name).freeze
+  end
+end
+
+
+ +
+ +
+

+ + columns_hash?(table_name) + +

+ + +
+

Checks whether the columns hash is already cached for a table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 130
+def columns_hash?(table_name)
+  @columns_hash.key?(table_name)
+end
+
+
+ +
+ +
+

+ + data_source_exists?(name) + +

+ + +
+

A cached lookup for table existence.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 88
+def data_source_exists?(name)
+  return if ignored_table?(name)
+  prepare_data_sources if @data_sources.empty?
+  return @data_sources[name] if @data_sources.key? name
+
+  @data_sources[deep_deduplicate(name)] = connection.data_source_exists?(name)
+end
+
+
+ +
+ +
+

+ + data_sources(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 106
+def data_sources(name)
+  @data_sources[name]
+end
+
+
+ +
+ +
+

+ + dump_to(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 172
+def dump_to(filename)
+  clear!
+  tables_to_cache.each { |table| add(table) }
+  open(filename) { |f|
+    if filename.include?(".dump")
+      f.write(Marshal.dump(self))
+    else
+      f.write(YAML.dump(self))
+    end
+  }
+end
+
+
+ +
+ +
+

+ + encode_with(coder) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 57
+def encode_with(coder)
+  reset_version!
+
+  coder["columns"]          = @columns
+  coder["primary_keys"]     = @primary_keys
+  coder["data_sources"]     = @data_sources
+  coder["indexes"]          = @indexes
+  coder["version"]          = @version
+  coder["database_version"] = database_version
+end
+
+
+ +
+ +
+

+ + indexes(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 134
+def indexes(table_name)
+  @indexes.fetch(table_name) do
+    if data_source_exists?(table_name)
+      @indexes[deep_deduplicate(table_name)] = deep_deduplicate(connection.indexes(table_name))
+    else
+      []
+    end
+  end
+end
+
+
+ +
+ +
+

+ + init_with(coder) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 68
+def init_with(coder)
+  @columns          = coder["columns"]
+  @primary_keys     = coder["primary_keys"]
+  @data_sources     = coder["data_sources"]
+  @indexes          = coder["indexes"] || {}
+  @version          = coder["version"]
+  @database_version = coder["database_version"]
+
+  derive_columns_hash_and_deduplicate_values
+end
+
+
+ +
+ +
+

+ + initialize_dup(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 48
+def initialize_dup(other)
+  super
+  @columns      = @columns.dup
+  @columns_hash = @columns_hash.dup
+  @primary_keys = @primary_keys.dup
+  @data_sources = @data_sources.dup
+  @indexes      = @indexes.dup
+end
+
+
+ +
+ +
+

+ + marshal_dump() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 184
+def marshal_dump
+  reset_version!
+
+  [@version, @columns, {}, @primary_keys, @data_sources, @indexes, database_version]
+end
+
+
+ +
+ +
+

+ + marshal_load(array) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 190
+def marshal_load(array)
+  @version, @columns, _columns_hash, @primary_keys, @data_sources, @indexes, @database_version = array
+  @indexes ||= {}
+
+  derive_columns_hash_and_deduplicate_values
+end
+
+
+ +
+ +
+

+ + primary_keys(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 79
+def primary_keys(table_name)
+  @primary_keys.fetch(table_name) do
+    if data_source_exists?(table_name)
+      @primary_keys[deep_deduplicate(table_name)] = deep_deduplicate(connection.primary_key(table_name))
+    end
+  end
+end
+
+
+ +
+ +
+

+ + size() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/schema_cache.rb, line 159
+def size
+  [@columns, @columns_hash, @primary_keys, @data_sources].sum(&:size)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html new file mode 100644 index 0000000000..8f9ab51fca --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html @@ -0,0 +1,3013 @@ +--- +title: ActiveRecord::ConnectionAdapters::SchemaStatements +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + add_belongs_to(table_name, ref_name, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: add_reference +
+ + + +
+ +
+

+ + add_check_constraint(table_name, expression, **options) + +

+ + +
+

Adds a new check constraint to the table. expression is a String representation of verifiable boolean condition.

+ +
add_check_constraint :products, "price > 0", name: "price_check"
+
+ +

generates:

+ +
ALTER TABLE "products" ADD CONSTRAINT price_check CHECK (price > 0)
+
+ +

The options hash can include the following keys:

+
:name +
+

The constraint name. Defaults to chk_rails_<identifier>.

+
:validate +
+

(PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to true.

+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1186
+def add_check_constraint(table_name, expression, **options)
+  return unless supports_check_constraints?
+
+  options = check_constraint_options(table_name, expression, options)
+  at = create_alter_table(table_name)
+  at.add_check_constraint(expression, options)
+
+  execute schema_creation.accept(at)
+end
+
+
+ +
+ +
+

+ + add_column(table_name, column_name, type, **options) + +

+ + +
+

Add a new type column named column_name to table_name.

+ +

See ActiveRecord::ConnectionAdapters::TableDefinition.column.

+ +

The type parameter is normally one of the migrations native types, which is one of the following: :primary_key, :string, :text, :integer, :bigint, :float, :decimal, :numeric, :datetime, :time, :date, :binary, :blob, :boolean.

+ +

You may use a type not in this list as long as it is supported by your database (for example, “polygon” in MySQL), but this will not be database agnostic and should usually be avoided.

+ +

Available options are (none of these exists by default):

+
  • +

    :comment - Specifies the comment for the column. This option is ignored by some backends.

    +
  • +

    :collation - Specifies the collation for a :string or :text column. If not specified, the column will have the same collation as the table.

    +
  • +

    :default - The column’s default value. Use nil for NULL.

    +
  • +

    :limit - Requests a maximum column length. This is the number of characters for a :string column and number of bytes for :text, :binary, :blob, and :integer columns. This option is ignored by some backends.

    +
  • +

    :null - Allows or disallows NULL values in the column.

    +
  • +

    :precision - Specifies the precision for the :decimal, :numeric, :datetime, and :time columns.

    +
  • +

    :scale - Specifies the scale for the :decimal and :numeric columns.

    +
  • +

    :collation - Specifies the collation for a :string or :text column. If not specified, the column will have the same collation as the table.

    +
  • +

    :comment - Specifies the comment for the column. This option is ignored by some backends.

    +
  • +

    :if_not_exists - Specifies if the column already exists to not try to re-add it. This will avoid duplicate column errors.

    +
+ +

Note: The precision is the total number of significant digits, and the scale is the number of digits that can be stored following the decimal point. For example, the number 123.45 has a precision of 5 and a scale of 2. A decimal with a precision of 5 and a scale of 2 can range from -999.99 to 999.99.

+ +

Please be aware of different RDBMS implementations behavior with :decimal columns:

+
  • +

    The SQL standard says the default scale should be 0, :scale <= :precision, and makes no comments about the requirements of :precision.

    +
  • +

    MySQL: :precision [1..63], :scale [0..30]. Default is (10,0).

    +
  • +

    PostgreSQL: :precision [1..infinity], :scale [0..infinity]. No default.

    +
  • +

    SQLite3: No restrictions on :precision and :scale, but the maximum supported :precision is 16. No default.

    +
  • +

    Oracle: :precision [1..38], :scale [-84..127]. Default is (38,0).

    +
  • +

    SqlServer: :precision [1..38], :scale [0..38]. Default (38,0).

    +
+ +

Examples

+ +
add_column(:users, :picture, :binary, limit: 2.megabytes)
+# ALTER TABLE "users" ADD "picture" blob(2097152)
+
+add_column(:articles, :status, :string, limit: 20, default: 'draft', null: false)
+# ALTER TABLE "articles" ADD "status" varchar(20) DEFAULT 'draft' NOT NULL
+
+add_column(:answers, :bill_gates_money, :decimal, precision: 15, scale: 2)
+# ALTER TABLE "answers" ADD "bill_gates_money" decimal(15,2)
+
+add_column(:measurements, :sensor_reading, :decimal, precision: 30, scale: 20)
+# ALTER TABLE "measurements" ADD "sensor_reading" decimal(30,20)
+
+# While :scale defaults to zero on most databases, it
+# probably wouldn't hurt to include it.
+add_column(:measurements, :huge_integer, :decimal, precision: 30)
+# ALTER TABLE "measurements" ADD "huge_integer" decimal(30)
+
+# Defines a column that stores an array of a type.
+add_column(:users, :skills, :text, array: true)
+# ALTER TABLE "users" ADD "skills" text[]
+
+# Defines a column with a database-specific type.
+add_column(:shapes, :triangle, 'polygon')
+# ALTER TABLE "shapes" ADD "triangle" polygon
+
+# Ignores the method call if the column exists
+add_column(:shapes, :triangle, 'polygon', if_not_exists: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 617
+def add_column(table_name, column_name, type, **options)
+  return if options[:if_not_exists] == true && column_exists?(table_name, column_name)
+
+  if supports_datetime_with_precision?
+    if type == :datetime && !options.key?(:precision)
+      options[:precision] = 6
+    end
+  end
+
+  at = create_alter_table table_name
+  at.add_column(column_name, type, **options)
+  execute schema_creation.accept at
+end
+
+
+ +
+ +
+

+ + add_foreign_key(from_table, to_table, **options) + +

+ + +
+

Adds a new foreign key. from_table is the table with the key column, to_table contains the referenced primary key.

+ +

The foreign key will be named after the following pattern: fk_rails_<identifier>. identifier is a 10 character long string which is deterministically generated from the from_table and column. A custom name can be specified with the :name option.

+ +
Creating a simple foreign key
+ +
add_foreign_key :articles, :authors
+
+ +

generates:

+ +
ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id")
+
+ +
Creating a foreign key, ignoring method call if the foreign key exists
+ +
add_foreign_key(:articles, :authors, if_not_exists: true)
+
+ +
Creating a foreign key on a specific column
+ +
add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"
+
+ +

generates:

+ +
ALTER TABLE "articles" ADD CONSTRAINT fk_rails_58ca3d3a82 FOREIGN KEY ("author_id") REFERENCES "users" ("lng_id")
+
+ +
Creating a cascading foreign key
+ +
add_foreign_key :articles, :authors, on_delete: :cascade
+
+ +

generates:

+ +
ALTER TABLE "articles" ADD CONSTRAINT fk_rails_e74ce85cbc FOREIGN KEY ("author_id") REFERENCES "authors" ("id") ON DELETE CASCADE
+
+ +

The options hash can include the following keys:

+
:column +
+

The foreign key column name on from_table. Defaults to to_table.singularize + "_id"

+
:primary_key +
+

The primary key column name on to_table. Defaults to id.

+
:name +
+

The constraint name. Defaults to fk_rails_<identifier>.

+
:on_delete +
+

Action that happens ON DELETE. Valid values are :nullify, :cascade, and :restrict

+
:on_update +
+

Action that happens ON UPDATE. Valid values are :nullify, :cascade, and :restrict

+
:if_not_exists +
+

Specifies if the foreign key already exists to not try to re-add it. This will avoid duplicate column errors.

+
:validate +
+

(PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to true.

+
:deferrable +
+

(PostgreSQL only) Specify whether or not the foreign key should be deferrable. Valid values are booleans or :deferred or :immediate to specify the default behavior. Defaults to false.

+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1086
+def add_foreign_key(from_table, to_table, **options)
+  return unless supports_foreign_keys?
+  return if options[:if_not_exists] == true && foreign_key_exists?(from_table, to_table)
+
+  options = foreign_key_options(from_table, to_table, options)
+  at = create_alter_table from_table
+  at.add_foreign_key to_table, options
+
+  execute schema_creation.accept(at)
+end
+
+
+ +
+ +
+

+ + add_index(table_name, column_name, **options) + +

+ + +
+

Adds a new index to the table. column_name can be a single Symbol, or an Array of Symbols.

+ +

The index will be named after the table and the column name(s), unless you pass :name as an option.

+ +
Creating a simple index
+ +
add_index(:suppliers, :name)
+
+ +

generates:

+ +
CREATE INDEX index_suppliers_on_name ON suppliers(name)
+
+ +
Creating a index which already exists
+ +
add_index(:suppliers, :name, if_not_exists: true)
+
+ +

generates:

+ +
CREATE INDEX IF NOT EXISTS index_suppliers_on_name ON suppliers(name)
+
+ +

Note: Not supported by MySQL.

+ +
Creating a unique index
+ +
add_index(:accounts, [:branch_id, :party_id], unique: true)
+
+ +

generates:

+ +
CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id)
+
+ +
Creating a named index
+ +
add_index(:accounts, [:branch_id, :party_id], unique: true, name: 'by_branch_party')
+
+ +

generates:

+ +
CREATE UNIQUE INDEX by_branch_party ON accounts(branch_id, party_id)
+
+ +
Creating an index with specific key length
+ +
add_index(:accounts, :name, name: 'by_name', length: 10)
+
+ +

generates:

+ +
CREATE INDEX by_name ON accounts(name(10))
+
+ +
Creating an index with specific key lengths for multiple keys
+ +
add_index(:accounts, [:name, :surname], name: 'by_name_surname', length: {name: 10, surname: 15})
+
+ +

generates:

+ +
CREATE INDEX by_name_surname ON accounts(name(10), surname(15))
+
+ +

Note: only supported by MySQL

+ +
Creating an index with a sort order (desc or asc, asc is the default)
+ +
add_index(:accounts, [:branch_id, :party_id, :surname], name: 'by_branch_desc_party', order: {branch_id: :desc, party_id: :asc})
+
+ +

generates:

+ +
CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
+
+ +

Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).

+ +
Creating a partial index
+ +
add_index(:accounts, [:branch_id, :party_id], unique: true, where: "active")
+
+ +

generates:

+ +
CREATE UNIQUE INDEX index_accounts_on_branch_id_and_party_id ON accounts(branch_id, party_id) WHERE active
+
+ +

Note: Partial indexes are only supported for PostgreSQL and SQLite.

+ +
Creating an index with a specific method
+ +
add_index(:developers, :name, using: 'btree')
+
+ +

generates:

+ +
CREATE INDEX index_developers_on_name ON developers USING btree (name) -- PostgreSQL
+CREATE INDEX index_developers_on_name USING btree ON developers (name) -- MySQL
+
+ +

Note: only supported by PostgreSQL and MySQL

+ +
Creating an index with a specific operator class
+ +
add_index(:developers, :name, using: 'gist', opclass: :gist_trgm_ops)
+# CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
+
+add_index(:developers, [:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
+# CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
+
+add_index(:developers, [:name, :city], using: 'gist', opclass: :gist_trgm_ops)
+# CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
+
+ +

Note: only supported by PostgreSQL

+ +
Creating an index with a specific type
+ +
add_index(:developers, :name, type: :fulltext)
+
+ +

generates:

+ +
CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
+
+ +

Note: only supported by MySQL.

+ +
Creating an index with a specific algorithm
+ +
add_index(:developers, :name, algorithm: :concurrently)
+# CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
+
+ +

Note: only supported by PostgreSQL.

+ +

Concurrently adding an index is not supported in a transaction.

+ +

For more information see the “Transactional Migrations” section.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 852
+def add_index(table_name, column_name, **options)
+  index, algorithm, if_not_exists = add_index_options(table_name, column_name, **options)
+
+  create_index = CreateIndexDefinition.new(index, algorithm, if_not_exists)
+  execute schema_creation.accept(create_index)
+end
+
+
+ +
+ +
+

+ + add_reference(table_name, ref_name, **options) + +

+ + +
+

Adds a reference. The reference column is a bigint by default, the :type option can be used to specify a different type. Optionally adds a _type column, if :polymorphic option is provided. add_reference and add_belongs_to are acceptable.

+ +

The options hash can include the following keys:

+
:type +
+

The reference column type. Defaults to :bigint.

+
:index +
+

Add an appropriate index. Defaults to true. See add_index for usage of this option.

+
:foreign_key +
+

Add an appropriate foreign key constraint. Defaults to false, pass true to add. In case the join table can’t be inferred from the association pass :to_table with the appropriate table name.

+
:polymorphic +
+

Whether an additional _type column should be added. Defaults to false.

+
:null +
+

Whether the column allows nulls. Defaults to true.

+
+ +
Create a user_id bigint column without an index
+ +
add_reference(:products, :user, index: false)
+
+ +
Create a user_id string column
+ +
add_reference(:products, :user, type: :string)
+
+ +
Create supplier_id, supplier_type columns
+ +
add_reference(:products, :supplier, polymorphic: true)
+
+ +
Create a supplier_id column with a unique index
+ +
add_reference(:products, :supplier, index: { unique: true })
+
+ +
Create a supplier_id column with a named index
+ +
add_reference(:products, :supplier, index: { name: "my_supplier_index" })
+
+ +
Create a supplier_id column and appropriate foreign key
+ +
add_reference(:products, :supplier, foreign_key: true)
+
+ +
Create a supplier_id column and a foreign key to the firms table
+ +
add_reference(:products, :supplier, foreign_key: { to_table: :firms })
+
+
+ + + +
+ Also aliased as: add_belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 989
+def add_reference(table_name, ref_name, **options)
+  ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
+end
+
+
+ +
+ +
+

+ + add_timestamps(table_name, **options) + +

+ + +
+

Adds timestamps (created_at and updated_at) columns to table_name. Additional options (like :null) are forwarded to add_column.

+ +
add_timestamps(:suppliers, null: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1317
+def add_timestamps(table_name, **options)
+  options[:null] = false if options[:null].nil?
+
+  if !options.key?(:precision) && supports_datetime_with_precision?
+    options[:precision] = 6
+  end
+
+  add_column table_name, :created_at, :datetime, **options
+  add_column table_name, :updated_at, :datetime, **options
+end
+
+
+ +
+ +
+

+ + assume_migrated_upto_version(version) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1229
+def assume_migrated_upto_version(version)
+  version = version.to_i
+  sm_table = quote_table_name(schema_migration.table_name)
+
+  migrated = migration_context.get_all_versions
+  versions = migration_context.migrations.map(&:version)
+
+  unless migrated.include?(version)
+    execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
+  end
+
+  inserting = (versions - migrated).select { |v| v < version }
+  if inserting.any?
+    if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
+      raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
+    end
+    execute insert_versions_sql(inserting)
+  end
+end
+
+
+ +
+ +
+

+ + change_column(table_name, column_name, type, **options) + +

+ + +
+

Changes the column’s definition according to the new options. See TableDefinition#column for details of the options you can use.

+ +
change_column(:suppliers, :name, :string, limit: 80)
+change_column(:accounts, :description, :text)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 680
+def change_column(table_name, column_name, type, **options)
+  raise NotImplementedError, "change_column is not implemented"
+end
+
+
+ +
+ +
+

+ + change_column_comment(table_name, column_name, comment_or_changes) + +

+ + +
+

Changes the comment for a column or removes it if nil.

+ +

Passing a hash containing :from and :to will make this change reversible in migration:

+ +
change_column_comment(:posts, :state, from: "old_comment", to: "new_comment")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1399
+def change_column_comment(table_name, column_name, comment_or_changes)
+  raise NotImplementedError, "#{self.class} does not support changing column comments"
+end
+
+
+ +
+ +
+

+ + change_column_default(table_name, column_name, default_or_changes) + +

+ + +
+

Sets a new default value for a column:

+ +
change_column_default(:suppliers, :qualification, 'new')
+change_column_default(:accounts, :authorized, 1)
+
+ +

Setting the default to nil effectively drops the default:

+ +
change_column_default(:users, :email, nil)
+
+ +

Passing a hash containing :from and :to will make this change reversible in migration:

+ +
change_column_default(:posts, :state, from: nil, to: "draft")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 698
+def change_column_default(table_name, column_name, default_or_changes)
+  raise NotImplementedError, "change_column_default is not implemented"
+end
+
+
+ +
+ +
+

+ + change_column_null(table_name, column_name, null, default = nil) + +

+ + +
+

Sets or removes a NOT NULL constraint on a column. The null flag indicates whether the value can be NULL. For example

+ +
change_column_null(:users, :nickname, false)
+
+ +

says nicknames cannot be NULL (adds the constraint), whereas

+ +
change_column_null(:users, :nickname, true)
+
+ +

allows them to be NULL (drops the constraint).

+ +

The method accepts an optional fourth argument to replace existing NULLs with some other value. Use that one when enabling the constraint if needed, since otherwise those rows would not be valid.

+ +

Please note the fourth argument does not set a column’s default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 718
+def change_column_null(table_name, column_name, null, default = nil)
+  raise NotImplementedError, "change_column_null is not implemented"
+end
+
+
+ +
+ +
+

+ + change_table(table_name, **options) + +

+ + +
+

A block for changing columns in table.

+ +
# change_table() yields a Table instance
+change_table(:suppliers) do |t|
+  t.column :name, :string, limit: 60
+  # Other column alterations here
+end
+
+ +

The options hash can include the following keys:

+
:bulk +
+

Set this to true to make this a bulk alter query, such as

+ +
ALTER TABLE `users` ADD COLUMN age INT, ADD COLUMN birthdate DATETIME ...
+
+ +

Defaults to false.

+ +

Only supported on the MySQL and PostgreSQL adapter, ignored elsewhere.

+
+ +
Add a column
+ +
change_table(:suppliers) do |t|
+  t.column :name, :string, limit: 60
+end
+
+ +
Change type of a column
+ +
change_table(:suppliers) do |t|
+  t.change :metadata, :json
+end
+
+ +
Add 2 integer columns
+ +
change_table(:suppliers) do |t|
+  t.integer :width, :height, null: false, default: 0
+end
+
+ +
Add created_at/updated_at columns
+ +
change_table(:suppliers) do |t|
+  t.timestamps
+end
+
+ +
Add a foreign key column
+ +
change_table(:suppliers) do |t|
+  t.references :company
+end
+
+ +

Creates a company_id(bigint) column.

+ +
Add a polymorphic foreign key column
+ +
change_table(:suppliers) do |t|
+  t.belongs_to :company, polymorphic: true
+end
+
+ +

Creates company_type(varchar) and company_id(bigint) columns.

+ +
Remove a column
+ +
change_table(:suppliers) do |t|
+  t.remove :company
+end
+
+ +
Remove several columns
+ +
change_table(:suppliers) do |t|
+  t.remove :company_id
+  t.remove :width, :height
+end
+
+ +
Remove an index
+ +
change_table(:suppliers) do |t|
+  t.remove_index :company_id
+end
+
+ +

See also Table for details on all of the various column transformations.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 488
+def change_table(table_name, **options)
+  if supports_bulk_alter? && options[:bulk]
+    recorder = ActiveRecord::Migration::CommandRecorder.new(self)
+    yield update_table_definition(table_name, recorder)
+    bulk_change_table(table_name, recorder.commands)
+  else
+    yield update_table_definition(table_name, self)
+  end
+end
+
+
+ +
+ +
+

+ + change_table_comment(table_name, comment_or_changes) + +

+ + +
+

Changes the comment for a table or removes it if nil.

+ +

Passing a hash containing :from and :to will make this change reversible in migration:

+ +
change_table_comment(:posts, from: "old_comment", to: "new_comment")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1389
+def change_table_comment(table_name, comment_or_changes)
+  raise NotImplementedError, "#{self.class} does not support changing table comments"
+end
+
+
+ +
+ +
+

+ + check_constraints(table_name) + +

+ + +
+

Returns an array of check constraints for the given table. The check constraints are represented as CheckConstraintDefinition objects.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1168
+def check_constraints(table_name)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + column_exists?(table_name, column_name, type = nil, **options) + +

+ + +
+

Checks to see if a column exists in a given table.

+ +
# Check a column exists
+column_exists?(:suppliers, :name)
+
+# Check a column exists of a particular type
+#
+# This works for standard non-casted types (eg. string) but is unreliable
+# for types that may get cast to something else (eg. char, bigint).
+column_exists?(:suppliers, :name, :string)
+
+# Check a column exists with a specific definition
+column_exists?(:suppliers, :name, :string, limit: 100)
+column_exists?(:suppliers, :name, :string, default: 'default')
+column_exists?(:suppliers, :name, :string, null: false)
+column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 139
+def column_exists?(table_name, column_name, type = nil, **options)
+  column_name = column_name.to_s
+  checks = []
+  checks << lambda { |c| c.name == column_name }
+  checks << lambda { |c| c.type == type.to_sym rescue nil } if type
+  column_options_keys.each do |attr|
+    checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
+  end
+
+  columns(table_name).any? { |c| checks.all? { |check| check[c] } }
+end
+
+
+ +
+ +
+

+ + columns(table_name) + +

+ + +
+

Returns an array of Column objects for the table specified by table_name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 115
+def columns(table_name)
+  table_name = table_name.to_s
+  column_definitions(table_name).map do |field|
+    new_column_from_field(table_name, field)
+  end
+end
+
+
+ +
+ +
+

+ + create_join_table(table_1, table_2, column_options: {}, **options) + +

+ + +
+

Creates a new join table with the name created using the lexical order of the first two arguments. These arguments can be a String or a Symbol.

+ +
# Creates a table called 'assemblies_parts' with no id.
+create_join_table(:assemblies, :parts)
+
+ +

You can pass an options hash which can include the following keys:

+
:table_name +
+

Sets the table name, overriding the default.

+
:column_options +
+

Any extra options you want appended to the columns definition.

+
:options +
+

Any extra options you want appended to the table definition.

+
:temporary +
+

Make a temporary table.

+
:force +
+

Set to true to drop the table before creating it. Defaults to false.

+
+ +

Note that create_join_table does not create any indices by default; you can use its block form to do so yourself:

+ +
create_join_table :products, :categories do |t|
+  t.index :product_id
+  t.index :category_id
+end
+
+ +
Add a backend specific option to the generated SQL (MySQL)
+ +
create_join_table(:assemblies, :parts, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
+
+ +

generates:

+ +
CREATE TABLE assemblies_parts (
+  assembly_id bigint NOT NULL,
+  part_id bigint NOT NULL,
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 385
+def create_join_table(table_1, table_2, column_options: {}, **options)
+  join_table_name = find_join_table_name(table_1, table_2, options)
+
+  column_options.reverse_merge!(null: false, index: false)
+
+  t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
+
+  create_table(join_table_name, **options.merge!(id: false)) do |td|
+    td.references t1_ref, **column_options
+    td.references t2_ref, **column_options
+    yield td if block_given?
+  end
+end
+
+
+ +
+ +
+

+ + create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options) + +

+ + +
+

Creates a new table with the name table_name. table_name may either be a String or a Symbol.

+ +

There are two ways to work with create_table. You can use the block form or the regular form, like this:

+ +

Block form

+ +
# create_table() passes a TableDefinition object to the block.
+# This form will not only create the table, but also columns for the
+# table.
+
+create_table(:suppliers) do |t|
+  t.column :name, :string, limit: 60
+  # Other fields here
+end
+
+ +

Block form, with shorthand

+ +
# You can also use the column types as method calls, rather than calling the column method.
+create_table(:suppliers) do |t|
+  t.string :name, limit: 60
+  # Other fields here
+end
+
+ +

Regular form

+ +
# Creates a table called 'suppliers' with no columns.
+create_table(:suppliers)
+# Add a column to 'suppliers'.
+add_column(:suppliers, :name, :string, {limit: 60})
+
+ +

The options hash can include the following keys:

+
:id +
+

Whether to automatically add a primary key column. Defaults to true. Join tables for ActiveRecord::Base.has_and_belongs_to_many should set it to false.

+ +

A Symbol can be used to specify the type of the generated primary key column.

+
:primary_key +
+

The name of the primary key, if one is to be added automatically. Defaults to id. If :id is false, then this option is ignored.

+ +

If an array is passed, a composite primary key will be created.

+ +

Note that Active Record models will automatically detect their primary key. This can be avoided by using self.primary_key= on the model to define the key explicitly.

+
:options +
+

Any extra options you want appended to the table definition.

+
:temporary +
+

Make a temporary table.

+
:force +
+

Set to true to drop the table before creating it. Set to :cascade to drop dependent objects as well. Defaults to false.

+
:if_not_exists +
+

Set to true to avoid raising an error when the table already exists. Defaults to false.

+
:as +
+

SQL to use to generate the table. When this option is used, the block is ignored, as are the :id and :primary_key options.

+
+ +
Add a backend specific option to the generated SQL (MySQL)
+ +
create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
+
+ +

generates:

+ +
CREATE TABLE suppliers (
+  id bigint auto_increment PRIMARY KEY
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
+
+ +
Rename the primary key column
+ +
create_table(:objects, primary_key: 'guid') do |t|
+  t.column :name, :string, limit: 80
+end
+
+ +

generates:

+ +
CREATE TABLE objects (
+  guid bigint auto_increment PRIMARY KEY,
+  name varchar(80)
+)
+
+ +
Change the primary key column type
+ +
create_table(:tags, id: :string) do |t|
+  t.column :label, :string
+end
+
+ +

generates:

+ +
CREATE TABLE tags (
+  id varchar PRIMARY KEY,
+  label varchar
+)
+
+ +
Create a composite primary key
+ +
create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
+  t.belongs_to :product
+  t.belongs_to :client
+end
+
+ +

generates:

+ +
CREATE TABLE orders (
+    product_id bigint NOT NULL,
+    client_id bigint NOT NULL
+);
+
+ALTER TABLE ONLY "orders"
+  ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
+
+ +
Do not add a primary key column
+ +
create_table(:categories_suppliers, id: false) do |t|
+  t.column :category_id, :bigint
+  t.column :supplier_id, :bigint
+end
+
+ +

generates:

+ +
CREATE TABLE categories_suppliers (
+  category_id bigint,
+  supplier_id bigint
+)
+
+ +
Create a temporary table based on a query
+ +
create_table(:long_query, temporary: true,
+  as: "SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id")
+
+ +

generates:

+ +
CREATE TEMPORARY TABLE long_query AS
+  SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
+
+ +

See also TableDefinition#column for details on how to create columns.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 300
+def create_table(table_name, id: :primary_key, primary_key: nil, force: nil, **options)
+  td = create_table_definition(table_name, **extract_table_options!(options))
+
+  if id && !td.as
+    pk = primary_key || Base.get_primary_key(table_name.to_s.singularize)
+
+    if id.is_a?(Hash)
+      options.merge!(id.except(:type))
+      id = id.fetch(:type, :primary_key)
+    end
+
+    if pk.is_a?(Array)
+      td.primary_keys pk
+    else
+      td.primary_key pk, id, **options
+    end
+  end
+
+  yield td if block_given?
+
+  if force
+    drop_table(table_name, force: force, if_exists: true)
+  else
+    schema_cache.clear_data_source_cache!(table_name.to_s)
+  end
+
+  result = execute schema_creation.accept td
+
+  unless supports_indexes_in_create?
+    td.indexes.each do |column_name, index_options|
+      add_index(table_name, column_name, **index_options, if_not_exists: td.if_not_exists)
+    end
+  end
+
+  if supports_comments? && !supports_comments_in_create?
+    if table_comment = td.comment.presence
+      change_table_comment(table_name, table_comment)
+    end
+
+    td.columns.each do |column|
+      change_column_comment(table_name, column.name, column.comment) if column.comment.present?
+    end
+  end
+
+  result
+end
+
+
+ +
+ +
+

+ + data_source_exists?(name) + +

+ + +
+

Checks to see if the data source name exists on the database.

+ +
data_source_exists?(:ebooks)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 44
+def data_source_exists?(name)
+  query_values(data_source_sql(name), "SCHEMA").any? if name.present?
+rescue NotImplementedError
+  data_sources.include?(name.to_s)
+end
+
+
+ +
+ +
+

+ + data_sources() + +

+ + +
+

Returns the relation names usable to back Active Record models. For most adapters this means all tables and views.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 34
+def data_sources
+  query_values(data_source_sql, "SCHEMA")
+rescue NotImplementedError
+  tables | views
+end
+
+
+ +
+ +
+

+ + drop_join_table(table_1, table_2, **options) + +

+ + +
+

Drops the join table specified by the given arguments. See create_join_table for details.

+ +

Although this command ignores the block if one is given, it can be helpful to provide one in a migration’s change method so it can be reverted. In that case, the block will be used by create_join_table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 405
+def drop_join_table(table_1, table_2, **options)
+  join_table_name = find_join_table_name(table_1, table_2, options)
+  drop_table(join_table_name)
+end
+
+
+ +
+ +
+

+ + drop_table(table_name, **options) + +

+ + +
+

Drops a table from the database.

+
:force +
+

Set to :cascade to drop dependent objects as well. Defaults to false.

+
:if_exists +
+

Set to true to only drop the table if it exists. Defaults to false.

+
+ +

Although this command ignores most options and the block if one is given, it can be helpful to provide these in a migration’s change method so it can be reverted. In that case, options and the block will be used by create_table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 518
+def drop_table(table_name, **options)
+  schema_cache.clear_data_source_cache!(table_name.to_s)
+  execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
+end
+
+
+ +
+ +
+

+ + foreign_key_exists?(from_table, to_table = nil, **options) + +

+ + +
+

Checks to see if a foreign key exists on a table for a given foreign key definition.

+ +
# Checks to see if a foreign key exists.
+foreign_key_exists?(:accounts, :branches)
+
+# Checks to see if a foreign key on a specified column exists.
+foreign_key_exists?(:accounts, column: :owner_id)
+
+# Checks to see if a foreign key with a custom name exists.
+foreign_key_exists?(:accounts, name: "special_fk_name")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1150
+def foreign_key_exists?(from_table, to_table = nil, **options)
+  foreign_key_for(from_table, to_table: to_table, **options).present?
+end
+
+
+ +
+ +
+

+ + foreign_keys(table_name) + +

+ + +
+

Returns an array of foreign keys for the given table. The foreign keys are represented as ForeignKeyDefinition objects.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1028
+def foreign_keys(table_name)
+  raise NotImplementedError, "foreign_keys is not implemented"
+end
+
+
+ +
+ +
+

+ + index_exists?(table_name, column_name, **options) + +

+ + +
+

Checks to see if an index exists on a table for a given index definition.

+ +
# Check an index exists
+index_exists?(:suppliers, :company_id)
+
+# Check an index on multiple columns exists
+index_exists?(:suppliers, [:company_id, :company_type])
+
+# Check a unique index exists
+index_exists?(:suppliers, :company_id, unique: true)
+
+# Check an index with a custom name exists
+index_exists?(:suppliers, :company_id, name: "idx_company_id")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 99
+def index_exists?(table_name, column_name, **options)
+  checks = []
+  column_name = options[:column] if column_name.nil?
+
+  if column_name.present?
+    column_names = Array(column_name).map(&:to_s)
+    checks << lambda { |i| Array(i.columns) == column_names }
+  end
+
+  checks << lambda { |i| i.unique } if options[:unique]
+  checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
+
+  indexes(table_name).any? { |i| checks.all? { |check| check[i] } }
+end
+
+
+ +
+ +
+

+ + index_name_exists?(table_name, index_name) + +

+ + +
+

Verifies the existence of an index with a given name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 936
+def index_name_exists?(table_name, index_name)
+  index_name = index_name.to_s
+  indexes(table_name).detect { |i| i.name == index_name }
+end
+
+
+ +
+ +
+

+ + indexes(table_name) + +

+ + +
+

Returns an array of indexes for the given table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 81
+def indexes(table_name)
+  raise NotImplementedError, "#indexes is not implemented"
+end
+
+
+ +
+ +
+

+ + native_database_types() + +

+ + +
+

Returns a hash of mappings from the abstract data types to the native database types. See TableDefinition#column for details on the recognized abstract data types.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 14
+def native_database_types
+  {}
+end
+
+
+ +
+ +
+

+ + options_include_default?(options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1379
+def options_include_default?(options)
+  options.include?(:default) && !(options[:null] == false && options[:default].nil?)
+end
+
+
+ +
+ +
+

+ + primary_key(table_name) + +

+ + +
+

Returns just a table’s primary key

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 152
+def primary_key(table_name)
+  pk = primary_keys(table_name)
+  pk = pk.first unless pk.size > 1
+  pk
+end
+
+
+ +
+ +
+

+ + remove_belongs_to(table_name, ref_name, foreign_key: false, polymorphic: false, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: remove_reference +
+ + + +
+ +
+

+ + remove_check_constraint(table_name, expression = nil, **options) + +

+ + +
+

Removes the given check constraint from the table.

+ +
remove_check_constraint :products, name: "price_check"
+
+ +

The expression parameter will be ignored if present. It can be helpful to provide this in a migration’s change method so it can be reverted. In that case, expression will be used by add_check_constraint.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1209
+def remove_check_constraint(table_name, expression = nil, **options)
+  return unless supports_check_constraints?
+
+  chk_name_to_delete = check_constraint_for!(table_name, expression: expression, **options).name
+
+  at = create_alter_table(table_name)
+  at.drop_check_constraint(chk_name_to_delete)
+
+  execute schema_creation.accept(at)
+end
+
+
+ +
+ +
+

+ + remove_column(table_name, column_name, type = nil, **options) + +

+ + +
+

Removes the column from the table definition.

+ +
remove_column(:suppliers, :qualification)
+
+ +

The type and options parameters will be ignored if present. It can be helpful to provide these in a migration’s change method so it can be reverted. In that case, type and options will be used by add_column. Depending on the database you’re using, indexes using this column may be automatically removed or modified to remove this column from the index.

+ +

If the options provided include an if_exists key, it will be used to check if the column does not exist. This will silently ignore the migration rather than raising if the column was already used.

+ +
remove_column(:suppliers, :qualification, if_exists: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 668
+def remove_column(table_name, column_name, type = nil, **options)
+  return if options[:if_exists] == true && !column_exists?(table_name, column_name)
+
+  execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, **options)}"
+end
+
+
+ +
+ +
+

+ + remove_columns(table_name, *column_names, type: nil, **options) + +

+ + +
+

Removes the given columns from the table definition.

+ +
remove_columns(:suppliers, :qualification, :experience)
+
+ +

type and other column options can be passed to make migration reversible.

+ +
remove_columns(:suppliers, :qualification, :experience, type: :string, null: false)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 644
+def remove_columns(table_name, *column_names, type: nil, **options)
+  if column_names.empty?
+    raise ArgumentError.new("You must specify at least one column name. Example: remove_columns(:people, :first_name)")
+  end
+
+  remove_column_fragments = remove_columns_for_alter(table_name, *column_names, type: type, **options)
+  execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_fragments.join(', ')}"
+end
+
+
+ +
+ +
+

+ + remove_foreign_key(from_table, to_table = nil, **options) + +

+ + +
+

Removes the given foreign key from the table. Any option parameters provided will be used to re-add the foreign key in case of a migration rollback. It is recommended that you provide any options used when creating the foreign key so that the migration can be reverted properly.

+ +

Removes the foreign key on accounts.branch_id.

+ +
remove_foreign_key :accounts, :branches
+
+ +

Removes the foreign key on accounts.owner_id.

+ +
remove_foreign_key :accounts, column: :owner_id
+
+ +

Removes the foreign key on accounts.owner_id.

+ +
remove_foreign_key :accounts, to_table: :owners
+
+ +

Removes the foreign key named special_fk_name on the accounts table.

+ +
remove_foreign_key :accounts, name: :special_fk_name
+
+ +

Checks if the foreign key exists before trying to remove it. Will silently ignore indexes that don’t exist.

+ +
remove_foreign_key :accounts, :branches, if_exists: true
+
+ +

The options hash accepts the same keys as SchemaStatements#add_foreign_key with an addition of

+
:to_table +
+

The name of the table that contains the referenced primary key.

+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1127
+def remove_foreign_key(from_table, to_table = nil, **options)
+  return unless supports_foreign_keys?
+  return if options.delete(:if_exists) == true && !foreign_key_exists?(from_table, to_table)
+
+  fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
+
+  at = create_alter_table from_table
+  at.drop_foreign_key fk_name_to_delete
+
+  execute schema_creation.accept(at)
+end
+
+
+ +
+ +
+

+ + remove_index(table_name, column_name = nil, **options) + +

+ + +
+

Removes the given index from the table.

+ +

Removes the index on branch_id in the accounts table if exactly one such index exists.

+ +
remove_index :accounts, :branch_id
+
+ +

Removes the index on branch_id in the accounts table if exactly one such index exists.

+ +
remove_index :accounts, column: :branch_id
+
+ +

Removes the index on branch_id and party_id in the accounts table if exactly one such index exists.

+ +
remove_index :accounts, column: [:branch_id, :party_id]
+
+ +

Removes the index named by_branch_party in the accounts table.

+ +
remove_index :accounts, name: :by_branch_party
+
+ +

Removes the index on branch_id named by_branch_party in the accounts table.

+ +
remove_index :accounts, :branch_id, name: :by_branch_party
+
+ +

Checks if the index exists before trying to remove it. Will silently ignore indexes that don’t exist.

+ +
remove_index :accounts, if_exists: true
+
+ +

Removes the index named by_branch_party in the accounts table concurrently.

+ +
remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
+
+ +

Note: only supported by PostgreSQL.

+ +

Concurrently removing an index is not supported in a transaction.

+ +

For more information see the “Transactional Migrations” section.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 895
+def remove_index(table_name, column_name = nil, **options)
+  return if options[:if_exists] && !index_exists?(table_name, column_name, **options)
+
+  index_name = index_name_for_remove(table_name, column_name, options)
+
+  execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
+end
+
+
+ +
+ +
+

+ + remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options) + +

+ + +
+

Removes the reference(s). Also removes a type column if one exists. remove_reference and remove_belongs_to are acceptable.

+ +
Remove the reference
+ +
remove_reference(:products, :user, index: false)
+
+ +
Remove polymorphic reference
+ +
remove_reference(:products, :supplier, polymorphic: true)
+
+ +
Remove the reference with a foreign key
+ +
remove_reference(:products, :user, foreign_key: true)
+
+
+ + + +
+ Also aliased as: remove_belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1009
+def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
+  if foreign_key
+    reference_name = Base.pluralize_table_names ? ref_name.to_s.pluralize : ref_name
+    if foreign_key.is_a?(Hash)
+      foreign_key_options = foreign_key
+    else
+      foreign_key_options = { to_table: reference_name }
+    end
+    foreign_key_options[:column] ||= "#{ref_name}_id"
+    remove_foreign_key(table_name, **foreign_key_options)
+  end
+
+  remove_column(table_name, "#{ref_name}_id")
+  remove_column(table_name, "#{ref_name}_type") if polymorphic
+end
+
+
+ +
+ +
+

+ + remove_timestamps(table_name, **options) + +

+ + +
+

Removes the timestamp columns (created_at and updated_at) from the table definition.

+ +
remove_timestamps(:suppliers)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 1332
+def remove_timestamps(table_name, **options)
+  remove_columns table_name, :updated_at, :created_at
+end
+
+
+ +
+ +
+

+ + rename_column(table_name, column_name, new_column_name) + +

+ + +
+

Renames a column.

+ +
rename_column(:suppliers, :description, :name)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 726
+def rename_column(table_name, column_name, new_column_name)
+  raise NotImplementedError, "rename_column is not implemented"
+end
+
+
+ +
+ +
+

+ + rename_index(table_name, old_name, new_name) + +

+ + +
+

Renames an index.

+ +

Rename the index_people_on_last_name index to index_users_on_last_name:

+ +
rename_index :people, 'index_people_on_last_name', 'index_users_on_last_name'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 909
+def rename_index(table_name, old_name, new_name)
+  old_name = old_name.to_s
+  new_name = new_name.to_s
+  validate_index_length!(table_name, new_name)
+
+  # this is a naive implementation; some DBs may support this more efficiently (PostgreSQL, for instance)
+  old_index_def = indexes(table_name).detect { |i| i.name == old_name }
+  return unless old_index_def
+  add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
+  remove_index(table_name, name: old_name)
+end
+
+
+ +
+ +
+

+ + rename_table(table_name, new_name) + +

+ + +
+

Renames a table.

+ +
rename_table('octopuses', 'octopi')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 502
+def rename_table(table_name, new_name)
+  raise NotImplementedError, "rename_table is not implemented"
+end
+
+
+ +
+ +
+

+ + table_alias_for(table_name) + +

+ + +
+

Truncates a table alias according to the limits of the current adapter.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 28
+def table_alias_for(table_name)
+  table_name[0...table_alias_length].tr(".", "_")
+end
+
+
+ +
+ +
+

+ + table_comment(table_name) + +

+ + +
+

Returns the table comment that’s stored in database metadata.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 23
+def table_comment(table_name)
+  nil
+end
+
+
+ +
+ +
+

+ + table_exists?(table_name) + +

+ + +
+

Checks to see if the table table_name exists on the database.

+ +
table_exists?(:developers)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 59
+def table_exists?(table_name)
+  query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
+rescue NotImplementedError
+  tables.include?(table_name.to_s)
+end
+
+
+ +
+ +
+

+ + table_options(table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 18
+def table_options(table_name)
+  nil
+end
+
+
+ +
+ +
+

+ + tables() + +

+ + +
+

Returns an array of table names defined in the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 51
+def tables
+  query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
+end
+
+
+ +
+ +
+

+ + view_exists?(view_name) + +

+ + +
+

Checks to see if the view view_name exists on the database.

+ +
view_exists?(:ebooks)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 74
+def view_exists?(view_name)
+  query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
+rescue NotImplementedError
+  views.include?(view_name.to_s)
+end
+
+
+ +
+ +
+

+ + views() + +

+ + +
+

Returns an array of view names defined in the database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb, line 66
+def views
+  query_values(data_source_sql(type: "VIEW"), "SCHEMA")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/SqlTypeMetadata.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SqlTypeMetadata.html new file mode 100644 index 0000000000..09c16bd31f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/SqlTypeMetadata.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::ConnectionAdapters::SqlTypeMetadata +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/Table.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Table.html new file mode 100644 index 0000000000..3be281a780 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/Table.html @@ -0,0 +1,1155 @@ +--- +title: ActiveRecord::ConnectionAdapters::Table +layout: default +--- +
+ +
+
+ +
+ +

Represents an SQL table in an abstract way for updating a table. Also see TableDefinition and connection.create_table

+ +

Available transformations are:

+ +
change_table :table do |t|
+  t.primary_key
+  t.column
+  t.index
+  t.rename_index
+  t.timestamps
+  t.change
+  t.change_default
+  t.change_null
+  t.rename
+  t.references
+  t.belongs_to
+  t.check_constraint
+  t.string
+  t.text
+  t.integer
+  t.bigint
+  t.float
+  t.decimal
+  t.numeric
+  t.datetime
+  t.timestamp
+  t.time
+  t.date
+  t.binary
+  t.blob
+  t.boolean
+  t.foreign_key
+  t.json
+  t.virtual
+  t.remove
+  t.remove_foreign_key
+  t.remove_references
+  t.remove_belongs_to
+  t.remove_index
+  t.remove_check_constraint
+  t.remove_timestamps
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + name
+ + + + +

Class Public methods

+ +
+

+ + new(table_name, base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 622
+def initialize(table_name, base)
+  @name = table_name
+  @base = base
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + belongs_to(*args, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: references +
+ + + +
+ +
+

+ + change(column_name, type, **options) + +

+ + +
+

Changes the column’s definition according to the new options.

+ +
t.change(:name, :string, limit: 80)
+t.change(:description, :text)
+
+ +

See TableDefinition#column for details of the options you can use.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 696
+def change(column_name, type, **options)
+  @base.change_column(name, column_name, type, **options)
+end
+
+
+ +
+ +
+

+ + change_default(column_name, default_or_changes) + +

+ + +
+

Sets a new default value for a column.

+ +
t.change_default(:qualification, 'new')
+t.change_default(:authorized, 1)
+t.change_default(:status, from: nil, to: "draft")
+
+ +

See connection.change_column_default

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 707
+def change_default(column_name, default_or_changes)
+  @base.change_column_default(name, column_name, default_or_changes)
+end
+
+
+ +
+ +
+

+ + change_null(column_name, null, default = nil) + +

+ + +
+

Sets or removes a NOT NULL constraint on a column.

+ +
t.change_null(:qualification, true)
+t.change_null(:qualification, false, 0)
+
+ +

See connection.change_column_null

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 717
+def change_null(column_name, null, default = nil)
+  @base.change_column_null(name, column_name, null, default)
+end
+
+
+ +
+ +
+

+ + check_constraint(*args, **options) + +

+ + +
+

Adds a check constraint.

+ +
t.check_constraint("price > 0", name: "price_check")
+
+ +

See connection.add_check_constraint

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 821
+def check_constraint(*args, **options)
+  @base.add_check_constraint(name, *args, **options)
+end
+
+
+ +
+ +
+

+ + column(column_name, type, index: nil, **options) + +

+ + +
+

Adds a new column to the named table.

+ +
t.column(:name, :string)
+
+ +

See TableDefinition#column for details of the options you can use.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 632
+def column(column_name, type, index: nil, **options)
+  @base.add_column(name, column_name, type, **options)
+  if index
+    index_options = index.is_a?(Hash) ? index : {}
+    index(column_name, **index_options)
+  end
+end
+
+
+ +
+ +
+

+ + column_exists?(column_name, type = nil, **options) + +

+ + +
+

Checks to see if a column exists.

+ +
t.string(:name) unless t.column_exists?(:name, :string)
+
+ +

See connection.column_exists?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 645
+def column_exists?(column_name, type = nil, **options)
+  @base.column_exists?(name, column_name, type, **options)
+end
+
+
+ +
+ +
+

+ + foreign_key(*args, **options) + +

+ + +
+

Adds a foreign key to the table using a supplied table name.

+ +
t.foreign_key(:authors)
+t.foreign_key(:authors, column: :author_id, primary_key: "id")
+
+ +

See connection.add_foreign_key

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 793
+def foreign_key(*args, **options)
+  @base.add_foreign_key(name, *args, **options)
+end
+
+
+ +
+ +
+

+ + foreign_key_exists?(*args, **options) + +

+ + +
+

Checks to see if a foreign key exists.

+ +
t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
+
+ +

See connection.foreign_key_exists?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 812
+def foreign_key_exists?(*args, **options)
+  @base.foreign_key_exists?(name, *args, **options)
+end
+
+
+ +
+ +
+

+ + index(column_name, **options) + +

+ + +
+

Adds a new index to the table. column_name can be a single Symbol, or an Array of Symbols.

+ +
t.index(:name)
+t.index([:branch_id, :party_id], unique: true)
+t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
+
+ +

See connection.add_index for details of the options you can use.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 657
+def index(column_name, **options)
+  @base.add_index(name, column_name, **options)
+end
+
+
+ +
+ +
+

+ + index_exists?(column_name, **options) + +

+ + +
+

Checks to see if an index exists.

+ +
unless t.index_exists?(:branch_id)
+  t.index(:branch_id)
+end
+
+ +

See connection.index_exists?

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 668
+def index_exists?(column_name, **options)
+  @base.index_exists?(name, column_name, **options)
+end
+
+
+ +
+ +
+

+ + references(*args, **options) + +

+ + +
+

Adds a reference.

+ +
t.references(:user)
+t.belongs_to(:supplier, foreign_key: true)
+
+ +

See connection.add_reference for details of the options you can use.

+
+ + + +
+ Also aliased as: belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 767
+def references(*args, **options)
+  args.each do |ref_name|
+    @base.add_reference(name, ref_name, **options)
+  end
+end
+
+
+ +
+ +
+

+ + remove(*column_names, **options) + +

+ + +
+

Removes the column(s) from the table definition.

+ +
t.remove(:qualification)
+t.remove(:qualification, :experience)
+
+ +

See connection.remove_columns

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 727
+def remove(*column_names, **options)
+  @base.remove_columns(name, *column_names, **options)
+end
+
+
+ +
+ +
+

+ + remove_belongs_to(*args, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: remove_references +
+ + + +
+ +
+

+ + remove_check_constraint(*args, **options) + +

+ + +
+

Removes the given check constraint from the table.

+ +
t.remove_check_constraint(name: "price_check")
+
+ +

See connection.remove_check_constraint

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 830
+def remove_check_constraint(*args, **options)
+  @base.remove_check_constraint(name, *args, **options)
+end
+
+
+ +
+ +
+

+ + remove_foreign_key(*args, **options) + +

+ + +
+

Removes the given foreign key from the table.

+ +
t.remove_foreign_key(:authors)
+t.remove_foreign_key(column: :author_id)
+
+ +

See connection.remove_foreign_key

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 803
+def remove_foreign_key(*args, **options)
+  @base.remove_foreign_key(name, *args, **options)
+end
+
+
+ +
+ +
+

+ + remove_index(column_name = nil, **options) + +

+ + +
+

Removes the given index from the table.

+ +
t.remove_index(:branch_id)
+t.remove_index(column: [:branch_id, :party_id])
+t.remove_index(name: :by_branch_party)
+t.remove_index(:branch_id, name: :by_branch_party)
+
+ +

See connection.remove_index

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 739
+def remove_index(column_name = nil, **options)
+  @base.remove_index(name, column_name, **options)
+end
+
+
+ +
+ +
+

+ + remove_references(*args, **options) + +

+ + +
+

Removes a reference. Optionally removes a type column.

+ +
t.remove_references(:user)
+t.remove_belongs_to(:supplier, polymorphic: true)
+
+ +

See connection.remove_reference

+
+ + + +
+ Also aliased as: remove_belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 780
+def remove_references(*args, **options)
+  args.each do |ref_name|
+    @base.remove_reference(name, ref_name, **options)
+  end
+end
+
+
+ +
+ +
+

+ + remove_timestamps(**options) + +

+ + +
+

Removes the timestamp columns (created_at and updated_at) from the table.

+ +
t.remove_timestamps
+
+ +

See connection.remove_timestamps

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 748
+def remove_timestamps(**options)
+  @base.remove_timestamps(name, **options)
+end
+
+
+ +
+ +
+

+ + rename(column_name, new_column_name) + +

+ + +
+

Renames a column.

+ +
t.rename(:description, :name)
+
+ +

See connection.rename_column

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 757
+def rename(column_name, new_column_name)
+  @base.rename_column(name, column_name, new_column_name)
+end
+
+
+ +
+ +
+

+ + rename_index(index_name, new_index_name) + +

+ + +
+

Renames the given index on the table.

+ +
t.rename_index(:user_id, :account_id)
+
+ +

See connection.rename_index

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 677
+def rename_index(index_name, new_index_name)
+  @base.rename_index(name, index_name, new_index_name)
+end
+
+
+ +
+ +
+

+ + timestamps(**options) + +

+ + +
+

Adds timestamps (created_at and updated_at) columns to the table.

+ +
t.timestamps(null: false)
+
+ +

See connection.add_timestamps

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 686
+def timestamps(**options)
+  @base.add_timestamps(name, **options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html new file mode 100644 index 0000000000..2a77a22f81 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html @@ -0,0 +1,723 @@ +--- +title: ActiveRecord::ConnectionAdapters::TableDefinition +layout: default +--- +
+ +
+
+ +
+ +

Represents the schema of an SQL table in an abstract way. This class provides methods for manipulating the schema representation.

+ +

Inside migration files, the t object in create_table is actually of this type:

+ +
class SomeMigration < ActiveRecord::Migration[7.0]
+  def up
+    create_table :foo do |t|
+      puts t.class  # => "ActiveRecord::ConnectionAdapters::TableDefinition"
+    end
+  end
+
+  def down
+    ...
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + as
+ [R] + check_constraints
+ [R] + comment
+ [R] + foreign_keys
+ [R] + if_not_exists
+ [R] + indexes
+ [R] + name
+ [R] + options
+ [R] + temporary
+ + + + +

Class Public methods

+ +
+

+ + new( conn, name, temporary: false, if_not_exists: false, options: nil, as: nil, comment: nil, ** ) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 306
+def initialize(
+  conn,
+  name,
+  temporary: false,
+  if_not_exists: false,
+  options: nil,
+  as: nil,
+  comment: nil,
+  **
+)
+  @conn = conn
+  @columns_hash = {}
+  @indexes = []
+  @foreign_keys = []
+  @primary_keys = nil
+  @check_constraints = []
+  @temporary = temporary
+  @if_not_exists = if_not_exists
+  @options = options
+  @as = as
+  @name = name
+  @comment = comment
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](name) + +

+ + +
+

Returns a ColumnDefinition for the column with name name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 339
+def [](name)
+  @columns_hash[name.to_s]
+end
+
+
+ +
+ +
+

+ + belongs_to(*args, **options) + +

+ + +
+ +
+ + + + + +
+ Alias for: references +
+ + + +
+ +
+

+ + check_constraint(expression, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 443
+def check_constraint(expression, **options)
+  check_constraints << new_check_constraint_definition(expression, options)
+end
+
+
+ +
+ +
+

+ + column(name, type, index: nil, **options) + +

+ + +
+

Instantiates a new column for the table. See connection.add_column for available options.

+ +

Additional options are:

+
  • +

    :index - Create an index for the column. Can be either true or an options hash.

    +
+ +

This method returns self.

+ +

Examples

+ +
# Assuming +td+ is an instance of TableDefinition
+td.column(:granted, :boolean, index: true)
+
+ +

Short-hand examples

+ +

Instead of calling column directly, you can also work with the short-hand definitions for the default types. They use the type as the method name instead of as a parameter and allow for multiple columns to be defined in a single statement.

+ +

What can be written like this with the regular calls to column:

+ +
create_table :products do |t|
+  t.column :shop_id,     :integer
+  t.column :creator_id,  :integer
+  t.column :item_number, :string
+  t.column :name,        :string, default: "Untitled"
+  t.column :value,       :string, default: "Untitled"
+  t.column :created_at,  :datetime
+  t.column :updated_at,  :datetime
+end
+add_index :products, :item_number
+
+ +

can also be written as follows using the short-hand:

+ +
create_table :products do |t|
+  t.integer :shop_id, :creator_id
+  t.string  :item_number, index: true
+  t.string  :name, :value, default: "Untitled"
+  t.timestamps null: false
+end
+
+ +

There’s a short-hand method for each of the type values declared at the top. And then there’s TableDefinition#timestamps that’ll add created_at and updated_at as datetimes.

+ +

TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type column if the :polymorphic option is supplied. If :polymorphic is a hash of options, these will be used when creating the _type column. The :index option will also create an index, similar to calling add_index. So what can be written like this:

+ +
create_table :taggings do |t|
+  t.integer :tag_id, :tagger_id, :taggable_id
+  t.string  :tagger_type
+  t.string  :taggable_type, default: 'Photo'
+end
+add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
+add_index :taggings, [:tagger_id, :tagger_type]
+
+ +

Can also be written as follows using references:

+ +
create_table :taggings do |t|
+  t.references :tag, index: { name: 'index_taggings_on_tag_id' }
+  t.references :tagger, polymorphic: true
+  t.references :taggable, polymorphic: { default: 'Photo' }, index: false
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 410
+def column(name, type, index: nil, **options)
+  name = name.to_s
+  type = type.to_sym if type
+
+  raise_on_duplicate_column(name)
+  @columns_hash[name] = new_column_definition(name, type, **options)
+
+  if index
+    index_options = index.is_a?(Hash) ? index : {}
+    index(name, **index_options)
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + columns() + +

+ + +
+

Returns an array of ColumnDefinition objects for the columns of the table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 336
+def columns; @columns_hash.values; end
+
+
+ +
+ +
+

+ + foreign_key(to_table, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 439
+def foreign_key(to_table, **options)
+  foreign_keys << new_foreign_key_definition(to_table, options)
+end
+
+
+ +
+ +
+

+ + index(column_name, **options) + +

+ + +
+

Adds index options to the indexes hash, keyed by column name This is primarily used to track indexes that need to be created after the table

+ +
index(:account_id, name: 'index_projects_on_account_id')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 435
+def index(column_name, **options)
+  indexes << [column_name, options]
+end
+
+
+ +
+ +
+

+ + references(*args, **options) + +

+ + +
+

Adds a reference.

+ +
t.references(:user)
+t.belongs_to(:supplier, foreign_key: true)
+t.belongs_to(:supplier, foreign_key: true, type: :integer)
+
+ +

See connection.add_reference for details of the options you can use.

+
+ + + +
+ Also aliased as: belongs_to +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 469
+def references(*args, **options)
+  args.each do |ref_name|
+    ReferenceDefinition.new(ref_name, **options).add_to(self)
+  end
+end
+
+
+ +
+ +
+

+ + remove_column(name) + +

+ + +
+

remove the column name from the table.

+ +
remove_column(:account_id)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 427
+def remove_column(name)
+  @columns_hash.delete name.to_s
+end
+
+
+ +
+ +
+

+ + timestamps(**options) + +

+ + +
+

Appends :datetime columns :created_at and :updated_at to the table. See connection.add_timestamps

+ +
t.timestamps null: false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb, line 451
+def timestamps(**options)
+  options[:null] = false if options[:null].nil?
+
+  if !options.key?(:precision) && @conn.supports_datetime_with_precision?
+    options[:precision] = 6
+  end
+
+  column(:created_at, :datetime, **options)
+  column(:updated_at, :datetime, **options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionAdapters/TransactionState.html b/src/7.0/classes/ActiveRecord/ConnectionAdapters/TransactionState.html new file mode 100644 index 0000000000..19abc4cf69 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionAdapters/TransactionState.html @@ -0,0 +1,700 @@ +--- +title: ActiveRecord::ConnectionAdapters::TransactionState +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(state = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 6
+def initialize(state = nil)
+  @state = state
+  @children = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_child(state) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 11
+def add_child(state)
+  @children ||= []
+  @children << state
+end
+
+
+ +
+ +
+

+ + commit!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 63
+def commit!
+  @state = :committed
+end
+
+
+ +
+ +
+

+ + committed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 20
+def committed?
+  @state == :committed || @state == :fully_committed
+end
+
+
+ +
+ +
+

+ + completed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 44
+def completed?
+  committed? || rolledback?
+end
+
+
+ +
+ +
+

+ + finalized?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 16
+def finalized?
+  @state
+end
+
+
+ +
+ +
+

+ + full_commit!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 67
+def full_commit!
+  @state = :fully_committed
+end
+
+
+ +
+ +
+

+ + full_rollback!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 53
+def full_rollback!
+  @children&.each { |c| c.rollback! }
+  @state = :fully_rolledback
+end
+
+
+ +
+ +
+

+ + fully_committed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 24
+def fully_committed?
+  @state == :fully_committed
+end
+
+
+ +
+ +
+

+ + fully_completed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 40
+def fully_completed?
+  completed?
+end
+
+
+ +
+ +
+

+ + fully_rolledback?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 32
+def fully_rolledback?
+  @state == :fully_rolledback
+end
+
+
+ +
+ +
+

+ + invalidate!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 58
+def invalidate!
+  @children&.each { |c| c.invalidate! }
+  @state = :invalidated
+end
+
+
+ +
+ +
+

+ + invalidated?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 36
+def invalidated?
+  @state == :invalidated
+end
+
+
+ +
+ +
+

+ + nullify!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 71
+def nullify!
+  @state = nil
+end
+
+
+ +
+ +
+

+ + rollback!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 48
+def rollback!
+  @children&.each { |c| c.rollback! }
+  @state = :rolledback
+end
+
+
+ +
+ +
+

+ + rolledback?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_adapters/abstract/transaction.rb, line 28
+def rolledback?
+  @state == :rolledback || @state == :fully_rolledback
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionHandling.html b/src/7.0/classes/ActiveRecord/ConnectionHandling.html new file mode 100644 index 0000000000..80ec7397f2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionHandling.html @@ -0,0 +1,993 @@ +--- +title: ActiveRecord::ConnectionHandling +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_ENV=-> { RAILS_ENV.call || "default_env" }
 
RAILS_ENV=-> { (Rails.env if defined?(Rails.env)) || ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence }
 
+ + + + +

Attributes

+ + + + + + + + +
+ [W] + connection_specification_name
+ + + + + +

Instance Public methods

+ +
+

+ + clear_query_caches_for_current_thread() + +

+ + +
+

Clears the query cache for all connections associated with the current thread.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 266
+def clear_query_caches_for_current_thread
+  if ActiveRecord.legacy_connection_handling
+    ActiveRecord::Base.connection_handlers.each_value do |handler|
+      clear_on_handler(handler)
+    end
+  else
+    clear_on_handler(ActiveRecord::Base.connection_handler)
+  end
+end
+
+
+ +
+ +
+

+ + connected?() + +

+ + +
+

Returns true if Active Record is connected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 317
+def connected?
+  connection_handler.connected?(connection_specification_name, role: current_role, shard: current_shard)
+end
+
+
+ +
+ +
+

+ + connected_to(role: nil, shard: nil, prevent_writes: false, &blk) + +

+ + +
+

Connects to a role (e.g. writing, reading, or a custom role) and/or shard for the duration of the block. At the end of the block the connection will be returned to the original role / shard.

+ +

If only a role is passed, Active Record will look up the connection based on the requested role. If a non-established role is requested an ActiveRecord::ConnectionNotEstablished error will be raised:

+ +
ActiveRecord::Base.connected_to(role: :writing) do
+  Dog.create! # creates dog using dog writing connection
+end
+
+ActiveRecord::Base.connected_to(role: :reading) do
+  Dog.create! # throws exception because we're on a replica
+end
+
+ +

When swapping to a shard, the role must be passed as well. If a non-existent shard is passed, an ActiveRecord::ConnectionNotEstablished error will be raised.

+ +

When a shard and role is passed, Active Record will first lookup the role, and then look up the connection by shard key.

+ +
ActiveRecord::Base.connected_to(role: :reading, shard: :shard_one_replica) do
+  Dog.first # finds first Dog record stored on the shard one replica
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 137
+def connected_to(role: nil, shard: nil, prevent_writes: false, &blk)
+  if ActiveRecord.legacy_connection_handling
+    if self != Base
+      raise NotImplementedError, "`connected_to` can only be called on ActiveRecord::Base with legacy connection handling."
+    end
+  else
+    if self != Base && !abstract_class
+      raise NotImplementedError, "calling `connected_to` is only allowed on ActiveRecord::Base or abstract classes."
+    end
+
+    if name != connection_specification_name && !primary_class?
+      raise NotImplementedError, "calling `connected_to` is only allowed on the abstract class that established the connection."
+    end
+  end
+
+  unless role || shard
+    raise ArgumentError, "must provide a `shard` and/or `role`."
+  end
+
+  with_role_and_shard(role, shard, prevent_writes, &blk)
+end
+
+
+ +
+ +
+

+ + connected_to?(role:, shard: ActiveRecord::Base.default_shard) + +

+ + +
+

Returns true if role is the current connected role.

+ +
ActiveRecord::Base.connected_to(role: :writing) do
+  ActiveRecord::Base.connected_to?(role: :writing) #=> true
+  ActiveRecord::Base.connected_to?(role: :reading) #=> false
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 252
+def connected_to?(role:, shard: ActiveRecord::Base.default_shard)
+  current_role == role.to_sym && current_shard == shard.to_sym
+end
+
+
+ +
+ +
+

+ + connected_to_many(*classes, role:, shard: nil, prevent_writes: false) + +

+ + +
+

Connects a role and/or shard to the provided connection names. Optionally prevent_writes can be passed to block writes on a connection. reading will automatically set prevent_writes to true.

+ +

connected_to_many is an alternative to deeply nested connected_to blocks.

+ +

Usage:

+ +
ActiveRecord::Base.connected_to_many(AnimalsRecord, MealsRecord, role: :reading) do
+  Dog.first # Read from animals replica
+  Dinner.first # Read from meals replica
+  Person.first # Read from primary writer
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 172
+def connected_to_many(*classes, role:, shard: nil, prevent_writes: false)
+  classes = classes.flatten
+
+  if ActiveRecord.legacy_connection_handling
+    raise NotImplementedError, "connected_to_many is not available with legacy connection handling"
+  end
+
+  if self != Base || classes.include?(Base)
+    raise NotImplementedError, "connected_to_many can only be called on ActiveRecord::Base."
+  end
+
+  prevent_writes = true if role == ActiveRecord.reading_role
+
+  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: classes)
+  yield
+ensure
+  connected_to_stack.pop
+end
+
+
+ +
+ +
+

+ + connecting_to(role: default_role, shard: default_shard, prevent_writes: false) + +

+ + +
+

Use a specified connection.

+ +

This method is useful for ensuring that a specific connection is being used. For example, when booting a console in readonly mode.

+ +

It is not recommended to use this method in a request since it does not yield to a block like connected_to.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 198
+def connecting_to(role: default_role, shard: default_shard, prevent_writes: false)
+  if ActiveRecord.legacy_connection_handling
+    raise NotImplementedError, "`connecting_to` is not available with `legacy_connection_handling`."
+  end
+
+  prevent_writes = true if role == ActiveRecord.reading_role
+
+  append_to_connected_to_stack(role: role, shard: shard, prevent_writes: prevent_writes, klasses: [self])
+end
+
+
+ +
+ +
+

+ + connection() + +

+ + +
+

Returns the connection currently associated with the class. This can also be used to “borrow” the connection to do database work unrelated to any of the specific Active Records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 279
+def connection
+  retrieve_connection
+end
+
+
+ +
+ +
+

+ + connection_db_config() + +

+ + +
+

Returns the db_config object from the associated connection:

+ +
ActiveRecord::Base.connection_db_config
+  #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
+    @name="primary", @config={pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}>
+
+ +

Use only for reading.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 304
+def connection_db_config
+  connection_pool.db_config
+end
+
+
+ +
+ +
+

+ + connection_pool() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 308
+def connection_pool
+  connection_handler.retrieve_connection_pool(connection_specification_name, role: current_role, shard: current_shard) || raise(ConnectionNotEstablished)
+end
+
+
+ +
+ +
+

+ + connection_specification_name() + +

+ + +
+

Return the connection specification name from the current class or its parent.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 286
+def connection_specification_name
+  if !defined?(@connection_specification_name) || @connection_specification_name.nil?
+    return self == Base ? Base.name : superclass.connection_specification_name
+  end
+  @connection_specification_name
+end
+
+
+ +
+ +
+

+ + connects_to(database: {}, shards: {}) + +

+ + +
+

Connects a model to the databases specified. The database keyword takes a hash consisting of a role and a database_key.

+ +

This will create a connection handler for switching between connections, look up the config hash using the database_key and finally establishes a connection to that config.

+ +
class AnimalsModel < ApplicationRecord
+  self.abstract_class = true
+
+  connects_to database: { writing: :primary, reading: :primary_replica }
+end
+
+ +

connects_to also supports horizontal sharding. The horizontal sharding API also supports read replicas. Connect a model to a list of shards like this:

+ +
class AnimalsModel < ApplicationRecord
+  self.abstract_class = true
+
+  connects_to shards: {
+    default: { writing: :primary, reading: :primary_replica },
+    shard_two: { writing: :primary_shard_two, reading: :primary_shard_replica_two }
+  }
+end
+
+ +

Returns an array of database connections.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 81
+def connects_to(database: {}, shards: {})
+  raise NotImplementedError, "`connects_to` can only be called on ActiveRecord::Base or abstract classes" unless self == Base || abstract_class?
+
+  if database.present? && shards.present?
+    raise ArgumentError, "`connects_to` can only accept a `database` or `shards` argument, but not both arguments."
+  end
+
+  connections = []
+
+  database.each do |role, database_key|
+    db_config, owner_name = resolve_config_for_connection(database_key)
+    handler = lookup_connection_handler(role.to_sym)
+
+    self.connection_class = true
+    connections << handler.establish_connection(db_config, owner_name: owner_name, role: role)
+  end
+
+  shards.each do |shard, database_keys|
+    database_keys.each do |role, database_key|
+      db_config, owner_name = resolve_config_for_connection(database_key)
+      handler = lookup_connection_handler(role.to_sym)
+
+      self.connection_class = true
+      connections << handler.establish_connection(db_config, owner_name: owner_name, role: role, shard: shard.to_sym)
+    end
+  end
+
+  connections
+end
+
+
+ +
+ +
+

+ + establish_connection(config_or_env = nil) + +

+ + +
+

Establishes the connection to the database. Accepts a hash as input where the :adapter key must be specified with the name of a database adapter (in lower-case) example for regular databases (MySQL, PostgreSQL, etc):

+ +
ActiveRecord::Base.establish_connection(
+  adapter:  "mysql2",
+  host:     "localhost",
+  username: "myuser",
+  password: "mypass",
+  database: "somedatabase"
+)
+
+ +

Example for SQLite database:

+ +
ActiveRecord::Base.establish_connection(
+  adapter:  "sqlite3",
+  database: "path/to/dbfile"
+)
+
+ +

Also accepts keys as strings (for parsing from YAML for example):

+ +
ActiveRecord::Base.establish_connection(
+  "adapter"  => "sqlite3",
+  "database" => "path/to/dbfile"
+)
+
+ +

Or a URL:

+ +
ActiveRecord::Base.establish_connection(
+  "postgres://myuser:mypass@localhost/somedatabase"
+)
+
+ +

In case ActiveRecord::Base.configurations is set (Rails automatically loads the contents of config/database.yml into it), a symbol can also be given as argument, representing a key in the configuration hash:

+ +
ActiveRecord::Base.establish_connection(:production)
+
+ +

The exceptions AdapterNotSpecified, AdapterNotFound, and ArgumentError may be returned on an error.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 49
+def establish_connection(config_or_env = nil)
+  config_or_env ||= DEFAULT_ENV.call.to_sym
+  db_config, owner_name = resolve_config_for_connection(config_or_env)
+  connection_handler.establish_connection(db_config, owner_name: owner_name, role: current_role, shard: current_shard)
+end
+
+
+ +
+ +
+

+ + prohibit_shard_swapping(enabled = true) + +

+ + +
+

Prohibit swapping shards while inside of the passed block.

+ +

In some cases you may want to be able to swap shards but not allow a nested call to connected_to or connected_to_many to swap again. This is useful in cases you’re using sharding to provide per-request database isolation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 214
+def prohibit_shard_swapping(enabled = true)
+  prev_value = ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
+  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = enabled
+  yield
+ensure
+  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping] = prev_value
+end
+
+
+ +
+ +
+

+ + remove_connection(name = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 321
+def remove_connection(name = nil)
+  name ||= @connection_specification_name if defined?(@connection_specification_name)
+  # if removing a connection that has a pool, we reset the
+  # connection_specification_name so it will use the parent
+  # pool.
+  if connection_handler.retrieve_connection_pool(name, role: current_role, shard: current_shard)
+    self.connection_specification_name = nil
+  end
+
+  connection_handler.remove_connection_pool(name, role: current_role, shard: current_shard)
+end
+
+
+ +
+ +
+

+ + retrieve_connection() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 312
+def retrieve_connection
+  connection_handler.retrieve_connection(connection_specification_name, role: current_role, shard: current_shard)
+end
+
+
+ +
+ +
+

+ + shard_swapping_prohibited?() + +

+ + +
+

Determine whether or not shard swapping is currently prohibited

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 223
+def shard_swapping_prohibited?
+  ActiveSupport::IsolatedExecutionState[:active_record_prohibit_shard_swapping]
+end
+
+
+ +
+ +
+

+ + while_preventing_writes(enabled = true, &block) + +

+ + +
+

Prevent writing to the database regardless of role.

+ +

In some cases you may want to prevent writes to the database even if you are on a database that can write. while_preventing_writes will prevent writes to the database for the duration of the block.

+ +

This method does not provide the same protection as a readonly user and is meant to be a safeguard against accidental writes.

+ +

See READ_QUERY for the queries that are blocked by this method.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/connection_handling.rb, line 238
+def while_preventing_writes(enabled = true, &block)
+  if ActiveRecord.legacy_connection_handling
+    connection_handler.while_preventing_writes(enabled, &block)
+  else
+    connected_to(role: current_role, prevent_writes: enabled, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionNotEstablished.html b/src/7.0/classes/ActiveRecord/ConnectionNotEstablished.html new file mode 100644 index 0000000000..25a1f92ed3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionNotEstablished.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ConnectionNotEstablished +layout: default +--- +
+ +
+
+ +
+ +

Raised when connection to the database could not been established (for example when ActiveRecord::Base.connection= is given a nil object).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ConnectionTimeoutError.html b/src/7.0/classes/ActiveRecord/ConnectionTimeoutError.html new file mode 100644 index 0000000000..f259d2f283 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ConnectionTimeoutError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ConnectionTimeoutError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a connection could not be obtained within the connection acquisition timeout period: because max connections in pool are in use.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Core.html b/src/7.0/classes/ActiveRecord/Core.html new file mode 100644 index 0000000000..3657ec6c70 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Core.html @@ -0,0 +1,1596 @@ +--- +title: ActiveRecord::Core +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + strict_loading_mode
+ + + + +

Class Public methods

+ +
+

+ + configurations() + +

+ + +
+

Returns fully resolved ActiveRecord::DatabaseConfigurations object

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 56
+def self.configurations
+  @@configurations
+end
+
+
+ +
+ +
+

+ + configurations=(config) + +

+ + +
+

Contains the database configuration - as is typically stored in config/database.yml - as an ActiveRecord::DatabaseConfigurations object.

+ +

For example, the following database.yml…

+ +
development:
+  adapter: sqlite3
+  database: db/development.sqlite3
+
+production:
+  adapter: sqlite3
+  database: db/production.sqlite3
+
+ +

…would result in ActiveRecord::Base.configurations to look like this:

+ +
#<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[
+  #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",
+    @name="primary", @config={adapter: "sqlite3", database: "db/development.sqlite3"}>,
+  #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="production",
+    @name="primary", @config={adapter: "sqlite3", database: "db/production.sqlite3"}>
+]>
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 50
+def self.configurations=(config)
+  @@configurations = ActiveRecord::DatabaseConfigurations.new(config)
+end
+
+
+ +
+ +
+

+ + connection_handler() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 94
+def self.connection_handler
+  ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] || default_connection_handler
+end
+
+
+ +
+ +
+

+ + connection_handler=(handler) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 98
+def self.connection_handler=(handler)
+  ActiveSupport::IsolatedExecutionState[:active_record_connection_handler] = handler
+end
+
+
+ +
+ +
+

+ + connection_handlers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 102
+def self.connection_handlers
+  if ActiveRecord.legacy_connection_handling
+  else
+    raise NotImplementedError, "The new connection handling does not support accessing multiple connection handlers."
+  end
+
+  @@connection_handlers ||= {}
+end
+
+
+ +
+ +
+

+ + connection_handlers=(handlers) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 111
+      def self.connection_handlers=(handlers)
+        if ActiveRecord.legacy_connection_handling
+          ActiveSupport::Deprecation.warn(<<~MSG)
+            Using legacy connection handling is deprecated. Please set
+            `legacy_connection_handling` to `false` in your application.
+
+            The new connection handling does not support `connection_handlers`
+            getter and setter.
+
+            Read more about how to migrate at: https://guides.rubyonrails.org/active_record_multiple_databases.html#migrate-to-the-new-connection-handling
+          MSG
+        else
+          raise NotImplementedError, "The new connection handling does not support multiple connection handlers."
+        end
+
+        @@connection_handlers = handlers
+      end
+
+
+ +
+ +
+

+ + current_preventing_writes() + +

+ + +
+

Returns the symbol representing the current setting for preventing writes.

+ +
ActiveRecord::Base.connected_to(role: :reading) do
+  ActiveRecord::Base.current_preventing_writes #=> true
+end
+
+ActiveRecord::Base.connected_to(role: :writing) do
+  ActiveRecord::Base.current_preventing_writes #=> false
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 188
+def self.current_preventing_writes
+  if ActiveRecord.legacy_connection_handling
+    connection_handler.prevent_writes
+  else
+    connected_to_stack.reverse_each do |hash|
+      return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(Base)
+      return hash[:prevent_writes] if !hash[:prevent_writes].nil? && hash[:klasses].include?(connection_class_for_self)
+    end
+
+    false
+  end
+end
+
+
+ +
+ +
+

+ + current_role() + +

+ + +
+

Returns the symbol representing the current connected role.

+ +
ActiveRecord::Base.connected_to(role: :writing) do
+  ActiveRecord::Base.current_role #=> :writing
+end
+
+ActiveRecord::Base.connected_to(role: :reading) do
+  ActiveRecord::Base.current_role #=> :reading
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 147
+def self.current_role
+  if ActiveRecord.legacy_connection_handling
+    connection_handlers.key(connection_handler) || default_role
+  else
+    connected_to_stack.reverse_each do |hash|
+      return hash[:role] if hash[:role] && hash[:klasses].include?(Base)
+      return hash[:role] if hash[:role] && hash[:klasses].include?(connection_class_for_self)
+    end
+
+    default_role
+  end
+end
+
+
+ +
+ +
+

+ + current_shard() + +

+ + +
+

Returns the symbol representing the current connected shard.

+ +
ActiveRecord::Base.connected_to(role: :reading) do
+  ActiveRecord::Base.current_shard #=> :default
+end
+
+ActiveRecord::Base.connected_to(role: :writing, shard: :one) do
+  ActiveRecord::Base.current_shard #=> :one
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 169
+def self.current_shard
+  connected_to_stack.reverse_each do |hash|
+    return hash[:shard] if hash[:shard] && hash[:klasses].include?(Base)
+    return hash[:shard] if hash[:shard] && hash[:klasses].include?(connection_class_for_self)
+  end
+
+  default_shard
+end
+
+
+ +
+ +
+

+ + destroy_association_async_job + +

+ + +
+

Specifies the job used to destroy associations in the background

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 26
+class_attribute :destroy_association_async_job, instance_writer: false, instance_predicate: false, default: false
+
+
+
+ +
+ +
+

+ + enumerate_columns_in_select_statements + +

+ + +
+

Force enumeration of all columns in SELECT statements. e.g. SELECT first_name, last_name FROM ... instead of SELECT * FROM ... This avoids PreparedStatementCacheExpired errors when a column is added to the database while the app is running.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 66
+class_attribute :enumerate_columns_in_select_statements, instance_accessor: false, default: false
+
+
+
+ +
+ +
+

+ + logger + +

+ + +
+

Accepts a logger conforming to the interface of Log4r which is then passed on to any new database connections made and which can be retrieved on both a class and instance level by calling logger.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 20
+class_attribute :logger, instance_writer: false
+
+
+
+ +
+ +
+

+ + new(attributes = nil) + +

+ + +
+

New objects can be instantiated as either empty (pass no construction parameter) or pre-set with attributes but not yet saved (pass a hash with key names matching the associated table column names). In both instances, valid attribute keys are determined by the column names of the associated table – hence you can’t have attributes that aren’t part of the table columns.

+ +

Example:

+ +
# Instantiates a single new object
+User.new(first_name: 'Jamie')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 461
+def initialize(attributes = nil)
+  @new_record = true
+  @attributes = self.class._default_attributes.deep_dup
+
+  init_internals
+  initialize_internals_callback
+
+  assign_attributes(attributes) if attributes
+
+  yield self if block_given?
+  _run_initialize_callbacks
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(other_object) + +

+ + +
+

Allows sort on objects

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 614
+def <=>(other_object)
+  if other_object.is_a?(self.class)
+    to_key <=> other_object.to_key
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + ==(comparison_object) + +

+ + +
+

Returns true if comparison_object is the same exact object, or comparison_object is of the same type and self has an ID and it is equal to comparison_object.id.

+ +

Note that new records are different from any other record by definition, unless the other record is the receiver itself. Besides, if you fetch existing records with select and leave the ID out, you’re on your own, this predicate will return false.

+ +

Note also that destroying a record preserves its ID in the model instance, so deleted models are still comparable.

+
+ + + +
+ Also aliased as: eql? +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 580
+def ==(comparison_object)
+  super ||
+    comparison_object.instance_of?(self.class) &&
+    !id.nil? &&
+    comparison_object.id == id
+end
+
+
+ +
+ +
+

+ + clone + +

+ + +
+

Identical to Ruby’s clone method. This is a “shallow” copy. Be warned that your attributes are not copied. That means that modifying attributes of the clone will modify the original, since they will both point to the same attributes hash. If you need a copy of your attributes hash, please use the dup method.

+ +
user = User.first
+new_user = user.clone
+user.name               # => "Bob"
+new_user.name = "Joe"
+user.name               # => "Joe"
+
+user.object_id == new_user.object_id            # => false
+user.name.object_id == new_user.name.object_id  # => true
+
+user.name.object_id == user.dup.name.object_id  # => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 513
+    
+
+
+ +
+ +
+

+ + connection_handler() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 682
+def connection_handler
+  self.class.connection_handler
+end
+
+
+ +
+ +
+

+ + dup + +

+ + +
+

Duped objects have no id assigned and are treated as new records. Note that this is a “shallow” copy as it copies the object’s attributes only, not its associations. The extent of a “deep” copy is application specific and is therefore left to the application to implement according to its need. The dup method does not preserve the timestamps (created|updated)_(at|on).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 530
+    
+
+
+ +
+ +
+

+ + encode_with(coder) + +

+ + +
+

Populate coder with attributes about this record that should be serialized. The structure of coder defined in this method is guaranteed to match the structure of coder passed to the init_with method.

+ +

Example:

+ +
class Post < ActiveRecord::Base
+end
+coder = {}
+Post.new.encode_with(coder)
+coder # => {"attributes" => {"id" => nil, ... }}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 565
+def encode_with(coder)
+  self.class.yaml_encoder.encode(@attributes, coder)
+  coder["new_record"] = new_record?
+  coder["active_record_yaml_version"] = 2
+end
+
+
+ +
+ +
+

+ + eql?(comparison_object) + +

+ + +
+ +
+ + + + + +
+ Alias for: == +
+ + + +
+ +
+

+ + freeze() + +

+ + +
+

Clone and freeze the attributes hash such that associations are still accessible, even on destroyed records, but cloned models will not be frozen.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 603
+def freeze
+  @attributes = @attributes.clone.freeze
+  self
+end
+
+
+ +
+ +
+

+ + frozen?() + +

+ + +
+

Returns true if the attributes hash has been frozen.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 609
+def frozen?
+  @attributes.frozen?
+end
+
+
+ +
+ +
+

+ + hash() + +

+ + +
+

Delegates to id in order to allow two records of the same type and id to work with something like:

+ +
[ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 590
+def hash
+  id = self.id
+
+  if id
+    self.class.hash ^ id.hash
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + init_with(coder, &block) + +

+ + +
+

Initialize an empty model object from coder. coder should be the result of previously encoding an Active Record model, using encode_with.

+ +
class Post < ActiveRecord::Base
+end
+
+old_post = Post.new(title: "hello world")
+coder = {}
+old_post.encode_with(coder)
+
+post = Post.allocate
+post.init_with(coder)
+post.title # => 'hello world'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 488
+def init_with(coder, &block)
+  coder = LegacyYamlAdapter.convert(coder)
+  attributes = self.class.yaml_encoder.decode(coder)
+  init_with_attributes(attributes, coder["new_record"], &block)
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+

Returns the contents of the record as a nicely formatted string.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 687
+def inspect
+  # We check defined?(@attributes) not to issue warnings if the object is
+  # allocated but not initialized.
+  inspection = if defined?(@attributes) && @attributes
+    self.class.attribute_names.filter_map do |name|
+      if _has_attribute?(name)
+        "#{name}: #{attribute_for_inspect(name)}"
+      end
+    end.join(", ")
+  else
+    "not initialized"
+  end
+
+  "#<#{self.class} #{inspection}>"
+end
+
+
+ +
+ +
+

+ + pretty_print(pp) + +

+ + +
+

Takes a PP and prettily prints this record to it, allowing you to get a nice result from pp record when pp is required.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 705
+def pretty_print(pp)
+  return super if custom_inspect_method_defined?
+  pp.object_address_group(self) do
+    if defined?(@attributes) && @attributes
+      attr_names = self.class.attribute_names.select { |name| _has_attribute?(name) }
+      pp.seplist(attr_names, proc { pp.text "," }) do |attr_name|
+        pp.breakable " "
+        pp.group(1) do
+          pp.text attr_name
+          pp.text ":"
+          pp.breakable
+          value = _read_attribute(attr_name)
+          value = inspection_filter.filter_param(attr_name, value) unless value.nil?
+          pp.pp value
+        end
+      end
+    else
+      pp.breakable " "
+      pp.text "not initialized"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + readonly!() + +

+ + +
+

Marks this record as read only.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 678
+def readonly!
+  @readonly = true
+end
+
+
+ +
+ +
+

+ + readonly?() + +

+ + +
+

Returns true if the record is read only.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 631
+def readonly?
+  @readonly
+end
+
+
+ +
+ +
+

+ + slice(*methods) + +

+ + +
+

Returns a hash of the given methods with their names as keys and returned values as values.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 729
+def slice(*methods)
+  methods.flatten.index_with { |method| public_send(method) }.with_indifferent_access
+end
+
+
+ +
+ +
+

+ + strict_loading!(value = true, mode: :all) + +

+ + +
+

Sets the record to strict_loading mode. This will raise an error if the record tries to lazily load an association.

+ +
user = User.first
+user.strict_loading! # => true
+user.comments
+=> ActiveRecord::StrictLoadingViolationError
+
+ +

Parameters:

+
  • +

    value - Boolean specifying whether to enable or disable strict loading.

    +
  • +

    mode - Symbol specifying strict loading mode. Defaults to :all. Using

    + +
    :n_plus_one_only mode will only raise an error if an association
    +that will lead to an n plus one query is lazily loaded.
    +
    +
+ +

Example:

+ +
user = User.first
+user.strict_loading!(false) # => false
+user.comments
+=> #<ActiveRecord::Associations::CollectionProxy>
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 661
+def strict_loading!(value = true, mode: :all)
+  unless [:all, :n_plus_one_only].include?(mode)
+    raise ArgumentError, "The :mode option must be one of [:all, :n_plus_one_only]."
+  end
+
+  @strict_loading_mode = mode
+  @strict_loading = value
+end
+
+
+ +
+ +
+

+ + strict_loading?() + +

+ + +
+

Returns true if the record is in strict_loading mode.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 636
+def strict_loading?
+  @strict_loading
+end
+
+
+ +
+ +
+

+ + strict_loading_n_plus_one_only?() + +

+ + +
+

Returns true if the record uses strict_loading with :n_plus_one_only mode enabled.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 673
+def strict_loading_n_plus_one_only?
+  @strict_loading_mode == :n_plus_one_only
+end
+
+
+ +
+ +
+

+ + values_at(*methods) + +

+ + +
+

Returns an array of the values returned by the given methods.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 734
+def values_at(*methods)
+  methods.flatten.map! { |method| public_send(method) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Core/ClassMethods.html b/src/7.0/classes/ActiveRecord/Core/ClassMethods.html new file mode 100644 index 0000000000..41de826ec8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Core/ClassMethods.html @@ -0,0 +1,145 @@ +--- +title: ActiveRecord::Core::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + filter_attributes() + +

+ + +
+

Returns columns which shouldn’t be exposed while calling #inspect.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 373
+def filter_attributes
+  if defined?(@filter_attributes)
+    @filter_attributes
+  else
+    superclass.filter_attributes
+  end
+end
+
+
+ +
+ +
+

+ + filter_attributes=(filter_attributes) + +

+ + +
+

Specifies columns which shouldn’t be exposed while calling #inspect.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 382
+def filter_attributes=(filter_attributes)
+  @inspection_filter = nil
+  @filter_attributes = filter_attributes
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Core/InspectionMask.html b/src/7.0/classes/ActiveRecord/Core/InspectionMask.html new file mode 100644 index 0000000000..4252db8c26 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Core/InspectionMask.html @@ -0,0 +1,107 @@ +--- +title: ActiveRecord::Core::InspectionMask +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + pretty_print(pp) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/core.rb, line 776
+def pretty_print(pp)
+  pp.text __getobj__
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/CounterCache.html b/src/7.0/classes/ActiveRecord/CounterCache.html new file mode 100644 index 0000000000..86dca7af8a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/CounterCache.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::CounterCache +layout: default +--- +
+ +
+
+ +
+ +

Active Record Counter Cache

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/CounterCache/ClassMethods.html b/src/7.0/classes/ActiveRecord/CounterCache/ClassMethods.html new file mode 100644 index 0000000000..631ac9bb61 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/CounterCache/ClassMethods.html @@ -0,0 +1,349 @@ +--- +title: ActiveRecord::CounterCache::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrement_counter(counter_name, id, touch: nil) + +

+ + +
+

Decrement a numeric field by one, via a direct SQL update.

+ +

This works the same as increment_counter but reduces the column value by 1 instead of increasing it.

+ +

Parameters

+
  • +

    counter_name - The name of the field that should be decremented.

    +
  • +

    id - The id of the object that should be decremented or an array of ids.

    +
  • +

    :touch - Touch timestamp columns when updating. Pass true to touch updated_at and/or updated_on. Pass a symbol to touch that column or an array of symbols to touch just those ones.

    +
+ +

Examples

+ +
# Decrement the posts_count column for the record with an id of 5
+DiscussionBoard.decrement_counter(:posts_count, 5)
+
+# Decrement the posts_count column for the record with an id of 5
+# and update the updated_at value.
+DiscussionBoard.decrement_counter(:posts_count, 5, touch: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/counter_cache.rb, line 159
+def decrement_counter(counter_name, id, touch: nil)
+  update_counters(id, counter_name => -1, touch: touch)
+end
+
+
+ +
+ +
+

+ + increment_counter(counter_name, id, touch: nil) + +

+ + +
+

Increment a numeric field by one, via a direct SQL update.

+ +

This method is used primarily for maintaining counter_cache columns that are used to store aggregate values. For example, a DiscussionBoard may cache posts_count and comments_count to avoid running an SQL query to calculate the number of posts and comments there are, each time it is displayed.

+ +

Parameters

+
  • +

    counter_name - The name of the field that should be incremented.

    +
  • +

    id - The id of the object that should be incremented or an array of ids.

    +
  • +

    :touch - Touch timestamp columns when updating. Pass true to touch updated_at and/or updated_on. Pass a symbol to touch that column or an array of symbols to touch just those ones.

    +
+ +

Examples

+ +
# Increment the posts_count column for the record with an id of 5
+DiscussionBoard.increment_counter(:posts_count, 5)
+
+# Increment the posts_count column for the record with an id of 5
+# and update the updated_at value.
+DiscussionBoard.increment_counter(:posts_count, 5, touch: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/counter_cache.rb, line 134
+def increment_counter(counter_name, id, touch: nil)
+  update_counters(id, counter_name => 1, touch: touch)
+end
+
+
+ +
+ +
+

+ + reset_counters(id, *counters, touch: nil) + +

+ + +
+

Resets one or more counter caches to their correct value using an SQL count query. This is useful when adding new counter caches, or if the counter has been corrupted or modified directly by SQL.

+ +

Parameters

+
  • +

    id - The id of the object you wish to reset a counter on.

    +
  • +

    counters - One or more association counters to reset. Association name or counter name can be given.

    +
  • +

    :touch - Touch timestamp columns when updating. Pass true to touch updated_at and/or updated_on. Pass a symbol to touch that column or an array of symbols to touch just those ones.

    +
+ +

Examples

+ +
# For the Post with id #1, reset the comments_count
+Post.reset_counters(1, :comments)
+
+# Like above, but also touch the +updated_at+ and/or +updated_on+
+# attributes.
+Post.reset_counters(1, :comments, touch: true)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/counter_cache.rb, line 29
+def reset_counters(id, *counters, touch: nil)
+  object = find(id)
+
+  counters.each do |counter_association|
+    has_many_association = _reflect_on_association(counter_association)
+    unless has_many_association
+      has_many = reflect_on_all_associations(:has_many)
+      has_many_association = has_many.find { |association| association.counter_cache_column && association.counter_cache_column.to_sym == counter_association.to_sym }
+      counter_association = has_many_association.plural_name if has_many_association
+    end
+    raise ArgumentError, "'#{name}' has no association called '#{counter_association}'" unless has_many_association
+
+    if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
+      has_many_association = has_many_association.through_reflection
+    end
+
+    foreign_key  = has_many_association.foreign_key.to_s
+    child_class  = has_many_association.klass
+    reflection   = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
+    counter_name = reflection.counter_cache_column
+
+    updates = { counter_name => object.send(counter_association).count(:all) }
+
+    if touch
+      names = touch if touch != true
+      names = Array.wrap(names)
+      options = names.extract_options!
+      touch_updates = touch_attributes_with_time(*names, **options)
+      updates.merge!(touch_updates)
+    end
+
+    unscoped.where(primary_key => object.id).update_all(updates)
+  end
+
+  true
+end
+
+
+ +
+ +
+

+ + update_counters(id, counters) + +

+ + +
+

A generic “counter updater” implementation, intended primarily to be used by increment_counter and decrement_counter, but which may also be useful on its own. It simply does a direct SQL update for the record with the given ID, altering the given hash of counters by the amount given by the corresponding value:

+ +

Parameters

+
  • +

    id - The id of the object you wish to update a counter on or an array of ids.

    +
  • +

    counters - A Hash containing the names of the fields to update as keys and the amount to update the field by as values.

    +
  • +

    :touch option - Touch timestamp columns when updating. If attribute names are passed, they are updated along with updated_at/on attributes.

    +
+ +

Examples

+ +
# For the Post with id of 5, decrement the comment_count by 1, and
+# increment the action_count by 1
+Post.update_counters 5, comment_count: -1, action_count: 1
+# Executes the following SQL:
+# UPDATE posts
+#    SET comment_count = COALESCE(comment_count, 0) - 1,
+#        action_count = COALESCE(action_count, 0) + 1
+#  WHERE id = 5
+
+# For the Posts with id of 10 and 15, increment the comment_count by 1
+Post.update_counters [10, 15], comment_count: 1
+# Executes the following SQL:
+# UPDATE posts
+#    SET comment_count = COALESCE(comment_count, 0) + 1
+#  WHERE id IN (10, 15)
+
+# For the Posts with id of 10 and 15, increment the comment_count by 1
+# and update the updated_at value for each counter.
+Post.update_counters [10, 15], comment_count: 1, touch: true
+# Executes the following SQL:
+# UPDATE posts
+#    SET comment_count = COALESCE(comment_count, 0) + 1,
+#    `updated_at` = '2016-10-13T09:59:23-05:00'
+#  WHERE id IN (10, 15)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/counter_cache.rb, line 107
+def update_counters(id, counters)
+  unscoped.where!(primary_key => id).update_counters(counters)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DangerousAttributeError.html b/src/7.0/classes/ActiveRecord/DangerousAttributeError.html new file mode 100644 index 0000000000..c125250cea --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DangerousAttributeError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::DangerousAttributeError +layout: default +--- +
+ +
+
+ +
+ +

Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseAlreadyExists.html b/src/7.0/classes/ActiveRecord/DatabaseAlreadyExists.html new file mode 100644 index 0000000000..9f37d250e7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseAlreadyExists.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::DatabaseAlreadyExists +layout: default +--- +
+ +
+
+ +
+ +

Raised when creating a database if it exists.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseConfigurations.html b/src/7.0/classes/ActiveRecord/DatabaseConfigurations.html new file mode 100644 index 0000000000..68cccbc7b4 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseConfigurations.html @@ -0,0 +1,346 @@ +--- +title: ActiveRecord::DatabaseConfigurations +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::DatabaseConfigurations returns an array of DatabaseConfig objects (either a HashConfig or UrlConfig) that are constructed from the application’s database configuration hash or URL string.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + configurations
+ + + + +

Class Public methods

+ +
+

+ + new(configurations = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations.rb, line 19
+def initialize(configurations = {})
+  @configurations = build_configs(configurations)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + blank?() + +

+ + +
+ +
+ + + + + +
+ Alias for: empty? +
+ + + +
+ +
+

+ + configs_for(env_name: nil, name: nil, include_replicas: false, include_hidden: false) + +

+ + +
+

Collects the configs for the environment and optionally the specification name passed in. To include replica configurations pass include_hidden: true.

+ +

If a name is provided a single DatabaseConfig object will be returned, otherwise an array of DatabaseConfig objects will be returned that corresponds with the environment and type requested.

+ +

Options

+
  • +

    env_name: The environment name. Defaults to nil which will collect configs for all environments.

    +
  • +

    name: The db config name (i.e. primary, animals, etc.). Defaults to nil. If no env_name is specified the config for the default env and the passed name will be returned.

    +
  • +

    include_replicas: Deprecated. Determines whether to include replicas in the returned list. Most of the time we’re only iterating over the write connection (i.e. migrations don’t need to run for the write and read connection). Defaults to false.

    +
  • +

    include_hidden: Determines whether to include replicas and configurations hidden by +database_tasks: false+ in the returned list. Most of the time we’re only iterating over the primary connections (i.e. migrations don’t need to run for the write and read connection). Defaults to false.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations.rb, line 45
+def configs_for(env_name: nil, name: nil, include_replicas: false, include_hidden: false)
+  if include_replicas
+    include_hidden = include_replicas
+    ActiveSupport::Deprecation.warn("The kwarg `include_replicas` is deprecated in favor of `include_hidden`. When `include_hidden` is passed, configurations with `replica: true` or `database_tasks: false` will be returned. `include_replicas` will be removed in Rails 7.1.")
+  end
+
+  env_name ||= default_env if name
+  configs = env_with_configs(env_name)
+
+  unless include_hidden
+    configs = configs.select do |db_config|
+      db_config.database_tasks?
+    end
+  end
+
+  if name
+    configs.find do |db_config|
+      db_config.name == name
+    end
+  else
+    configs
+  end
+end
+
+
+ +
+ +
+

+ + empty?() + +

+ + +
+

Checks if the application’s configurations are empty.

+ +

Aliased to blank?

+
+ + + +
+ Also aliased as: blank? +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations.rb, line 98
+def empty?
+  configurations.empty?
+end
+
+
+ +
+ +
+

+ + find_db_config(env) + +

+ + +
+

Returns a single DatabaseConfig object based on the requested environment.

+ +

If the application has multiple databases find_db_config will return the first DatabaseConfig for the environment.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations.rb, line 73
+def find_db_config(env)
+  configurations
+    .sort_by.with_index { |db_config, i| db_config.for_current_env? ? [0, i] : [1, i] }
+    .find do |db_config|
+      db_config.env_name == env.to_s ||
+        (db_config.for_current_env? && db_config.name == env.to_s)
+    end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseConfigurations/HashConfig.html b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/HashConfig.html new file mode 100644 index 0000000000..1f7bc11493 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/HashConfig.html @@ -0,0 +1,788 @@ +--- +title: ActiveRecord::DatabaseConfigurations::HashConfig +layout: default +--- +
+ +
+
+ +
+ +

A HashConfig object is created for each database configuration entry that is created from a hash.

+ +

A hash config:

+ +
{ "development" => { "database" => "db_name" } }
+
+ +

Becomes:

+ +
#<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
+  @env_name="development", @name="primary", @config={database: "db_name"}>
+
+ +

Options

+
  • +

    :env_name - The Rails environment, i.e. “development”.

    +
  • +

    :name - The db config name. In a standard two-tier database configuration this will default to “primary”. In a multiple database three-tier database configuration this corresponds to the name used in the second tier, for example “primary_readonly”.

    +
  • +

    :config - The config hash. This is the hash that contains the database adapter, name, and other important information for database connections.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + configuration_hash
+ + + + +

Class Public methods

+ +
+

+ + new(env_name, name, configuration_hash) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 30
+def initialize(env_name, name, configuration_hash)
+  super(env_name, name)
+  @configuration_hash = configuration_hash.symbolize_keys.freeze
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + adapter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 96
+def adapter
+  configuration_hash[:adapter]
+end
+
+
+ +
+ +
+

+ + checkout_timeout() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 81
+def checkout_timeout
+  (configuration_hash[:checkout_timeout] || 5).to_f
+end
+
+
+ +
+ +
+

+ + database() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 57
+def database
+  configuration_hash[:database]
+end
+
+
+ +
+ +
+

+ + default_schema_cache_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 107
+def default_schema_cache_path
+  "db/schema_cache.yml"
+end
+
+
+ +
+ +
+

+ + host() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 49
+def host
+  configuration_hash[:host]
+end
+
+
+ +
+ +
+

+ + idle_timeout() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 91
+def idle_timeout
+  timeout = configuration_hash.fetch(:idle_timeout, 300).to_f
+  timeout if timeout > 0
+end
+
+
+ +
+ +
+

+ + lazy_schema_cache_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 111
+def lazy_schema_cache_path
+  schema_cache_path || default_schema_cache_path
+end
+
+
+ +
+ +
+

+ + max_queue() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 77
+def max_queue
+  max_threads * 4
+end
+
+
+ +
+ +
+

+ + max_threads() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 73
+def max_threads
+  (configuration_hash[:max_threads] || pool).to_i
+end
+
+
+ +
+ +
+

+ + migrations_paths() + +

+ + +
+

The migrations paths for a database configuration. If the migrations_paths key is present in the config, migrations_paths will return its value.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 45
+def migrations_paths
+  configuration_hash[:migrations_paths]
+end
+
+
+ +
+ +
+

+ + min_threads() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 69
+def min_threads
+  (configuration_hash[:min_threads] || 0).to_i
+end
+
+
+ +
+ +
+

+ + pool() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 65
+def pool
+  (configuration_hash[:pool] || 5).to_i
+end
+
+
+ +
+ +
+

+ + reaping_frequency() + +

+ + +
+

reaping_frequency is configurable mostly for historical reasons, but it could also be useful if someone wants a very low idle_timeout.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 87
+def reaping_frequency
+  configuration_hash.fetch(:reaping_frequency, 60)&.to_f
+end
+
+
+ +
+ +
+

+ + replica?() + +

+ + +
+

Determines whether a database configuration is for a replica / readonly connection. If the replica key is present in the config, replica? will return true.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 38
+def replica?
+  configuration_hash[:replica]
+end
+
+
+ +
+ +
+

+ + schema_cache_path() + +

+ + +
+

The path to the schema cache dump file for a database. If omitted, the filename will be read from ENV or a default will be derived.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 103
+def schema_cache_path
+  configuration_hash[:schema_cache_path]
+end
+
+
+ +
+ +
+

+ + schema_dump(format = ActiveRecord.schema_format) + +

+ + +
+

Determines whether to dump the schema/structure files and the filename that should be used.

+ +

If configuration_hash[:schema_dump] is set to false or nil the schema will not be dumped.

+ +

If the config option is set that will be used. Otherwise Rails will generate the filename from the database config name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/hash_config.rb, line 127
+def schema_dump(format = ActiveRecord.schema_format)
+  if configuration_hash.key?(:schema_dump)
+    if config = configuration_hash[:schema_dump]
+      config
+    end
+  elsif primary?
+    schema_file_type(format)
+  else
+    "#{name}_#{schema_file_type(format)}"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseConfigurations/InvalidConfigurationError.html b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/InvalidConfigurationError.html new file mode 100644 index 0000000000..0ab7e81cee --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/InvalidConfigurationError.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::DatabaseConfigurations::InvalidConfigurationError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseConfigurations/UrlConfig.html b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/UrlConfig.html new file mode 100644 index 0000000000..cf599cee11 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseConfigurations/UrlConfig.html @@ -0,0 +1,154 @@ +--- +title: ActiveRecord::DatabaseConfigurations::UrlConfig +layout: default +--- +
+ +
+
+ +
+ +

A UrlConfig object is created for each database configuration entry that is created from a URL. This can either be a URL string or a hash with a URL in place of the config hash.

+ +

A URL config:

+ +
postgres://localhost/foo
+
+ +

Becomes:

+ +
#<ActiveRecord::DatabaseConfigurations::UrlConfig:0x00007fdc3238f340
+  @env_name="default_env", @name="primary",
+  @config={adapter: "postgresql", database: "foo", host: "localhost"},
+  @url="postgres://localhost/foo">
+
+ +

Options

+
  • +

    :env_name - The Rails environment, i.e. “development”.

    +
  • +

    :name - The db config name. In a standard two-tier database configuration this will default to “primary”. In a multiple database three-tier database configuration this corresponds to the name used in the second tier, for example “primary_readonly”.

    +
  • +

    :url - The database URL.

    +
  • +

    :config - The config hash. This is the hash that contains the database adapter, name, and other important information for database connections.

    +
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + url
+ + + + +

Class Public methods

+ +
+

+ + new(env_name, name, url, configuration_hash = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/database_configurations/url_config.rb, line 34
+def initialize(env_name, name, url, configuration_hash = {})
+  super(env_name, name, configuration_hash)
+
+  @url = url
+  @configuration_hash = @configuration_hash.merge(build_url_hash).freeze
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DatabaseConnectionError.html b/src/7.0/classes/ActiveRecord/DatabaseConnectionError.html new file mode 100644 index 0000000000..9ad109808a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DatabaseConnectionError.html @@ -0,0 +1,197 @@ +--- +title: ActiveRecord::DatabaseConnectionError +layout: default +--- +
+ +
+
+ +
+ +

Raised when connection to the database could not been established because it was not able to connect to the host or when the authorization failed.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + hostname_error(hostname) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 74
+      def hostname_error(hostname)
+        DatabaseConnectionError.new(<<~MSG)
+          There is an issue connecting with your hostname: #{hostname}.\n
+          Please check your database configuration and ensure there is a valid connection to your database.
+        MSG
+      end
+
+
+ +
+ +
+

+ + new(message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 69
+def initialize(message = nil)
+  super(message || "Database connection error")
+end
+
+
+ +
+ +
+

+ + username_error(username) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 81
+      def username_error(username)
+        DatabaseConnectionError.new(<<~MSG)
+          There is an issue connecting to your database with your username/password, username: #{username}.\n
+          Please check your database configuration to ensure the username/password are valid.
+        MSG
+      end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Deadlocked.html b/src/7.0/classes/ActiveRecord/Deadlocked.html new file mode 100644 index 0000000000..0df3510744 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Deadlocked.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::Deadlocked +layout: default +--- +
+ +
+
+ +
+ +

Deadlocked will be raised when a transaction is rolled back by the database when a deadlock is encountered.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DelegatedType.html b/src/7.0/classes/ActiveRecord/DelegatedType.html new file mode 100644 index 0000000000..7aa7de9040 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DelegatedType.html @@ -0,0 +1,288 @@ +--- +title: ActiveRecord::DelegatedType +layout: default +--- +
+ +
+
+ +
+ +

Delegated types

+ +

Class hierarchies can map to relational database tables in many ways. Active Record, for example, offers purely abstract classes, where the superclass doesn’t persist any attributes, and single-table inheritance, where all attributes from all levels of the hierarchy are represented in a single table. Both have their places, but neither are without their drawbacks.

+ +

The problem with purely abstract classes is that all concrete subclasses must persist all the shared attributes themselves in their own tables (also known as class-table inheritance). This makes it hard to do queries across the hierarchy. For example, imagine you have the following hierarchy:

+ +
Entry < ApplicationRecord
+Message < Entry
+Comment < Entry
+
+ +

How do you show a feed that has both Message and Comment records, which can be easily paginated? Well, you can’t! Messages are backed by a messages table and comments by a comments table. You can’t pull from both tables at once and use a consistent OFFSET/LIMIT scheme.

+ +

You can get around the pagination problem by using single-table inheritance, but now you’re forced into a single mega table with all the attributes from all subclasses. No matter how divergent. If a Message has a subject, but the comment does not, well, now the comment does anyway! So STI works best when there’s little divergence between the subclasses and their attributes.

+ +

But there’s a third way: Delegated types. With this approach, the “superclass” is a concrete class that is represented by its own table, where all the superclass attributes that are shared amongst all the “subclasses” are stored. And then each of the subclasses have their own individual tables for additional attributes that are particular to their implementation. This is similar to what’s called multi-table inheritance in Django, but instead of actual inheritance, this approach uses delegation to form the hierarchy and share responsibilities.

+ +

Let’s look at that entry/message/comment example using delegated types:

+ +
# Schema: entries[ id, account_id, creator_id, created_at, updated_at, entryable_type, entryable_id ]
+class Entry < ApplicationRecord
+  belongs_to :account
+  belongs_to :creator
+  delegated_type :entryable, types: %w[ Message Comment ]
+end
+
+module Entryable
+  extend ActiveSupport::Concern
+
+  included do
+    has_one :entry, as: :entryable, touch: true
+  end
+end
+
+# Schema: messages[ id, subject, body ]
+class Message < ApplicationRecord
+  include Entryable
+end
+
+# Schema: comments[ id, content ]
+class Comment < ApplicationRecord
+  include Entryable
+end
+
+ +

As you can see, neither Message nor Comment are meant to stand alone. Crucial metadata for both classes resides in the Entry “superclass”. But the Entry absolutely can stand alone in terms of querying capacity in particular. You can now easily do things like:

+ +
Account.find(1).entries.order(created_at: :desc).limit(50)
+
+ +

Which is exactly what you want when displaying both comments and messages together. The entry itself can be rendered as its delegated type easily, like so:

+ +
# entries/_entry.html.erb
+<%= render "entries/entryables/#{entry.entryable_name}", entry: entry %>
+
+# entries/entryables/_message.html.erb
+<div class="message">
+  <div class="subject"><%= entry.message.subject %></div>
+  <p><%= entry.message.body %></p>
+  <i>Posted on <%= entry.created_at %> by <%= entry.creator.name %></i>
+</div>
+
+# entries/entryables/_comment.html.erb
+<div class="comment">
+  <%= entry.creator.name %> said: <%= entry.comment.content %>
+</div>
+
+ +

Sharing behavior with concerns and controllers

+ +

The entry “superclass” also serves as a perfect place to put all that shared logic that applies to both messages and comments, and which acts primarily on the shared attributes. Imagine:

+ +
class Entry < ApplicationRecord
+  include Eventable, Forwardable, Redeliverable
+end
+
+ +

Which allows you to have controllers for things like ForwardsController and RedeliverableController that both act on entries, and thus provide the shared functionality to both messages and comments.

+ +

Creating new records

+ +

You create a new record that uses delegated typing by creating the delegator and delegatee at the same time, like so:

+ +
Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user
+
+ +

If you need more complicated composition, or you need to perform dependent validation, you should build a factory method or class to take care of the complicated needs. This could be as simple as:

+ +
class Entry < ApplicationRecord
+  def self.create_with_comment(content, creator: Current.user)
+    create! entryable: Comment.new(content: content), creator: creator
+  end
+end
+
+ +

Adding further delegation

+ +

The delegated type shouldn’t just answer the question of what the underlying class is called. In fact, that’s an anti-pattern most of the time. The reason you’re building this hierarchy is to take advantage of polymorphism. So here’s a simple example of that:

+ +
class Entry < ApplicationRecord
+  delegated_type :entryable, types: %w[ Message Comment ]
+  delegate :title, to: :entryable
+end
+
+class Message < ApplicationRecord
+  def title
+    subject
+  end
+end
+
+class Comment < ApplicationRecord
+  def title
+    content.truncate(20)
+  end
+end
+
+ +

Now you can list a bunch of entries, call Entry#title, and polymorphism will provide you with the answer.

+ +

Nested Attributes

+ +

Enabling nested attributes on a delegated_type association allows you to create the entry and message in one go:

+ +
class Entry < ApplicationRecord
+  delegated_type :entryable, types: %w[ Message Comment ]
+  accepts_nested_attributes_for :entryable
+end
+
+params = { entry: { entryable_type: 'Message', entryable_attributes: { subject: 'Smiling' } } }
+entry = Entry.create(params[:entry])
+entry.entryable.id # => 2
+entry.entryable.subject # => 'Smiling'
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + delegated_type(role, types:, **options) + +

+ + +
+

Defines this as a class that’ll delegate its type for the passed role to the class references in types. That’ll create a polymorphic belongs_to relationship to that role, and it’ll add all the delegated type convenience methods:

+ +
class Entry < ApplicationRecord
+  delegated_type :entryable, types: %w[ Message Comment ], dependent: :destroy
+end
+
+Entry#entryable_class # => +Message+ or +Comment+
+Entry#entryable_name  # => "message" or "comment"
+Entry.messages        # => Entry.where(entryable_type: "Message")
+Entry#message?        # => true when entryable_type == "Message"
+Entry#message         # => returns the message record, when entryable_type == "Message", otherwise nil
+Entry#message_id      # => returns entryable_id, when entryable_type == "Message", otherwise nil
+Entry.comments        # => Entry.where(entryable_type: "Comment")
+Entry#comment?        # => true when entryable_type == "Comment"
+Entry#comment         # => returns the comment record, when entryable_type == "Comment", otherwise nil
+Entry#comment_id      # => returns entryable_id, when entryable_type == "Comment", otherwise nil
+
+ +

You can also declare namespaced types:

+ +
class Entry < ApplicationRecord
+  delegated_type :entryable, types: %w[ Message Comment Access::NoticeMessage ], dependent: :destroy
+end
+
+Entry.access_notice_messages
+entry.access_notice_message
+entry.access_notice_message?
+
+ +

Options

+ +

The options are passed directly to the belongs_to call, so this is where you declare dependent etc. The following options can be included to specialize the behavior of the delegated type convenience methods.

+
:foreign_key +
+

Specify the foreign key used for the convenience methods. By default this is guessed to be the passed role with an “_id” suffix. So a class that defines a delegated_type :entryable, types: %w[ Message Comment ] association will use “entryable_id” as the default :foreign_key.

+
:primary_key +
+

Specify the method that returns the primary key of associated object used for the convenience methods. By default this is id.

+
+ +

Option examples:

+ +
class Entry < ApplicationRecord
+  delegated_type :entryable, types: %w[ Message Comment ], primary_key: :uuid, foreign_key: :entryable_uuid
+end
+
+Entry#message_uuid      # => returns entryable_uuid, when entryable_type == "Message", otherwise nil
+Entry#comment_uuid      # => returns entryable_uuid, when entryable_type == "Comment", otherwise nil
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/delegated_type.rb, line 206
+def delegated_type(role, types:, **options)
+  belongs_to role, options.delete(:scope), **options.merge(polymorphic: true)
+  define_delegated_type_methods role, types: types, options: options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncError.html b/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncError.html new file mode 100644 index 0000000000..16482ef897 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncError.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::DestroyAssociationAsyncError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncJob.html b/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncJob.html new file mode 100644 index 0000000000..b83845886b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DestroyAssociationAsyncJob.html @@ -0,0 +1,127 @@ +--- +title: ActiveRecord::DestroyAssociationAsyncJob +layout: default +--- +
+ +
+
+ +
+ +

Job to destroy the records associated with a destroyed record in background.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform( owner_model_name: nil, owner_id: nil, association_class: nil, association_ids: nil, association_primary_key_column: nil, ensuring_owner_was_method: nil ) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/destroy_association_async_job.rb, line 13
+def perform(
+  owner_model_name: nil, owner_id: nil,
+  association_class: nil, association_ids: nil, association_primary_key_column: nil,
+  ensuring_owner_was_method: nil
+)
+  association_model = association_class.constantize
+  owner_class = owner_model_name.constantize
+  owner = owner_class.find_by(owner_class.primary_key.to_sym => owner_id)
+
+  if !owner_destroyed?(owner, ensuring_owner_was_method)
+    raise DestroyAssociationAsyncError, "owner record not destroyed"
+  end
+
+  association_model.where(association_primary_key_column => association_ids).find_each do |r|
+    r.destroy
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DynamicMatchers.html b/src/7.0/classes/ActiveRecord/DynamicMatchers.html new file mode 100644 index 0000000000..c1810b25cc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DynamicMatchers.html @@ -0,0 +1,71 @@ +--- +title: ActiveRecord::DynamicMatchers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DynamicMatchers/FindBy.html b/src/7.0/classes/ActiveRecord/DynamicMatchers/FindBy.html new file mode 100644 index 0000000000..294cc8fa28 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DynamicMatchers/FindBy.html @@ -0,0 +1,149 @@ +--- +title: ActiveRecord::DynamicMatchers::FindBy +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + prefix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 96
+def self.prefix
+  "find_by"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finder() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 100
+def finder
+  "find_by"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DynamicMatchers/FindByBang.html b/src/7.0/classes/ActiveRecord/DynamicMatchers/FindByBang.html new file mode 100644 index 0000000000..9c6db337ab --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DynamicMatchers/FindByBang.html @@ -0,0 +1,188 @@ +--- +title: ActiveRecord::DynamicMatchers::FindByBang +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + prefix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 108
+def self.prefix
+  "find_by"
+end
+
+
+ +
+ +
+

+ + suffix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 112
+def self.suffix
+  "!"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finder() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 116
+def finder
+  "find_by!"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/DynamicMatchers/Method.html b/src/7.0/classes/ActiveRecord/DynamicMatchers/Method.html new file mode 100644 index 0000000000..4838e8f9ef --- /dev/null +++ b/src/7.0/classes/ActiveRecord/DynamicMatchers/Method.html @@ -0,0 +1,390 @@ +--- +title: ActiveRecord::DynamicMatchers::Method +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + matchers
+ [R] + attribute_names
+ [R] + model
+ [R] + name
+ + + + +

Class Public methods

+ +
+

+ + match(model, name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 32
+def match(model, name)
+  klass = matchers.find { |k| k.pattern.match?(name) }
+  klass.new(model, name) if klass
+end
+
+
+ +
+ +
+

+ + new(model, method_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 52
+def initialize(model, method_name)
+  @model           = model
+  @name            = method_name.to_s
+  @attribute_names = @name.match(self.class.pattern)[1].split("_and_")
+  @attribute_names.map! { |name| @model.attribute_aliases[name] || name }
+end
+
+
+ +
+ +
+

+ + pattern() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 37
+def pattern
+  @pattern ||= /\A#{prefix}_([_a-zA-Z]\w*)#{suffix}\Z/
+end
+
+
+ +
+ +
+

+ + prefix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 41
+def prefix
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + suffix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 45
+def suffix
+  ""
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + define() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 63
+        def define
+          model.class_eval <<-CODE, __FILE__, __LINE__ + 1
+            def self.#{name}(#{signature})
+              #{body}
+            end
+          CODE
+        end
+
+
+ +
+ +
+

+ + valid?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/dynamic_matchers.rb, line 59
+def valid?
+  attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/EagerLoadPolymorphicError.html b/src/7.0/classes/ActiveRecord/EagerLoadPolymorphicError.html new file mode 100644 index 0000000000..1c6696c73c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/EagerLoadPolymorphicError.html @@ -0,0 +1,117 @@ +--- +title: ActiveRecord::EagerLoadPolymorphicError +layout: default +--- +
+ +
+
+ +
+ +

This error is raised when trying to eager load a polymorphic association using a JOIN. Eager loading polymorphic associations is only possible with ActiveRecord::Relation#preload.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(reflection = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/associations.rb, line 228
+def initialize(reflection = nil)
+  if reflection
+    super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
+  else
+    super("Eager load polymorphic error.")
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption.html b/src/7.0/classes/ActiveRecord/Encryption.html new file mode 100644 index 0000000000..edf4685f23 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption.html @@ -0,0 +1,245 @@ +--- +title: ActiveRecord::Encryption +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + eager_load!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption.rb, line 49
+def self.eager_load!
+  super
+
+  Cipher.eager_load!
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Cipher.html b/src/7.0/classes/ActiveRecord/Encryption/Cipher.html new file mode 100644 index 0000000000..86390be19a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Cipher.html @@ -0,0 +1,275 @@ +--- +title: ActiveRecord::Encryption::Cipher +layout: default +--- +
+ +
+
+ +
+ +

The algorithm used for encrypting and decrypting Message objects.

+ +

It uses AES-256-GCM. It will generate a random IV for non deterministic encryption (default) or derive an initialization vector from the encrypted content for deterministic encryption.

+ +

See Cipher::Aes256Gcm.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_ENCODING=Encoding::UTF_8
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_message, key:) + +

+ + +
+

Decrypt the provided Message.

+ +

When key is an Array, it will try all the keys raising a ActiveRecord::Encryption::Errors::Decryption if none works.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher.rb, line 25
+def decrypt(encrypted_message, key:)
+  try_to_decrypt_with_each(encrypted_message, keys: Array(key)).tap do |decrypted_text|
+    decrypted_text.force_encoding(encrypted_message.headers.encoding || DEFAULT_ENCODING)
+  end
+end
+
+
+ +
+ +
+

+ + encrypt(clean_text, key:, deterministic: false) + +

+ + +
+

Encrypts the provided text and return an encrypted Message.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher.rb, line 15
+def encrypt(clean_text, key:, deterministic: false)
+  cipher_for(key, deterministic: deterministic).encrypt(clean_text).tap do |message|
+    message.headers.encoding = clean_text.encoding.name unless clean_text.encoding == DEFAULT_ENCODING
+  end
+end
+
+
+ +
+ +
+

+ + iv_length() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher.rb, line 35
+def iv_length
+  Aes256Gcm.iv_length
+end
+
+
+ +
+ +
+

+ + key_length() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher.rb, line 31
+def key_length
+  Aes256Gcm.key_length
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Cipher/Aes256Gcm.html b/src/7.0/classes/ActiveRecord/Encryption/Cipher/Aes256Gcm.html new file mode 100644 index 0000000000..2958f009ea --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Cipher/Aes256Gcm.html @@ -0,0 +1,335 @@ +--- +title: ActiveRecord::Encryption::Cipher::Aes256Gcm +layout: default +--- +
+ +
+
+ +
+ +

A 256-GCM cipher.

+ +

By default it will use random initialization vectors. For deterministic encryption, it will use a SHA-256 hash of the text to encrypt and the secret.

+ +

See Encryptor

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
CIPHER_TYPE="aes-256-gcm"
 
+ + + + + + +

Class Public methods

+ +
+

+ + iv_length() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher/aes256_gcm.rb, line 23
+def iv_length
+  OpenSSL::Cipher.new(CIPHER_TYPE).iv_len
+end
+
+
+ +
+ +
+

+ + key_length() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher/aes256_gcm.rb, line 19
+def key_length
+  OpenSSL::Cipher.new(CIPHER_TYPE).key_len
+end
+
+
+ +
+ +
+

+ + new(secret, deterministic: false) + +

+ + +
+

When iv not provided, it will generate a random iv on each encryption operation (default and recommended operation)

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher/aes256_gcm.rb, line 30
+def initialize(secret, deterministic: false)
+  @secret = secret
+  @deterministic = deterministic
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher/aes256_gcm.rb, line 56
+def decrypt(encrypted_message)
+  encrypted_data = encrypted_message.payload
+  iv = encrypted_message.headers.iv
+  auth_tag = encrypted_message.headers.auth_tag
+
+  # Currently the OpenSSL bindings do not raise an error if auth_tag is
+  # truncated, which would allow an attacker to easily forge it. See
+  # https://github.com/ruby/openssl/issues/63
+  raise ActiveRecord::Encryption::Errors::EncryptedContentIntegrity if auth_tag.nil? || auth_tag.bytes.length != 16
+
+  cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
+
+  cipher.decrypt
+  cipher.key = @secret
+  cipher.iv = iv
+
+  cipher.auth_tag = auth_tag
+  cipher.auth_data = ""
+
+  decrypted_data = encrypted_data.empty? ? encrypted_data : cipher.update(encrypted_data)
+  decrypted_data << cipher.final
+
+  decrypted_data
+rescue OpenSSL::Cipher::CipherError, TypeError, ArgumentError
+  raise ActiveRecord::Encryption::Errors::Decryption
+end
+
+
+ +
+ +
+

+ + encrypt(clear_text) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/cipher/aes256_gcm.rb, line 35
+def encrypt(clear_text)
+  # This code is extracted from +ActiveSupport::MessageEncryptor+. Not using it directly because we want to control
+  # the message format and only serialize things once at the +ActiveRecord::Encryption::Message+ level. Also, this
+  # cipher is prepared to deal with deterministic/non deterministic encryption modes.
+
+  cipher = OpenSSL::Cipher.new(CIPHER_TYPE)
+  cipher.encrypt
+  cipher.key = @secret
+
+  iv = generate_iv(cipher, clear_text)
+  cipher.iv = iv
+
+  encrypted_data = clear_text.empty? ? clear_text.dup : cipher.update(clear_text)
+  encrypted_data << cipher.final
+
+  ActiveRecord::Encryption::Message.new(payload: encrypted_data).tap do |message|
+    message.headers.iv = iv
+    message.headers.auth_tag = cipher.auth_tag
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Config.html b/src/7.0/classes/ActiveRecord/Encryption/Config.html new file mode 100644 index 0000000000..08cce6c8d3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Config.html @@ -0,0 +1,262 @@ +--- +title: ActiveRecord::Encryption::Config +layout: default +--- +
+ +
+
+ +
+ +

Container of configuration options

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + add_to_filter_parameters
+ [RW] + deterministic_key
+ [RW] + encrypt_fixtures
+ [RW] + excluded_from_filter_parameters
+ [RW] + extend_queries
+ [RW] + forced_encoding_for_deterministic_encryption
+ [RW] + key_derivation_salt
+ [RW] + previous_schemes
+ [RW] + primary_key
+ [RW] + store_key_references
+ [RW] + support_unencrypted_data
+ [RW] + validate_column_size
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/config.rb, line 11
+def initialize
+  set_defaults
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + previous=(previous_schemes_properties) + +

+ + +
+

Configure previous encryption schemes.

+ +
config.active_record.encryption.previous = [ { key_provider: MyOldKeyProvider.new } ]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/config.rb, line 18
+def previous=(previous_schemes_properties)
+  previous_schemes_properties.each do |properties|
+    add_previous_scheme(**properties)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Configurable.html b/src/7.0/classes/ActiveRecord/Encryption/Configurable.html new file mode 100644 index 0000000000..5fc357564b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Configurable.html @@ -0,0 +1,154 @@ +--- +title: ActiveRecord::Encryption::Configurable +layout: default +--- +
+ +
+
+ +
+ +

Configuration API for ActiveRecord::Encryption

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + excluded_from_filter_parameters?(filter_parameter) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/configurable.rb, line 61
+def excluded_from_filter_parameters?(filter_parameter)
+  ActiveRecord::Encryption.config.excluded_from_filter_parameters.find { |excluded_filter| excluded_filter.to_s == filter_parameter }
+end
+
+
+ +
+ +
+

+ + on_encrypted_attribute_declared(&block) + +

+ + +
+

Register callback to be invoked when an encrypted attribute is declared.

+ +

Example:

+ +
ActiveRecord::Encryption.on_encrypted_attribute_declared do |klass, attribute_name|
+  ...
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/configurable.rb, line 42
+def on_encrypted_attribute_declared(&block)
+  self.encrypted_attribute_declaration_listeners ||= Concurrent::Array.new
+  self.encrypted_attribute_declaration_listeners << block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Context.html b/src/7.0/classes/ActiveRecord/Encryption/Context.html new file mode 100644 index 0000000000..87440b57ad --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Context.html @@ -0,0 +1,142 @@ +--- +title: ActiveRecord::Encryption::Context +layout: default +--- +
+ +
+
+ +
+ +

An encryption context configures the different entities used to perform encryption:

+
  • +

    A key provider

    +
  • +

    A key generator

    +
  • +

    An encryptor, the facade to encrypt data

    +
  • +

    A cipher, the encryption algorithm

    +
  • +

    A message serializer

    +
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PROPERTIES=%i[ key_provider key_generator cipher message_serializer encryptor frozen_encryption ]
 
+ + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/context.rb, line 19
+def initialize
+  set_defaults
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Contexts.html b/src/7.0/classes/ActiveRecord/Encryption/Contexts.html new file mode 100644 index 0000000000..81ac069357 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Contexts.html @@ -0,0 +1,296 @@ +--- +title: ActiveRecord::Encryption::Contexts +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::Encryption uses encryption contexts to configure the different entities used to encrypt/decrypt at a given moment in time.

+ +

By default, the library uses a default encryption context. This is the Context that gets configured initially via config.active_record.encryption options. Library users can define nested encryption contexts when running blocks of code.

+ +

See Context.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + context() + +

+ + +
+

Returns the current context. By default it will return the current context.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/contexts.rb, line 62
+def context
+  self.current_custom_context || self.default_context
+end
+
+
+ +
+ +
+

+ + current_custom_context() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/contexts.rb, line 66
+def current_custom_context
+  self.custom_contexts&.last
+end
+
+
+ +
+ +
+

+ + protecting_encrypted_data(&block) + +

+ + +
+

Runs the provided block in an encryption context where:

+
  • +

    Reading encrypted content will return its ciphertext.

    +
  • +

    Writing encrypted content will fail.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/contexts.rb, line 57
+def protecting_encrypted_data(&block)
+  with_encryption_context encryptor: ActiveRecord::Encryption::EncryptingOnlyEncryptor.new, frozen_encryption: true, &block
+end
+
+
+ +
+ +
+

+ + with_encryption_context(properties) + +

+ + +
+

Configures a custom encryption context to use when running the provided block of code.

+ +

It supports overriding all the properties defined in Context.

+ +

Example:

+ +
ActiveRecord::Encryption.with_encryption_context(encryptor: ActiveRecord::Encryption::NullEncryptor.new) do
+  ...
+end
+
+ +

Encryption contexts can be nested.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/contexts.rb, line 33
+def with_encryption_context(properties)
+  self.custom_contexts ||= []
+  self.custom_contexts << default_context.dup
+  properties.each do |key, value|
+    self.current_custom_context.send("#{key}=", value)
+  end
+
+  yield
+ensure
+  self.custom_contexts.pop
+end
+
+
+ +
+ +
+

+ + without_encryption(&block) + +

+ + +
+

Runs the provided block in an encryption context where encryption is disabled:

+
  • +

    Reading encrypted content will return its ciphertexts.

    +
  • +

    Writing encrypted content will write its clear text.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/contexts.rb, line 49
+def without_encryption(&block)
+  with_encryption_context encryptor: ActiveRecord::Encryption::NullEncryptor.new, &block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/DerivedSecretKeyProvider.html b/src/7.0/classes/ActiveRecord/Encryption/DerivedSecretKeyProvider.html new file mode 100644 index 0000000000..76f476a068 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/DerivedSecretKeyProvider.html @@ -0,0 +1,113 @@ +--- +title: ActiveRecord::Encryption::DerivedSecretKeyProvider +layout: default +--- +
+ +
+
+ +
+ +

A KeyProvider that derives keys from passwords.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(passwords) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/derived_secret_key_provider.rb, line 7
+def initialize(passwords)
+  super(Array(passwords).collect { |password| Key.derive_from(password) })
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/DeterministicKeyProvider.html b/src/7.0/classes/ActiveRecord/Encryption/DeterministicKeyProvider.html new file mode 100644 index 0000000000..7e6bff7c36 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/DeterministicKeyProvider.html @@ -0,0 +1,115 @@ +--- +title: ActiveRecord::Encryption::DeterministicKeyProvider +layout: default +--- +
+ +
+
+ +
+ +

A KeyProvider that derives keys from passwords.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(password) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/deterministic_key_provider.rb, line 7
+def initialize(password)
+  passwords = Array(password)
+  raise ActiveRecord::Encryption::Errors::Configuration, "Deterministic encryption keys can't be rotated" if passwords.length > 1
+  super(passwords)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/EncryptableRecord.html b/src/7.0/classes/ActiveRecord/Encryption/EncryptableRecord.html new file mode 100644 index 0000000000..147e1ac16c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/EncryptableRecord.html @@ -0,0 +1,735 @@ +--- +title: ActiveRecord::Encryption::EncryptableRecord +layout: default +--- +
+ +
+
+ +
+ +

This is the concern mixed in Active Record models to make them encryptable. It adds the encrypts attribute declaration, as well as the API to encrypt and decrypt records.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ORIGINAL_ATTRIBUTE_PREFIX="original_"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + add_length_validation_for_encrypted_columns() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 127
+def add_length_validation_for_encrypted_columns
+  encrypted_attributes&.each do |attribute_name|
+    validate_column_size attribute_name
+  end
+end
+
+
+ +
+ +
+

+ + ciphertext_for(attribute_name) + +

+ + +
+

Returns the ciphertext for attribute_name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 146
+def ciphertext_for(attribute_name)
+  read_attribute_before_type_cast(attribute_name)
+end
+
+
+ +
+ +
+

+ + decrypt() + +

+ + +
+

Decrypts all the encryptable attributes and saves the changes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 156
+def decrypt
+  decrypt_attributes if has_encrypted_attributes?
+end
+
+
+ +
+ +
+

+ + deterministic_encrypted_attributes() + +

+ + +
+

Returns the list of deterministic encryptable attributes in the model class.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 56
+def deterministic_encrypted_attributes
+  @deterministic_encrypted_attributes ||= encrypted_attributes&.find_all do |attribute_name|
+    type_for_attribute(attribute_name).deterministic?
+  end
+end
+
+
+ +
+ +
+

+ + encrypt() + +

+ + +
+

Encrypts all the encryptable attributes and saves the changes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 151
+def encrypt
+  encrypt_attributes if has_encrypted_attributes?
+end
+
+
+ +
+ +
+

+ + encrypt_attribute(name, attribute_scheme) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 82
+def encrypt_attribute(name, attribute_scheme)
+  encrypted_attributes << name.to_sym
+
+  attribute name do |cast_type|
+    ActiveRecord::Encryption::EncryptedAttributeType.new scheme: attribute_scheme, cast_type: cast_type
+  end
+
+  preserve_original_encrypted(name) if attribute_scheme.ignore_case?
+  ActiveRecord::Encryption.encrypted_attribute_was_declared(self, name)
+end
+
+
+ +
+ +
+

+ + encrypted_attribute?(attribute_name) + +

+ + +
+

Returns whether a given attribute is encrypted or not.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 141
+def encrypted_attribute?(attribute_name)
+  ActiveRecord::Encryption.encryptor.encrypted? ciphertext_for(attribute_name)
+end
+
+
+ +
+ +
+

+ + encrypts(*names, key_provider: nil, key: nil, deterministic: false, downcase: false, ignore_case: false, previous: [], **context_properties) + +

+ + +
+

Encrypts the name attribute.

+ +

Options

+
  • +

    :key_provider - A key provider to provide encryption and decryption keys. Defaults to ActiveRecord::Encryption.key_provider.

    +
  • +

    :key - A password to derive the key from. It’s a shorthand for a :key_provider that serves derivated keys. Both options can’t be used at the same time.

    +
  • +

    :deterministic - By default, encryption is not deterministic. It will use a random initialization vector for each encryption operation. This means that encrypting the same content with the same key twice will generate different ciphertexts. When set to true, it will generate the initialization vector based on the encrypted content. This means that the same content will generate the same ciphertexts. This enables querying encrypted text with Active Record. Deterministic encryption will use the oldest encryption scheme to encrypt new data by default. You can change this by setting +deterministic: { fixed: false }+. That will make it use the newest encryption scheme for encrypting new data.

    +
  • +

    :downcase - When true, it converts the encrypted content to downcase automatically. This allows to effectively ignore case when querying data. Notice that the case is lost. Use :ignore_case if you are interested in preserving it.

    +
  • +

    :ignore_case - When true, it behaves like :downcase but, it also preserves the original case in a specially designated column +original_<name>+. When reading the encrypted content, the version with the original case is served. But you can still execute queries that will ignore the case. This option can only be used when :deterministic is true.

    +
  • +

    :context_properties - Additional properties that will override Context settings when this attribute is encrypted and decrypted. E.g: encryptor:, cipher:, message_serializer:, etc.

    +
  • +

    :previous - List of previous encryption schemes. When provided, they will be used in order when trying to read the attribute. Each entry of the list can contain the properties supported by encrypts. Also, when deterministic encryption is used, they will be used to generate additional ciphertexts to check in the queries.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 45
+def encrypts(*names, key_provider: nil, key: nil, deterministic: false, downcase: false, ignore_case: false, previous: [], **context_properties)
+  self.encrypted_attributes ||= Set.new # not using :default because the instance would be shared across classes
+  scheme = scheme_for key_provider: key_provider, key: key, deterministic: deterministic, downcase: downcase, \
+      ignore_case: ignore_case, previous: previous, **context_properties
+
+  names.each do |name|
+    encrypt_attribute name, scheme
+  end
+end
+
+
+ +
+ +
+

+ + global_previous_schemes_for(scheme) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 76
+def global_previous_schemes_for(scheme)
+  ActiveRecord::Encryption.config.previous_schemes.collect do |previous_scheme|
+    scheme.merge(previous_scheme)
+  end
+end
+
+
+ +
+ +
+

+ + load_schema!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 121
+def load_schema!
+  super
+
+  add_length_validation_for_encrypted_columns if ActiveRecord::Encryption.config.validate_column_size
+end
+
+
+ +
+ +
+

+ + override_accessors_to_preserve_original(name, original_attribute_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 104
+def override_accessors_to_preserve_original(name, original_attribute_name)
+  include(Module.new do
+    define_method name do
+      if ((value = super()) && encrypted_attribute?(name)) || !ActiveRecord::Encryption.config.support_unencrypted_data
+        send(original_attribute_name)
+      else
+        value
+      end
+    end
+
+    define_method "#{name}=" do |value|
+      self.send "#{original_attribute_name}=", value
+      super(value)
+    end
+  end)
+end
+
+
+ +
+ +
+

+ + preserve_original_encrypted(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 93
+def preserve_original_encrypted(name)
+  original_attribute_name = "#{ORIGINAL_ATTRIBUTE_PREFIX}#{name}".to_sym
+
+  if !ActiveRecord::Encryption.config.support_unencrypted_data && !column_names.include?(original_attribute_name.to_s)
+    raise Errors::Configuration, "To use :ignore_case for '#{name}' you must create an additional column named '#{original_attribute_name}'"
+  end
+
+  encrypts original_attribute_name
+  override_accessors_to_preserve_original name, original_attribute_name
+end
+
+
+ +
+ +
+

+ + scheme_for(key_provider: nil, key: nil, deterministic: false, downcase: false, ignore_case: false, previous: [], **context_properties) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 68
+def scheme_for(key_provider: nil, key: nil, deterministic: false, downcase: false, ignore_case: false, previous: [], **context_properties)
+  ActiveRecord::Encryption::Scheme.new(key_provider: key_provider, key: key, deterministic: deterministic,
+                                       downcase: downcase, ignore_case: ignore_case, **context_properties).tap do |scheme|
+    scheme.previous_schemes = global_previous_schemes_for(scheme) +
+      Array.wrap(previous).collect { |scheme_config| ActiveRecord::Encryption::Scheme.new(**scheme_config) }
+  end
+end
+
+
+ +
+ +
+

+ + source_attribute_from_preserved_attribute(attribute_name) + +

+ + +
+

Given a attribute name, it returns the name of the source attribute when it’s a preserved one.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 63
+def source_attribute_from_preserved_attribute(attribute_name)
+  attribute_name.to_s.sub(ORIGINAL_ATTRIBUTE_PREFIX, "") if /^#{ORIGINAL_ATTRIBUTE_PREFIX}/.match?(attribute_name)
+end
+
+
+ +
+ +
+

+ + validate_column_size(attribute_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptable_record.rb, line 133
+def validate_column_size(attribute_name)
+  if limit = columns_hash[attribute_name.to_s]&.limit
+    validates_length_of attribute_name, maximum: limit
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/EncryptedAttributeType.html b/src/7.0/classes/ActiveRecord/Encryption/EncryptedAttributeType.html new file mode 100644 index 0000000000..142d01659f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/EncryptedAttributeType.html @@ -0,0 +1,284 @@ +--- +title: ActiveRecord::Encryption::EncryptedAttributeType +layout: default +--- +
+ +
+
+ +
+ +

An ActiveModel::Type::Value that encrypts/decrypts strings of text.

+ +

This is the central piece that connects the encryption system with encrypts declarations in the model classes. Whenever you declare an attribute as encrypted, it configures an EncryptedAttributeType for that attribute.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + cast_type
+ [R] + scheme
+ + + + +

Class Public methods

+ +
+

+ + new(scheme:, cast_type: ActiveModel::Type::String.new, previous_type: false) + +

+ + +
+

Options

+
  • +

    :scheme - A Scheme with the encryption properties for this attribute.

    +
  • +

    :cast_type - A type that will be used to serialize (before encrypting) and deserialize (after decrypting). ActiveModel::Type::String by default.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypted_attribute_type.rb, line 23
+def initialize(scheme:, cast_type: ActiveModel::Type::String.new, previous_type: false)
+  super()
+  @scheme = scheme
+  @cast_type = cast_type
+  @previous_type = previous_type
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + changed_in_place?(raw_old_value, new_value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypted_attribute_type.rb, line 42
+def changed_in_place?(raw_old_value, new_value)
+  old_value = raw_old_value.nil? ? nil : deserialize(raw_old_value)
+  old_value != new_value
+end
+
+
+ +
+ +
+

+ + deserialize(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypted_attribute_type.rb, line 30
+def deserialize(value)
+  cast_type.deserialize decrypt(value)
+end
+
+
+ +
+ +
+

+ + serialize(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypted_attribute_type.rb, line 34
+def serialize(value)
+  if serialize_with_oldest?
+    serialize_with_oldest(value)
+  else
+    serialize_with_current(value)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/EncryptedFixtures.html b/src/7.0/classes/ActiveRecord/Encryption/EncryptedFixtures.html new file mode 100644 index 0000000000..6d33e43dd6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/EncryptedFixtures.html @@ -0,0 +1,104 @@ +--- +title: ActiveRecord::Encryption::EncryptedFixtures +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(fixture, model_class) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypted_fixtures.rb, line 6
+def initialize(fixture, model_class)
+  @clean_values = {}
+  encrypt_fixture_data(fixture, model_class)
+  process_preserved_original_columns(fixture, model_class)
+  super
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/EncryptingOnlyEncryptor.html b/src/7.0/classes/ActiveRecord/Encryption/EncryptingOnlyEncryptor.html new file mode 100644 index 0000000000..d74160da78 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/EncryptingOnlyEncryptor.html @@ -0,0 +1,113 @@ +--- +title: ActiveRecord::Encryption::EncryptingOnlyEncryptor +layout: default +--- +
+ +
+
+ +
+ +

An encryptor that can encrypt data but can’t decrypt it.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_text, key_provider: nil, cipher_options: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encrypting_only_encryptor.rb, line 7
+def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
+  encrypted_text
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Encryptor.html b/src/7.0/classes/ActiveRecord/Encryption/Encryptor.html new file mode 100644 index 0000000000..89f93ae18d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Encryptor.html @@ -0,0 +1,275 @@ +--- +title: ActiveRecord::Encryption::Encryptor +layout: default +--- +
+ +
+
+ +
+ +

An encryptor exposes the encryption API that ActiveRecord::Encryption::EncryptedAttributeType uses for encrypting and decrypting attribute values.

+ +

It interacts with a KeyProvider for getting the keys, and delegate to ActiveRecord::Encryption::Cipher the actual encryption algorithm.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DECRYPT_ERRORS=[OpenSSL::Cipher::CipherError, Errors::EncryptedContentIntegrity, Errors::Decryption]
 
ENCODING_ERRORS=[EncodingError, Errors::Encoding]
 
THRESHOLD_TO_JUSTIFY_COMPRESSION=140.bytes
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_text, key_provider: default_key_provider, cipher_options: {}) + +

+ + +
+

Decrypts a clean_text and returns the result as clean text

+ +

Options

+
:key_provider +
+

Key provider to use for the encryption operation. It will default to ActiveRecord::Encryption.key_provider when not provided

+
:cipher_options +
+

Cipher-specific options that will be passed to the Cipher configured in ActiveRecord::Encryption.cipher

+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptor.rb, line 52
+def decrypt(encrypted_text, key_provider: default_key_provider, cipher_options: {})
+  message = deserialize_message(encrypted_text)
+  keys = key_provider.decryption_keys(message)
+  raise Errors::Decryption unless keys.present?
+  uncompress_if_needed(cipher.decrypt(message, key: keys.collect(&:secret), **cipher_options), message.headers.compressed)
+rescue *(ENCODING_ERRORS + DECRYPT_ERRORS)
+  raise Errors::Decryption
+end
+
+
+ +
+ +
+

+ + encrypt(clear_text, key_provider: default_key_provider, cipher_options: {}) + +

+ + +
+

Encrypts clean_text and returns the encrypted result

+ +

Internally, it will:

+
  1. +

    Create a new ActiveRecord::Encryption::Message

    +
  2. +

    Compress and encrypt clean_text as the message payload

    +
  3. +

    Serialize it with ActiveRecord::Encryption.message_serializer (ActiveRecord::Encryption::SafeMarshal by default)

    +
  4. +

    Encode the result with Base 64

    +
+ +

Options

+
:key_provider +
+

Key provider to use for the encryption operation. It will default to ActiveRecord::Encryption.key_provider when not provided.

+
:cipher_options +
+

Cipher-specific options that will be passed to the Cipher configured in ActiveRecord::Encryption.cipher

+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptor.rb, line 34
+def encrypt(clear_text, key_provider: default_key_provider, cipher_options: {})
+  clear_text = force_encoding_if_needed(clear_text) if cipher_options[:deterministic]
+
+  validate_payload_type(clear_text)
+  serialize_message build_encrypted_message(clear_text, key_provider: key_provider, cipher_options: cipher_options)
+end
+
+
+ +
+ +
+

+ + encrypted?(text) + +

+ + +
+

Returns whether the text is encrypted or not

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/encryptor.rb, line 62
+def encrypted?(text)
+  deserialize_message(text)
+  true
+rescue Errors::Encoding, *DECRYPT_ERRORS
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/EnvelopeEncryptionKeyProvider.html b/src/7.0/classes/ActiveRecord/Encryption/EnvelopeEncryptionKeyProvider.html new file mode 100644 index 0000000000..ae967e94c8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/EnvelopeEncryptionKeyProvider.html @@ -0,0 +1,205 @@ +--- +title: ActiveRecord::Encryption::EnvelopeEncryptionKeyProvider +layout: default +--- +
+ +
+
+ +
+ +

Implements a simple envelope encryption approach where:

+
  • +

    It generates a random data-encryption key for each encryption operation.

    +
  • +

    It stores the generated key along with the encrypted payload. It encrypts this key with the master key provided in the active_record_encryption.primary_key credential.

    +
+ +

This provider can work with multiple master keys. It will use the last one for encrypting.

+ +

When config.active_record.encryption.store_key_references is true, it will also store a reference to the specific master key that was used to encrypt the data-encryption key. When not set, it will try all the configured master keys looking for the right one, in order to return the right decryption key.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + active_primary_key() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/envelope_encryption_key_provider.rb, line 31
+def active_primary_key
+  @active_primary_key ||= primary_key_provider.encryption_key
+end
+
+
+ +
+ +
+

+ + decryption_keys(encrypted_message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/envelope_encryption_key_provider.rb, line 26
+def decryption_keys(encrypted_message)
+  secret = decrypt_data_key(encrypted_message)
+  secret ? [ActiveRecord::Encryption::Key.new(secret)] : []
+end
+
+
+ +
+ +
+

+ + encryption_key() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/envelope_encryption_key_provider.rb, line 18
+def encryption_key
+  random_secret = generate_random_secret
+  ActiveRecord::Encryption::Key.new(random_secret).tap do |key|
+    key.public_tags.encrypted_data_key = encrypt_data_key(random_secret)
+    key.public_tags.encrypted_data_key_id = active_primary_key.id if ActiveRecord::Encryption.config.store_key_references
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors.html b/src/7.0/classes/ActiveRecord/Encryption/Errors.html new file mode 100644 index 0000000000..0439058d82 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors.html @@ -0,0 +1,89 @@ +--- +title: ActiveRecord::Encryption::Errors +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/Base.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/Base.html new file mode 100644 index 0000000000..4709d72fbe --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/Base.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/Configuration.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/Configuration.html new file mode 100644 index 0000000000..73dd34db51 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/Configuration.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/Decryption.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/Decryption.html new file mode 100644 index 0000000000..7789e59173 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/Decryption.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::Decryption +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/Encoding.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/Encoding.html new file mode 100644 index 0000000000..9147805573 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/Encoding.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::Encoding +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/EncryptedContentIntegrity.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/EncryptedContentIntegrity.html new file mode 100644 index 0000000000..89d3ad7ed8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/EncryptedContentIntegrity.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::EncryptedContentIntegrity +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/Encryption.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/Encryption.html new file mode 100644 index 0000000000..ae4390123d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/Encryption.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::Encryption +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Errors/ForbiddenClass.html b/src/7.0/classes/ActiveRecord/Encryption/Errors/ForbiddenClass.html new file mode 100644 index 0000000000..b19edc2dbc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Errors/ForbiddenClass.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Encryption::Errors::ForbiddenClass +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries.html new file mode 100644 index 0000000000..30fa7dd2ba --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries.html @@ -0,0 +1,166 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries +layout: default +--- +
+ +
+
+ +
+ +

Automatically expand encrypted arguments to support querying both encrypted and unencrypted data

+ +

Active Record Encryption supports querying the db using deterministic attributes. For example:

+ +
Contact.find_by(email_address: "jorge@hey.com")
+
+ +

The value “jorge@hey.com” will get encrypted automatically to perform the query. But there is a problem while the data is being encrypted. This won’t work. During that time, you need these queries to be:

+ +
Contact.find_by(email_address: [ "jorge@hey.com", "<encrypted jorge@hey.com>" ])
+
+ +

This patches ActiveRecord to support this automatically. It addresses both:

+ + +

ActiveRecord::Base relies on ActiveRecord::Relation (ActiveRecord::QueryMethods) but it does some prepared statements caching. That’s why we need to intercept ActiveRecord::Base as soon as it’s invoked (so that the proper prepared statement is cached).

+ +

When modifying this file run performance tests in test/performance/extended_deterministic_queries_performance_test.rb to

+ +
make sure performance overhead is acceptable.
+
+ +

We will extend this to support previous “encryption context” versions in future iterations

+ +

@TODO Experimental. Support for every kind of query is pending @TODO It should not patch anything if not needed (no previous schemes or no support for previous encryption schemes)

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + install_support() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 34
+def self.install_support
+  ActiveRecord::Relation.prepend(RelationQueries)
+  ActiveRecord::Base.include(CoreQueries)
+  ActiveRecord::Encryption::EncryptedAttributeType.prepend(ExtendedEncryptableType)
+  Arel::Nodes::HomogeneousIn.prepend(InWithAdditionalValues)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/AdditionalValue.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/AdditionalValue.html new file mode 100644 index 0000000000..13e61f2b92 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/AdditionalValue.html @@ -0,0 +1,130 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::AdditionalValue +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + type
+ [R] + value
+ + + + +

Class Public methods

+ +
+

+ + new(value, type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 124
+def initialize(value, type)
+  @type = type
+  @value = process(value)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/CoreQueries.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/CoreQueries.html new file mode 100644 index 0000000000..46b5b86129 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/CoreQueries.html @@ -0,0 +1,116 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::CoreQueries +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + find_by(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 114
+def find_by(*args)
+  process_encrypted_query_arguments(args, false) unless self.deterministic_encrypted_attributes&.empty?
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/EncryptedQueryArgumentProcessor.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/EncryptedQueryArgumentProcessor.html new file mode 100644 index 0000000000..5e87913e0e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/EncryptedQueryArgumentProcessor.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::EncryptedQueryArgumentProcessor +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/ExtendedEncryptableType.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/ExtendedEncryptableType.html new file mode 100644 index 0000000000..ced1569764 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/ExtendedEncryptableType.html @@ -0,0 +1,105 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::ExtendedEncryptableType +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + serialize(data) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 136
+def serialize(data)
+  if data.is_a?(AdditionalValue)
+    data.value
+  else
+    super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/InWithAdditionalValues.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/InWithAdditionalValues.html new file mode 100644 index 0000000000..38da51cdde --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/InWithAdditionalValues.html @@ -0,0 +1,144 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::InWithAdditionalValues +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + encryption_aware_type_caster() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 150
+def encryption_aware_type_caster
+  if attribute.type_caster.is_a?(ActiveRecord::Encryption::EncryptedAttributeType)
+    attribute.type_caster.cast_type
+  else
+    attribute.type_caster
+  end
+end
+
+
+ +
+ +
+

+ + proc_for_binds() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 146
+def proc_for_binds
+  -> value { ActiveModel::Attribute.with_cast_value(attribute.name, value, encryption_aware_type_caster) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/RelationQueries.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/RelationQueries.html new file mode 100644 index 0000000000..20aa42c54d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicQueries/RelationQueries.html @@ -0,0 +1,234 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicQueries::RelationQueries +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + exists?(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 89
+def exists?(*args)
+  process_encrypted_query_arguments_if_needed(args)
+  super
+end
+
+
+ +
+ +
+

+ + find_or_create_by(attributes, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 94
+def find_or_create_by(attributes, &block)
+  find_by(attributes.dup) || create(attributes, &block)
+end
+
+
+ +
+ +
+

+ + find_or_create_by!(attributes, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 98
+def find_or_create_by!(attributes, &block)
+  find_by(attributes.dup) || create!(attributes, &block)
+end
+
+
+ +
+ +
+

+ + where(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_queries.rb, line 84
+def where(*args)
+  process_encrypted_query_arguments_if_needed(args)
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator.html new file mode 100644 index 0000000000..72468369f6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator.html @@ -0,0 +1,114 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + install_support() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb, line 6
+def self.install_support
+  ActiveRecord::Validations::UniquenessValidator.prepend(EncryptedUniquenessValidator)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator/EncryptedUniquenessValidator.html b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator/EncryptedUniquenessValidator.html new file mode 100644 index 0000000000..838a4405a4 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ExtendedDeterministicUniquenessValidator/EncryptedUniquenessValidator.html @@ -0,0 +1,112 @@ +--- +title: ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator::EncryptedUniquenessValidator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + validate_each(record, attribute, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb, line 11
+def validate_each(record, attribute, value)
+  super(record, attribute, value)
+
+  klass = record.class
+  klass.deterministic_encrypted_attributes&.each do |attribute_name|
+    encrypted_type = klass.type_for_attribute(attribute_name)
+    [ encrypted_type, *encrypted_type.previous_types ].each do |type|
+      encrypted_value = type.serialize(value)
+      ActiveRecord::Encryption.without_encryption do
+        super(record, attribute, encrypted_value)
+      end
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Key.html b/src/7.0/classes/ActiveRecord/Encryption/Key.html new file mode 100644 index 0000000000..d431150e54 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Key.html @@ -0,0 +1,220 @@ +--- +title: ActiveRecord::Encryption::Key +layout: default +--- +
+ +
+
+ +
+ +

A key is a container for a given secret

+ +

Optionally, it can include public_tags. These tags are meant to be stored in clean (public) and can be used, for example, to include information that references the key for a future retrieval operation.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + public_tags
+ [R] + secret
+ + + + +

Class Public methods

+ +
+

+ + derive_from(password) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key.rb, line 18
+def self.derive_from(password)
+  secret = ActiveRecord::Encryption.key_generator.derive_key_from(password)
+  ActiveRecord::Encryption::Key.new(secret)
+end
+
+
+ +
+ +
+

+ + new(secret) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key.rb, line 13
+def initialize(secret)
+  @secret = secret
+  @public_tags = Properties.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + id() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key.rb, line 23
+def id
+  Digest::SHA1.hexdigest(secret).first(4)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/KeyGenerator.html b/src/7.0/classes/ActiveRecord/Encryption/KeyGenerator.html new file mode 100644 index 0000000000..20007c6c6b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/KeyGenerator.html @@ -0,0 +1,200 @@ +--- +title: ActiveRecord::Encryption::KeyGenerator +layout: default +--- +
+ +
+
+ +
+ +

Utility for generating and deriving random keys.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + derive_key_from(password, length: key_length) + +

+ + +
+

Derives a key from the given password. The key will have a size in bytes of :length (configured Cipher‘s length by default)

+ +

The generated key will be salted with the value of ActiveRecord::Encryption.key_derivation_salt

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_generator.rb, line 32
+def derive_key_from(password, length: key_length)
+  ActiveSupport::KeyGenerator.new(password).generate_key(ActiveRecord::Encryption.config.key_derivation_salt, length)
+end
+
+
+ +
+ +
+

+ + generate_random_hex_key(length: key_length) + +

+ + +
+

Returns a random key in hexadecimal format. The key will have a size in bytes of :length (configured Cipher‘s length by default)

+ +

Hexadecimal format is handy for representing keys as printable text. To maximize the space of characters used, it is good practice including not printable characters. Hexadecimal format ensures that generated keys are representable with plain text

+ +

To convert back to the original string with the desired length:

+ +
[ value ].pack("H*")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_generator.rb, line 24
+def generate_random_hex_key(length: key_length)
+  generate_random_key(length: length).unpack("H*")[0]
+end
+
+
+ +
+ +
+

+ + generate_random_key(length: key_length) + +

+ + +
+

Returns a random key. The key will have a size in bytes of :length (configured Cipher‘s length by default)

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_generator.rb, line 10
+def generate_random_key(length: key_length)
+  SecureRandom.random_bytes(length)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/KeyProvider.html b/src/7.0/classes/ActiveRecord/Encryption/KeyProvider.html new file mode 100644 index 0000000000..27ff3591ce --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/KeyProvider.html @@ -0,0 +1,211 @@ +--- +title: ActiveRecord::Encryption::KeyProvider +layout: default +--- +
+ +
+
+ +
+ +

A KeyProvider serves keys:

+
  • +

    An encryption key

    +
  • +

    A list of potential decryption keys. Serving multiple decryption keys supports rotation-schemes where new keys are added but old keys need to continue working

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(keys) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_provider.rb, line 11
+def initialize(keys)
+  @keys = Array(keys)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + decryption_keys(encrypted_message) + +

+ + +
+

Returns the list of decryption keys

+ +

When the message holds a reference to its encryption key, it will return an array with that key. If not, it will return the list of keys.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_provider.rb, line 32
+def decryption_keys(encrypted_message)
+  if encrypted_message.headers.encrypted_data_key_id
+    keys_grouped_by_id[encrypted_message.headers.encrypted_data_key_id]
+  else
+    @keys
+  end
+end
+
+
+ +
+ +
+

+ + encryption_key() + +

+ + +
+

Returns the first key in the list as the active key to perform encryptions

+ +

When ActiveRecord::Encryption.config.store_key_references is true, the key will include a public tag referencing the key itself. That key will be stored in the public headers of the encrypted message

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/key_provider.rb, line 20
+def encryption_key
+  @encryption_key ||= @keys.last.tap do |key|
+    key.public_tags.encrypted_data_key_id = key.id if ActiveRecord::Encryption.config.store_key_references
+  end
+
+  @encryption_key
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Message.html b/src/7.0/classes/ActiveRecord/Encryption/Message.html new file mode 100644 index 0000000000..7dae544bb6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Message.html @@ -0,0 +1,187 @@ +--- +title: ActiveRecord::Encryption::Message +layout: default +--- +
+ +
+
+ +
+ +

A message defines the structure of the data we store in encrypted attributes. It contains:

+
  • +

    An encrypted payload

    +
  • +

    A list of unencrypted headers

    +
+ +

See Encryptor#encrypt

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + == +
  • + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + headers
+ [RW] + payload
+ + + + +

Class Public methods

+ +
+

+ + new(payload: nil, headers: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/message.rb, line 14
+def initialize(payload: nil, headers: {})
+  validate_payload_type(payload)
+
+  @payload = payload
+  @headers = Properties.new(headers)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other_message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/message.rb, line 21
+def ==(other_message)
+  payload == other_message.payload && headers == other_message.headers
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/MessageSerializer.html b/src/7.0/classes/ActiveRecord/Encryption/MessageSerializer.html new file mode 100644 index 0000000000..d14a7931d2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/MessageSerializer.html @@ -0,0 +1,170 @@ +--- +title: ActiveRecord::Encryption::MessageSerializer +layout: default +--- +
+ +
+
+ +
+ +

A message serializer that serializes Messages with JSON.

+ +

The generated structure is pretty simple:

+ +
{
+  p: <payload>,
+  h: {
+    header1: value1,
+    header2: value2,
+    ...
+  }
+}
+
+ +

Both the payload and the header values are encoded with Base64 to prevent JSON parsing errors and encoding issues when storing the resulting serialized data.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + dump(message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/message_serializer.rb, line 29
+def dump(message)
+  raise ActiveRecord::Encryption::Errors::ForbiddenClass unless message.is_a?(ActiveRecord::Encryption::Message)
+  JSON.dump message_to_json(message)
+end
+
+
+ +
+ +
+

+ + load(serialized_content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/message_serializer.rb, line 22
+def load(serialized_content)
+  data = JSON.parse(serialized_content)
+  parse_message(data, 1)
+rescue JSON::ParserError
+  raise ActiveRecord::Encryption::Errors::Encoding
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/NullEncryptor.html b/src/7.0/classes/ActiveRecord/Encryption/NullEncryptor.html new file mode 100644 index 0000000000..edd2beae90 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/NullEncryptor.html @@ -0,0 +1,191 @@ +--- +title: ActiveRecord::Encryption::NullEncryptor +layout: default +--- +
+ +
+
+ +
+ +

An encryptor that won’t decrypt or encrypt. It will just return the passed values

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_text, key_provider: nil, cipher_options: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/null_encryptor.rb, line 12
+def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
+  encrypted_text
+end
+
+
+ +
+ +
+

+ + encrypt(clean_text, key_provider: nil, cipher_options: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/null_encryptor.rb, line 8
+def encrypt(clean_text, key_provider: nil, cipher_options: {})
+  clean_text
+end
+
+
+ +
+ +
+

+ + encrypted?(text) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/null_encryptor.rb, line 16
+def encrypted?(text)
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Properties.html b/src/7.0/classes/ActiveRecord/Encryption/Properties.html new file mode 100644 index 0000000000..e3a96aa96e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Properties.html @@ -0,0 +1,325 @@ +--- +title: ActiveRecord::Encryption::Properties +layout: default +--- +
+ +
+
+ +
+ +

This is a wrapper for a hash of encryption properties. It is used by Key (public tags) and Message (headers).

+ +

Since properties are serialized in messages, it is important for storage efficiency to keep their keys as short as possible. It defines accessors for common properties that will keep these keys very short while exposing a readable name.

+ +
message.headers.encrypted_data_key # instead of message.headers[:k]
+
+ +

See Properties::DEFAULT_PROPERTIES, Key, Message

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
ALLOWED_VALUE_CLASSES=[String, ActiveRecord::Encryption::Message, Numeric, TrueClass, FalseClass, Symbol, NilClass]
 
DEFAULT_PROPERTIES={ +encrypted_data_key: "k", +encrypted_data_key_id: "i", +compressed: "c", +iv: "iv", +auth_tag: "at", +encoding: "e" +}
 

For each entry it generates an accessor exposing the full name

+ + + + + + +

Class Public methods

+ +
+

+ + new(initial_properties = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/properties.rb, line 42
+def initialize(initial_properties = {})
+  @data = {}
+  add(initial_properties)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + []=(key, value) + +

+ + +
+

Set a value for a given key

+ +

It will raise an EncryptedContentIntegrity if the value exists

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/properties.rb, line 50
+def []=(key, value)
+  raise Errors::EncryptedContentIntegrity, "Properties can't be overridden: #{key}" if key?(key)
+  validate_value_type(value)
+  data[key] = value
+end
+
+
+ +
+ +
+

+ + add(other_properties) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/properties.rb, line 62
+def add(other_properties)
+  other_properties.each do |key, value|
+    self[key.to_sym] = value
+  end
+end
+
+
+ +
+ +
+

+ + to_h() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/properties.rb, line 68
+def to_h
+  data
+end
+
+
+ +
+ +
+

+ + validate_value_type(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/properties.rb, line 56
+def validate_value_type(value)
+  unless ALLOWED_VALUE_CLASSES.find { |klass| value.is_a?(klass) }
+    raise ActiveRecord::Encryption::Errors::ForbiddenClass, "Can't store a #{value.class}, only properties of type #{ALLOWED_VALUE_CLASSES.inspect} are allowed"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/ReadOnlyNullEncryptor.html b/src/7.0/classes/ActiveRecord/Encryption/ReadOnlyNullEncryptor.html new file mode 100644 index 0000000000..8c3ce147a6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/ReadOnlyNullEncryptor.html @@ -0,0 +1,193 @@ +--- +title: ActiveRecord::Encryption::ReadOnlyNullEncryptor +layout: default +--- +
+ +
+
+ +
+ +

A NullEncryptor that will raise an error when trying to encrypt data

+ +

This is useful when you want to reveal ciphertexts for debugging purposes and you want to make sure you won’t overwrite any encryptable attribute with the wrong content.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrypt(encrypted_text, key_provider: nil, cipher_options: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/read_only_null_encryptor.rb, line 15
+def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
+  encrypted_text
+end
+
+
+ +
+ +
+

+ + encrypt(clean_text, key_provider: nil, cipher_options: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/read_only_null_encryptor.rb, line 11
+def encrypt(clean_text, key_provider: nil, cipher_options: {})
+  raise Errors::Encryption, "This encryptor is read-only"
+end
+
+
+ +
+ +
+

+ + encrypted?(text) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/read_only_null_encryptor.rb, line 19
+def encrypted?(text)
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Encryption/Scheme.html b/src/7.0/classes/ActiveRecord/Encryption/Scheme.html new file mode 100644 index 0000000000..824cbae28b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Encryption/Scheme.html @@ -0,0 +1,468 @@ +--- +title: ActiveRecord::Encryption::Scheme +layout: default +--- +
+ +
+
+ +
+ +

A container of attribute encryption options.

+ +

It validates and serves attribute encryption options.

+ +

See EncryptedAttributeType, Context

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + previous_schemes
+ + + + +

Class Public methods

+ +
+

+ + new(key_provider: nil, key: nil, deterministic: nil, downcase: nil, ignore_case: nil, previous_schemes: nil, **context_properties) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 13
+def initialize(key_provider: nil, key: nil, deterministic: nil, downcase: nil, ignore_case: nil,
+               previous_schemes: nil, **context_properties)
+  # Initializing all attributes to +nil+ as we want to allow a "not set" semantics so that we
+  # can merge schemes without overriding values with defaults. See +#merge+
+
+  @key_provider_param = key_provider
+  @key = key
+  @deterministic = deterministic
+  @downcase = downcase || ignore_case
+  @ignore_case = ignore_case
+  @previous_schemes_param = previous_schemes
+  @previous_schemes = Array.wrap(previous_schemes)
+  @context_properties = context_properties
+
+  validate_config!
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + deterministic?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 38
+def deterministic?
+  @deterministic
+end
+
+
+ +
+ +
+

+ + downcase?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 34
+def downcase?
+  @downcase
+end
+
+
+ +
+ +
+

+ + fixed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 42
+def fixed?
+  # by default deterministic encryption is fixed
+  @fixed ||= @deterministic && (!@deterministic.is_a?(Hash) || @deterministic[:fixed])
+end
+
+
+ +
+ +
+

+ + ignore_case?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 30
+def ignore_case?
+  @ignore_case
+end
+
+
+ +
+ +
+

+ + key_provider() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 47
+def key_provider
+  @key_provider ||= begin
+    validate_keys!
+    @key_provider_param || build_key_provider
+  end
+end
+
+
+ +
+ +
+

+ + merge(other_scheme) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 54
+def merge(other_scheme)
+  self.class.new(**to_h.merge(other_scheme.to_h))
+end
+
+
+ +
+ +
+

+ + to_h() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 58
+def to_h
+  { key_provider: @key_provider_param, key: @key, deterministic: @deterministic, downcase: @downcase, ignore_case: @ignore_case,
+    previous_schemes: @previous_schemes_param, **@context_properties }.compact
+end
+
+
+ +
+ +
+

+ + with_context(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/encryption/scheme.rb, line 63
+def with_context(&block)
+  if @context_properties.present?
+    ActiveRecord::Encryption.with_encryption_context(**@context_properties, &block)
+  else
+    block.call
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Enum.html b/src/7.0/classes/ActiveRecord/Enum.html new file mode 100644 index 0000000000..78d7ad66c8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Enum.html @@ -0,0 +1,216 @@ +--- +title: ActiveRecord::Enum +layout: default +--- +
+ +
+
+ +
+ +

Declare an enum attribute where the values map to integers in the database, but can be queried by name. Example:

+ +
class Conversation < ActiveRecord::Base
+  enum :status, [ :active, :archived ]
+end
+
+# conversation.update! status: 0
+conversation.active!
+conversation.active? # => true
+conversation.status  # => "active"
+
+# conversation.update! status: 1
+conversation.archived!
+conversation.archived? # => true
+conversation.status    # => "archived"
+
+# conversation.status = 1
+conversation.status = "archived"
+
+conversation.status = nil
+conversation.status.nil? # => true
+conversation.status      # => nil
+
+ +

Scopes based on the allowed values of the enum field will be provided as well. With the above example:

+ +
Conversation.active
+Conversation.not_active
+Conversation.archived
+Conversation.not_archived
+
+ +

Of course, you can also query them directly if the scopes don’t fit your needs:

+ +
Conversation.where(status: [:active, :archived])
+Conversation.where.not(status: :active)
+
+ +

Defining scopes can be disabled by setting :scopes to false.

+ +
class Conversation < ActiveRecord::Base
+  enum :status, [ :active, :archived ], scopes: false
+end
+
+ +

You can set the default enum value by setting :default, like:

+ +
class Conversation < ActiveRecord::Base
+  enum :status, [ :active, :archived ], default: :active
+end
+
+conversation = Conversation.new
+conversation.status # => "active"
+
+ +

It’s possible to explicitly map the relation between attribute and database integer with a hash:

+ +
class Conversation < ActiveRecord::Base
+  enum :status, active: 0, archived: 1
+end
+
+ +

Finally it’s also possible to use a string column to persist the enumerated value. Note that this will likely lead to slower database queries:

+ +
class Conversation < ActiveRecord::Base
+  enum :status, active: "active", archived: "archived"
+end
+
+ +

Note that when an array is used, the implicit mapping from the values to database integers is derived from the order the values appear in the array. In the example, :active is mapped to 0 as it’s the first element, and :archived is mapped to 1. In general, the i-th element is mapped to i-1 in the database.

+ +

Therefore, once a value is added to the enum array, its position in the array must be maintained, and new values should only be added to the end of the array. To remove unused values, the explicit hash syntax should be used.

+ +

In rare circumstances you might need to access the mapping directly. The mappings are exposed through a class method with the pluralized attribute name, which return the mapping in a ActiveSupport::HashWithIndifferentAccess :

+ +
Conversation.statuses[:active]    # => 0
+Conversation.statuses["archived"] # => 1
+
+ +

Use that class method when you need to know the ordinal value of an enum. For example, you can use that when manually building SQL strings:

+ +
Conversation.where("status <> ?", Conversation.statuses[:archived])
+
+ +

You can use the :prefix or :suffix options when you need to define multiple enums with same values. If the passed value is true, the methods are prefixed/suffixed with the name of the enum. It is also possible to supply a custom value:

+ +
class Conversation < ActiveRecord::Base
+  enum :status, [ :active, :archived ], suffix: true
+  enum :comments_status, [ :active, :inactive ], prefix: :comments
+end
+
+ +

With the above example, the bang and predicate methods along with the associated scopes are now prefixed and/or suffixed accordingly:

+ +
conversation.active_status!
+conversation.archived_status? # => false
+
+conversation.comments_inactive!
+conversation.comments_active? # => false
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + enum(name = nil, values = nil, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/enum.rb, line 167
+def enum(name = nil, values = nil, **options)
+  if name
+    values, options = options, {} unless values
+    return _enum(name, values, **options)
+  end
+
+  definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default)
+  options.transform_keys! { |key| :"#{key[1..-1]}" }
+
+  definitions.each { |name, values| _enum(name, values, **options) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/EnvironmentMismatchError.html b/src/7.0/classes/ActiveRecord/EnvironmentMismatchError.html new file mode 100644 index 0000000000..027922269a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/EnvironmentMismatchError.html @@ -0,0 +1,115 @@ +--- +title: ActiveRecord::EnvironmentMismatchError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(current: nil, stored: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 198
+def initialize(current: nil, stored: nil)
+  msg = +"You are attempting to modify a database that was last run in `#{ stored }` environment.\n"
+  msg << "You are running in `#{ current }` environment. "
+  msg << "If you are sure you want to continue, first set the environment using:\n\n"
+  msg << "        bin/rails db:environment:set"
+  if defined?(Rails.env)
+    super("#{msg} RAILS_ENV=#{::Rails.env}\n\n")
+  else
+    super("#{msg}\n\n")
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ExclusiveConnectionTimeoutError.html b/src/7.0/classes/ActiveRecord/ExclusiveConnectionTimeoutError.html new file mode 100644 index 0000000000..c76f10044c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ExclusiveConnectionTimeoutError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ExclusiveConnectionTimeoutError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a pool was unable to get ahold of all its connections to perform a “group” action such as ActiveRecord::Base.connection_pool.disconnect! or ActiveRecord::Base.clear_reloadable_connections!.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Explain.html b/src/7.0/classes/ActiveRecord/Explain.html new file mode 100644 index 0000000000..8c1bb258cd --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Explain.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Explain +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/FinderMethods.html b/src/7.0/classes/ActiveRecord/FinderMethods.html new file mode 100644 index 0000000000..3b34d6d67d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/FinderMethods.html @@ -0,0 +1,1360 @@ +--- +title: ActiveRecord::FinderMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ONE_AS_ONE="1 AS one"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + exists?(conditions = :none) + +

+ + +
+

Returns true if a record exists in the table that matches the id or conditions given, or false otherwise. The argument can take six forms:

+
  • +

    Integer - Finds the record with this primary key.

    +
  • +

    String - Finds the record with a primary key corresponding to this string (such as '5').

    +
  • +

    Array - Finds the record that matches these where-style conditions (such as ['name LIKE ?', "%#{query}%"]).

    +
  • +

    Hash - Finds the record that matches these where-style conditions (such as {name: 'David'}).

    +
  • +

    false - Returns always false.

    +
  • +

    No args - Returns false if the relation is empty, true otherwise.

    +
+ +

For more information about specifying conditions as a hash or array, see the Conditions section in the introduction to ActiveRecord::Base.

+ +

Note: You can’t pass in a condition as a string (like name = 'Jamie'), since it would be sanitized and then queried against the primary key column, like id = 'name = \'Jamie\''.

+ +
Person.exists?(5)
+Person.exists?('5')
+Person.exists?(['name LIKE ?', "%#{query}%"])
+Person.exists?(id: [1, 4, 8])
+Person.exists?(name: 'David')
+Person.exists?(false)
+Person.exists?
+Person.where(name: 'Spartacus', rating: 4).exists?
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 326
+    def exists?(conditions = :none)
+      if Base === conditions
+        raise ArgumentError, <<-MSG.squish
+          You are passing an instance of ActiveRecord::Base to `exists?`.
+          Please pass the id of the object by calling `.id`.
+        MSG
+      end
+
+      return false if !conditions || limit_value == 0
+
+      if eager_loading?
+        relation = apply_join_dependency(eager_loading: false)
+        return relation.exists?(conditions)
+      end
+
+      relation = construct_relation_for_exists(conditions)
+      return false if relation.where_clause.contradiction?
+
+      skip_query_cache_if_necessary { connection.select_rows(relation.arel, "#{name} Exists?").size == 1 }
+    end
+
+
+ +
+ +
+

+ + fifth() + +

+ + +
+

Find the fifth record. If no order is defined it will order by primary key.

+ +
Person.fifth # returns the fifth object fetched by SELECT * FROM people
+Person.offset(3).fifth # returns the fifth object from OFFSET 3 (which is OFFSET 7)
+Person.where(["user_name = :u", { u: user_name }]).fifth
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 240
+def fifth
+  find_nth 4
+end
+
+
+ +
+ +
+

+ + fifth!() + +

+ + +
+

Same as fifth but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 246
+def fifth!
+  fifth || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + find(*args) + +

+ + +
+

Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). If one or more records cannot be found for the requested ids, then ActiveRecord::RecordNotFound will be raised. If the primary key is an integer, find by id coerces its arguments by using to_i.

+ +
Person.find(1)          # returns the object for ID = 1
+Person.find("1")        # returns the object for ID = 1
+Person.find("31-sarah") # returns the object for ID = 31
+Person.find(1, 2, 6)    # returns an array for objects with IDs in (1, 2, 6)
+Person.find([7, 17])    # returns an array for objects with IDs in (7, 17)
+Person.find([1])        # returns an array for the object with ID = 1
+Person.where("administrator = 1").order("created_on DESC").find(1)
+
+ +

NOTE: The returned records are in the same order as the ids you provide. If you want the results to be sorted by database, you can use ActiveRecord::QueryMethods#where method and provide an explicit ActiveRecord::QueryMethods#order option. But ActiveRecord::QueryMethods#where method doesn’t raise ActiveRecord::RecordNotFound.

+ +

Find with lock

+ +

Example for find with a lock: Imagine two concurrent transactions: each will read person.visits == 2, add 1 to it, and save, resulting in two saves of person.visits = 3. By locking the row, the second transaction has to wait until the first is finished; we get the expected person.visits == 4.

+ +
Person.transaction do
+  person = Person.lock(true).find(1)
+  person.visits += 1
+  person.save!
+end
+
+ +

Variations of find

+ +
Person.where(name: 'Spartacus', rating: 4)
+# returns a chainable list (which can be empty).
+
+Person.find_by(name: 'Spartacus', rating: 4)
+# returns the first item or nil.
+
+Person.find_or_initialize_by(name: 'Spartacus', rating: 4)
+# returns the first item or returns a new instance (requires you call .save to persist against the database).
+
+Person.find_or_create_by(name: 'Spartacus', rating: 4)
+# returns the first item or creates it and returns it.
+
+ +

Alternatives for find

+ +
Person.where(name: 'Spartacus', rating: 4).exists?(conditions = :none)
+# returns a boolean indicating if any record with the given conditions exist.
+
+Person.where(name: 'Spartacus', rating: 4).select("field1, field2, field3")
+# returns a chainable list of instances with only the mentioned fields.
+
+Person.where(name: 'Spartacus', rating: 4).ids
+# returns an Array of ids.
+
+Person.where(name: 'Spartacus', rating: 4).pluck(:field1, :field2)
+# returns an Array of the required fields.
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 67
+def find(*args)
+  return super if block_given?
+  find_with_ids(*args)
+end
+
+
+ +
+ +
+

+ + find_by(arg, *args) + +

+ + +
+

Finds the first record matching the specified conditions. There is no implied ordering so if order matters, you should specify it yourself.

+ +

If no record is found, returns nil.

+ +
Post.find_by name: 'Spartacus', rating: 4
+Post.find_by "published_at < ?", 2.weeks.ago
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 80
+def find_by(arg, *args)
+  where(arg, *args).take
+end
+
+
+ +
+ +
+

+ + find_by!(arg, *args) + +

+ + +
+

Like find_by, except that if no record is found, raises an ActiveRecord::RecordNotFound error.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 86
+def find_by!(arg, *args)
+  where(arg, *args).take!
+end
+
+
+ +
+ +
+

+ + find_sole_by(arg, *args) + +

+ + +
+

Finds the sole matching record. Raises ActiveRecord::RecordNotFound if no record is found. Raises ActiveRecord::SoleRecordExceeded if more than one record is found.

+ +
Product.find_sole_by(["price = %?", price])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 129
+def find_sole_by(arg, *args)
+  where(arg, *args).sole
+end
+
+
+ +
+ +
+

+ + first(limit = nil) + +

+ + +
+

Find the first record (or first N records if a parameter is supplied). If no order is defined it will order by primary key.

+ +
Person.first # returns the first object fetched by SELECT * FROM people ORDER BY people.id LIMIT 1
+Person.where(["user_name = ?", user_name]).first
+Person.where(["user_name = :u", { u: user_name }]).first
+Person.order("created_on DESC").offset(5).first
+Person.first(3) # returns the first three objects fetched by SELECT * FROM people ORDER BY people.id LIMIT 3
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 142
+def first(limit = nil)
+  if limit
+    find_nth_with_limit(0, limit)
+  else
+    find_nth 0
+  end
+end
+
+
+ +
+ +
+

+ + first!() + +

+ + +
+

Same as first but raises ActiveRecord::RecordNotFound if no record is found. Note that first! accepts no arguments.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 152
+def first!
+  first || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + forty_two() + +

+ + +
+

Find the forty-second record. Also known as accessing “the reddit”. If no order is defined it will order by primary key.

+ +
Person.forty_two # returns the forty-second object fetched by SELECT * FROM people
+Person.offset(3).forty_two # returns the forty-second object from OFFSET 3 (which is OFFSET 44)
+Person.where(["user_name = :u", { u: user_name }]).forty_two
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 256
+def forty_two
+  find_nth 41
+end
+
+
+ +
+ +
+

+ + forty_two!() + +

+ + +
+

Same as forty_two but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 262
+def forty_two!
+  forty_two || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + fourth() + +

+ + +
+

Find the fourth record. If no order is defined it will order by primary key.

+ +
Person.fourth # returns the fourth object fetched by SELECT * FROM people
+Person.offset(3).fourth # returns the fourth object from OFFSET 3 (which is OFFSET 6)
+Person.where(["user_name = :u", { u: user_name }]).fourth
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 224
+def fourth
+  find_nth 3
+end
+
+
+ +
+ +
+

+ + fourth!() + +

+ + +
+

Same as fourth but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 230
+def fourth!
+  fourth || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + include?(record) + +

+ + +
+

Returns true if the relation contains the given record or false otherwise.

+ +

No query is performed if the relation is loaded; the given record is compared to the records in memory. If the relation is unloaded, an efficient existence query is performed, as in exists?.

+
+ + + +
+ Also aliased as: member? +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 352
+def include?(record)
+  if loaded? || offset_value || limit_value || having_clause.any?
+    records.include?(record)
+  else
+    record.is_a?(klass) && exists?(record.id)
+  end
+end
+
+
+ +
+ +
+

+ + last(limit = nil) + +

+ + +
+

Find the last record (or last N records if a parameter is supplied). If no order is defined it will order by primary key.

+ +
Person.last # returns the last object fetched by SELECT * FROM people
+Person.where(["user_name = ?", user_name]).last
+Person.order("created_on DESC").offset(5).last
+Person.last(3) # returns the last three objects fetched by SELECT * FROM people.
+
+ +

Take note that in that last case, the results are sorted in ascending order:

+ +
[#<Person id:2>, #<Person id:3>, #<Person id:4>]
+
+ +

and not:

+ +
[#<Person id:4>, #<Person id:3>, #<Person id:2>]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 171
+def last(limit = nil)
+  return find_last(limit) if loaded? || has_limit_or_offset?
+
+  result = ordered_relation.limit(limit)
+  result = result.reverse_order!
+
+  limit ? result.reverse : result.first
+end
+
+
+ +
+ +
+

+ + last!() + +

+ + +
+

Same as last but raises ActiveRecord::RecordNotFound if no record is found. Note that last! accepts no arguments.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 182
+def last!
+  last || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + member?(record) + +

+ + +
+ +
+ + + + + +
+ Alias for: include? +
+ + + +
+ +
+

+ + second() + +

+ + +
+

Find the second record. If no order is defined it will order by primary key.

+ +
Person.second # returns the second object fetched by SELECT * FROM people
+Person.offset(3).second # returns the second object from OFFSET 3 (which is OFFSET 4)
+Person.where(["user_name = :u", { u: user_name }]).second
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 192
+def second
+  find_nth 1
+end
+
+
+ +
+ +
+

+ + second!() + +

+ + +
+

Same as second but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 198
+def second!
+  second || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + second_to_last() + +

+ + +
+

Find the second-to-last record. If no order is defined it will order by primary key.

+ +
Person.second_to_last # returns the second-to-last object fetched by SELECT * FROM people
+Person.offset(3).second_to_last # returns the second-to-last object from OFFSET 3
+Person.where(["user_name = :u", { u: user_name }]).second_to_last
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 288
+def second_to_last
+  find_nth_from_last 2
+end
+
+
+ +
+ +
+

+ + second_to_last!() + +

+ + +
+

Same as second_to_last but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 294
+def second_to_last!
+  second_to_last || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + sole() + +

+ + +
+

Finds the sole matching record. Raises ActiveRecord::RecordNotFound if no record is found. Raises ActiveRecord::SoleRecordExceeded if more than one record is found.

+ +
Product.where(["price = %?", price]).sole
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 112
+def sole
+  found, undesired = first(2)
+
+  if found.nil?
+    raise_record_not_found_exception!
+  elsif undesired.present?
+    raise ActiveRecord::SoleRecordExceeded.new(self)
+  else
+    found
+  end
+end
+
+
+ +
+ +
+

+ + take(limit = nil) + +

+ + +
+

Gives a record (or N records if a parameter is supplied) without any implied order. The order will depend on the database implementation. If an order is supplied it will be respected.

+ +
Person.take # returns an object fetched by SELECT * FROM people LIMIT 1
+Person.take(5) # returns 5 objects fetched by SELECT * FROM people LIMIT 5
+Person.where(["name LIKE '%?'", name]).take
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 97
+def take(limit = nil)
+  limit ? find_take_with_limit(limit) : find_take
+end
+
+
+ +
+ +
+

+ + take!() + +

+ + +
+

Same as take but raises ActiveRecord::RecordNotFound if no record is found. Note that take! accepts no arguments.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 103
+def take!
+  take || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + third() + +

+ + +
+

Find the third record. If no order is defined it will order by primary key.

+ +
Person.third # returns the third object fetched by SELECT * FROM people
+Person.offset(3).third # returns the third object from OFFSET 3 (which is OFFSET 5)
+Person.where(["user_name = :u", { u: user_name }]).third
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 208
+def third
+  find_nth 2
+end
+
+
+ +
+ +
+

+ + third!() + +

+ + +
+

Same as third but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 214
+def third!
+  third || raise_record_not_found_exception!
+end
+
+
+ +
+ +
+

+ + third_to_last() + +

+ + +
+

Find the third-to-last record. If no order is defined it will order by primary key.

+ +
Person.third_to_last # returns the third-to-last object fetched by SELECT * FROM people
+Person.offset(3).third_to_last # returns the third-to-last object from OFFSET 3
+Person.where(["user_name = :u", { u: user_name }]).third_to_last
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 272
+def third_to_last
+  find_nth_from_last 3
+end
+
+
+ +
+ +
+

+ + third_to_last!() + +

+ + +
+

Same as third_to_last but raises ActiveRecord::RecordNotFound if no record is found.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/finder_methods.rb, line 278
+def third_to_last!
+  third_to_last || raise_record_not_found_exception!
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/FixtureSet.html b/src/7.0/classes/ActiveRecord/FixtureSet.html new file mode 100644 index 0000000000..36218703c2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/FixtureSet.html @@ -0,0 +1,1261 @@ +--- +title: ActiveRecord::FixtureSet +layout: default +--- +
+ +
+
+ +
+ +

Fixtures are a way of organizing data that you want to test against; in short, sample data.

+ +

They are stored in YAML files, one file per model, which are placed in the directory appointed by ActiveSupport::TestCase.fixture_path=(path) (this is automatically configured for Rails, so you can just put your files in <your-rails-app>/test/fixtures/). The fixture file ends with the .yml file extension, for example: <your-rails-app>/test/fixtures/web_sites.yml).

+ +

The format of a fixture file looks like this:

+ +
rubyonrails:
+  id: 1
+  name: Ruby on Rails
+  url: http://www.rubyonrails.org
+
+google:
+  id: 2
+  name: Google
+  url: http://www.google.com
+
+ +

This fixture file includes two fixtures. Each YAML fixture (i.e. record) is given a name and is followed by an indented list of key/value pairs in the “key: value” format. Records are separated by a blank line for your viewing pleasure.

+ +

Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type. See yaml.org/type/omap.html for the specification. You will need ordered fixtures when you have foreign key constraints on keys in the same table. This is commonly needed for tree structures. Example:

+ +
--- !omap
+- parent:
+    id:         1
+    parent_id:  NULL
+    title:      Parent
+- child:
+    id:         2
+    parent_id:  1
+    title:      Child
+
+ +

Using Fixtures in Test Cases

+ +

Since fixtures are a testing construct, we use them in our unit and functional tests. There are two ways to use the fixtures, but first let’s take a look at a sample unit test:

+ +
require "test_helper"
+
+class WebSiteTest < ActiveSupport::TestCase
+  test "web_site_count" do
+    assert_equal 2, WebSite.count
+  end
+end
+
+ +

By default, test_helper.rb will load all of your fixtures into your test database, so this test will succeed.

+ +

The testing environment will automatically load all the fixtures into the database before each test. To ensure consistent data, the environment deletes the fixtures before running the load.

+ +

In addition to being available in the database, the fixture’s data may also be accessed by using a special dynamic method, which has the same name as the model.

+ +

Passing in a fixture name to this dynamic method returns the fixture matching this name:

+ +
test "find one" do
+  assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
+end
+
+ +

Passing in multiple fixture names returns all fixtures matching these names:

+ +
test "find all by name" do
+  assert_equal 2, web_sites(:rubyonrails, :google).length
+end
+
+ +

Passing in no arguments returns all fixtures:

+ +
test "find all" do
+  assert_equal 2, web_sites.length
+end
+
+ +

Passing in any fixture name that does not exist will raise StandardError:

+ +
test "find by name that does not exist" do
+  assert_raise(StandardError) { web_sites(:reddit) }
+end
+
+ +

Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the following tests:

+ +
test "find_alt_method_1" do
+  assert_equal "Ruby on Rails", @web_sites['rubyonrails']['name']
+end
+
+test "find_alt_method_2" do
+  assert_equal "Ruby on Rails", @rubyonrails.name
+end
+
+ +

In order to use these methods to access fixtured data within your test cases, you must specify one of the following in your ActiveSupport::TestCase-derived class:

+
  • +

    to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)

    + +
    self.use_instantiated_fixtures = true
    +
    +
  • +

    create only the hash for the fixtures, do not ‘find’ each instance (enable alternate method #1 only)

    + +
    self.use_instantiated_fixtures = :no_instances
    +
    +
+ +

Using either of these alternate methods incurs a performance hit, as the fixtured data must be fully traversed in the database to create the fixture hash and/or instance variables. This is expensive for large sets of fixtured data.

+ +

Dynamic fixtures with ERB

+ +

Sometimes you don’t care about the content of the fixtures as much as you care about the volume. In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load testing, like:

+ +
<% 1.upto(1000) do |i| %>
+fix_<%= i %>:
+  id: <%= i %>
+  name: guy_<%= i %>
+<% end %>
+
+ +

This will create 1000 very simple fixtures.

+ +

Using ERB, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d") %>. This is however a feature to be used with some caution. The point of fixtures are that they’re stable units of predictable sample data. If you feel that you need to inject dynamic values, then perhaps you should reexamine whether your application is properly testable. Hence, dynamic values in fixtures are to be considered a code smell.

+ +

Helper methods defined in a fixture will not be available in other fixtures, to prevent against unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module that is included in ActiveRecord::FixtureSet.context_class.

+
  • +

    define a helper method in test_helper.rb

    + +
    module FixtureFileHelpers
    +  def file_sha(path)
    +    OpenSSL::Digest::SHA256.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
    +  end
    +end
    +ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
    +
    +
  • +

    use the helper method in a fixture

    + +
    photo:
    +  name: kitten.png
    +  sha: <%= file_sha 'files/kitten.png' %>
    +
    +
+ +

Transactional Tests

+ +

Test cases can use begin+rollback to isolate their changes to the database instead of having to delete+insert for every test case.

+ +
class FooTest < ActiveSupport::TestCase
+  self.use_transactional_tests = true
+
+  test "godzilla" do
+    assert_not_empty Foo.all
+    Foo.destroy_all
+    assert_empty Foo.all
+  end
+
+  test "godzilla aftermath" do
+    assert_not_empty Foo.all
+  end
+end
+
+ +

If you preload your test database with all fixture data (probably by running bin/rails db:fixtures:load) and use transactional tests, then you may omit all fixtures declarations in your test cases since all the data’s already there and every case rolls back its changes.

+ +

In order to use instantiated fixtures with preloaded data, set self.pre_loaded_fixtures to true. This will provide access to fixture data for every table that has been loaded through fixtures (depending on the value of use_instantiated_fixtures).

+ +

When not to use transactional tests:

+
  1. +

    You’re testing whether a transaction works correctly. Nested transactions don’t commit until all parent transactions commit, particularly, the fixtures transaction which is begun in setup and rolled back in teardown. Thus, you won’t be able to verify the results of your transaction until Active Record supports nested transactions or savepoints (in progress).

    +
  2. +

    Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM. Use InnoDB, MaxDB, or NDB instead.

    +
+ +

Advanced Fixtures

+ +

Fixtures that don’t specify an ID get some extra features:

+
  • +

    Stable, autogenerated IDs

    +
  • +

    Label references for associations (belongs_to, has_one, has_many)

    +
  • +

    HABTM associations as inline lists

    +
+ +

There are some more advanced features available even if the id is specified:

+
  • +

    Autofilled timestamp columns

    +
  • +

    Fixture label interpolation

    +
  • +

    Support for YAML defaults

    +
+ +

Stable, Autogenerated IDs

+ +

Here, have a monkey fixture:

+ +
george:
+  id: 1
+  name: George the Monkey
+
+reginald:
+  id: 2
+  name: Reginald the Pirate
+
+ +

Each of these fixtures has two unique identifiers: one for the database and one for the humans. Why don’t we generate the primary key instead? Hashing each fixture’s label yields a consistent ID:

+ +
george: # generated id: 503576764
+  name: George the Monkey
+
+reginald: # generated id: 324201669
+  name: Reginald the Pirate
+
+ +

Active Record looks at the fixture’s model class, discovers the correct primary key, and generates it right before inserting the fixture into the database.

+ +

The generated ID for a given label is constant, so we can discover any fixture’s ID without loading anything, as long as we know the label.

+ +

Label references for associations (belongs_to, has_one, has_many)

+ +

Specifying foreign keys in fixtures can be very fragile, not to mention difficult to read. Since Active Record can figure out the ID of any fixture from its label, you can specify FK’s by label instead of ID.

+ +

belongs_to

+ +

Let’s break out some more monkeys and pirates.

+ +
### in pirates.yml
+
+reginald:
+  id: 1
+  name: Reginald the Pirate
+  monkey_id: 1
+
+### in monkeys.yml
+
+george:
+  id: 1
+  name: George the Monkey
+  pirate_id: 1
+
+ +

Add a few more monkeys and pirates and break this into multiple files, and it gets pretty hard to keep track of what’s going on. Let’s use labels instead of IDs:

+ +
### in pirates.yml
+
+reginald:
+  name: Reginald the Pirate
+  monkey: george
+
+### in monkeys.yml
+
+george:
+  name: George the Monkey
+  pirate: reginald
+
+ +

Pow! All is made clear. Active Record reflects on the fixture’s model class, finds all the belongs_to associations, and allows you to specify a target label for the association (monkey: george) rather than a target id for the FK (monkey_id: 1).

+ +

Polymorphic belongs_to

+ +

Supporting polymorphic relationships is a little bit more complicated, since Active Record needs to know what type your association is pointing at. Something like this should look familiar:

+ +
### in fruit.rb
+
+belongs_to :eater, polymorphic: true
+
+### in fruits.yml
+
+apple:
+  id: 1
+  name: apple
+  eater_id: 1
+  eater_type: Monkey
+
+ +

Can we do better? You bet!

+ +
apple:
+  eater: george (Monkey)
+
+ +

Just provide the polymorphic target type and Active Record will take care of the rest.

+ +

has_and_belongs_to_many or has_many :through

+ +

Time to give our monkey some fruit.

+ +
### in monkeys.yml
+
+george:
+  id: 1
+  name: George the Monkey
+
+### in fruits.yml
+
+apple:
+  id: 1
+  name: apple
+
+orange:
+  id: 2
+  name: orange
+
+grape:
+  id: 3
+  name: grape
+
+### in fruits_monkeys.yml
+
+apple_george:
+  fruit_id: 1
+  monkey_id: 1
+
+orange_george:
+  fruit_id: 2
+  monkey_id: 1
+
+grape_george:
+  fruit_id: 3
+  monkey_id: 1
+
+ +

Let’s make the HABTM fixture go away.

+ +
### in monkeys.yml
+
+george:
+  id: 1
+  name: George the Monkey
+  fruits: apple, orange, grape
+
+### in fruits.yml
+
+apple:
+  name: apple
+
+orange:
+  name: orange
+
+grape:
+  name: grape
+
+ +

Zap! No more fruits_monkeys.yml file. We’ve specified the list of fruits on George’s fixture, but we could’ve just as easily specified a list of monkeys on each fruit. As with belongs_to, Active Record reflects on the fixture’s model class and discovers the has_and_belongs_to_many associations.

+ +

Autofilled Timestamp Columns

+ +

If your table/model specifies any of Active Record’s standard timestamp columns (created_at, created_on, updated_at, updated_on), they will automatically be set to Time.now.

+ +

If you’ve set specific values, they’ll be left alone.

+ +

Fixture label interpolation

+ +

The label of the current fixture is always available as a column value:

+ +
geeksomnia:
+  name: Geeksomnia's Account
+  subdomain: $LABEL
+  email: $LABEL@email.com
+
+ +

Also, sometimes (like when porting older join table fixtures) you’ll need to be able to get a hold of the identifier for a given label. ERB to the rescue:

+ +
george_reginald:
+  monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
+  pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
+
+ +

Support for YAML defaults

+ +

You can set and reuse defaults in your fixtures YAML file. This is the same technique used in the database.yml file to specify defaults:

+ +
DEFAULTS: &DEFAULTS
+  created_on: <%= 3.weeks.ago.to_fs(:db) %>
+
+first:
+  name: Smurf
+  <<: *DEFAULTS
+
+second:
+  name: Fraggle
+  <<: *DEFAULTS
+
+ +

Any fixture labeled “DEFAULTS” is safely ignored.

+ +

Besides using “DEFAULTS”, you can also specify what fixtures will be ignored by setting “ignore” in “_fixture” section.

+ +
# users.yml
+_fixture:
+  ignore:
+    - base
+  # or use "ignore: base" when there is only one fixture that needs to be ignored.
+
+base: &base
+  admin: false
+  introduction: "This is a default description"
+
+admin:
+  <<: *base
+  admin: true
+
+visitor:
+  <<: *base
+
+ +

In the above example, ‘base’ will be ignored when creating fixtures. This can be used for common attributes inheriting.

+ +

Configure the fixture model class

+ +

It’s possible to set the fixture’s model class directly in the YAML file. This is helpful when fixtures are loaded outside tests and set_fixture_class is not available (e.g. when running bin/rails db:fixtures:load).

+ +
_fixture:
+  model_class: User
+david:
+  name: David
+
+ +

Any fixtures labeled “_fixture” are safely ignored.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MAX_ID=2**30 - 1
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + config
+ [R] + fixtures
+ [R] + ignored_fixtures
+ [R] + model_class
+ [R] + name
+ [R] + table_name
+ + + + +

Class Public methods

+ +
+

+ + cache_fixtures(connection, fixtures_map) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 536
+def cache_fixtures(connection, fixtures_map)
+  cache_for_connection(connection).update(fixtures_map)
+end
+
+
+ +
+ +
+

+ + cache_for_connection(connection) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 520
+def cache_for_connection(connection)
+  @@all_cached_fixtures[connection]
+end
+
+
+ +
+ +
+

+ + cached_fixtures(connection, keys_to_fetch = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 528
+def cached_fixtures(connection, keys_to_fetch = nil)
+  if keys_to_fetch
+    cache_for_connection(connection).values_at(*keys_to_fetch)
+  else
+    cache_for_connection(connection).values
+  end
+end
+
+
+ +
+ +
+

+ + context_class() + +

+ + +
+

Superclass for the evaluation contexts used by ERB fixtures.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 589
+def context_class
+  @context_class ||= Class.new
+end
+
+
+ +
+ +
+

+ + create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 555
+def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
+  fixture_set_names = Array(fixture_set_names).map(&:to_s)
+  class_names = ClassCache.new class_names, config
+
+  # FIXME: Apparently JK uses this.
+  connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
+
+  fixture_files_to_read = fixture_set_names.reject do |fs_name|
+    fixture_is_cached?(connection.call, fs_name)
+  end
+
+  if fixture_files_to_read.any?
+    fixtures_map = read_and_insert(
+      fixtures_directory,
+      fixture_files_to_read,
+      class_names,
+      connection,
+    )
+    cache_fixtures(connection.call, fixtures_map)
+  end
+  cached_fixtures(connection.call, fixture_set_names)
+end
+
+
+ +
+ +
+

+ + fixture_is_cached?(connection, table_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 524
+def fixture_is_cached?(connection, table_name)
+  cache_for_connection(connection)[table_name]
+end
+
+
+ +
+ +
+

+ + identify(label, column_type = :integer) + +

+ + +
+

Returns a consistent, platform-independent identifier for label. Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 580
+def identify(label, column_type = :integer)
+  if column_type == :uuid
+    Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
+  else
+    Zlib.crc32(label.to_s) % MAX_ID
+  end
+end
+
+
+ +
+ +
+

+ + instantiate_all_loaded_fixtures(object, load_instances = true) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 549
+def instantiate_all_loaded_fixtures(object, load_instances = true)
+  all_loaded_fixtures.each_value do |fixture_set|
+    instantiate_fixtures(object, fixture_set, load_instances)
+  end
+end
+
+
+ +
+ +
+

+ + instantiate_fixtures(object, fixture_set, load_instances = true) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 540
+def instantiate_fixtures(object, fixture_set, load_instances = true)
+  return unless load_instances
+  fixture_set.each do |fixture_name, fixture|
+    object.instance_variable_set "@#{fixture_name}", fixture.find
+  rescue FixtureClassNotFound
+    nil
+  end
+end
+
+
+ +
+ +
+

+ + new(_, name, class_name, path, config = ActiveRecord::Base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 650
+def initialize(_, name, class_name, path, config = ActiveRecord::Base)
+  @name     = name
+  @path     = path
+  @config   = config
+
+  self.model_class = class_name
+
+  @fixtures = read_fixture_files(path)
+
+  @table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
+end
+
+
+ +
+ +
+

+ + reset_cache() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 516
+def reset_cache
+  @@all_cached_fixtures.clear
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](x) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 662
+def [](x)
+  fixtures[x]
+end
+
+
+ +
+ +
+

+ + []=(k, v) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 666
+def []=(k, v)
+  fixtures[k] = v
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 670
+def each(&block)
+  fixtures.each(&block)
+end
+
+
+ +
+ +
+

+ + size() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 674
+def size
+  fixtures.size
+end
+
+
+ +
+ +
+

+ + table_rows() + +

+ + +
+

Returns a hash of rows to be inserted. The key is the table, the value is a list of rows to insert to that table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 680
+def table_rows
+  # allow specifying fixtures to be ignored by setting `ignore` in `_fixture` section
+  fixtures.except!(*ignored_fixtures)
+
+  TableRows.new(
+    table_name,
+    model_class: model_class,
+    fixtures: fixtures,
+  ).to_hash
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/FixtureSet/ClassCache.html b/src/7.0/classes/ActiveRecord/FixtureSet/ClassCache.html new file mode 100644 index 0000000000..b6db7a6a39 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/FixtureSet/ClassCache.html @@ -0,0 +1,158 @@ +--- +title: ActiveRecord::FixtureSet::ClassCache +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + [] +
  • + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(class_names, config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 471
+def initialize(class_names, config)
+  @class_names = class_names.stringify_keys
+  @config      = config
+
+  # Remove string values that aren't constants or subclasses of AR
+  @class_names.delete_if do |klass_name, klass|
+    !insert_class(@class_names, klass_name, klass)
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](fs_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/fixtures.rb, line 481
+def [](fs_name)
+  @class_names.fetch(fs_name) do
+    klass = default_fixture_model(fs_name, @config).safe_constantize
+    insert_class(@class_names, fs_name, klass)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/FutureResult.html b/src/7.0/classes/ActiveRecord/FutureResult.html new file mode 100644 index 0000000000..7c60270c22 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/FutureResult.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::FutureResult +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/FutureResult/EventBuffer.html b/src/7.0/classes/ActiveRecord/FutureResult/EventBuffer.html new file mode 100644 index 0000000000..31ffda6c38 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/FutureResult/EventBuffer.html @@ -0,0 +1,196 @@ +--- +title: ActiveRecord::FutureResult::EventBuffer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(future_result, instrumenter) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/future_result.rb, line 6
+def initialize(future_result, instrumenter)
+  @future_result = future_result
+  @instrumenter = instrumenter
+  @events = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + flush() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/future_result.rb, line 18
+def flush
+  events, @events = @events, []
+  events.each do |event|
+    event.payload[:lock_wait] = @future_result.lock_wait
+    ActiveSupport::Notifications.publish_event(event)
+  end
+end
+
+
+ +
+ +
+

+ + instrument(name, payload = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/future_result.rb, line 12
+def instrument(name, payload = {}, &block)
+  event = @instrumenter.new_event(name, payload)
+  @events << event
+  event.record(&block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ImmutableRelation.html b/src/7.0/classes/ActiveRecord/ImmutableRelation.html new file mode 100644 index 0000000000..7e22e67169 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ImmutableRelation.html @@ -0,0 +1,77 @@ +--- +title: ActiveRecord::ImmutableRelation +layout: default +--- +
+ +
+
+ +
+ +

Raised when a relation cannot be mutated because it’s already loaded.

+ +
class Task < ActiveRecord::Base
+end
+
+relation = Task.all
+relation.loaded? # => true
+
+# Methods which try to mutate a loaded relation fail.
+relation.where!(title: 'TODO')  # => ActiveRecord::ImmutableRelation
+relation.limit!(5)              # => ActiveRecord::ImmutableRelation
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Inheritance.html b/src/7.0/classes/ActiveRecord/Inheritance.html new file mode 100644 index 0000000000..d45ac83154 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Inheritance.html @@ -0,0 +1,142 @@ +--- +title: ActiveRecord::Inheritance +layout: default +--- +
+ +
+
+ +
+ +

Single table inheritance

+ +

Active Record allows inheritance by storing the name of the class in a column that by default is named “type” (can be changed by overwriting Base.inheritance_column). This means that an inheritance looking like this:

+ +
class Company < ActiveRecord::Base; end
+class Firm < Company; end
+class Client < Company; end
+class PriorityClient < Client; end
+
+ +

When you do Firm.create(name: "37signals"), this record will be saved in the companies table with type = “Firm”. You can then fetch this row again using Company.where(name: '37signals').first and it will return a Firm object.

+ +

Be aware that because the type column is an attribute on the record every new subclass will instantly be marked as dirty and the type column will be included in the list of changed attributes on the record. This is different from non Single Table Inheritance(STI) classes:

+ +
Company.new.changed? # => false
+Firm.new.changed?    # => true
+Firm.new.changes     # => {"type"=>["","Firm"]}
+
+ +

If you don’t have a type column defined in your table, single-table inheritance won’t be triggered. In that case, it’ll work just like normal subclasses with no special magic for differentiating between them or reloading the right type with find.

+ +

Note, all the attributes for all the cases are kept in the same table. Read more: www.martinfowler.com/eaaCatalog/singleTableInheritance.html

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + initialize_dup(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 327
+def initialize_dup(other)
+  super
+  ensure_proper_type
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Inheritance/ClassMethods.html b/src/7.0/classes/ActiveRecord/Inheritance/ClassMethods.html new file mode 100644 index 0000000000..894a889d77 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Inheritance/ClassMethods.html @@ -0,0 +1,629 @@ +--- +title: ActiveRecord::Inheritance::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + abstract_class

Set this to true if this is an abstract class (see abstract_class?). If you are using inheritance with Active Record and don’t want a class to be considered as part of the STI hierarchy, you must set this to true. ApplicationRecord, for example, is generated as an abstract class.

+ +

Consider the following default behaviour:

+ +
Shape = Class.new(ActiveRecord::Base)
+Polygon = Class.new(Shape)
+Square = Class.new(Polygon)
+
+Shape.table_name   # => "shapes"
+Polygon.table_name # => "shapes"
+Square.table_name  # => "shapes"
+Shape.create!      # => #<Shape id: 1, type: nil>
+Polygon.create!    # => #<Polygon id: 2, type: "Polygon">
+Square.create!     # => #<Square id: 3, type: "Square">
+
+ +

However, when using abstract_class, Shape is omitted from the hierarchy:

+ +
class Shape < ActiveRecord::Base
+  self.abstract_class = true
+end
+Polygon = Class.new(Shape)
+Square = Class.new(Polygon)
+
+Shape.table_name   # => nil
+Polygon.table_name # => "polygons"
+Square.table_name  # => "polygons"
+Shape.create!      # => NotImplementedError: Shape is an abstract class and cannot be instantiated.
+Polygon.create!    # => #<Polygon id: 1, type: nil>
+Square.create!     # => #<Square id: 2, type: "Square">
+
+ +

Note that in the above example, to disallow the creation of a plain Polygon, you should use validates :type, presence: true, instead of setting it as an abstract class. This way, Polygon will stay in the hierarchy, and Active Record will continue to correctly derive the table name.

+ [R] + base_class

Returns the class descending directly from ActiveRecord::Base, or an abstract class, if any, in the inheritance hierarchy.

+ +

If A extends ActiveRecord::Base, A.base_class will return A. If B descends from A through some arbitrarily deep hierarchy, B.base_class will return A.

+ +

If B < A and C < B and if A is an abstract_class then both B.base_class and C.base_class would return B as the answer since A is an abstract_class.

+ + + + + +

Instance Public methods

+ +
+

+ + abstract_class?() + +

+ + +
+

Returns whether this class is an abstract class or not.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 156
+def abstract_class?
+  defined?(@abstract_class) && @abstract_class == true
+end
+
+
+ +
+ +
+

+ + base_class?() + +

+ + +
+

Returns whether the class is a base class. See base_class for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 108
+def base_class?
+  base_class == self
+end
+
+
+ +
+ +
+

+ + descends_from_active_record?() + +

+ + +
+

Returns true if this does not need STI type condition. Returns false if STI type condition needs to be applied.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 81
+def descends_from_active_record?
+  if self == Base
+    false
+  elsif superclass.abstract_class?
+    superclass.descends_from_active_record?
+  else
+    superclass == Base || !columns_hash.include?(inheritance_column)
+  end
+end
+
+
+ +
+ +
+

+ + inherited(subclass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 213
+def inherited(subclass)
+  subclass.set_base_class
+  subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
+  super
+end
+
+
+ +
+ +
+

+ + new(attributes = nil, &block) + +

+ + +
+

Determines if one of the attributes passed in is the inheritance column, and if the inheritance column is attr accessible, it initializes an instance of the given subclass instead of the base class.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 55
+def new(attributes = nil, &block)
+  if abstract_class? || self == Base
+    raise NotImplementedError, "#{self} is an abstract class and cannot be instantiated."
+  end
+
+  if _has_attribute?(inheritance_column)
+    subclass = subclass_from_attributes(attributes)
+
+    if subclass.nil? && scope_attributes = current_scope&.scope_for_create
+      subclass = subclass_from_attributes(scope_attributes)
+    end
+
+    if subclass.nil? && base_class?
+      subclass = subclass_from_attributes(column_defaults)
+    end
+  end
+
+  if subclass && subclass != self
+    subclass.new(attributes, &block)
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + polymorphic_class_for(name) + +

+ + +
+

Returns the class for the provided name.

+ +

It is used to find the class correspondent to the value stored in the polymorphic type column.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 205
+def polymorphic_class_for(name)
+  if store_full_class_name
+    name.constantize
+  else
+    compute_type(name)
+  end
+end
+
+
+ +
+ +
+

+ + polymorphic_name() + +

+ + +
+

Returns the value to be stored in the polymorphic type column for Polymorphic Associations.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 198
+def polymorphic_name
+  store_full_class_name ? base_class.name : base_class.name.demodulize
+end
+
+
+ +
+ +
+

+ + primary_abstract_class() + +

+ + +
+

Sets the application record class for Active Record

+ +

This is useful if your application uses a different class than ApplicationRecord for your primary abstract class. This class will share a database connection with Active Record. It is the class that connects to your primary database.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 166
+def primary_abstract_class
+  if ActiveRecord.application_record_class && ActiveRecord.application_record_class.name != name
+    raise ArgumentError, "The `primary_abstract_class` is already set to #{ActiveRecord.application_record_class.inspect}. There can only be one `primary_abstract_class` in an application."
+  end
+
+  self.abstract_class = true
+  ActiveRecord.application_record_class = self
+end
+
+
+ +
+ +
+

+ + sti_class_for(type_name) + +

+ + +
+

Returns the class for the provided type_name.

+ +

It is used to find the class correspondent to the value stored in the inheritance column.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 183
+def sti_class_for(type_name)
+  if store_full_sti_class && store_full_class_name
+    type_name.constantize
+  else
+    compute_type(type_name)
+  end
+rescue NameError
+  raise SubclassNotFound,
+    "The single-table inheritance mechanism failed to locate the subclass: '#{type_name}'. " \
+    "This error is raised because the column '#{inheritance_column}' is reserved for storing the class in case of inheritance. " \
+    "Please rename this column if you didn't intend it to be used for storing the inheritance class " \
+    "or overwrite #{name}.inheritance_column to use another column for that information."
+end
+
+
+ +
+ +
+

+ + sti_name() + +

+ + +
+

Returns the value to be stored in the inheritance column for STI.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 176
+def sti_name
+  store_full_sti_class && store_full_class_name ? name : name.demodulize
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + compute_type(type_name) + +

+ + +
+

Returns the class type of the record using the current module as a prefix. So descendants of MyApp::Business::Account would appear as MyApp::Business::AccountSubclass.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/inheritance.rb, line 235
+def compute_type(type_name)
+  if type_name.start_with?("::")
+    # If the type is prefixed with a scope operator then we assume that
+    # the type_name is an absolute reference.
+    type_name.constantize
+  else
+    type_candidate = @_type_candidates_cache[type_name]
+    if type_candidate && type_constant = type_candidate.safe_constantize
+      return type_constant
+    end
+
+    # Build a list of candidates to search for
+    candidates = []
+    name.scan(/::|$/) { candidates.unshift "#{$`}::#{type_name}" }
+    candidates << type_name
+
+    candidates.each do |candidate|
+      constant = candidate.safe_constantize
+      if candidate == constant.to_s
+        @_type_candidates_cache[type_name] = candidate
+        return constant
+      end
+    end
+
+    raise NameError.new("uninitialized constant #{candidates.first}", candidates.first)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Integration.html b/src/7.0/classes/ActiveRecord/Integration.html new file mode 100644 index 0000000000..7af189890b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Integration.html @@ -0,0 +1,416 @@ +--- +title: ActiveRecord::Integration +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + cache_timestamp_format + +

+ + +
+

Indicates the format used to generate the timestamp in the cache key, if versioning is off. Accepts any of the symbols in Time::DATE_FORMATS.

+ +

This is :usec, by default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 16
+class_attribute :cache_timestamp_format, instance_writer: false, default: :usec
+
+
+
+ +
+ +
+

+ + cache_versioning + +

+ + +
+

Indicates whether to use a stable cache_key method that is accompanied by a changing version in the cache_version method.

+ +

This is true, by default on Rails 5.2 and above.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 24
+class_attribute :cache_versioning, instance_writer: false, default: false
+
+
+
+ +
+ +
+

+ + collection_cache_versioning + +

+ + +
+

Indicates whether to use a stable cache_key method that is accompanied by a changing version in the cache_version method on collections.

+ +

This is false, by default until Rails 6.1.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 32
+class_attribute :collection_cache_versioning, instance_writer: false, default: false
+
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cache_key() + +

+ + +
+

Returns a stable cache key that can be used to identify this record.

+ +
Product.new.cache_key     # => "products/new"
+Product.find(5).cache_key # => "products/5"
+
+ +

If ActiveRecord::Base.cache_versioning is turned off, as it was in Rails 5.1 and earlier, the cache key will also include a version.

+ +
Product.cache_versioning = false
+Product.find(5).cache_key  # => "products/5-20071224150000" (updated_at available)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 72
+def cache_key
+  if new_record?
+    "#{model_name.cache_key}/new"
+  else
+    if cache_version
+      "#{model_name.cache_key}/#{id}"
+    else
+      timestamp = max_updated_column_timestamp
+
+      if timestamp
+        timestamp = timestamp.utc.to_fs(cache_timestamp_format)
+        "#{model_name.cache_key}/#{id}-#{timestamp}"
+      else
+        "#{model_name.cache_key}/#{id}"
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + cache_key_with_version() + +

+ + +
+

Returns a cache key along with the version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 114
+def cache_key_with_version
+  if version = cache_version
+    "#{cache_key}-#{version}"
+  else
+    cache_key
+  end
+end
+
+
+ +
+ +
+

+ + cache_version() + +

+ + +
+

Returns a cache version that can be used together with the cache key to form a recyclable caching scheme. By default, the updated_at column is used for the cache_version, but this method can be overwritten to return something else.

+ +

Note, this method will return nil if ActiveRecord::Base.cache_versioning is set to false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 97
+def cache_version
+  return unless cache_versioning
+
+  if has_attribute?("updated_at")
+    timestamp = updated_at_before_type_cast
+    if can_use_fast_cache_version?(timestamp)
+      raw_timestamp_to_cache_version(timestamp)
+
+    elsif timestamp = updated_at
+      timestamp.utc.to_fs(cache_timestamp_format)
+    end
+  elsif self.class.has_attribute?("updated_at")
+    raise ActiveModel::MissingAttributeError, "missing attribute: updated_at"
+  end
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Returns a String, which Action Pack uses for constructing a URL to this object. The default implementation returns this record’s id as a String, or nil if this record’s unsaved.

+ +

For example, suppose that you have a User model, and that you have a resources :users route. Normally, user_path will construct a path with the user object’s ‘id’ in it:

+ +
user = User.find_by(name: 'Phusion')
+user_path(user)  # => "/users/1"
+
+ +

You can override to_param in your model to make user_path construct a path using the user’s name instead of the user’s id:

+ +
class User < ActiveRecord::Base
+  def to_param  # overridden
+    name
+  end
+end
+
+user = User.find_by(name: 'Phusion')
+user_path(user)  # => "/users/Phusion"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 57
+def to_param
+  # We can't use alias_method here, because method 'id' optimizes itself on the fly.
+  id && id.to_s # Be sure to stringify the id for routes
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Integration/ClassMethods.html b/src/7.0/classes/ActiveRecord/Integration/ClassMethods.html new file mode 100644 index 0000000000..e5e31c5f5f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Integration/ClassMethods.html @@ -0,0 +1,135 @@ +--- +title: ActiveRecord::Integration::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + to_param(method_name = nil) + +

+ + +
+

Defines your model’s to_param method to generate “pretty” URLs using method_name, which can be any attribute or method that responds to to_s.

+ +
class User < ActiveRecord::Base
+  to_param :name
+end
+
+user = User.find_by(name: 'Fancy Pants')
+user.id         # => 123
+user_path(user) # => "/users/123-fancy-pants"
+
+ +

Values longer than 20 characters will be truncated. The value is truncated word by word.

+ +
user = User.find_by(name: 'David Heinemeier Hansson')
+user.id         # => 125
+user_path(user) # => "/users/125-david-heinemeier"
+
+ +

Because the generated param begins with the record’s id, it is suitable for passing to find. In a controller, for example:

+ +
params[:id]               # => "123-fancy-pants"
+User.find(params[:id]).id # => 123
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/integration.rb, line 147
+def to_param(method_name = nil)
+  if method_name.nil?
+    super()
+  else
+    define_method :to_param do
+      if (default = super()) &&
+           (result = send(method_name).to_s).present? &&
+             (param = result.squish.parameterize.truncate(20, separator: /-/, omission: "")).present?
+        "#{default}-#{param}"
+      else
+        default
+      end
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/InvalidForeignKey.html b/src/7.0/classes/ActiveRecord/InvalidForeignKey.html new file mode 100644 index 0000000000..fcba9dc5e7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/InvalidForeignKey.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::InvalidForeignKey +layout: default +--- +
+ +
+
+ +
+ +

Raised when a record cannot be inserted or updated because it references a non-existent record, or when a record cannot be deleted because a parent record references it.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/IrreversibleMigration.html b/src/7.0/classes/ActiveRecord/IrreversibleMigration.html new file mode 100644 index 0000000000..9ae89c0a4f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/IrreversibleMigration.html @@ -0,0 +1,139 @@ +--- +title: ActiveRecord::IrreversibleMigration +layout: default +--- +
+ +
+
+ +
+ +

Exception that can be raised to stop migrations from being rolled back. For example the following migration is not reversible. Rolling back this migration will raise an ActiveRecord::IrreversibleMigration error.

+ +
class IrreversibleMigrationExample < ActiveRecord::Migration[7.0]
+  def change
+    create_table :distributors do |t|
+      t.string :zipcode
+    end
+
+    execute <<~SQL
+      ALTER TABLE distributors
+        ADD CONSTRAINT zipchk
+          CHECK (char_length(zipcode) = 5) NO INHERIT;
+    SQL
+  end
+end
+
+ +

There are two ways to mitigate this problem.

+
  1. +

    Define #up and #down methods instead of #change:

    +
+ +
class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
+  def up
+    create_table :distributors do |t|
+      t.string :zipcode
+    end
+
+    execute <<~SQL
+      ALTER TABLE distributors
+        ADD CONSTRAINT zipchk
+          CHECK (char_length(zipcode) = 5) NO INHERIT;
+    SQL
+  end
+
+  def down
+    execute <<~SQL
+      ALTER TABLE distributors
+        DROP CONSTRAINT zipchk
+    SQL
+
+    drop_table :distributors
+  end
+end
+
+
  1. +

    Use the reversible method in #change method:

    +
+ +
class ReversibleMigrationExample < ActiveRecord::Migration[7.0]
+  def change
+    create_table :distributors do |t|
+      t.string :zipcode
+    end
+
+    reversible do |dir|
+      dir.up do
+        execute <<~SQL
+          ALTER TABLE distributors
+            ADD CONSTRAINT zipchk
+              CHECK (char_length(zipcode) = 5) NO INHERIT;
+        SQL
+      end
+
+      dir.down do
+        execute <<~SQL
+          ALTER TABLE distributors
+            DROP CONSTRAINT zipchk
+        SQL
+      end
+    end
+  end
+end
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/IrreversibleOrderError.html b/src/7.0/classes/ActiveRecord/IrreversibleOrderError.html new file mode 100644 index 0000000000..bf57e2f20f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/IrreversibleOrderError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::IrreversibleOrderError +layout: default +--- +
+ +
+
+ +
+ +

IrreversibleOrderError is raised when a relation’s order is too complex for reverse_order to automatically reverse.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/LockWaitTimeout.html b/src/7.0/classes/ActiveRecord/LockWaitTimeout.html new file mode 100644 index 0000000000..af9f87f206 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/LockWaitTimeout.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::LockWaitTimeout +layout: default +--- +
+ +
+
+ +
+ +

LockWaitTimeout will be raised when lock wait timeout exceeded.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Locking.html b/src/7.0/classes/ActiveRecord/Locking.html new file mode 100644 index 0000000000..4b0d5bf5ec --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Locking.html @@ -0,0 +1,71 @@ +--- +title: ActiveRecord::Locking +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Locking/Optimistic.html b/src/7.0/classes/ActiveRecord/Locking/Optimistic.html new file mode 100644 index 0000000000..2786645e87 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Locking/Optimistic.html @@ -0,0 +1,113 @@ +--- +title: ActiveRecord::Locking::Optimistic +layout: default +--- +
+ +
+
+ +
+ +

What is Optimistic Locking

+ +

Optimistic locking allows multiple users to access the same record for edits, and assumes a minimum of conflicts with the data. It does this by checking whether another process has made changes to a record since it was opened, an ActiveRecord::StaleObjectError exception is thrown if that has occurred and the update is ignored.

+ +

Check out ActiveRecord::Locking::Pessimistic for an alternative.

+ +

Usage

+ +

Active Record supports optimistic locking if the lock_version field is present. Each update to the record increments the lock_version column and the locking facilities ensure that records instantiated twice will let the last one saved raise a StaleObjectError if the first was also updated. Example:

+ +
p1 = Person.find(1)
+p2 = Person.find(1)
+
+p1.first_name = "Michael"
+p1.save
+
+p2.first_name = "should fail"
+p2.save # Raises an ActiveRecord::StaleObjectError
+
+ +

Optimistic locking will also check for stale data when objects are destroyed. Example:

+ +
p1 = Person.find(1)
+p2 = Person.find(1)
+
+p1.first_name = "Michael"
+p1.save
+
+p2.destroy # Raises an ActiveRecord::StaleObjectError
+
+ +

You’re then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging, or otherwise apply the business logic needed to resolve the conflict.

+ +

This locking mechanism will function inside a single Ruby process. To make it work across all web requests, the recommended approach is to add lock_version as a hidden field to your form.

+ +

This behavior can be turned off by setting ActiveRecord::Base.lock_optimistically = false. To override the name of the lock_version column, set the locking_column class attribute:

+ +
class Person < ActiveRecord::Base
+  self.locking_column = :lock_person
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Locking/Optimistic/ClassMethods.html b/src/7.0/classes/ActiveRecord/Locking/Optimistic/ClassMethods.html new file mode 100644 index 0000000000..564f93e07d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Locking/Optimistic/ClassMethods.html @@ -0,0 +1,252 @@ +--- +title: ActiveRecord::Locking::Optimistic::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_LOCKING_COLUMN="lock_version"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + locking_column

The version column used for optimistic locking. Defaults to lock_version.

+ + + + + +

Instance Public methods

+ +
+

+ + locking_column=(value) + +

+ + +
+

Set the column to use for optimistic locking. Defaults to lock_version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/optimistic.rb, line 165
+def locking_column=(value)
+  reload_schema_from_cache
+  @locking_column = value.to_s
+end
+
+
+ +
+ +
+

+ + locking_enabled?() + +

+ + +
+

Returns true if the lock_optimistically flag is set to true (which it is, by default) and the table includes the locking_column column (defaults to lock_version).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/optimistic.rb, line 160
+def locking_enabled?
+  lock_optimistically && columns_hash[locking_column]
+end
+
+
+ +
+ +
+

+ + reset_locking_column() + +

+ + +
+

Reset the column used for optimistic locking back to the lock_version default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/optimistic.rb, line 174
+def reset_locking_column
+  self.locking_column = DEFAULT_LOCKING_COLUMN
+end
+
+
+ +
+ +
+

+ + update_counters(id, counters) + +

+ + +
+

Make sure the lock version column gets updated when counters are updated.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/optimistic.rb, line 180
+def update_counters(id, counters)
+  counters = counters.merge(locking_column => 1) if locking_enabled?
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Locking/Pessimistic.html b/src/7.0/classes/ActiveRecord/Locking/Pessimistic.html new file mode 100644 index 0000000000..2a45311111 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Locking/Pessimistic.html @@ -0,0 +1,220 @@ +--- +title: ActiveRecord::Locking::Pessimistic +layout: default +--- +
+ +
+
+ +
+ +

Locking::Pessimistic provides support for row-level locking using SELECT … FOR UPDATE and other lock types.

+ +

Chain ActiveRecord::Base#find to ActiveRecord::QueryMethods#lock to obtain an exclusive lock on the selected rows:

+ +
# select * from accounts where id=1 for update
+Account.lock.find(1)
+
+ +

Call lock('some locking clause') to use a database-specific locking clause of your own such as ‘LOCK IN SHARE MODE’ or ‘FOR UPDATE NOWAIT’. Example:

+ +
Account.transaction do
+  # select * from accounts where name = 'shugo' limit 1 for update nowait
+  shugo = Account.lock("FOR UPDATE NOWAIT").find_by(name: "shugo")
+  yuko = Account.lock("FOR UPDATE NOWAIT").find_by(name: "yuko")
+  shugo.balance -= 100
+  shugo.save!
+  yuko.balance += 100
+  yuko.save!
+end
+
+ +

You can also use ActiveRecord::Base#lock! method to lock one record by id. This may be better if you don’t need to lock every row. Example:

+ +
Account.transaction do
+  # select * from accounts where ...
+  accounts = Account.where(...)
+  account1 = accounts.detect { |account| ... }
+  account2 = accounts.detect { |account| ... }
+  # select * from accounts where id=? for update
+  account1.lock!
+  account2.lock!
+  account1.balance -= 100
+  account1.save!
+  account2.balance += 100
+  account2.save!
+end
+
+ +

You can start a transaction and acquire the lock in one go by calling with_lock with a block. The block is called from within a transaction, the object is already locked. Example:

+ +
account = Account.first
+account.with_lock do
+  # This block is called within a transaction,
+  # account is already locked.
+  account.balance -= 100
+  account.save!
+end
+
+ +

Database-specific information on row locking:

+
MySQL +
+

dev.mysql.com/doc/refman/en/innodb-locking-reads.html

+
PostgreSQL +
+

www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE

+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + lock!(lock = true) + +

+ + +
+

Obtain a row lock on this record. Reloads the record to obtain the requested lock. Pass an SQL locking clause to append the end of the SELECT statement or pass true for “FOR UPDATE” (the default, an exclusive row lock). Returns the locked record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/pessimistic.rb, line 67
+      def lock!(lock = true)
+        if persisted?
+          if has_changes_to_save?
+            raise(<<-MSG.squish)
+              Locking a record with unpersisted changes is not supported. Use
+              `save` to persist the changes, or `reload` to discard them
+              explicitly.
+            MSG
+          end
+
+          reload(lock: lock)
+        end
+        self
+      end
+
+
+ +
+ +
+

+ + with_lock(*args) + +

+ + +
+

Wraps the passed block in a transaction, locking the object before yielding. You can pass the SQL locking clause as an optional argument (see lock!).

+ +

You can also pass options like requires_new:, isolation:, and joinable: to the wrapping transaction (see ActiveRecord::ConnectionAdapters::DatabaseStatements#transaction).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/locking/pessimistic.rb, line 89
+def with_lock(*args)
+  transaction_opts = args.extract_options!
+  lock = args.present? ? args.first : true
+  transaction(**transaction_opts) do
+    lock!(lock)
+    yield
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/LogSubscriber.html b/src/7.0/classes/ActiveRecord/LogSubscriber.html new file mode 100644 index 0000000000..e1e6657208 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/LogSubscriber.html @@ -0,0 +1,329 @@ +--- +title: ActiveRecord::LogSubscriber +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
IGNORE_PAYLOAD_NAMES=["SCHEMA", "EXPLAIN"]
 
+ + + + + + +

Class Public methods

+ +
+

+ + reset_runtime() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/log_subscriber.rb, line 17
+def self.reset_runtime
+  rt, self.runtime = runtime, 0
+  rt
+end
+
+
+ +
+ +
+

+ + runtime() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/log_subscriber.rb, line 13
+def self.runtime
+  ActiveRecord::RuntimeRegistry.sql_runtime ||= 0
+end
+
+
+ +
+ +
+

+ + runtime=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/log_subscriber.rb, line 9
+def self.runtime=(value)
+  ActiveRecord::RuntimeRegistry.sql_runtime = value
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + sql(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/log_subscriber.rb, line 30
+def sql(event)
+  self.class.runtime += event.duration
+  return unless logger.debug?
+
+  payload = event.payload
+
+  return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
+
+  name = if payload[:async]
+    "ASYNC #{payload[:name]} (#{payload[:lock_wait].round(1)}ms) (db time #{event.duration.round(1)}ms)"
+  else
+    "#{payload[:name]} (#{event.duration.round(1)}ms)"
+  end
+  name  = "CACHE #{name}" if payload[:cached]
+  sql   = payload[:sql]
+  binds = nil
+
+  if payload[:binds]&.any?
+    casted_params = type_casted_binds(payload[:type_casted_binds])
+
+    binds = []
+    payload[:binds].each_with_index do |attr, i|
+      attribute_name = if attr.respond_to?(:name)
+        attr.name
+      elsif attr.respond_to?(:[]) && attr[i].respond_to?(:name)
+        attr[i].name
+      else
+        nil
+      end
+
+      filtered_params = filter(attribute_name, casted_params[i])
+
+      binds << render_bind(attr, filtered_params)
+    end
+    binds = binds.inspect
+    binds.prepend("  ")
+  end
+
+  name = colorize_payload_name(name, payload[:name])
+  sql  = color(sql, sql_color(sql), true) if colorize_logging
+
+  debug "  #{name}  #{sql}#{binds}"
+end
+
+
+ +
+ +
+

+ + strict_loading_violation(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/log_subscriber.rb, line 22
+def strict_loading_violation(event)
+  debug do
+    owner = event.payload[:owner]
+    reflection = event.payload[:reflection]
+    color(reflection.strict_loading_violation_message(owner), RED)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Middleware.html b/src/7.0/classes/ActiveRecord/Middleware.html new file mode 100644 index 0000000000..ad0afa9f41 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Middleware.html @@ -0,0 +1,77 @@ +--- +title: ActiveRecord::Middleware +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Middleware/DatabaseSelector.html b/src/7.0/classes/ActiveRecord/Middleware/DatabaseSelector.html new file mode 100644 index 0000000000..1d7a32c81d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Middleware/DatabaseSelector.html @@ -0,0 +1,225 @@ +--- +title: ActiveRecord::Middleware::DatabaseSelector +layout: default +--- +
+ +
+
+ +
+ +

The DatabaseSelector Middleware provides a framework for automatically swapping from the primary to the replica database connection. Rails provides a basic framework to determine when to swap and allows for applications to write custom strategy classes to override the default behavior.

+ +

The resolver class defines when the application should switch (i.e. read from the primary if a write occurred less than 2 seconds ago) and a resolver context class that sets a value that helps the resolver class decide when to switch.

+ +

Rails default middleware uses the request’s session to set a timestamp that informs the application when to read from a primary or read from a replica.

+ +

To use the DatabaseSelector in your application with default settings, run the provided generator.

+ +
bin/rails g active_record:multi_db
+
+ +

This will create a file named config/initializers/multi_db.rb with the following contents:

+ +
Rails.application.configure do
+  config.active_record.database_selector = { delay: 2.seconds }
+  config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
+  config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
+end
+
+ +

Alternatively you can set the options in your environment config or any other config file loaded on boot.

+ +

The default behavior can be changed by setting the config options to a custom class:

+ +
config.active_record.database_selector = { delay: 2.seconds }
+config.active_record.database_resolver = MyResolver
+config.active_record.database_resolver_context = MyResolver::MySession
+
+ +

Note: If you are using rails new my_app --minimal you will need to call require "active_support/core_ext/integer/time" to load the core extension in order to use 2.seconds

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + context_klass
+ [R] + options
+ [R] + resolver_klass
+ + + + +

Class Public methods

+ +
+

+ + new(app, resolver_klass = nil, context_klass = nil, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/middleware/database_selector.rb, line 50
+def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
+  @app = app
+  @resolver_klass = resolver_klass || Resolver
+  @context_klass = context_klass || Resolver::Session
+  @options = options
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+

Middleware that determines which database connection to use in a multiple database application.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/middleware/database_selector.rb, line 61
+def call(env)
+  request = ActionDispatch::Request.new(env)
+
+  select_database(request) do
+    @app.call(env)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Middleware/ShardSelector.html b/src/7.0/classes/ActiveRecord/Middleware/ShardSelector.html new file mode 100644 index 0000000000..03890692a6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Middleware/ShardSelector.html @@ -0,0 +1,201 @@ +--- +title: ActiveRecord::Middleware::ShardSelector +layout: default +--- +
+ +
+
+ +
+ +

The ShardSelector Middleware provides a framework for automatically swapping shards. Rails provides a basic framework to determine which shard to switch to and allows for applications to write custom strategies for swapping if needed.

+ +

The ShardSelector takes a set of options (currently only lock is supported) that can be used by the middleware to alter behavior. lock is true by default and will prohibit the request from switching shards once inside the block. If lock is false, then shard swapping will be allowed. For tenant based sharding, lock should always be true to prevent application code from mistakenly switching between tenants.

+ +

Options can be set in the config:

+ +
config.active_record.shard_selector = { lock: true }
+
+ +

Applications must also provide the code for the resolver as it depends on application specific models. An example resolver would look like this:

+ +
config.active_record.shard_resolver = ->(request) {
+  subdomain = request.subdomain
+  tenant = Tenant.find_by_subdomain!(subdomain)
+  tenant.shard
+}
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + options
+ [R] + resolver
+ + + + +

Class Public methods

+ +
+

+ + new(app, resolver, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/middleware/shard_selector.rb, line 30
+def initialize(app, resolver, options = {})
+  @app = app
+  @resolver = resolver
+  @options = options
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/middleware/shard_selector.rb, line 38
+def call(env)
+  request = ActionDispatch::Request.new(env)
+
+  shard = selected_shard(request)
+
+  set_shard(shard) do
+    @app.call(env)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration.html b/src/7.0/classes/ActiveRecord/Migration.html new file mode 100644 index 0000000000..532cca039f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration.html @@ -0,0 +1,1647 @@ +--- +title: ActiveRecord::Migration +layout: default +--- +
+ +
+
+ +
+ +

Active Record Migrations

+ +

Migrations can manage the evolution of a schema used by several physical databases. It’s a solution to the common problem of adding a field to make a new feature work in your local database, but being unsure of how to push that change to other developers and to the production server. With migrations, you can describe the transformations in self-contained classes that can be checked into version control systems and executed against another database that might be one, two, or five versions behind.

+ +

Example of a simple migration:

+ +
class AddSsl < ActiveRecord::Migration[7.0]
+  def up
+    add_column :accounts, :ssl_enabled, :boolean, default: true
+  end
+
+  def down
+    remove_column :accounts, :ssl_enabled
+  end
+end
+
+ +

This migration will add a boolean flag to the accounts table and remove it if you’re backing out of the migration. It shows how all migrations have two methods up and down that describes the transformations required to implement or remove the migration. These methods can consist of both the migration specific methods like add_column and remove_column, but may also contain regular Ruby code for generating data needed for the transformations.

+ +

Example of a more complex migration that also needs to initialize data:

+ +
class AddSystemSettings < ActiveRecord::Migration[7.0]
+  def up
+    create_table :system_settings do |t|
+      t.string  :name
+      t.string  :label
+      t.text    :value
+      t.string  :type
+      t.integer :position
+    end
+
+    SystemSetting.create  name:  'notice',
+                          label: 'Use notice?',
+                          value: 1
+  end
+
+  def down
+    drop_table :system_settings
+  end
+end
+
+ +

This migration first adds the system_settings table, then creates the very first row in it using the Active Record model that relies on the table. It also uses the more advanced create_table syntax where you can specify a complete table schema in one block call.

+ +

Available transformations

+ +

Creation

+
  • +

    create_join_table(table_1, table_2, options): Creates a join table having its name as the lexical order of the first two arguments. See ActiveRecord::ConnectionAdapters::SchemaStatements#create_join_table for details.

    +
  • +

    create_table(name, options): Creates a table called name and makes the table object available to a block that can then add columns to it, following the same format as add_column. See example above. The options hash is for fragments like “DEFAULT CHARSET=UTF-8” that are appended to the create table definition.

    +
  • +

    add_column(table_name, column_name, type, options): Adds a new column to the table called table_name named column_name specified to be one of the following types: :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean. A default value can be specified by passing an options hash like { default: 11 }. Other options include :limit and :null (e.g. { limit: 50, null: false }) – see ActiveRecord::ConnectionAdapters::TableDefinition#column for details.

    +
  • +

    add_foreign_key(from_table, to_table, options): Adds a new foreign key. from_table is the table with the key column, to_table contains the referenced primary key.

    +
  • +

    add_index(table_name, column_names, options): Adds a new index with the name of the column. Other options include :name, :unique (e.g. { name: 'users_name_index', unique: true }) and :order (e.g. { order: { name: :desc } }).

    +
  • +

    add_reference(:table_name, :reference_name): Adds a new column reference_name_id by default an integer. See ActiveRecord::ConnectionAdapters::SchemaStatements#add_reference for details.

    +
  • +

    add_timestamps(table_name, options): Adds timestamps (created_at and updated_at) columns to table_name.

    +
+ +

Modification

+
  • +

    change_column(table_name, column_name, type, options): Changes the column to a different type using the same parameters as add_column.

    +
  • +

    change_column_default(table_name, column_name, default_or_changes): Sets a default value for column_name defined by default_or_changes on table_name. Passing a hash containing :from and :to as default_or_changes will make this change reversible in the migration.

    +
  • +

    change_column_null(table_name, column_name, null, default = nil): Sets or removes a NOT NULL constraint on column_name. The null flag indicates whether the value can be NULL. See ActiveRecord::ConnectionAdapters::SchemaStatements#change_column_null for details.

    +
  • +

    change_table(name, options): Allows to make column alterations to the table called name. It makes the table object available to a block that can then add/remove columns, indexes, or foreign keys to it.

    +
  • +

    rename_column(table_name, column_name, new_column_name): Renames a column but keeps the type and content.

    +
  • +

    rename_index(table_name, old_name, new_name): Renames an index.

    +
  • +

    rename_table(old_name, new_name): Renames the table called old_name to new_name.

    +
+ +

Deletion

+
  • +

    drop_table(name): Drops the table called name.

    +
  • +

    drop_join_table(table_1, table_2, options): Drops the join table specified by the given arguments.

    +
  • +

    remove_column(table_name, column_name, type, options): Removes the column named column_name from the table called table_name.

    +
  • +

    remove_columns(table_name, *column_names): Removes the given columns from the table definition.

    +
  • +

    remove_foreign_key(from_table, to_table = nil, **options): Removes the given foreign key from the table called table_name.

    +
  • +

    remove_index(table_name, column: column_names): Removes the index specified by column_names.

    +
  • +

    remove_index(table_name, name: index_name): Removes the index specified by index_name.

    +
  • +

    remove_reference(table_name, ref_name, options): Removes the reference(s) on table_name specified by ref_name.

    +
  • +

    remove_timestamps(table_name, options): Removes the timestamp columns (created_at and updated_at) from the table definition.

    +
+ +

Irreversible transformations

+ +

Some transformations are destructive in a manner that cannot be reversed. Migrations of that kind should raise an ActiveRecord::IrreversibleMigration exception in their down method.

+ +

Running migrations from within Rails

+ +

The Rails package has several tools to help create and apply migrations.

+ +

To generate a new migration, you can use

+ +
bin/rails generate migration MyNewMigration
+
+ +

where MyNewMigration is the name of your migration. The generator will create an empty migration file timestamp_my_new_migration.rb in the db/migrate/ directory where timestamp is the UTC formatted date and time that the migration was generated.

+ +

There is a special syntactic shortcut to generate migrations that add fields to a table.

+ +
bin/rails generate migration add_fieldname_to_tablename fieldname:string
+
+ +

This will generate the file timestamp_add_fieldname_to_tablename.rb, which will look like this:

+ +
class AddFieldnameToTablename < ActiveRecord::Migration[7.0]
+  def change
+    add_column :tablenames, :fieldname, :string
+  end
+end
+
+ +

To run migrations against the currently configured database, use bin/rails db:migrate. This will update the database by running all of the pending migrations, creating the schema_migrations table (see “About the schema_migrations table” section below) if missing. It will also invoke the db:schema:dump command, which will update your db/schema.rb file to match the structure of your database.

+ +

To roll the database back to a previous migration version, use bin/rails db:rollback VERSION=X where X is the version to which you wish to downgrade. Alternatively, you can also use the STEP option if you wish to rollback last few migrations. bin/rails db:rollback STEP=2 will rollback the latest two migrations.

+ +

If any of the migrations throw an ActiveRecord::IrreversibleMigration exception, that step will fail and you’ll have some manual work to do.

+ +

More examples

+ +

Not all migrations change the schema. Some just fix the data:

+ +
class RemoveEmptyTags < ActiveRecord::Migration[7.0]
+  def up
+    Tag.all.each { |tag| tag.destroy if tag.pages.empty? }
+  end
+
+  def down
+    # not much we can do to restore deleted data
+    raise ActiveRecord::IrreversibleMigration, "Can't recover the deleted tags"
+  end
+end
+
+ +

Others remove columns when they migrate up instead of down:

+ +
class RemoveUnnecessaryItemAttributes < ActiveRecord::Migration[7.0]
+  def up
+    remove_column :items, :incomplete_items_count
+    remove_column :items, :completed_items_count
+  end
+
+  def down
+    add_column :items, :incomplete_items_count
+    add_column :items, :completed_items_count
+  end
+end
+
+ +

And sometimes you need to do something in SQL not abstracted directly by migrations:

+ +
class MakeJoinUnique < ActiveRecord::Migration[7.0]
+  def up
+    execute "ALTER TABLE `pages_linked_pages` ADD UNIQUE `page_id_linked_page_id` (`page_id`,`linked_page_id`)"
+  end
+
+  def down
+    execute "ALTER TABLE `pages_linked_pages` DROP INDEX `page_id_linked_page_id`"
+  end
+end
+
+ +

Using a model after changing its table

+ +

Sometimes you’ll want to add a column in a migration and populate it immediately after. In that case, you’ll need to make a call to Base#reset_column_information in order to ensure that the model has the latest column data from after the new column was added. Example:

+ +
class AddPeopleSalary < ActiveRecord::Migration[7.0]
+  def up
+    add_column :people, :salary, :integer
+    Person.reset_column_information
+    Person.all.each do |p|
+      p.update_attribute :salary, SalaryCalculator.compute(p)
+    end
+  end
+end
+
+ +

Controlling verbosity

+ +

By default, migrations will describe the actions they are taking, writing them to the console as they happen, along with benchmarks describing how long each step took.

+ +

You can quiet them down by setting ActiveRecord::Migration.verbose = false.

+ +

You can also insert your own messages and benchmarks by using the say_with_time method:

+ +
def up
+  ...
+  say_with_time "Updating salaries..." do
+    Person.all.each do |p|
+      p.update_attribute :salary, SalaryCalculator.compute(p)
+    end
+  end
+  ...
+end
+
+ +

The phrase “Updating salaries…” would then be printed, along with the benchmark for the block when the block completes.

+ +

Timestamped Migrations

+ +

By default, Rails generates migrations that look like:

+ +
20080717013526_your_migration_name.rb
+
+ +

The prefix is a generation timestamp (in UTC).

+ +

If you’d prefer to use numeric prefixes, you can turn timestamped migrations off by setting:

+ +
config.active_record.timestamped_migrations = false
+
+ +

In application.rb.

+ +

Reversible Migrations

+ +

Reversible migrations are migrations that know how to go down for you. You simply supply the up logic, and the Migration system figures out how to execute the down commands for you.

+ +

To define a reversible migration, define the change method in your migration like this:

+ +
class TenderloveMigration < ActiveRecord::Migration[7.0]
+  def change
+    create_table(:horses) do |t|
+      t.column :content, :text
+      t.column :remind_at, :datetime
+    end
+  end
+end
+
+ +

This migration will create the horses table for you on the way up, and automatically figure out how to drop the table on the way down.

+ +

Some commands cannot be reversed. If you care to define how to move up and down in these cases, you should define the up and down methods as before.

+ +

If a command cannot be reversed, an ActiveRecord::IrreversibleMigration exception will be raised when the migration is moving down.

+ +

For a list of commands that are reversible, please see ActiveRecord::Migration::CommandRecorder.

+ +

Transactional Migrations

+ +

If the database adapter supports DDL transactions, all migrations will automatically be wrapped in a transaction. There are queries that you can’t execute inside a transaction though, and for these situations you can turn the automatic transactions off.

+ +
class ChangeEnum < ActiveRecord::Migration[7.0]
+  disable_ddl_transaction!
+
+  def up
+    execute "ALTER TYPE model_size ADD VALUE 'new_value'"
+  end
+end
+
+ +

Remember that you can still open your own transactions, even if you are in a Migration with self.disable_ddl_transaction!.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + name
+ [RW] + version
+ + + + +

Class Public methods

+ +
+

+ + [](version) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 603
+def self.[](version)
+  Compatibility.find(version)
+end
+
+
+ +
+ +
+

+ + check_pending!(connection = Base.connection) + +

+ + +
+

Raises ActiveRecord::PendingMigrationError error if any migrations are pending.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 661
+def check_pending!(connection = Base.connection)
+  raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
+end
+
+
+ +
+ +
+

+ + current_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 607
+def self.current_version
+  ActiveRecord::VERSION::STRING.to_f
+end
+
+
+ +
+ +
+

+ + disable_ddl_transaction!() + +

+ + +
+

Disable the transaction wrapping this migration. You can still create your own transactions even after calling disable_ddl_transaction!

+ +

For more details read the “Transactional Migrations” section above.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 707
+def disable_ddl_transaction!
+  @disable_ddl_transaction = true
+end
+
+
+ +
+ +
+

+ + load_schema_if_pending!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 665
+def load_schema_if_pending!
+  current_db_config = Base.connection_db_config
+  all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)
+
+  needs_update = !all_configs.all? do |db_config|
+    Tasks::DatabaseTasks.schema_up_to_date?(db_config, ActiveRecord.schema_format)
+  end
+
+  if needs_update
+    # Roundtrip to Rake to allow plugins to hook into database initialization.
+    root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
+    FileUtils.cd(root) do
+      Base.clear_all_connections!
+      system("bin/rails db:test:prepare")
+    end
+  end
+
+  # Establish a new connection, the old database may be gone (db:test:prepare uses purge)
+  Base.establish_connection(current_db_config)
+
+  check_pending!
+end
+
+
+ +
+ +
+

+ + migrate(direction) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 699
+def migrate(direction)
+  new.migrate direction
+end
+
+
+ +
+ +
+

+ + new(name = self.class.name, version = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 719
+def initialize(name = self.class.name, version = nil)
+  @name       = name
+  @version    = version
+  @connection = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + announce(message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 918
+def announce(message)
+  text = "#{version} #{name}: #{message}"
+  length = [0, 75 - text.length].max
+  write "== %s %s" % [text, "=" * length]
+end
+
+
+ +
+ +
+

+ + connection() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 949
+def connection
+  @connection || ActiveRecord::Base.connection
+end
+
+
+ +
+ +
+

+ + copy(destination, sources, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 970
+def copy(destination, sources, options = {})
+  copied = []
+  schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration
+
+  FileUtils.mkdir_p(destination) unless File.exist?(destination)
+
+  destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations
+  last = destination_migrations.last
+  sources.each do |scope, path|
+    source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
+
+    source_migrations.each do |migration|
+      source = File.binread(migration.filename)
+      inserted_comment = "# This migration comes from #{scope} (originally #{migration.version})\n"
+      magic_comments = +""
+      loop do
+        # If we have a magic comment in the original migration,
+        # insert our comment after the first newline(end of the magic comment line)
+        # so the magic keep working.
+        # Note that magic comments must be at the first line(except sh-bang).
+        source.sub!(/\A(?:#.*\b(?:en)?coding:\s*\S+|#\s*frozen_string_literal:\s*(?:true|false)).*\n/) do |magic_comment|
+          magic_comments << magic_comment; ""
+        end || break
+      end
+
+      if !magic_comments.empty? && source.start_with?("\n")
+        magic_comments << "\n"
+        source = source[1..-1]
+      end
+
+      source = "#{magic_comments}#{inserted_comment}#{source}"
+
+      if duplicate = destination_migrations.detect { |m| m.name == migration.name }
+        if options[:on_skip] && duplicate.scope != scope.to_s
+          options[:on_skip].call(scope, migration)
+        end
+        next
+      end
+
+      migration.version = next_migration_number(last ? last.version + 1 : 0).to_i
+      new_path = File.join(destination, "#{migration.version}_#{migration.name.underscore}.#{scope}.rb")
+      old_path, migration.filename = migration.filename, new_path
+      last = migration
+
+      File.binwrite(migration.filename, source)
+      copied << migration
+      options[:on_copy].call(scope, migration, old_path) if options[:on_copy]
+      destination_migrations << migration
+    end
+  end
+
+  copied
+end
+
+
+ +
+ +
+

+ + down() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 871
+def down
+  self.class.delegate = self
+  return unless self.class.respond_to?(:down)
+  self.class.down
+end
+
+
+ +
+ +
+

+ + exec_migration(conn, direction) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 899
+def exec_migration(conn, direction)
+  @connection = conn
+  if respond_to?(:change)
+    if direction == :down
+      revert { change }
+    else
+      change
+    end
+  else
+    public_send(direction)
+  end
+ensure
+  @connection = nil
+end
+
+
+ +
+ +
+

+ + method_missing(method, *arguments, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 953
+def method_missing(method, *arguments, &block)
+  say_with_time "#{method}(#{format_arguments(arguments)})" do
+    unless connection.respond_to? :revert
+      unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
+        arguments[0] = proper_table_name(arguments.first, table_name_options)
+        if method == :rename_table ||
+          (method == :remove_foreign_key && !arguments.second.is_a?(Hash))
+          arguments[1] = proper_table_name(arguments.second, table_name_options)
+        end
+      end
+    end
+    return super unless connection.respond_to?(method)
+    connection.send(method, *arguments, &block)
+  end
+end
+
+
+ +
+ +
+

+ + migrate(direction) + +

+ + +
+

Execute this migration in the named direction

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 878
+def migrate(direction)
+  return unless respond_to?(direction)
+
+  case direction
+  when :up   then announce "migrating"
+  when :down then announce "reverting"
+  end
+
+  time = nil
+  ActiveRecord::Base.connection_pool.with_connection do |conn|
+    time = Benchmark.measure do
+      exec_migration(conn, direction)
+    end
+  end
+
+  case direction
+  when :up   then announce "migrated (%.4fs)" % time.real; write
+  when :down then announce "reverted (%.4fs)" % time.real; write
+  end
+end
+
+
+ +
+ +
+

+ + next_migration_number(number) + +

+ + +
+

Determines the version number of the next migration.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 1036
+def next_migration_number(number)
+  if ActiveRecord.timestamped_migrations
+    [Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
+  else
+    SchemaMigration.normalize_migration_number(number)
+  end
+end
+
+
+ +
+ +
+

+ + proper_table_name(name, options = {}) + +

+ + +
+

Finds the correct table name given an Active Record object. Uses the Active Record object’s own table_name, or pre/suffix from the options passed in.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 1027
+def proper_table_name(name, options = {})
+  if name.respond_to? :table_name
+    name.table_name
+  else
+    "#{options[:table_name_prefix]}#{name}#{options[:table_name_suffix]}"
+  end
+end
+
+
+ +
+ +
+

+ + reversible() + +

+ + +
+

Used to specify an operation that can be run in one direction or another. Call the methods up and down of the yielded object to run a block only in one given direction. The whole block will be called in the right order within the migration.

+ +

In the following example, the looping on users will always be done when the three columns ‘first_name’, ‘last_name’ and ‘full_name’ exist, even when migrating down:

+ +
class SplitNameMigration < ActiveRecord::Migration[7.0]
+  def change
+    add_column :users, :first_name, :string
+    add_column :users, :last_name, :string
+
+    reversible do |dir|
+      User.reset_column_information
+      User.all.each do |u|
+        dir.up   { u.first_name, u.last_name = u.full_name.split(' ') }
+        dir.down { u.full_name = "#{u.first_name} #{u.last_name}" }
+        u.save
+      end
+    end
+
+    revert { add_column :users, :full_name, :string }
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 823
+def reversible
+  helper = ReversibleBlockHelper.new(reverting?)
+  execute_block { yield helper }
+end
+
+
+ +
+ +
+

+ + revert(*migration_classes, &block) + +

+ + +
+

Reverses the migration commands for the given block and the given migrations.

+ +

The following migration will remove the table ‘horses’ and create the table ‘apples’ on the way up, and the reverse on the way down.

+ +
class FixTLMigration < ActiveRecord::Migration[7.0]
+  def change
+    revert do
+      create_table(:horses) do |t|
+        t.text :content
+        t.datetime :remind_at
+      end
+    end
+    create_table(:apples) do |t|
+      t.string :variety
+    end
+  end
+end
+
+ +

Or equivalently, if TenderloveMigration is defined as in the documentation for Migration:

+ +
require_relative "20121212123456_tenderlove_migration"
+
+class FixupTLMigration < ActiveRecord::Migration[7.0]
+  def change
+    revert TenderloveMigration
+
+    create_table(:apples) do |t|
+      t.string :variety
+    end
+  end
+end
+
+ +

This command can be nested.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 766
+def revert(*migration_classes, &block)
+  run(*migration_classes.reverse, revert: true) unless migration_classes.empty?
+  if block_given?
+    if connection.respond_to? :revert
+      connection.revert(&block)
+    else
+      recorder = command_recorder
+      @connection = recorder
+      suppress_messages do
+        connection.revert(&block)
+      end
+      @connection = recorder.delegate
+      recorder.replay(self)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + reverting?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 783
+def reverting?
+  connection.respond_to?(:reverting) && connection.reverting
+end
+
+
+ +
+ +
+

+ + run(*migration_classes) + +

+ + +
+

Runs the given migration classes. Last argument can specify options:

+
  • +

    :direction - Default is :up.

    +
  • +

    :revert - Default is false.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 851
+def run(*migration_classes)
+  opts = migration_classes.extract_options!
+  dir = opts[:direction] || :up
+  dir = (dir == :down ? :up : :down) if opts[:revert]
+  if reverting?
+    # If in revert and going :up, say, we want to execute :down without reverting, so
+    revert { run(*migration_classes, direction: dir, revert: true) }
+  else
+    migration_classes.each do |migration_class|
+      migration_class.new.exec_migration(connection, dir)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + say(message, subitem = false) + +

+ + +
+

Takes a message argument and outputs it as is. A second boolean argument can be passed to specify whether to indent or not.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 926
+def say(message, subitem = false)
+  write "#{subitem ? "   ->" : "--"} #{message}"
+end
+
+
+ +
+ +
+

+ + say_with_time(message) + +

+ + +
+

Outputs text along with how long it took to run its block. If the block returns an integer it assumes it is the number of rows affected.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 932
+def say_with_time(message)
+  say(message)
+  result = nil
+  time = Benchmark.measure { result = yield }
+  say "%.4fs" % time.real, :subitem
+  say("#{result} rows", :subitem) if result.is_a?(Integer)
+  result
+end
+
+
+ +
+ +
+

+ + suppress_messages() + +

+ + +
+

Takes a block as an argument and suppresses any output generated by the block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 942
+def suppress_messages
+  save, self.verbose = verbose, false
+  yield
+ensure
+  self.verbose = save
+end
+
+
+ +
+ +
+

+ + up() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 865
+def up
+  self.class.delegate = self
+  return unless self.class.respond_to?(:up)
+  self.class.up
+end
+
+
+ +
+ +
+

+ + up_only(&block) + +

+ + +
+

Used to specify an operation that is only run when migrating up (for example, populating a new column with its initial values).

+ +

In the following example, the new column published will be given the value true for all existing records.

+ +
class AddPublishedToPosts < ActiveRecord::Migration[7.0]
+  def change
+    add_column :posts, :published, :boolean, default: false
+    up_only do
+      execute "update posts set published = 'true'"
+    end
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 842
+def up_only(&block)
+  execute_block(&block) unless reverting?
+end
+
+
+ +
+ +
+

+ + write(text = "") + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 914
+def write(text = "")
+  puts(text) if verbose
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/CheckPending.html b/src/7.0/classes/ActiveRecord/Migration/CheckPending.html new file mode 100644 index 0000000000..07531b556b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/CheckPending.html @@ -0,0 +1,172 @@ +--- +title: ActiveRecord::Migration::CheckPending +layout: default +--- +
+ +
+
+ +
+ +

This class is used to verify that all migrations have been run before loading a web page if config.active_record.migration_error is set to :page_load.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, file_watcher: ActiveSupport::FileUpdateChecker) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 616
+def initialize(app, file_watcher: ActiveSupport::FileUpdateChecker)
+  @app = app
+  @needs_check = true
+  @mutex = Mutex.new
+  @file_watcher = file_watcher
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 623
+def call(env)
+  @mutex.synchronize do
+    @watcher ||= build_watcher do
+      @needs_check = true
+      ActiveRecord::Migration.check_pending!(connection)
+      @needs_check = false
+    end
+
+    if @needs_check
+      @watcher.execute
+    else
+      @watcher.execute_if_updated
+    end
+  end
+
+  @app.call(env)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/CommandRecorder.html b/src/7.0/classes/ActiveRecord/Migration/CommandRecorder.html new file mode 100644 index 0000000000..47cc4e167a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/CommandRecorder.html @@ -0,0 +1,422 @@ +--- +title: ActiveRecord::Migration::CommandRecorder +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::Migration::CommandRecorder records commands done during a migration and knows how to reverse those commands. The CommandRecorder knows how to invert the following commands:

+
  • +

    add_column

    +
  • +

    add_foreign_key

    +
  • +

    add_check_constraint

    +
  • +

    add_index

    +
  • +

    add_reference

    +
  • +

    add_timestamps

    +
  • +

    change_column_default (must supply a :from and :to option)

    +
  • +

    change_column_null

    +
  • +

    change_column_comment (must supply a :from and :to option)

    +
  • +

    change_table_comment (must supply a :from and :to option)

    +
  • +

    create_join_table

    +
  • +

    create_table

    +
  • +

    disable_extension

    +
  • +

    drop_join_table

    +
  • +

    drop_table (must supply a block)

    +
  • +

    enable_extension

    +
  • +

    remove_column (must supply a type)

    +
  • +

    remove_columns (must supply a :type option)

    +
  • +

    remove_foreign_key (must supply a second table)

    +
  • +

    remove_check_constraint

    +
  • +

    remove_index

    +
  • +

    remove_reference

    +
  • +

    remove_timestamps

    +
  • +

    rename_column

    +
  • +

    rename_index

    +
  • +

    rename_table

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ReversibleAndIrreversibleMethods=[ +:create_table, :create_join_table, :rename_table, :add_column, :remove_column, +:rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, +:change_column_default, :add_reference, :remove_reference, :transaction, +:drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension, +:change_column, :execute, :remove_columns, :change_column_null, +:add_foreign_key, :remove_foreign_key, +:change_column_comment, :change_table_comment, +:add_check_constraint, :remove_check_constraint +]
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [RW] + commands
+ [RW] + delegate
+ [RW] + reverting
+ + + + +

Class Public methods

+ +
+

+ + new(delegate = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration/command_recorder.rb, line 50
+def initialize(delegate = nil)
+  @commands = []
+  @delegate = delegate
+  @reverting = false
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + inverse_of(command, args, &block) + +

+ + +
+

Returns the inverse of the given command. For example:

+ +
recorder.inverse_of(:rename_table, [:old, :new])
+# => [:rename_table, [:new, :old]]
+
+ +

If the inverse of a command requires several commands, returns array of commands.

+ +
recorder.inverse_of(:remove_columns, [:some_table, :foo, :bar, type: :string])
+# => [[:add_column, :some_table, :foo, :string], [:add_column, :some_table, :bar, :string]]
+
+ +

This method will raise an IrreversibleMigration exception if it cannot invert the command.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration/command_recorder.rb, line 97
+      def inverse_of(command, args, &block)
+        method = :"invert_#{command}"
+        raise IrreversibleMigration, <<~MSG unless respond_to?(method, true)
+          This migration uses #{command}, which is not automatically reversible.
+          To make the migration reversible you can either:
+          1. Define #up and #down methods in place of the #change method.
+          2. Use the #reversible method to define reversible behavior.
+        MSG
+        send(method, args, &block)
+      end
+
+
+ +
+ +
+

+ + record(*command, &block) + +

+ + +
+

Record command. command should be a method name and arguments. For example:

+ +
recorder.record(:method_name, [:arg1, :arg2])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration/command_recorder.rb, line 77
+def record(*command, &block)
+  if @reverting
+    @commands << inverse_of(*command, &block)
+  else
+    @commands << (command << block)
+  end
+end
+
+
+ +
+ +
+

+ + replay(migration) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration/command_recorder.rb, line 123
+def replay(migration)
+  commands.each do |cmd, args, block|
+    migration.send(cmd, *args, &block)
+  end
+end
+
+
+ +
+ +
+

+ + revert() + +

+ + +
+

While executing the given block, the recorded will be in reverting mode. All commands recorded will end up being recorded reverted and in reverse order. For example:

+ +
recorder.revert{ recorder.record(:rename_table, [:old, :new]) }
+# same effect as recorder.record(:rename_table, [:new, :old])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration/command_recorder.rb, line 63
+def revert
+  @reverting = !@reverting
+  previous = @commands
+  @commands = []
+  yield
+ensure
+  @commands = previous.concat(@commands.reverse)
+  @reverting = !@reverting
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility.html new file mode 100644 index 0000000000..40952c090d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility.html @@ -0,0 +1,77 @@ +--- +title: ActiveRecord::Migration::Compatibility +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2.html new file mode 100644 index 0000000000..6bca540d1f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::Migration::Compatibility::V4_2 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2/TableDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2/TableDefinition.html new file mode 100644 index 0000000000..cbf4d7d690 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V4_2/TableDefinition.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V4_2::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0.html new file mode 100644 index 0000000000..fc6be4676b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_0 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0/TableDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0/TableDefinition.html new file mode 100644 index 0000000000..df2ce68a26 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_0/TableDefinition.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_0::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_1.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_1.html new file mode 100644 index 0000000000..a16f51cde5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_1.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_1 +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2.html new file mode 100644 index 0000000000..40c87976e5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_2 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/CommandRecorder.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/CommandRecorder.html new file mode 100644 index 0000000000..0d1b114537 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/CommandRecorder.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_2::CommandRecorder +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/TableDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/TableDefinition.html new file mode 100644 index 0000000000..37c7cfbe30 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V5_2/TableDefinition.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V5_2::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0.html new file mode 100644 index 0000000000..5c1d303405 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0.html @@ -0,0 +1,80 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_0 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/ReferenceDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/ReferenceDefinition.html new file mode 100644 index 0000000000..5ceae35354 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/ReferenceDefinition.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_0::ReferenceDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/TableDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/TableDefinition.html new file mode 100644 index 0000000000..0f174dd3f2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_0/TableDefinition.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_0::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1.html new file mode 100644 index 0000000000..38e53793ff --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1.html @@ -0,0 +1,80 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_1 +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/PostgreSQLCompat.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/PostgreSQLCompat.html new file mode 100644 index 0000000000..2cd1b0c512 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/PostgreSQLCompat.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_1::PostgreSQLCompat +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/TableDefinition.html b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/TableDefinition.html new file mode 100644 index 0000000000..daba89e73c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Migration/Compatibility/V6_1/TableDefinition.html @@ -0,0 +1,54 @@ +--- +title: ActiveRecord::Migration::Compatibility::V6_1::TableDefinition +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/MigrationContext.html b/src/7.0/classes/ActiveRecord/MigrationContext.html new file mode 100644 index 0000000000..6626c90327 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/MigrationContext.html @@ -0,0 +1,197 @@ +--- +title: ActiveRecord::MigrationContext +layout: default +--- +
+ +
+
+ +
+ +

MigrationContext sets the context in which a migration is run.

+ +

A migration context requires the path to the migrations is set in the migrations_paths parameter. Optionally a schema_migration class can be provided. For most applications, SchemaMigration is sufficient. Multiple database applications need a SchemaMigration per primary database.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + migrations_paths
+ [R] + schema_migration
+ + + + +

Class Public methods

+ +
+

+ + new(migrations_paths, schema_migration = SchemaMigration) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 1120
+def initialize(migrations_paths, schema_migration = SchemaMigration)
+  @migrations_paths = migrations_paths
+  @schema_migration = schema_migration
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + migrate(target_version = nil, &block) + +

+ + +
+

Runs the migrations in the migrations_path.

+ +

If target_version is nil, migrate will run up.

+ +

If the current_version and target_version are both 0 then an empty array will be returned and no migrations will be run.

+ +

If the current_version in the schema is greater than the target_version, then down will be run.

+ +

If none of the conditions are met, up will be run with the target_version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/migration.rb, line 1138
+def migrate(target_version = nil, &block)
+  case
+  when target_version.nil?
+    up(target_version, &block)
+  when current_version == 0 && target_version == 0
+    []
+  when current_version > target_version
+    down(target_version, &block)
+  else
+    up(target_version, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/MismatchedForeignKey.html b/src/7.0/classes/ActiveRecord/MismatchedForeignKey.html new file mode 100644 index 0000000000..8b543ac89d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/MismatchedForeignKey.html @@ -0,0 +1,139 @@ +--- +title: ActiveRecord::MismatchedForeignKey +layout: default +--- +
+ +
+
+ +
+ +

Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new( message: nil, sql: nil, binds: nil, table: nil, foreign_key: nil, target_table: nil, primary_key: nil, primary_key_column: nil ) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 184
+    def initialize(
+      message: nil,
+      sql: nil,
+      binds: nil,
+      table: nil,
+      foreign_key: nil,
+      target_table: nil,
+      primary_key: nil,
+      primary_key_column: nil
+    )
+      if table
+        type = primary_key_column.bigint? ? :bigint : primary_key_column.type
+        msg = <<~EOM.squish
+          Column `#{foreign_key}` on table `#{table}` does not match column `#{primary_key}` on `#{target_table}`,
+          which has type `#{primary_key_column.sql_type}`.
+          To resolve this issue, change the type of the `#{foreign_key}` column on `#{table}` to be :#{type}.
+          (For example `t.#{type} :#{foreign_key}`).
+        EOM
+      else
+        msg = <<~EOM.squish
+          There is a mismatch between the foreign key and primary key column types.
+          Verify that the foreign key column type and the primary key of the associated table match types.
+        EOM
+      end
+      if message
+        msg << "\nOriginal message: #{message}"
+      end
+      super(msg, sql: sql, binds: binds)
+    end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ModelSchema.html b/src/7.0/classes/ActiveRecord/ModelSchema.html new file mode 100644 index 0000000000..778ca1dbeb --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ModelSchema.html @@ -0,0 +1,754 @@ +--- +title: ActiveRecord::ModelSchema +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + immutable_strings_by_default=(bool) + + +

+ + +
+

Determines whether columns should infer their type as :string or :immutable_string. This setting does not affect the behavior of attribute :foo, :string. Defaults to false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 122
+    
+
+
+ +
+ +
+

+ + implicit_order_column + + +

+ + +
+

The name of the column records are ordered by if no explicit order clause is used during an ordered finder call. If not set the primary key is used.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 106
+    
+
+
+ +
+ +
+

+ + implicit_order_column=(column_name) + + +

+ + +
+

Sets the column to sort records by when no explicit order clause is used during an ordered finder call. Useful when the primary key is not an auto-incrementing integer, for example when it’s a UUID. Records are subsorted by the primary key if it exists to ensure deterministic results.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 113
+    
+
+
+ +
+ +
+

+ + inheritance_column + + +

+ + +
+

The name of the table column which stores the class name on single-table inheritance situations.

+ +

The default inheritance column name is type, which means it’s a reserved word inside Active Record. To be able to use single-table inheritance with another column name, or to use the column type in your own model for something else, you can set inheritance_column:

+ +
self.inheritance_column = 'zoink'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 130
+    
+
+
+ +
+ +
+

+ + inheritance_column=(column) + + +

+ + +
+

Defines the name of the table column which will store the class name on single-table inheritance situations.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 150
+included do
+  class_attribute :primary_key_prefix_type, instance_writer: false
+  class_attribute :table_name_prefix, instance_writer: false, default: ""
+  class_attribute :table_name_suffix, instance_writer: false, default: ""
+  class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
+  class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
+  class_attribute :pluralize_table_names, instance_writer: false, default: true
+  class_attribute :implicit_order_column, instance_accessor: false
+  class_attribute :immutable_strings_by_default, instance_accessor: false
+
+  class_attribute :inheritance_column, instance_accessor: false, default: "type"
+  singleton_class.class_eval do
+    alias_method :_inheritance_column=, :inheritance_column=
+    private :_inheritance_column=
+    alias_method :inheritance_column=, :real_inheritance_column=
+  end
+
+  self.protected_environments = ["production"]
+
+  self.ignored_columns = [].freeze
+
+  delegate :type_for_attribute, :column_for_attribute, to: :class
+
+  initialize_load_schema_monitor
+end
+
+
+ +
+ +
+

+ + internal_metadata_table_name + + +

+ + +
+

The name of the internal metadata table. By default, the value is "ar_internal_metadata".

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 78
+    
+
+
+ +
+ +
+

+ + internal_metadata_table_name=(table_name) + + +

+ + +
+

Sets the name of the internal metadata table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 84
+    
+
+
+ +
+ +
+

+ + pluralize_table_names + + +

+ + +
+

Indicates whether table names should be the pluralized versions of the corresponding class names. If true, the default table name for a Product class will be “products”. If false, it would just be “product”. See table_name for the full rules on table/class naming. This is true, by default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 90
+    
+
+
+ +
+ +
+

+ + pluralize_table_names=(value) + + +

+ + +
+

Set whether table names should be the pluralized versions of the corresponding class names. If true, the default table name for a Product class will be “products”. If false, it would just be “product”. See table_name for the full rules on table/class naming. This is true, by default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 98
+    
+
+
+ +
+ +
+

+ + primary_key_prefix_type + + +

+ + +
+

The prefix type that will be prepended to every primary key column name. The options are :table_name and :table_name_with_underscore. If the first is specified, the Product class will look for “productid” instead of “id” as the primary column. If the latter is specified, the Product class will look for “product_id” instead of “id”. Remember that this is a global setting for all Active Records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 10
+    
+
+
+ +
+ +
+

+ + primary_key_prefix_type=(prefix_type) + + +

+ + +
+

Sets the prefix type that will be prepended to every primary key column name. The options are :table_name and :table_name_with_underscore. If the first is specified, the Product class will look for “productid” instead of “id” as the primary column. If the latter is specified, the Product class will look for “product_id” instead of “id”. Remember that this is a global setting for all Active Records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 20
+    
+
+
+ +
+ +
+

+ + schema_migrations_table_name + + +

+ + +
+

The name of the schema migrations table. By default, the value is "schema_migrations".

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 66
+    
+
+
+ +
+ +
+

+ + schema_migrations_table_name=(table_name) + + +

+ + +
+

Sets the name of the schema migrations table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 72
+    
+
+
+ +
+ +
+

+ + table_name_prefix + + +

+ + +
+

The prefix string to prepend to every table name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 30
+    
+
+
+ +
+ +
+

+ + table_name_prefix=(prefix) + + +

+ + +
+

Sets the prefix string to prepend to every table name. So if set to “basecamp_”, all table names will be named like “basecamp_projects”, “basecamp_people”, etc. This is a convenient way of creating a namespace for tables in a shared database. By default, the prefix is the empty string.

+ +

If you are organising your models within modules you can add a prefix to the models within a namespace by defining a singleton method in the parent module called table_name_prefix which returns your chosen prefix.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 36
+    
+
+
+ +
+ +
+

+ + table_name_suffix + + +

+ + +
+

The suffix string to append to every table name.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 49
+    
+
+
+ +
+ +
+

+ + table_name_suffix=(suffix) + + +

+ + +
+

Works like table_name_prefix=, but appends instead of prepends (set to “_basecamp” gives “projects_basecamp”, “people_basecamp”). By default, the suffix is the empty string.

+ +

If you are organising your models within modules, you can add a suffix to the models within a namespace by defining a singleton method in the parent module called table_name_suffix which returns your chosen suffix.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 55
+    
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ModelSchema/ClassMethods.html b/src/7.0/classes/ActiveRecord/ModelSchema/ClassMethods.html new file mode 100644 index 0000000000..2eb7ac9ef5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ModelSchema/ClassMethods.html @@ -0,0 +1,1019 @@ +--- +title: ActiveRecord::ModelSchema::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + column_defaults() + +

+ + +
+

Returns a hash where the keys are column names and the values are default values when instantiating the Active Record object for this table.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 481
+def column_defaults
+  load_schema
+  @column_defaults ||= _default_attributes.deep_dup.to_hash.freeze
+end
+
+
+ +
+ +
+

+ + column_for_attribute(name) + +

+ + +
+

Returns the column object for the named attribute. Returns an ActiveRecord::ConnectionAdapters::NullColumn if the named attribute does not exist.

+ +
class Person < ActiveRecord::Base
+end
+
+person = Person.new
+person.column_for_attribute(:name) # the result depends on the ConnectionAdapter
+# => #<ActiveRecord::ConnectionAdapters::Column:0x007ff4ab083980 @name="name", @sql_type="varchar(255)", @null=true, ...>
+
+person.column_for_attribute(:nothing)
+# => #<ActiveRecord::ConnectionAdapters::NullColumn:0xXXX @name=nil, @sql_type=nil, @cast_type=#<Type::Value>, ...>
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 472
+def column_for_attribute(name)
+  name = name.to_s
+  columns_hash.fetch(name) do
+    ConnectionAdapters::NullColumn.new(name)
+  end
+end
+
+
+ +
+ +
+

+ + column_names() + +

+ + +
+

Returns an array of column names as strings.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 492
+def column_names
+  @column_names ||= columns.map(&:name).freeze
+end
+
+
+ +
+ +
+

+ + columns() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 423
+def columns
+  load_schema
+  @columns ||= columns_hash.values.freeze
+end
+
+
+ +
+ +
+

+ + content_columns() + +

+ + +
+

Returns an array of column objects where the primary id, all columns ending in “_id” or “_count”, and columns used for single table inheritance have been removed.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 503
+def content_columns
+  @content_columns ||= columns.reject do |c|
+    c.name == primary_key ||
+    c.name == inheritance_column ||
+    c.name.end_with?("_id", "_count")
+  end.freeze
+end
+
+
+ +
+ +
+

+ + ignored_columns() + +

+ + +
+

The list of columns names the model should ignore. Ignored columns won’t have attribute accessors defined, and won’t be referenced in SQL queries.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 317
+def ignored_columns
+  if defined?(@ignored_columns)
+    @ignored_columns
+  else
+    superclass.ignored_columns
+  end
+end
+
+
+ +
+ +
+

+ + ignored_columns=(columns) + +

+ + +
+

Sets the columns names the model should ignore. Ignored columns won’t have attribute accessors defined, and won’t be referenced in SQL queries.

+ +

A common usage pattern for this method is to ensure all references to an attribute have been removed and deployed, before a migration to drop the column from the database has been deployed and run. Using this two step approach to dropping columns ensures there is no code that raises errors due to having a cached schema in memory at the time the schema migration is run.

+ +

For example, given a model where you want to drop the “category” attribute, first mark it as ignored:

+ +
class Project < ActiveRecord::Base
+  # schema:
+  #   id         :bigint
+  #   name       :string, limit: 255
+  #   category   :string, limit: 255
+
+  self.ignored_columns = [:category]
+end
+
+ +

The schema still contains “category”, but now the model omits it, so any meta-driven code or schema caching will not attempt to use the column:

+ +
Project.columns_hash["category"] => nil
+
+ +

You will get an error if accessing that attribute directly, so ensure all usages of the column are removed (automated tests can help you find any usages).

+ +
user = Project.create!(name: "First Project")
+user.category # => raises NoMethodError
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 356
+def ignored_columns=(columns)
+  reload_schema_from_cache
+  @ignored_columns = columns.map(&:to_s).freeze
+end
+
+
+ +
+ +
+

+ + next_sequence_value() + +

+ + +
+

Returns the next value that will be used as the primary key on an insert statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 401
+def next_sequence_value
+  connection.next_sequence_value(sequence_name)
+end
+
+
+ +
+ +
+

+ + prefetch_primary_key?() + +

+ + +
+

Determines if the primary key values should be selected from their corresponding sequence before the insert statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 395
+def prefetch_primary_key?
+  connection.prefetch_primary_key?(table_name)
+end
+
+
+ +
+ +
+

+ + protected_environments() + +

+ + +
+

The array of names of environments where destructive actions should be prohibited. By default, the value is ["production"].

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 298
+def protected_environments
+  if defined?(@protected_environments)
+    @protected_environments
+  else
+    superclass.protected_environments
+  end
+end
+
+
+ +
+ +
+

+ + protected_environments=(environments) + +

+ + +
+

Sets an array of names of environments where destructive actions should be prohibited.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 307
+def protected_environments=(environments)
+  @protected_environments = environments.map(&:to_s)
+end
+
+
+ +
+ +
+

+ + quoted_table_name() + +

+ + +
+

Returns a quoted version of the table name, used to construct SQL statements.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 273
+def quoted_table_name
+  @quoted_table_name ||= connection.quote_table_name(table_name)
+end
+
+
+ +
+ +
+

+ + reset_column_information() + +

+ + +
+

Resets all the cached information about columns, which will cause them to be reloaded on the next request.

+ +

The most common usage pattern for this method is probably in a migration, when just after creating a table you want to populate it with some default values, e.g.:

+ +
class CreateJobLevels < ActiveRecord::Migration[7.0]
+  def up
+    create_table :job_levels do |t|
+      t.integer :id
+      t.string :name
+
+      t.timestamps
+    end
+
+    JobLevel.reset_column_information
+    %w{assistant executive manager director}.each do |type|
+      JobLevel.create(name: type)
+    end
+  end
+
+  def down
+    drop_table :job_levels
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 537
+def reset_column_information
+  connection.clear_cache!
+  ([self] + descendants).each(&:undefine_attribute_methods)
+  connection.schema_cache.clear_data_source_cache!(table_name)
+
+  reload_schema_from_cache
+  initialize_find_by_cache
+end
+
+
+ +
+ +
+

+ + sequence_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 361
+def sequence_name
+  if base_class?
+    @sequence_name ||= reset_sequence_name
+  else
+    (@sequence_name ||= nil) || base_class.sequence_name
+  end
+end
+
+
+ +
+ +
+

+ + sequence_name=(value) + +

+ + +
+

Sets the name of the sequence to use when generating ids to the given value, or (if the value is nil or false) to the value returned by the given block. This is required for Oracle and is useful for any database which relies on sequences for primary key generation.

+ +

If a sequence name is not explicitly set when using Oracle, it will default to the commonly used pattern of: #{table_name}_seq

+ +

If a sequence name is not explicitly set when using PostgreSQL, it will discover the sequence corresponding to your primary key for you.

+ +
class Project < ActiveRecord::Base
+  self.sequence_name = "projectseq"   # default would have been "project_seq"
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 388
+def sequence_name=(value)
+  @sequence_name          = value.to_s
+  @explicit_sequence_name = true
+end
+
+
+ +
+ +
+

+ + table_exists?() + +

+ + +
+

Indicates whether the table associated with this class exists

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 406
+def table_exists?
+  connection.schema_cache.data_source_exists?(table_name)
+end
+
+
+ +
+ +
+

+ + table_name() + +

+ + +
+

Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending directly from ActiveRecord::Base. So if the hierarchy looks like: Reply < Message < ActiveRecord::Base, then Message is used to guess the table name even when called on Reply. The rules used to do the guess are handled by the Inflector class in Active Support, which knows almost all common English inflections. You can add new inflections in config/initializers/inflections.rb.

+ +

Nested classes are given table names prefixed by the singular form of the parent’s table name. Enclosing modules are not considered.

+ +

Examples

+ +
class Invoice < ActiveRecord::Base
+end
+
+file                  class               table_name
+invoice.rb            Invoice             invoices
+
+class Invoice < ActiveRecord::Base
+  class Lineitem < ActiveRecord::Base
+  end
+end
+
+file                  class               table_name
+invoice.rb            Invoice::Lineitem   invoice_lineitems
+
+module Invoice
+  class Lineitem < ActiveRecord::Base
+  end
+end
+
+file                  class               table_name
+invoice/lineitem.rb   Invoice::Lineitem   lineitems
+
+ +

Additionally, the class-level table_name_prefix is prepended and the table_name_suffix is appended. So if you have “myapp_” as a prefix, the table name guess for an Invoice class becomes “myapp_invoices”. Invoice::Lineitem becomes “myapp_invoice_lineitems”.

+ +

Active Model Naming’s model_name is the base name used to guess the table name. In case a custom Active Model Name is defined, it will be used for the table name as well:

+ +
class PostRecord < ActiveRecord::Base
+  class << self
+    def model_name
+      ActiveModel::Name.new(self, nil, "Post")
+    end
+  end
+end
+
+PostRecord.table_name
+# => "posts"
+
+ +

You can also set your own table name explicitly:

+ +
class Mouse < ActiveRecord::Base
+  self.table_name = "mice"
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 247
+def table_name
+  reset_table_name unless defined?(@table_name)
+  @table_name
+end
+
+
+ +
+ +
+

+ + table_name=(value) + +

+ + +
+

Sets the table name explicitly. Example:

+ +
class Project < ActiveRecord::Base
+  self.table_name = "project"
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 257
+def table_name=(value)
+  value = value && value.to_s
+
+  if defined?(@table_name)
+    return if value == @table_name
+    reset_column_information if connected?
+  end
+
+  @table_name        = value
+  @quoted_table_name = nil
+  @arel_table        = nil
+  @sequence_name     = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
+  @predicate_builder = nil
+end
+
+
+ +
+ +
+

+ + type_for_attribute(attr_name, &block) + +

+ + +
+

Returns the type of the attribute with the given name, after applying all modifiers. This method is the only valid source of information for anything related to the types of a model’s attributes. This method will access the database and load the model’s schema if it is required.

+ +

The return value of this method will implement the interface described by ActiveModel::Type::Value (though the object itself may not subclass it).

+ +

attr_name The name of the attribute to retrieve the type for. Must be a string or a symbol.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 448
+def type_for_attribute(attr_name, &block)
+  attr_name = attr_name.to_s
+  attr_name = attribute_aliases[attr_name] || attr_name
+
+  if block
+    attribute_types.fetch(attr_name, &block)
+  else
+    attribute_types[attr_name]
+  end
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + initialize_load_schema_monitor() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/model_schema.rb, line 547
+def initialize_load_schema_monitor
+  @load_schema_monitor = Monitor.new
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/MultiparameterAssignmentErrors.html b/src/7.0/classes/ActiveRecord/MultiparameterAssignmentErrors.html new file mode 100644 index 0000000000..f3a308b17a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/MultiparameterAssignmentErrors.html @@ -0,0 +1,127 @@ +--- +title: ActiveRecord::MultiparameterAssignmentErrors +layout: default +--- +
+ +
+
+ +
+ +

Raised when there are multiple errors while doing a mass assignment through the ActiveRecord::Base#attributes= method. The exception has an errors property that contains an array of AttributeAssignmentError objects, each corresponding to the error while assigning to an attribute.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + errors
+ + + + +

Class Public methods

+ +
+

+ + new(errors = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 369
+def initialize(errors = nil)
+  @errors = errors
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NestedAttributes.html b/src/7.0/classes/ActiveRecord/NestedAttributes.html new file mode 100644 index 0000000000..fd70134cc5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NestedAttributes.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::NestedAttributes +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NestedAttributes/ClassMethods.html b/src/7.0/classes/ActiveRecord/NestedAttributes/ClassMethods.html new file mode 100644 index 0000000000..5d924a8022 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NestedAttributes/ClassMethods.html @@ -0,0 +1,406 @@ +--- +title: ActiveRecord::NestedAttributes::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Active Record Nested Attributes

+ +

Nested attributes allow you to save attributes on associated records through the parent. By default nested attribute updating is turned off and you can enable it using the accepts_nested_attributes_for class method. When you enable nested attributes an attribute writer is defined on the model.

+ +

The attribute writer is named after the association, which means that in the following example, two new methods are added to your model:

+ +

author_attributes=(attributes) and pages_attributes=(attributes).

+ +
class Book < ActiveRecord::Base
+  has_one :author
+  has_many :pages
+
+  accepts_nested_attributes_for :author, :pages
+end
+
+ +

Note that the :autosave option is automatically enabled on every association that accepts_nested_attributes_for is used for.

+ +

One-to-one

+ +

Consider a Member model that has one Avatar:

+ +
class Member < ActiveRecord::Base
+  has_one :avatar
+  accepts_nested_attributes_for :avatar
+end
+
+ +

Enabling nested attributes on a one-to-one association allows you to create the member and avatar in one go:

+ +
params = { member: { name: 'Jack', avatar_attributes: { icon: 'smiling' } } }
+member = Member.create(params[:member])
+member.avatar.id # => 2
+member.avatar.icon # => 'smiling'
+
+ +

It also allows you to update the avatar through the member:

+ +
params = { member: { avatar_attributes: { id: '2', icon: 'sad' } } }
+member.update params[:member]
+member.avatar.icon # => 'sad'
+
+ +

If you want to update the current avatar without providing the id, you must add :update_only option.

+ +
class Member < ActiveRecord::Base
+  has_one :avatar
+  accepts_nested_attributes_for :avatar, update_only: true
+end
+
+params = { member: { avatar_attributes: { icon: 'sad' } } }
+member.update params[:member]
+member.avatar.id # => 2
+member.avatar.icon # => 'sad'
+
+ +

By default you will only be able to set and update attributes on the associated model. If you want to destroy the associated model through the attributes hash, you have to enable it first using the :allow_destroy option.

+ +
class Member < ActiveRecord::Base
+  has_one :avatar
+  accepts_nested_attributes_for :avatar, allow_destroy: true
+end
+
+ +

Now, when you add the _destroy key to the attributes hash, with a value that evaluates to true, you will destroy the associated model:

+ +
member.avatar_attributes = { id: '2', _destroy: '1' }
+member.avatar.marked_for_destruction? # => true
+member.save
+member.reload.avatar # => nil
+
+ +

Note that the model will not be destroyed until the parent is saved.

+ +

Also note that the model will not be destroyed unless you also specify its id in the updated hash.

+ +

One-to-many

+ +

Consider a member that has a number of posts:

+ +
class Member < ActiveRecord::Base
+  has_many :posts
+  accepts_nested_attributes_for :posts
+end
+
+ +

You can now set or update attributes on the associated posts through an attribute hash for a member: include the key :posts_attributes with an array of hashes of post attributes as a value.

+ +

For each hash that does not have an id key a new record will be instantiated, unless the hash also contains a _destroy key that evaluates to true.

+ +
params = { member: {
+  name: 'joe', posts_attributes: [
+    { title: 'Kari, the awesome Ruby documentation browser!' },
+    { title: 'The egalitarian assumption of the modern citizen' },
+    { title: '', _destroy: '1' } # this will be ignored
+  ]
+}}
+
+member = Member.create(params[:member])
+member.posts.length # => 2
+member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
+member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
+
+ +

You may also set a :reject_if proc to silently ignore any new record hashes if they fail to pass your criteria. For example, the previous example could be rewritten as:

+ +
class Member < ActiveRecord::Base
+  has_many :posts
+  accepts_nested_attributes_for :posts, reject_if: proc { |attributes| attributes['title'].blank? }
+end
+
+params = { member: {
+  name: 'joe', posts_attributes: [
+    { title: 'Kari, the awesome Ruby documentation browser!' },
+    { title: 'The egalitarian assumption of the modern citizen' },
+    { title: '' } # this will be ignored because of the :reject_if proc
+  ]
+}}
+
+member = Member.create(params[:member])
+member.posts.length # => 2
+member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
+member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
+
+ +

Alternatively, :reject_if also accepts a symbol for using methods:

+ +
class Member < ActiveRecord::Base
+  has_many :posts
+  accepts_nested_attributes_for :posts, reject_if: :new_record?
+end
+
+class Member < ActiveRecord::Base
+  has_many :posts
+  accepts_nested_attributes_for :posts, reject_if: :reject_posts
+
+  def reject_posts(attributes)
+    attributes['title'].blank?
+  end
+end
+
+ +

If the hash contains an id key that matches an already associated record, the matching record will be modified:

+ +
member.attributes = {
+  name: 'Joe',
+  posts_attributes: [
+    { id: 1, title: '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!' },
+    { id: 2, title: '[UPDATED] other post' }
+  ]
+}
+
+member.posts.first.title # => '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!'
+member.posts.second.title # => '[UPDATED] other post'
+
+ +

However, the above applies if the parent model is being updated as well. For example, if you wanted to create a member named joe and wanted to update the posts at the same time, that would give an ActiveRecord::RecordNotFound error.

+ +

By default the associated records are protected from being destroyed. If you want to destroy any of the associated records through the attributes hash, you have to enable it first using the :allow_destroy option. This will allow you to also use the _destroy key to destroy existing records:

+ +
class Member < ActiveRecord::Base
+  has_many :posts
+  accepts_nested_attributes_for :posts, allow_destroy: true
+end
+
+params = { member: {
+  posts_attributes: [{ id: '2', _destroy: '1' }]
+}}
+
+member.attributes = params[:member]
+member.posts.detect { |p| p.id == 2 }.marked_for_destruction? # => true
+member.posts.length # => 2
+member.save
+member.reload.posts.length # => 1
+
+ +

Nested attributes for an associated collection can also be passed in the form of a hash of hashes instead of an array of hashes:

+ +
Member.create(
+  name: 'joe',
+  posts_attributes: {
+    first:  { title: 'Foo' },
+    second: { title: 'Bar' }
+  }
+)
+
+ +

has the same effect as

+ +
Member.create(
+  name: 'joe',
+  posts_attributes: [
+    { title: 'Foo' },
+    { title: 'Bar' }
+  ]
+)
+
+ +

The keys of the hash which is the value for :posts_attributes are ignored in this case. However, it is not allowed to use 'id' or :id for one of such keys, otherwise the hash will be wrapped in an array and interpreted as an attribute hash for a single post.

+ +

Passing attributes for an associated collection in the form of a hash of hashes can be used with hashes generated from HTTP/HTML parameters, where there may be no natural way to submit an array of hashes.

+ +

Saving

+ +

All changes to models, including the destruction of those marked for destruction, are saved and destroyed automatically and atomically when the parent model is saved. This happens inside the transaction initiated by the parent’s save method. See ActiveRecord::AutosaveAssociation.

+ +

Validating the presence of a parent model

+ +

The belongs_to association validates the presence of the parent model by default. You can disable this behavior by specifying optional: true. This can be used, for example, when conditionally validating the presence of the parent model:

+ +
class Veterinarian < ActiveRecord::Base
+  has_many :patients, inverse_of: :veterinarian
+  accepts_nested_attributes_for :patients
+end
+
+class Patient < ActiveRecord::Base
+  belongs_to :veterinarian, inverse_of: :patients, optional: true
+  validates :veterinarian, presence: true, unless: -> { awaiting_intake }
+end
+
+ +

Note that if you do not specify the :inverse_of option, then Active Record will try to automatically guess the inverse association based on heuristics.

+ +

For one-to-one nested associations, if you build the new (in-memory) child object yourself before assignment, then this module will not overwrite it, e.g.:

+ +
class Member < ActiveRecord::Base
+  has_one :avatar
+  accepts_nested_attributes_for :avatar
+
+  def avatar
+    super || build_avatar(width: 200)
+  end
+end
+
+member = Member.new
+member.avatar_attributes = {icon: 'sad'}
+member.avatar.width # => 200
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
REJECT_ALL_BLANK_PROC=proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + accepts_nested_attributes_for(*attr_names) + +

+ + +
+

Defines an attributes writer for the specified association(s).

+ +

Supported options:

+
:allow_destroy +
+

If true, destroys any members from the attributes hash with a _destroy key and a value that evaluates to true (e.g. 1, ‘1’, true, or ‘true’). This option is off by default.

+
:reject_if +
+

Allows you to specify a Proc or a Symbol pointing to a method that checks whether a record should be built for a certain attribute hash. The hash is passed to the supplied Proc or the method and it should return either true or false. When no :reject_if is specified, a record will be built for all attribute hashes that do not have a _destroy value that evaluates to true. Passing :all_blank instead of a Proc will create a proc that will reject a record where all the attributes are blank excluding any value for _destroy.

+
:limit +
+

Allows you to specify the maximum number of associated records that can be processed with the nested attributes. Limit also can be specified as a Proc or a Symbol pointing to a method that should return a number. If the size of the nested attributes array exceeds the specified limit, NestedAttributes::TooManyRecords exception is raised. If omitted, any number of associations can be processed. Note that the :limit option is only applicable to one-to-many associations.

+
:update_only +
+

For a one-to-one association, this option allows you to specify how nested attributes are going to be used when an associated record already exists. In general, an existing record may either be updated with the new set of attribute values or be replaced by a wholly new record containing those values. By default the :update_only option is false and the nested attributes are used to update the existing record only if they include the record’s :id value. Otherwise a new record will be instantiated and used to replace the existing one. However if the :update_only option is true, the nested attributes are used to update the record’s attributes always, regardless of whether the :id is present. The option is ignored for collection associations.

+
+ +

Examples:

+ +
# creates avatar_attributes=
+accepts_nested_attributes_for :avatar, reject_if: proc { |attributes| attributes['name'].blank? }
+# creates avatar_attributes=
+accepts_nested_attributes_for :avatar, reject_if: :all_blank
+# creates avatar_attributes= and posts_attributes=
+accepts_nested_attributes_for :avatar, :posts, allow_destroy: true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/nested_attributes.rb, line 333
+def accepts_nested_attributes_for(*attr_names)
+  options = { allow_destroy: false, update_only: false }
+  options.update(attr_names.extract_options!)
+  options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
+  options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
+
+  attr_names.each do |association_name|
+    if reflection = _reflect_on_association(association_name)
+      reflection.autosave = true
+      define_autosave_validation_callbacks(reflection)
+
+      nested_attributes_options = self.nested_attributes_options.dup
+      nested_attributes_options[association_name.to_sym] = options
+      self.nested_attributes_options = nested_attributes_options
+
+      type = (reflection.collection? ? :collection : :one_to_one)
+      generate_association_writer(association_name, type)
+    else
+      raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?"
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NestedAttributes/TooManyRecords.html b/src/7.0/classes/ActiveRecord/NestedAttributes/TooManyRecords.html new file mode 100644 index 0000000000..3ed51b7893 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NestedAttributes/TooManyRecords.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::NestedAttributes::TooManyRecords +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NoDatabaseError.html b/src/7.0/classes/ActiveRecord/NoDatabaseError.html new file mode 100644 index 0000000000..c2028d6c15 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NoDatabaseError.html @@ -0,0 +1,175 @@ +--- +title: ActiveRecord::NoDatabaseError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a given database does not exist.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + db_error(db_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 250
+      def db_error(db_name)
+        NoDatabaseError.new(<<~MSG)
+          We could not find your database: #{db_name}. Which can be found in the database configuration file located at config/database.yml.
+
+          To resolve this issue:
+
+          - Did you create the database for this app, or delete it? You may need to create your database.
+          - Has the database name changed? Check your database.yml config has the correct database name.
+
+          To create your database, run:\n\n        bin/rails db:create
+        MSG
+      end
+
+
+ +
+ +
+

+ + new(message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 245
+def initialize(message = nil)
+  super(message || "Database not found")
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NoTouching.html b/src/7.0/classes/ActiveRecord/NoTouching.html new file mode 100644 index 0000000000..98844c80f0 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NoTouching.html @@ -0,0 +1,126 @@ +--- +title: ActiveRecord::NoTouching +layout: default +--- +
+ +
+
+ +
+ +

Active Record No Touching

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + no_touching?() + +

+ + +
+

Returns true if the class has no_touching set, false otherwise.

+ +
Project.no_touching do
+  Project.first.no_touching? # true
+  Message.first.no_touching? # false
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/no_touching.rb, line 53
+def no_touching?
+  NoTouching.applied_to?(self.class)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NoTouching/ClassMethods.html b/src/7.0/classes/ActiveRecord/NoTouching/ClassMethods.html new file mode 100644 index 0000000000..63813807d6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NoTouching/ClassMethods.html @@ -0,0 +1,114 @@ +--- +title: ActiveRecord::NoTouching::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + no_touching(&block) + +

+ + +
+

Lets you selectively disable calls to touch for the duration of a block.

+ +

Examples

+ +
ActiveRecord::Base.no_touching do
+  Project.first.touch  # does nothing
+  Message.first.touch  # does nothing
+end
+
+Project.no_touching do
+  Project.first.touch  # does nothing
+  Message.first.touch  # works, but does not touch the associated project
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/no_touching.rb, line 23
+def no_touching(&block)
+  NoTouching.apply_to(self, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/NotNullViolation.html b/src/7.0/classes/ActiveRecord/NotNullViolation.html new file mode 100644 index 0000000000..ccea2f528d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/NotNullViolation.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::NotNullViolation +layout: default +--- +
+ +
+
+ +
+ +

Raised when a record cannot be inserted or updated because it would violate a not null constraint.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Persistence.html b/src/7.0/classes/ActiveRecord/Persistence.html new file mode 100644 index 0000000000..d0c5402fd3 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Persistence.html @@ -0,0 +1,1301 @@ +--- +title: ActiveRecord::Persistence +layout: default +--- +
+ +
+
+ +
+ +

Active Record Persistence

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + becomes(klass) + +

+ + +
+

Returns an instance of the specified klass with the attributes of the current record. This is mostly useful in relation to single table inheritance (STI) structures where you want a subclass to appear as the superclass. This can be used along with record identification in Action Pack to allow, say, Client < Company to do something like render partial: @client.becomes(Company) to render that instance using the companies/company partial instead of clients/client.

+ +

Note: The new instance will share a link to the same attributes as the original class. Therefore the STI column value will still be the same. Any change to the attributes on either instance will affect both instances. If you want to change the STI column as well, use becomes! instead.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 713
+def becomes(klass)
+  became = klass.allocate
+
+  became.send(:initialize) do |becoming|
+    becoming.instance_variable_set(:@attributes, @attributes)
+    becoming.instance_variable_set(:@mutations_from_database, @mutations_from_database ||= nil)
+    becoming.instance_variable_set(:@new_record, new_record?)
+    becoming.instance_variable_set(:@destroyed, destroyed?)
+    becoming.errors.copy!(errors)
+  end
+
+  became
+end
+
+
+ +
+ +
+

+ + becomes!(klass) + +

+ + +
+

Wrapper around becomes that also changes the instance’s STI column value. This is especially useful if you want to persist the changed class in your database.

+ +

Note: The old instance’s STI column value will be changed too, as both objects share the same set of attributes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 733
+def becomes!(klass)
+  became = becomes(klass)
+  sti_type = nil
+  if !klass.descends_from_active_record?
+    sti_type = klass.sti_name
+  end
+  became.public_send("#{klass.inheritance_column}=", sti_type)
+  became
+end
+
+
+ +
+ +
+

+ + decrement(attribute, by = 1) + +

+ + +
+

Initializes attribute to zero if nil and subtracts the value passed as by (default is 1). The decrement is performed directly on the underlying attribute, no setter is invoked. Only makes sense for number-based attributes. Returns self.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 858
+def decrement(attribute, by = 1)
+  increment(attribute, -by)
+end
+
+
+ +
+ +
+

+ + decrement!(attribute, by = 1, touch: nil) + +

+ + +
+

Wrapper around decrement that writes the update to the database. Only attribute is updated; the record itself is not saved. This means that any other modified attributes will still be dirty. Validations and callbacks are skipped. Supports the touch option from update_counters, see that for more. Returns self.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 868
+def decrement!(attribute, by = 1, touch: nil)
+  increment!(attribute, -by, touch: touch)
+end
+
+
+ +
+ +
+

+ + delete() + +

+ + +
+

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can’t be persisted). Returns the frozen instance.

+ +

The row is simply removed with an SQL DELETE statement on the record’s primary key, and no callbacks are executed.

+ +

Note that this will also delete records marked as #readonly?.

+ +

To enforce the object’s before_destroy and after_destroy callbacks or any :dependent association options, use destroy.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 663
+def delete
+  _delete_row if persisted?
+  @destroyed = true
+  @previously_new_record = false
+  freeze
+end
+
+
+ +
+ +
+

+ + destroy() + +

+ + +
+

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can’t be persisted).

+ +

There’s a series of callbacks associated with destroy. If the before_destroy callback throws :abort the action is cancelled and destroy returns false. See ActiveRecord::Callbacks for further details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 677
+def destroy
+  _raise_readonly_record_error if readonly?
+  destroy_associations
+  @_trigger_destroy_callback = if persisted?
+    destroy_row > 0
+  else
+    true
+  end
+  @destroyed = true
+  @previously_new_record = false
+  freeze
+end
+
+
+ +
+ +
+

+ + destroy!() + +

+ + +
+

Deletes the record in the database and freezes this instance to reflect that no changes should be made (since they can’t be persisted).

+ +

There’s a series of callbacks associated with destroy!. If the before_destroy callback throws :abort the action is cancelled and destroy! raises ActiveRecord::RecordNotDestroyed. See ActiveRecord::Callbacks for further details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 697
+def destroy!
+  destroy || _raise_record_not_destroyed
+end
+
+
+ +
+ +
+

+ + destroyed?() + +

+ + +
+

Returns true if this object has been destroyed, otherwise returns false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 579
+def destroyed?
+  @destroyed
+end
+
+
+ +
+ +
+

+ + increment(attribute, by = 1) + +

+ + +
+

Initializes attribute to zero if nil and adds the value passed as by (default is 1). The increment is performed directly on the underlying attribute, no setter is invoked. Only makes sense for number-based attributes. Returns self.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 835
+def increment(attribute, by = 1)
+  self[attribute] ||= 0
+  self[attribute] += by
+  self
+end
+
+
+ +
+ +
+

+ + increment!(attribute, by = 1, touch: nil) + +

+ + +
+

Wrapper around increment that writes the update to the database. Only attribute is updated; the record itself is not saved. This means that any other modified attributes will still be dirty. Validations and callbacks are skipped. Supports the touch option from update_counters, see that for more. Returns self.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 847
+def increment!(attribute, by = 1, touch: nil)
+  increment(attribute, by)
+  change = public_send(attribute) - (public_send(:"#{attribute}_in_database") || 0)
+  self.class.update_counters(id, attribute => change, touch: touch)
+  public_send(:"clear_#{attribute}_change")
+  self
+end
+
+
+ +
+ +
+

+ + new_record?() + +

+ + +
+

Returns true if this object hasn’t been saved yet – that is, a record for the object doesn’t exist in the database yet; otherwise, returns false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 562
+def new_record?
+  @new_record
+end
+
+
+ +
+ +
+

+ + persisted?() + +

+ + +
+

Returns true if the record is persisted, i.e. it’s not a new record and it was not destroyed, otherwise returns false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 585
+def persisted?
+  !(@new_record || @destroyed)
+end
+
+
+ +
+ +
+

+ + previously_new_record?() + +

+ + +
+

Returns true if this object was just created – that is, prior to the last update or delete, the object didn’t exist in the database and new_record? would have returned true.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 569
+def previously_new_record?
+  @previously_new_record
+end
+
+
+ +
+ +
+

+ + previously_persisted?() + +

+ + +
+

Returns true if this object was previously persisted but now it has been deleted.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 574
+def previously_persisted?
+  !new_record? && destroyed?
+end
+
+
+ +
+ +
+

+ + reload(options = nil) + +

+ + +
+

Reloads the record from the database.

+ +

This method finds the record by its primary key (which could be assigned manually) and modifies the receiver in-place:

+ +
account = Account.new
+# => #<Account id: nil, email: nil>
+account.id = 1
+account.reload
+# Account Load (1.2ms)  SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1  [["id", 1]]
+# => #<Account id: 1, email: 'account@example.com'>
+
+ +

Attributes are reloaded from the database, and caches busted, in particular the associations cache and the QueryCache.

+ +

If the record no longer exists in the database ActiveRecord::RecordNotFound is raised. Otherwise, in addition to the in-place modification the method returns self for convenience.

+ +

The optional :lock flag option allows you to lock the reloaded record:

+ +
reload(lock: true) # reload with pessimistic locking
+
+ +

Reloading is commonly used in test suites to test something is actually written to the database, or when some action modifies the corresponding row in the database but not the object in memory:

+ +
assert account.deposit!(25)
+assert_equal 25, account.credit        # check it is updated in memory
+assert_equal 25, account.reload.credit # check it is also persisted
+
+ +

Another common use case is optimistic locking handling:

+ +
def with_optimistic_retry
+  begin
+    yield
+  rescue ActiveRecord::StaleObjectError
+    begin
+      # Reload lock_version in particular.
+      reload
+    rescue ActiveRecord::RecordNotFound
+      # If the record is gone there is nothing to do.
+    else
+      retry
+    end
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 945
+def reload(options = nil)
+  self.class.connection.clear_query_cache
+
+  fresh_object = if apply_scoping?(options)
+    _find_record(options)
+  else
+    self.class.unscoped { _find_record(options) }
+  end
+
+  @association_cache = fresh_object.instance_variable_get(:@association_cache)
+  @attributes = fresh_object.instance_variable_get(:@attributes)
+  @new_record = false
+  @previously_new_record = false
+  self
+end
+
+
+ +
+ +
+

+ + save(**options) + + +

+ + +
+

Saves the model.

+ +

If the model is new, a record gets created in the database, otherwise the existing record gets updated.

+ +

By default, save always runs validations. If any of them fail the action is cancelled and save returns false, and the record won’t be saved. However, if you supply validate: false, validations are bypassed altogether. See ActiveRecord::Validations for more information.

+ +

By default, save also sets the updated_at/updated_on attributes to the current time. However, if you supply touch: false, these timestamps will not be updated.

+ +

There’s a series of callbacks associated with save. If any of the before_* callbacks throws :abort the action is cancelled and save returns false. See ActiveRecord::Callbacks for further details.

+ +

Attributes marked as readonly are silently ignored if the record is being updated.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 614
+def save(**options, &block)
+  create_or_update(**options, &block)
+rescue ActiveRecord::RecordInvalid
+  false
+end
+
+
+ +
+ +
+

+ + save!(**options) + + +

+ + +
+

Saves the model.

+ +

If the model is new, a record gets created in the database, otherwise the existing record gets updated.

+ +

By default, save! always runs validations. If any of them fail ActiveRecord::RecordInvalid gets raised, and the record won’t be saved. However, if you supply validate: false, validations are bypassed altogether. See ActiveRecord::Validations for more information.

+ +

By default, save! also sets the updated_at/updated_on attributes to the current time. However, if you supply touch: false, these timestamps will not be updated.

+ +

There’s a series of callbacks associated with save!. If any of the before_* callbacks throws :abort the action is cancelled and save! raises ActiveRecord::RecordNotSaved. See ActiveRecord::Callbacks for further details.

+ +

Attributes marked as readonly are silently ignored if the record is being updated.

+ +

Unless an error is raised, returns true.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 647
+def save!(**options, &block)
+  create_or_update(**options, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
+end
+
+
+ +
+ +
+

+ + toggle(attribute) + +

+ + +
+

Assigns to attribute the boolean opposite of attribute?. So if the predicate returns true the attribute will become false. This method toggles directly the underlying value without calling any setter. Returns self.

+ +

Example:

+ +
user = User.first
+user.banned? # => false
+user.toggle(:banned)
+user.banned? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 884
+def toggle(attribute)
+  self[attribute] = !public_send("#{attribute}?")
+  self
+end
+
+
+ +
+ +
+

+ + toggle!(attribute) + +

+ + +
+

Wrapper around toggle that saves the record. This method differs from its non-bang version in the sense that it passes through the attribute setter. Saving is not subjected to validation checks. Returns true if the record could be saved.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 893
+def toggle!(attribute)
+  toggle(attribute).update_attribute(attribute, self[attribute])
+end
+
+
+ +
+ +
+

+ + touch(*names, time: nil) + +

+ + +
+

Saves the record with the updated_at/on attributes set to the current time or the time specified. Please note that no validation is performed and only the after_touch, after_commit and after_rollback callbacks are executed.

+ +

This method can be passed attribute names and an optional time argument. If attribute names are passed, they are updated along with updated_at/on attributes. If no time argument is passed, the current time is used as default.

+ +
product.touch                         # updates updated_at/on with current time
+product.touch(time: Time.new(2015, 2, 16, 0, 0, 0)) # updates updated_at/on with specified time
+product.touch(:designed_at)           # updates the designed_at attribute and updated_at/on
+product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
+
+ +

If used along with belongs_to then touch will invoke touch method on associated object.

+ +
class Brake < ActiveRecord::Base
+  belongs_to :car, touch: true
+end
+
+class Car < ActiveRecord::Base
+  belongs_to :corporation, touch: true
+end
+
+# triggers @brake.car.touch and @brake.car.corporation.touch
+@brake.touch
+
+ +

Note that touch must be used on a persisted object, or else an ActiveRecordError will be thrown. For example:

+ +
ball = Ball.new
+ball.touch(:updated_at)   # => raises ActiveRecordError
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 995
+def touch(*names, time: nil)
+  _raise_record_not_touched_error unless persisted?
+  _raise_readonly_record_error if readonly?
+
+  attribute_names = timestamp_attributes_for_update_in_model
+  attribute_names |= names.map! do |name|
+    name = name.to_s
+    self.class.attribute_aliases[name] || name
+  end unless names.empty?
+
+  unless attribute_names.empty?
+    affected_rows = _touch_row(attribute_names, time)
+    @_trigger_update_callback = affected_rows == 1
+  else
+    true
+  end
+end
+
+
+ +
+ +
+

+ + update(attributes) + +

+ + +
+

Updates the attributes of the model from the passed-in hash and saves the record, all wrapped in a transaction. If the object is invalid, the saving will fail and false will be returned.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 766
+def update(attributes)
+  # The following transaction covers any possible database side-effects of the
+  # attributes assignment. For example, setting the IDs of a child collection.
+  with_transaction_returning_status do
+    assign_attributes(attributes)
+    save
+  end
+end
+
+
+ +
+ +
+

+ + update!(attributes) + +

+ + +
+

Updates its receiver just like update but calls save! instead of save, so an exception is raised if the record is invalid and saving will fail.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 777
+def update!(attributes)
+  # The following transaction covers any possible database side-effects of the
+  # attributes assignment. For example, setting the IDs of a child collection.
+  with_transaction_returning_status do
+    assign_attributes(attributes)
+    save!
+  end
+end
+
+
+ +
+ +
+

+ + update_attribute(name, value) + +

+ + +
+

Updates a single attribute and saves the record. This is especially useful for boolean flags on existing records. Also note that

+
  • +

    Validation is skipped.

    +
  • +

    Callbacks are invoked.

    +
  • +

    updated_at/updated_on column is updated if that column is available.

    +
  • +

    Updates all the attributes that are dirty in this object.

    +
+ +

This method raises an ActiveRecord::ActiveRecordError if the attribute is marked as readonly.

+ +

Also see update_column.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 755
+def update_attribute(name, value)
+  name = name.to_s
+  verify_readonly_attribute(name)
+  public_send("#{name}=", value)
+
+  save(validate: false)
+end
+
+
+ +
+ +
+

+ + update_column(name, value) + +

+ + +
+

Equivalent to update_columns(name => value).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 787
+def update_column(name, value)
+  update_columns(name => value)
+end
+
+
+ +
+ +
+

+ + update_columns(attributes) + +

+ + +
+

Updates the attributes directly in the database issuing an UPDATE SQL statement and sets them in the receiver:

+ +
user.update_columns(last_request_at: Time.current)
+
+ +

This is the fastest way to update attributes because it goes straight to the database, but take into account that in consequence the regular update procedures are totally bypassed. In particular:

+
  • +

    Validations are skipped.

    +
  • +

    Callbacks are skipped.

    +
  • +

    updated_at/updated_on are not updated.

    +
  • +

    However, attributes are serialized with the same rules as ActiveRecord::Relation#update_all

    +
+ +

This method raises an ActiveRecord::ActiveRecordError when called on new objects, or when at least one of the attributes is marked as readonly.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 807
+def update_columns(attributes)
+  raise ActiveRecordError, "cannot update a new record" if new_record?
+  raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
+  _raise_readonly_record_error if readonly?
+
+  attributes = attributes.transform_keys do |key|
+    name = key.to_s
+    name = self.class.attribute_aliases[name] || name
+    verify_readonly_attribute(name) || name
+  end
+
+  update_constraints = _query_constraints_hash
+  attributes = attributes.each_with_object({}) do |(k, v), h|
+    h[k] = @attributes.write_cast_value(k, v)
+    clear_attribute_change(k)
+  end
+
+  affected_rows = self.class._update_record(
+    attributes,
+    update_constraints
+  )
+
+  affected_rows == 1
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Persistence/ClassMethods.html b/src/7.0/classes/ActiveRecord/Persistence/ClassMethods.html new file mode 100644 index 0000000000..c3da8c19a6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Persistence/ClassMethods.html @@ -0,0 +1,900 @@ +--- +title: ActiveRecord::Persistence::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create(attributes = nil, &block) + +

+ + +
+

Creates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.

+ +

The attributes parameter can be either a Hash or an Array of Hashes. These Hashes describe the attributes on the objects that are to be created.

+ +

Examples

+ +
# Create a single new object
+User.create(first_name: 'Jamie')
+
+# Create an Array of new objects
+User.create([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }])
+
+# Create a single object and pass it into a block to set other attributes.
+User.create(first_name: 'Jamie') do |u|
+  u.is_admin = false
+end
+
+# Creating an Array of new objects using a block, where the block is executed for each object:
+User.create([{ first_name: 'Jamie' }, { first_name: 'Jeremy' }]) do |u|
+  u.is_admin = false
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 33
+def create(attributes = nil, &block)
+  if attributes.is_a?(Array)
+    attributes.collect { |attr| create(attr, &block) }
+  else
+    object = new(attributes, &block)
+    object.save
+    object
+  end
+end
+
+
+ +
+ +
+

+ + create!(attributes = nil, &block) + +

+ + +
+

Creates an object (or multiple objects) and saves it to the database, if validations pass. Raises a RecordInvalid error if validations fail, unlike Base#create.

+ +

The attributes parameter can be either a Hash or an Array of Hashes. These describe which attributes to be created on the object, or multiple objects when given an Array of Hashes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 50
+def create!(attributes = nil, &block)
+  if attributes.is_a?(Array)
+    attributes.collect { |attr| create!(attr, &block) }
+  else
+    object = new(attributes, &block)
+    object.save!
+    object
+  end
+end
+
+
+ +
+ +
+

+ + delete(id_or_array) + +

+ + +
+

Deletes the row with a primary key matching the id argument, using an SQL DELETE statement, and returns the number of rows deleted. Active Record objects are not instantiated, so the object’s callbacks are not executed, including any :dependent association options.

+ +

You can delete multiple rows at once by passing an Array of ids.

+ +

Note: Although it is often much faster than the alternative, destroy, skipping callbacks might bypass business logic in your application that ensures referential integrity or performs other essential jobs.

+ +

Examples

+ +
# Delete a single row
+Todo.delete(1)
+
+# Delete multiple rows
+Todo.delete([2,3,4])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 473
+def delete(id_or_array)
+  delete_by(primary_key => id_or_array)
+end
+
+
+ +
+ +
+

+ + destroy(id) + +

+ + +
+

Destroy an object (or multiple objects) that has the given id. The object is instantiated first, therefore all callbacks and filters are fired off before the object is deleted. This method is less efficient than delete but allows cleanup methods and other actions to be run.

+ +

This essentially finds the object (or multiple objects) with the given id, creates a new object from the attributes, and then calls destroy on it.

+ +

Parameters

+
  • +

    id - This should be the id or an array of ids to be destroyed.

    +
+ +

Examples

+ +
# Destroy a single object
+Todo.destroy(1)
+
+# Destroy multiple objects
+todos = [1,2,3]
+Todo.destroy(todos)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 447
+def destroy(id)
+  if id.is_a?(Array)
+    find(id).each(&:destroy)
+  else
+    find(id).destroy
+  end
+end
+
+
+ +
+ +
+

+ + insert(attributes, returning: nil, unique_by: nil, record_timestamps: nil) + +

+ + +
+

Inserts a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

See insert_all for documentation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 66
+def insert(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
+  insert_all([ attributes ], returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
+end
+
+
+ +
+ +
+

+ + insert!(attributes, returning: nil, record_timestamps: nil) + +

+ + +
+

Inserts a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

See insert_all! for more.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 155
+def insert!(attributes, returning: nil, record_timestamps: nil)
+  insert_all!([ attributes ], returning: returning, record_timestamps: record_timestamps)
+end
+
+
+ +
+ +
+

+ + insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil) + +

+ + +
+

Inserts multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

The attributes parameter is an Array of Hashes. Every Hash determines the attributes for a single row and must have the same keys.

+ +

Rows are considered to be unique by every unique index on the table. Any duplicate rows are skipped. Override with :unique_by (see below).

+ +

Returns an ActiveRecord::Result with its contents based on :returning (see below).

+ +

Options

+
:returning +
+

(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass returning: %w[ id name ] for both id and name or returning: false to omit the underlying RETURNING SQL clause entirely.

+ +

You can also pass an SQL string if you need more control on the return values (for example, returning: "id, name as new_name").

+
:unique_by +
+

(PostgreSQL and SQLite only) By default rows are considered to be unique by every unique index on the table. Any duplicate rows are skipped.

+ +

To skip rows according to just one unique index pass :unique_by.

+ +

Consider a Book model where no duplicate ISBNs make sense, but if any row has an existing id, or is not unique by another unique index, ActiveRecord::RecordNotUnique is raised.

+ +

Unique indexes can be identified by columns or name:

+ +
unique_by: :isbn
+unique_by: %i[ author_id name ]
+unique_by: :index_books_on_isbn
+
+
:record_timestamps +
+

By default, automatic setting of timestamp columns is controlled by the model’s record_timestamps config, matching typical behavior.

+ +

To override this and force automatic setting of timestamp columns one way or the other, pass :record_timestamps:

+ +
record_timestamps: true  # Always set timestamps automatically
+record_timestamps: false # Never set timestamps automatically
+
+
+ +

Because it relies on the index information from the database :unique_by is recommended to be paired with Active Record’s schema_cache.

+ +

Example

+ +
# Insert records and skip inserting any duplicates.
+# Here "Eloquent Ruby" is skipped because its id is not unique.
+
+Book.insert_all([
+  { id: 1, title: "Rework", author: "David" },
+  { id: 1, title: "Eloquent Ruby", author: "Russ" }
+])
+
+# insert_all works on chained scopes, and you can use create_with
+# to set default attributes for all inserted records.
+
+author.books.create_with(created_at: Time.now).insert_all([
+  { id: 1, title: "Rework" },
+  { id: 2, title: "Eloquent Ruby" }
+])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 145
+def insert_all(attributes, returning: nil, unique_by: nil, record_timestamps: nil)
+  InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps).execute
+end
+
+
+ +
+ +
+

+ + insert_all!(attributes, returning: nil, record_timestamps: nil) + +

+ + +
+

Inserts multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

The attributes parameter is an Array of Hashes. Every Hash determines the attributes for a single row and must have the same keys.

+ +

Raises ActiveRecord::RecordNotUnique if any rows violate a unique index on the table. In that case, no rows are inserted.

+ +

To skip duplicate rows, see insert_all. To replace them, see upsert_all.

+ +

Returns an ActiveRecord::Result with its contents based on :returning (see below).

+ +

Options

+
:returning +
+

(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass returning: %w[ id name ] for both id and name or returning: false to omit the underlying RETURNING SQL clause entirely.

+ +

You can also pass an SQL string if you need more control on the return values (for example, returning: "id, name as new_name").

+
:record_timestamps +
+

By default, automatic setting of timestamp columns is controlled by the model’s record_timestamps config, matching typical behavior.

+ +

To override this and force automatic setting of timestamp columns one way or the other, pass :record_timestamps:

+ +
record_timestamps: true  # Always set timestamps automatically
+record_timestamps: false # Never set timestamps automatically
+
+
+ +

Examples

+ +
# Insert multiple records
+Book.insert_all!([
+  { title: "Rework", author: "David" },
+  { title: "Eloquent Ruby", author: "Russ" }
+])
+
+# Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby"
+# does not have a unique id.
+Book.insert_all!([
+  { id: 1, title: "Rework", author: "David" },
+  { id: 1, title: "Eloquent Ruby", author: "Russ" }
+])
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 212
+def insert_all!(attributes, returning: nil, record_timestamps: nil)
+  InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning, record_timestamps: record_timestamps).execute
+end
+
+
+ +
+ +
+

+ + instantiate(attributes, column_types = {}, &block) + +

+ + +
+

Given an attributes hash, instantiate returns a new instance of the appropriate class. Accepts only keys as strings.

+ +

For example, Post.all may return Comments, Messages, and Emails by storing the record’s subclass in a type attribute. By calling instantiate instead of new, finder methods ensure they get new instances of the appropriate class for each record.

+ +

See ActiveRecord::Inheritance#discriminate_class_for_record to see how this “single-table” inheritance mapping is implemented.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 346
+def instantiate(attributes, column_types = {}, &block)
+  klass = discriminate_class_for_record(attributes)
+  instantiate_instance_of(klass, attributes, column_types, &block)
+end
+
+
+ +
+ +
+

+ + update(id = :all, attributes) + +

+ + +
+

Updates an object (or multiple objects) and saves it to the database, if validations pass. The resulting object is returned whether the object was saved successfully to the database or not.

+ +

Parameters

+
  • +

    id - This should be the id or an array of ids to be updated. Optional argument, defaults to all records in the relation.

    +
  • +

    attributes - This should be a hash of attributes or an array of hashes.

    +
+ +

Examples

+ +
# Updates one record
+Person.update(15, user_name: "Samuel", group: "expert")
+
+# Updates multiple records
+people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
+Person.update(people.keys, people.values)
+
+# Updates multiple records from the result of a relation
+people = Person.where(group: "expert")
+people.update(group: "masters")
+
+ +

Note: Updating a large number of records will run an UPDATE query for each record, which may cause a performance issue. When running callbacks is not needed for each record update, it is preferred to use update_all for updating all records in a single query.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 378
+def update(id = :all, attributes)
+  if id.is_a?(Array)
+    if id.any?(ActiveRecord::Base)
+      raise ArgumentError,
+        "You are passing an array of ActiveRecord::Base instances to `update`. " \
+        "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`."
+    end
+    id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
+      object.update(attributes[idx])
+    }
+  elsif id == :all
+    all.each { |record| record.update(attributes) }
+  else
+    if ActiveRecord::Base === id
+      raise ArgumentError,
+        "You are passing an instance of ActiveRecord::Base to `update`. " \
+        "Please pass the id of the object by calling `.id`."
+    end
+    object = find(id)
+    object.update(attributes)
+    object
+  end
+end
+
+
+ +
+ +
+

+ + update!(id = :all, attributes) + +

+ + +
+

Updates the object (or multiple objects) just like update but calls update! instead of update, so an exception is raised if the record is invalid and saving will fail.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 404
+def update!(id = :all, attributes)
+  if id.is_a?(Array)
+    if id.any?(ActiveRecord::Base)
+      raise ArgumentError,
+        "You are passing an array of ActiveRecord::Base instances to `update!`. " \
+        "Please pass the ids of the objects by calling `pluck(:id)` or `map(&:id)`."
+    end
+    id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
+      object.update!(attributes[idx])
+    }
+  elsif id == :all
+    all.each { |record| record.update!(attributes) }
+  else
+    if ActiveRecord::Base === id
+      raise ArgumentError,
+        "You are passing an instance of ActiveRecord::Base to `update!`. " \
+        "Please pass the id of the object by calling `.id`."
+    end
+    object = find(id)
+    object.update!(attributes)
+    object
+  end
+end
+
+
+ +
+ +
+

+ + upsert(attributes, on_duplicate: :update, returning: nil, unique_by: nil, record_timestamps: nil) + +

+ + +
+

Updates or inserts (upserts) a single record into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

See upsert_all for documentation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 222
+def upsert(attributes, on_duplicate: :update, returning: nil, unique_by: nil, record_timestamps: nil)
+  upsert_all([ attributes ], on_duplicate: on_duplicate, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps)
+end
+
+
+ +
+ +
+

+ + upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) + +

+ + +
+

Updates or inserts (upserts) multiple records into the database in a single SQL INSERT statement. It does not instantiate any models nor does it trigger Active Record callbacks or validations. Though passed values go through Active Record’s type casting and serialization.

+ +

The attributes parameter is an Array of Hashes. Every Hash determines the attributes for a single row and must have the same keys.

+ +

Returns an ActiveRecord::Result with its contents based on :returning (see below).

+ +

By default, upsert_all will update all the columns that can be updated when there is a conflict. These are all the columns except primary keys, read-only columns, and columns covered by the optional unique_by.

+ +

Options

+
:returning +
+

(PostgreSQL only) An array of attributes to return for all successfully inserted records, which by default is the primary key. Pass returning: %w[ id name ] for both id and name or returning: false to omit the underlying RETURNING SQL clause entirely.

+ +

You can also pass an SQL string if you need more control on the return values (for example, returning: "id, name as new_name").

+
:unique_by +
+

(PostgreSQL and SQLite only) By default rows are considered to be unique by every unique index on the table. Any duplicate rows are skipped.

+ +

To skip rows according to just one unique index pass :unique_by.

+ +

Consider a Book model where no duplicate ISBNs make sense, but if any row has an existing id, or is not unique by another unique index, ActiveRecord::RecordNotUnique is raised.

+ +

Unique indexes can be identified by columns or name:

+ +
unique_by: :isbn
+unique_by: %i[ author_id name ]
+unique_by: :index_books_on_isbn
+
+
+ +

Because it relies on the index information from the database :unique_by is recommended to be paired with Active Record’s schema_cache.

+
:on_duplicate +
+

Configure the SQL update sentence that will be used in case of conflict.

+ +

NOTE: If you use this option you must provide all the columns you want to update by yourself.

+ +

Example:

+ +
Commodity.upsert_all(
+  [
+    { id: 2, name: "Copper", price: 4.84 },
+    { id: 4, name: "Gold", price: 1380.87 },
+    { id: 6, name: "Aluminium", price: 0.35 }
+  ],
+  on_duplicate: Arel.sql("price = GREATEST(commodities.price, EXCLUDED.price)")
+)
+
+ +

See the related :update_only option. Both options can’t be used at the same time.

+
:update_only +
+

Provide a list of column names that will be updated in case of conflict. If not provided, upsert_all will update all the columns that can be updated. These are all the columns except primary keys, read-only columns, and columns covered by the optional unique_by

+ +

Example:

+ +
Commodity.upsert_all(
+  [
+    { id: 2, name: "Copper", price: 4.84 },
+    { id: 4, name: "Gold", price: 1380.87 },
+    { id: 6, name: "Aluminium", price: 0.35 }
+  ],
+  update_only: [:price] # Only prices will be updated
+)
+
+ +

See the related :on_duplicate option. Both options can’t be used at the same time.

+
:record_timestamps +
+

By default, automatic setting of timestamp columns is controlled by the model’s record_timestamps config, matching typical behavior.

+ +

To override this and force automatic setting of timestamp columns one way or the other, pass :record_timestamps:

+ +
record_timestamps: true  # Always set timestamps automatically
+record_timestamps: false # Never set timestamps automatically
+
+
+ +

Examples

+ +
# Inserts multiple records, performing an upsert when records have duplicate ISBNs.
+# Here "Eloquent Ruby" overwrites "Rework" because its ISBN is duplicate.
+
+Book.upsert_all([
+  { title: "Rework", author: "David", isbn: "1" },
+  { title: "Eloquent Ruby", author: "Russ", isbn: "1" }
+], unique_by: :isbn)
+
+Book.find_by(isbn: "1").title # => "Eloquent Ruby"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/persistence.rb, line 332
+def upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
+  InsertAll.new(self, attributes, on_duplicate: on_duplicate, update_only: update_only, returning: returning, unique_by: unique_by, record_timestamps: record_timestamps).execute
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/PreparedStatementCacheExpired.html b/src/7.0/classes/ActiveRecord/PreparedStatementCacheExpired.html new file mode 100644 index 0000000000..159ec168d9 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/PreparedStatementCacheExpired.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::PreparedStatementCacheExpired +layout: default +--- +
+ +
+
+ +
+ +

Raised when PostgreSQL returns ‘cached plan must not change result type’ and we cannot retry gracefully (e.g. inside a transaction)

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/PreparedStatementInvalid.html b/src/7.0/classes/ActiveRecord/PreparedStatementInvalid.html new file mode 100644 index 0000000000..34ea4c2b64 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/PreparedStatementInvalid.html @@ -0,0 +1,71 @@ +--- +title: ActiveRecord::PreparedStatementInvalid +layout: default +--- +
+ +
+
+ +
+ +

Raised when the number of placeholders in an SQL fragment passed to ActiveRecord::Base.where does not match the number of values supplied.

+ +

For example, when there are two placeholders with only one value supplied:

+ +
Location.where("lat = ? AND lng = ?", 53.7362)
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryAborted.html b/src/7.0/classes/ActiveRecord/QueryAborted.html new file mode 100644 index 0000000000..7f6651c5fd --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryAborted.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::QueryAborted +layout: default +--- +
+ +
+
+ +
+ +

Superclass for errors that have been aborted (either by client or server).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryCache.html b/src/7.0/classes/ActiveRecord/QueryCache.html new file mode 100644 index 0000000000..c52d9cf3a0 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryCache.html @@ -0,0 +1,226 @@ +--- +title: ActiveRecord::QueryCache +layout: default +--- +
+ +
+
+ +
+ +

Active Record Query Cache

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + complete(pools) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/query_cache.rb, line 42
+def self.complete(pools)
+  pools.each { |pool| pool.disable_query_cache! }
+
+  if ActiveRecord.legacy_connection_handling
+    ActiveRecord::Base.connection_handlers.each do |_, handler|
+      handler.connection_pool_list.each do |pool|
+        pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
+      end
+    end
+  else
+    ActiveRecord::Base.connection_handler.all_connection_pools.each do |pool|
+      pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
+    end
+  end
+end
+
+
+ +
+ +
+

+ + install_executor_hooks(executor = ActiveSupport::Executor) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/query_cache.rb, line 58
+def self.install_executor_hooks(executor = ActiveSupport::Executor)
+  executor.register_hook(self)
+end
+
+
+ +
+ +
+

+ + run() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/query_cache.rb, line 28
+def self.run
+  pools = []
+
+  if ActiveRecord.legacy_connection_handling
+    ActiveRecord::Base.connection_handlers.each do |key, handler|
+      pools.concat(handler.connection_pool_list.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
+    end
+  else
+    pools.concat(ActiveRecord::Base.connection_handler.all_connection_pools.reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! })
+  end
+
+  pools
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryCache/ClassMethods.html b/src/7.0/classes/ActiveRecord/QueryCache/ClassMethods.html new file mode 100644 index 0000000000..41e4261195 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryCache/ClassMethods.html @@ -0,0 +1,148 @@ +--- +title: ActiveRecord::QueryCache::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + cache(&block) + +

+ + +
+

Enable the query cache within the block if Active Record is configured. If it’s not, it will execute the given block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/query_cache.rb, line 9
+def cache(&block)
+  if connected? || !configurations.empty?
+    connection.cache(&block)
+  else
+    yield
+  end
+end
+
+
+ +
+ +
+

+ + uncached(&block) + +

+ + +
+

Disable the query cache within the block if Active Record is configured. If it’s not, it will execute the given block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/query_cache.rb, line 19
+def uncached(&block)
+  if connected? || !configurations.empty?
+    connection.uncached(&block)
+  else
+    yield
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryCanceled.html b/src/7.0/classes/ActiveRecord/QueryCanceled.html new file mode 100644 index 0000000000..14eaf02957 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryCanceled.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::QueryCanceled +layout: default +--- +
+ +
+
+ +
+ +

QueryCanceled will be raised when canceling statement due to user request.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryLogs.html b/src/7.0/classes/ActiveRecord/QueryLogs.html new file mode 100644 index 0000000000..9213c0c0bd --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryLogs.html @@ -0,0 +1,139 @@ +--- +title: ActiveRecord::QueryLogs +layout: default +--- +
+ +
+
+ +
+ +

Active Record Query Logs

+ +

Automatically tag SQL queries with runtime information.

+ +

Default tags available for use:

+
  • +

    application

    +
  • +

    pid

    +
  • +

    socket

    +
  • +

    db_host

    +
  • +

    database

    +
+ +

_Action Controller and Active Job tags are also defined when used in Rails:_

+
  • +

    controller

    +
  • +

    action

    +
  • +

    job

    +
+ +

The tags used in a query can be configured directly:

+ +
ActiveRecord::QueryLogs.tags = [ :application, :controller, :action, :job ]
+
+ +

or via Rails configuration:

+ +
config.active_record.query_log_tags = [ :application, :controller, :action, :job ]
+
+ +

To add new comment tags, add a hash to the tags array containing the keys and values you want to add to the comment. Dynamic content can be created by setting a proc or lambda value in a hash, and can reference any value stored in the context object.

+ +

Escaping is performed on the string returned, however untrusted user input should not be used.

+ +

Example:

+ +
tags = [
+  :application,
+  {
+    custom_tag: ->(context) { context[:controller]&.controller_name },
+    custom_value: -> { Custom.value },
+  }
+]
+ActiveRecord::QueryLogs.tags = tags
+
+ +

The QueryLogs context can be manipulated via the ActiveSupport::ExecutionContext.set method.

+ +

Temporary updates limited to the execution of a block:

+ +
ActiveSupport::ExecutionContext.set(foo: Bar.new) do
+  posts = Post.all
+end
+
+ +

Direct updates to a context value:

+ +
ActiveSupport::ExecutionContext[:foo] = Bar.new
+
+ +

Tag comments can be prepended to the query:

+ +
ActiveRecord::QueryLogs.prepend_comment = true
+
+ +

For applications where the content will not change during the lifetime of the request or job execution, the tags can be cached for reuse in every query:

+ +
ActiveRecord::QueryLogs.cache_query_log_tags = true
+
+ +

This option can be set during application configuration or in a Rails initializer:

+ +
config.active_record.cache_query_log_tags = true
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryMethods.html b/src/7.0/classes/ActiveRecord/QueryMethods.html new file mode 100644 index 0000000000..f3dd7d7801 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryMethods.html @@ -0,0 +1,2301 @@ +--- +title: ActiveRecord::QueryMethods +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FROZEN_EMPTY_ARRAY=[].freeze
 
FROZEN_EMPTY_HASH={}.freeze
 
VALID_UNSCOPING_VALUES=Set.new([:where, :select, :group, :order, :lock, +:limit, :offset, :joins, :left_outer_joins, :annotate, +:includes, :from, :readonly, :having, :optimizer_hints])
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + and(other) + +

+ + +
+

Returns a new relation, which is the logical intersection of this relation and the one passed as an argument.

+ +

The two relations must be structurally compatible: they must be scoping the same model, and they must differ only by where (if no group has been defined) or having (if a group is present).

+ +
Post.where(id: [1, 2]).and(Post.where(id: [2, 3]))
+# SELECT `posts`.* FROM `posts` WHERE `posts`.`id` IN (1, 2) AND `posts`.`id` IN (2, 3)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 863
+def and(other)
+  if other.is_a?(Relation)
+    spawn.and!(other)
+  else
+    raise ArgumentError, "You have passed #{other.class.name} object to #and. Pass an ActiveRecord::Relation object instead."
+  end
+end
+
+
+ +
+ +
+

+ + annotate(*args) + +

+ + +
+

Adds an SQL comment to queries generated from this relation. For example:

+ +
User.annotate("selecting user names").select(:name)
+# SELECT "users"."name" FROM "users" /* selecting user names */
+
+User.annotate("selecting", "user", "names").select(:name)
+# SELECT "users"."name" FROM "users" /* selecting */ /* user */ /* names */
+
+ +

The SQL block comment delimiters, “/*” and “*/”, will be added automatically.

+ +

Some escaping is performed, however untrusted user input should not be used.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1239
+def annotate(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.annotate!(*args)
+end
+
+
+ +
+ +
+

+ + create_with(value) + +

+ + +
+

Sets attributes to be used when creating new records from a relation object.

+ +
users = User.where(name: 'Oscar')
+users.new.name # => 'Oscar'
+
+users = users.create_with(name: 'DHH')
+users.new.name # => 'DHH'
+
+ +

You can pass nil to create_with to reset attributes:

+ +
users = users.create_with(nil)
+users.new.name # => 'Oscar'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1056
+def create_with(value)
+  spawn.create_with!(value)
+end
+
+
+ +
+ +
+

+ + distinct(value = true) + +

+ + +
+

Specifies whether the records should be unique or not. For example:

+ +
User.select(:name)
+# Might return two records with the same name
+
+User.select(:name).distinct
+# Returns 1 record per distinct name
+
+User.select(:name).distinct.distinct(false)
+# You can also remove the uniqueness
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1120
+def distinct(value = true)
+  spawn.distinct!(value)
+end
+
+
+ +
+ +
+

+ + eager_load(*args) + +

+ + +
+

Forces eager loading by performing a LEFT OUTER JOIN on args:

+ +
User.eager_load(:posts)
+# SELECT "users"."id" AS t0_r0, "users"."name" AS t0_r1, ...
+# FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" =
+# "users"."id"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 215
+def eager_load(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.eager_load!(*args)
+end
+
+
+ +
+ +
+

+ + excluding(*records) + +

+ + +
+

Excludes the specified record (or collection of records) from the resulting relation. For example:

+ +
Post.excluding(post)
+# SELECT "posts".* FROM "posts" WHERE "posts"."id" != 1
+
+Post.excluding(post_one, post_two)
+# SELECT "posts".* FROM "posts" WHERE "posts"."id" NOT IN (1, 2)
+
+ +

This can also be called on associations. As with the above example, either a single record of collection thereof may be specified:

+ +
post = Post.find(1)
+comment = Comment.find(2)
+post.comments.excluding(comment)
+# SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 AND "comments"."id" != 2
+
+ +

This is short-hand for .where.not(id: post.id) and .where.not(id: [post_one.id, post_two.id]).

+ +

An ArgumentError will be raised if either no records are specified, or if any of the records in the collection (if a collection is passed in) are not instances of the same model that the relation is scoping.

+
+ + + +
+ Also aliased as: without +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1281
+def excluding(*records)
+  records.flatten!(1)
+  records.compact!
+
+  unless records.all?(klass)
+    raise ArgumentError, "You must only pass a single or collection of #{klass.name} objects to ##{__callee__}."
+  end
+
+  spawn.excluding!(records)
+end
+
+
+ +
+ +
+

+ + extending(*modules, &block) + +

+ + +
+

Used to extend a scope with additional methods, either through a module or through a block provided.

+ +

The object returned is a relation, which can be further extended.

+ +

Using a module

+ +
module Pagination
+  def page(number)
+    # pagination code goes here
+  end
+end
+
+scope = Model.all.extending(Pagination)
+scope.page(params[:page])
+
+ +

You can also pass a list of modules:

+ +
scope = Model.all.extending(Pagination, SomethingElse)
+
+ +

Using a block

+ +
scope = Model.all.extending do
+  def page(number)
+    # pagination code goes here
+  end
+end
+scope.page(params[:page])
+
+ +

You can also use a block and a module list:

+ +
scope = Model.all.extending(Pagination) do
+  def per_page(number)
+    # pagination code goes here
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1166
+def extending(*modules, &block)
+  if modules.any? || block
+    spawn.extending!(*modules, &block)
+  else
+    self
+  end
+end
+
+
+ +
+ +
+

+ + extract_associated(association) + +

+ + +
+

Extracts a named association from the relation. The named association is first preloaded, then the individual association records are collected from the relation. Like so:

+ +
account.memberships.extract_associated(:user)
+# => Returns collection of User records
+
+ +

This is short-hand for:

+ +
account.memberships.preload(:user).collect(&:user)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 248
+def extract_associated(association)
+  preload(association).collect(&association)
+end
+
+
+ +
+ +
+

+ + from(value, subquery_name = nil) + +

+ + +
+

Specifies the table from which the records will be fetched. For example:

+ +
Topic.select('title').from('posts')
+# SELECT title FROM posts
+
+ +

Can accept other relation objects. For example:

+ +
Topic.select('title').from(Topic.approved)
+# SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery
+
+ +

Passing a second argument (string or symbol), creates the alias for the SQL from clause. Otherwise the alias “subquery” is used:

+ +
Topic.select('a.title').from(Topic.approved, :a)
+# SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a
+
+ +

It does not add multiple arguments to the SQL from clause. The last from chained is the one used:

+ +
Topic.select('title').from(Topic.approved).from(Topic.inactive)
+# SELECT title FROM (SELECT topics.* FROM topics WHERE topics.active = 'f') subquery
+
+ +

For multiple arguments for the SQL from clause, you can pass a string with the exact elements in the SQL from list:

+ +
color = "red"
+Color
+  .from("colors c, JSONB_ARRAY_ELEMENTS(colored_things) AS colorvalues(colorvalue)")
+  .where("colorvalue->>'color' = ?", color)
+  .select("c.*").to_a
+# SELECT c.*
+# FROM colors c, JSONB_ARRAY_ELEMENTS(colored_things) AS colorvalues(colorvalue)
+# WHERE (colorvalue->>'color' = 'red')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1101
+def from(value, subquery_name = nil)
+  spawn.from!(value, subquery_name)
+end
+
+
+ +
+ +
+

+ + group(*args) + +

+ + +
+

Allows to specify a group attribute:

+ +
User.group(:name)
+# SELECT "users".* FROM "users" GROUP BY name
+
+ +

Returns an array with distinct records based on the group attribute:

+ +
User.select([:id, :name])
+# => [#<User id: 1, name: "Oscar">, #<User id: 2, name: "Oscar">, #<User id: 3, name: "Foo">]
+
+User.group(:name)
+# => [#<User id: 3, name: "Foo", ...>, #<User id: 2, name: "Oscar", ...>]
+
+User.group('name AS grouped_name, age')
+# => [#<User id: 3, name: "Foo", age: 21, ...>, #<User id: 2, name: "Oscar", age: 21, ...>, #<User id: 5, name: "Foo", age: 23, ...>]
+
+ +

Passing in an array of attributes to group by is also supported.

+ +
User.select([:id, :first_name]).group(:id, :first_name).first(3)
+# => [#<User id: 1, first_name: "Bill">, #<User id: 2, first_name: "Earl">, #<User id: 3, first_name: "Beto">]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 371
+def group(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.group!(*args)
+end
+
+
+ +
+ +
+

+ + having(opts, *rest) + +

+ + +
+

Allows to specify a HAVING clause. Note that you can’t use HAVING without also specifying a GROUP clause.

+ +
Order.having('SUM(price) > 30').group('user_id')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 921
+def having(opts, *rest)
+  opts.blank? ? self : spawn.having!(opts, *rest)
+end
+
+
+ +
+ +
+

+ + in_order_of(column, values) + +

+ + +
+

Allows to specify an order by a specific set of values.

+ +
User.in_order_of(:id, [1, 5, 3])
+# SELECT "users".* FROM "users"
+#   WHERE "users"."id" IN (1, 5, 3)
+#   ORDER BY CASE
+#     WHEN "users"."id" = 1 THEN 1
+#     WHEN "users"."id" = 5 THEN 2
+#     WHEN "users"."id" = 3 THEN 3
+#   END ASC
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 458
+def in_order_of(column, values)
+  klass.disallow_raw_sql!([column], permit: connection.column_name_with_order_matcher)
+  return spawn.none! if values.empty?
+
+  references = column_references([column])
+  self.references_values |= references unless references.empty?
+
+  values = values.map { |value| type_caster.type_cast_for_database(column, value) }
+  arel_column = column.is_a?(Symbol) ? order_column(column.to_s) : column
+
+  where_clause =
+    if values.include?(nil)
+      arel_column.in(values.compact).or(arel_column.eq(nil))
+    else
+      arel_column.in(values)
+    end
+
+  spawn
+    .order!(build_case_for_value_position(arel_column, values))
+    .where!(where_clause)
+end
+
+
+ +
+ +
+

+ + includes(*args) + +

+ + +
+

Specify relationships to be included in the result set. For example:

+ +
users = User.includes(:address)
+users.each do |user|
+  user.address.city
+end
+
+ +

allows you to access the address attribute of the User model without firing an additional query. This will often result in a performance improvement over a simple join.

+ +

You can also specify multiple relationships, like this:

+ +
users = User.includes(:address, :friends)
+
+ +

Loading nested relationships is possible using a Hash:

+ +
users = User.includes(:address, friends: [:address, :followers])
+
+ +

Conditions

+ +

If you want to add string conditions to your included models, you’ll have to explicitly reference them. For example:

+ +
User.includes(:posts).where('posts.name = ?', 'example')
+
+ +

Will throw an error, but this will work:

+ +
User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
+
+ +

Note that includes works with association names while references needs the actual table name.

+ +

If you pass the conditions via hash, you don’t need to call references explicitly, as where references the tables for you. For example, this will work correctly:

+ +
User.includes(:posts).where(posts: { name: 'example' })
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 199
+def includes(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.includes!(*args)
+end
+
+
+ +
+ +
+

+ + invert_where() + +

+ + +
+

Allows you to invert an entire where clause instead of manually applying conditions.

+ +
class User
+  scope :active, -> { where(accepted: true, locked: false) }
+end
+
+User.where(accepted: true)
+# WHERE `accepted` = 1
+
+User.where(accepted: true).invert_where
+# WHERE `accepted` != 1
+
+User.active
+# WHERE `accepted` = 1 AND `locked` = 0
+
+User.active.invert_where
+# WHERE NOT (`accepted` = 1 AND `locked` = 0)
+
+ +

Be careful because this inverts all conditions before invert_where call.

+ +
class User
+  scope :active, -> { where(accepted: true, locked: false) }
+  scope :inactive, -> { active.invert_where } # Do not attempt it
+end
+
+# It also inverts `where(role: 'admin')` unexpectedly.
+User.where(role: 'admin').inactive
+# WHERE NOT (`role` = 'admin' AND `accepted` = 1 AND `locked` = 0)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 829
+def invert_where
+  spawn.invert_where!
+end
+
+
+ +
+ +
+

+ + joins(*args) + +

+ + +
+

Performs JOINs on args. The given symbol(s) should match the name of the association(s).

+ +
User.joins(:posts)
+# SELECT "users".*
+# FROM "users"
+# INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
+
+ +

Multiple joins:

+ +
User.joins(:posts, :account)
+# SELECT "users".*
+# FROM "users"
+# INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
+# INNER JOIN "accounts" ON "accounts"."id" = "users"."account_id"
+
+ +

Nested joins:

+ +
User.joins(posts: [:comments])
+# SELECT "users".*
+# FROM "users"
+# INNER JOIN "posts" ON "posts"."user_id" = "users"."id"
+# INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
+
+ +

You can use strings in order to customize your joins:

+ +
User.joins("LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id")
+# SELECT "users".* FROM "users" LEFT JOIN bookmarks ON bookmarks.bookmarkable_type = 'Post' AND bookmarks.user_id = users.id
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 604
+def joins(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.joins!(*args)
+end
+
+
+ +
+ +
+

+ + left_joins(*args) + +

+ + +
+ +
+ + + + + +
+ Alias for: left_outer_joins +
+ + + +
+ +
+

+ + left_outer_joins(*args) + +

+ + +
+

Performs LEFT OUTER JOINs on args:

+ +
User.left_outer_joins(:posts)
+=> SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
+
+
+ + + +
+ Also aliased as: left_joins +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 619
+def left_outer_joins(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.left_outer_joins!(*args)
+end
+
+
+ +
+ +
+

+ + limit(value) + +

+ + +
+

Specifies a limit for the number of records to retrieve.

+ +
User.limit(10) # generated SQL has 'LIMIT 10'
+
+User.limit(10).limit(20) # generated SQL has 'LIMIT 20'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 935
+def limit(value)
+  spawn.limit!(value)
+end
+
+
+ +
+ +
+

+ + lock(locks = true) + +

+ + +
+

Specifies locking settings (default to true). For more information on locking, please see ActiveRecord::Locking.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 962
+def lock(locks = true)
+  spawn.lock!(locks)
+end
+
+
+ +
+ +
+

+ + none() + +

+ + +
+

Returns a chainable relation with zero records.

+ +

The returned relation implements the Null Object pattern. It is an object with defined null behavior and always returns an empty array of records without querying the database.

+ +

Any subsequent condition chained to the returned relation will continue generating an empty relation and will not fire any query to the database.

+ +

Used in cases where a method or scope could return zero records but the result needs to be chainable.

+ +

For example:

+ +
@posts = current_user.visible_posts.where(name: params[:name])
+# the visible_posts method is expected to return a chainable Relation
+
+def visible_posts
+  case role
+  when 'Country Manager'
+    Post.where(country: country)
+  when 'Reviewer'
+    Post.published
+  when 'Bad User'
+    Post.none # It can't be chained if [] is returned.
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1005
+def none
+  spawn.none!
+end
+
+
+ +
+ +
+

+ + offset(value) + +

+ + +
+

Specifies the number of rows to skip before returning rows.

+ +
User.offset(10) # generated SQL has "OFFSET 10"
+
+ +

Should be used with order.

+ +
User.offset(10).order("name ASC")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 951
+def offset(value)
+  spawn.offset!(value)
+end
+
+
+ +
+ +
+

+ + optimizer_hints(*args) + +

+ + +
+

Specify optimizer hints to be used in the SELECT statement.

+ +

Example (for MySQL):

+ +
Topic.optimizer_hints("MAX_EXECUTION_TIME(50000)", "NO_INDEX_MERGE(topics)")
+# SELECT /*+ MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(topics) */ `topics`.* FROM `topics`
+
+ +

Example (for PostgreSQL with pg_hint_plan):

+ +
Topic.optimizer_hints("SeqScan(topics)", "Parallel(topics 8)")
+# SELECT /*+ SeqScan(topics) Parallel(topics 8) */ "topics".* FROM "topics"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1195
+def optimizer_hints(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.optimizer_hints!(*args)
+end
+
+
+ +
+ +
+

+ + or(other) + +

+ + +
+

Returns a new relation, which is the logical union of this relation and the one passed as an argument.

+ +

The two relations must be structurally compatible: they must be scoping the same model, and they must differ only by where (if no group has been defined) or having (if a group is present).

+ +
Post.where("id = 1").or(Post.where("author_id = 3"))
+# SELECT `posts`.* FROM `posts` WHERE ((id = 1) OR (author_id = 3))
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 895
+def or(other)
+  if other.is_a?(Relation)
+    spawn.or!(other)
+  else
+    raise ArgumentError, "You have passed #{other.class.name} object to #or. Pass an ActiveRecord::Relation object instead."
+  end
+end
+
+
+ +
+ +
+

+ + order(*args) + +

+ + +
+

Applies an ORDER BY clause to a query.

+ +

order accepts arguments in one of several formats.

+ +

symbols

+ +

The symbol represents the name of the column you want to order the results by.

+ +
User.order(:name)
+# SELECT "users".* FROM "users" ORDER BY "users"."name" ASC
+
+ +

By default, the order is ascending. If you want descending order, you can map the column name symbol to :desc.

+ +
User.order(email: :desc)
+# SELECT "users".* FROM "users" ORDER BY "users"."email" DESC
+
+ +

Multiple columns can be passed this way, and they will be applied in the order specified.

+ +
User.order(:name, email: :desc)
+# SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC
+
+ +

strings

+ +

Strings are passed directly to the database, allowing you to specify simple SQL expressions.

+ +

This could be a source of SQL injection, so only strings composed of plain column names and simple function(column_name) expressions with optional ASC/DESC modifiers are allowed.

+ +
User.order('name')
+# SELECT "users".* FROM "users" ORDER BY name
+
+User.order('name DESC')
+# SELECT "users".* FROM "users" ORDER BY name DESC
+
+User.order('name DESC, email')
+# SELECT "users".* FROM "users" ORDER BY name DESC, email
+
+ +

Arel

+ +

If you need to pass in complicated expressions that you have verified are safe for the database, you can use Arel.

+ +
User.order(Arel.sql('end_date - start_date'))
+# SELECT "users".* FROM "users" ORDER BY end_date - start_date
+
+ +

Custom query syntax, like JSON columns for Postgres, is supported in this way.

+ +
User.order(Arel.sql("payload->>'kind'"))
+# SELECT "users".* FROM "users" ORDER BY payload->>'kind'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 433
+def order(*args)
+  check_if_method_has_arguments!(__callee__, args) do
+    sanitize_order_arguments(args)
+  end
+  spawn.order!(*args)
+end
+
+
+ +
+ +
+

+ + preload(*args) + +

+ + +
+

Allows preloading of args, in the same way that includes does:

+ +
User.preload(:posts)
+# SELECT "posts".* FROM "posts" WHERE "posts"."user_id" IN (1, 2, 3)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 229
+def preload(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.preload!(*args)
+end
+
+
+ +
+ +
+

+ + readonly(value = true) + +

+ + +
+

Sets readonly attributes for the returned relation. If value is true (default), attempting to update a record will result in an error.

+ +
users = User.readonly
+users.first.save
+=> ActiveRecord::ReadOnlyRecord: User is marked as readonly
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1019
+def readonly(value = true)
+  spawn.readonly!(value)
+end
+
+
+ +
+ +
+

+ + references(*table_names) + +

+ + +
+

Use to indicate that the given table_names are referenced by an SQL string, and should therefore be JOINed in any query rather than loaded separately. This method only works in conjunction with includes. See includes for more details.

+ +
User.includes(:posts).where("posts.name = 'foo'")
+# Doesn't JOIN the posts table, resulting in an error.
+
+User.includes(:posts).where("posts.name = 'foo'").references(:posts)
+# Query now knows the string references posts, so adds a JOIN
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 262
+def references(*table_names)
+  check_if_method_has_arguments!(__callee__, table_names)
+  spawn.references!(*table_names)
+end
+
+
+ +
+ +
+

+ + reorder(*args) + +

+ + +
+

Replaces any existing order defined on the relation with the specified order.

+ +
User.order('email DESC').reorder('id ASC') # generated SQL has 'ORDER BY id ASC'
+
+ +

Subsequent calls to order on the same relation will be appended. For example:

+ +
User.order('email DESC').reorder('id ASC').order('name ASC')
+
+ +

generates a query with ‘ORDER BY id ASC, name ASC’.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 489
+def reorder(*args)
+  check_if_method_has_arguments!(__callee__, args) do
+    sanitize_order_arguments(args)
+  end
+  spawn.reorder!(*args)
+end
+
+
+ +
+ +
+

+ + reselect(*args) + +

+ + +
+

Allows you to change a previously set select statement.

+ +
Post.select(:title, :body)
+# SELECT `posts`.`title`, `posts`.`body` FROM `posts`
+
+Post.select(:title, :body).reselect(:created_at)
+# SELECT `posts`.`created_at` FROM `posts`
+
+ +

This is short-hand for unscope(:select).select(fields). Note that we’re unscoping the entire select statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 340
+def reselect(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.reselect!(*args)
+end
+
+
+ +
+ +
+

+ + reverse_order() + +

+ + +
+

Reverse the existing order clause on the relation.

+ +
User.order('name ASC').reverse_order # generated SQL has 'ORDER BY name DESC'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1208
+def reverse_order
+  spawn.reverse_order!
+end
+
+
+ +
+ +
+

+ + rewhere(conditions) + +

+ + +
+

Allows you to change a previously set where condition for a given attribute, instead of appending to that condition.

+ +
Post.where(trashed: true).where(trashed: false)
+# WHERE `trashed` = 1 AND `trashed` = 0
+
+Post.where(trashed: true).rewhere(trashed: false)
+# WHERE `trashed` = 0
+
+Post.where(active: true).where(trashed: true).rewhere(trashed: false)
+# WHERE `active` = 1 AND `trashed` = 0
+
+ +

This is short-hand for unscope(where: conditions.keys).where(conditions). Note that unlike reorder, we’re only unscoping the named conditions – not the entire where statement.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 791
+def rewhere(conditions)
+  scope = spawn
+  where_clause = scope.build_where_clause(conditions)
+
+  scope.unscope!(where: where_clause.extract_attributes)
+  scope.where_clause += where_clause
+  scope
+end
+
+
+ +
+ +
+

+ + select(*fields) + +

+ + +
+

Works in two unique ways.

+ +

First: takes a block so it can be used just like Array#select.

+ +
Model.all.select { |m| m.field == value }
+
+ +

This will build an array of objects from the database for the scope, converting them into an array and iterating through them using Array#select.

+ +

Second: Modifies the SELECT statement for the query so that only certain fields are retrieved:

+ +
Model.select(:field)
+# => [#<Model id: nil, field: "value">]
+
+ +

Although in the above example it looks as though this method returns an array, it actually returns a relation object and can have other query methods appended to it, such as the other methods in ActiveRecord::QueryMethods.

+ +

The argument to the method can also be an array of fields.

+ +
Model.select(:field, :other_field, :and_one_more)
+# => [#<Model id: nil, field: "value", other_field: "value", and_one_more: "value">]
+
+ +

You can also use one or more strings, which will be used unchanged as SELECT fields.

+ +
Model.select('field AS field_one', 'other_field AS field_two')
+# => [#<Model id: nil, field_one: "value", field_two: "value">]
+
+ +

If an alias was specified, it will be accessible from the resulting objects:

+ +
Model.select('field AS field_one').first.field_one
+# => "value"
+
+ +

Accessing attributes of an object that do not have fields retrieved by a select except id will throw ActiveModel::MissingAttributeError:

+ +
Model.select(:field).first.other_field
+# => ActiveModel::MissingAttributeError: missing attribute: other_field
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 312
+def select(*fields)
+  if block_given?
+    if fields.any?
+      raise ArgumentError, "`select' with block doesn't take arguments."
+    end
+
+    return super()
+  end
+
+  check_if_method_has_arguments!(__callee__, fields, "Call `select' with at least one field.")
+  spawn._select!(*fields)
+end
+
+
+ +
+ +
+

+ + strict_loading(value = true) + +

+ + +
+

Sets the returned relation to strict_loading mode. This will raise an error if the record tries to lazily load an association.

+ +
user = User.strict_loading.first
+user.comments.to_a
+=> ActiveRecord::StrictLoadingViolationError
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1034
+def strict_loading(value = true)
+  spawn.strict_loading!(value)
+end
+
+
+ +
+ +
+

+ + structurally_compatible?(other) + +

+ + +
+

Checks whether the given relation is structurally compatible with this relation, to determine if it’s possible to use the and and or methods without raising an error. Structurally compatible is defined as: they must be scoping the same model, and they must differ only by where (if no group has been defined) or having (if a group is present).

+ +
Post.where("id = 1").structurally_compatible?(Post.where("author_id = 3"))
+# => true
+
+Post.joins(:comments).structurally_compatible?(Post.where("id = 1"))
+# => false
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 849
+def structurally_compatible?(other)
+  structurally_incompatible_values_for(other).empty?
+end
+
+
+ +
+ +
+

+ + uniq!(name) + +

+ + +
+

Deduplicate multiple values.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 1251
+def uniq!(name)
+  if values = @values[name]
+    values.uniq! if values.is_a?(Array) && !values.empty?
+  end
+  self
+end
+
+
+ +
+ +
+

+ + unscope(*args) + +

+ + +
+

Removes an unwanted relation that is already defined on a chain of relations. This is useful when passing around chains of relations and would like to modify the relations without reconstructing the entire chain.

+ +
User.order('email DESC').unscope(:order) == User.all
+
+ +

The method arguments are symbols which correspond to the names of the methods which should be unscoped. The valid arguments are given in VALID_UNSCOPING_VALUES. The method can also be called with multiple arguments. For example:

+ +
User.order('email DESC').select('id').where(name: "John")
+    .unscope(:order, :select, :where) == User.all
+
+ +

One can additionally pass a hash as an argument to unscope specific :where values. This is done by passing a hash with a single key-value pair. The key should be :where and the value should be the where value to unscope. For example:

+ +
User.where(name: "John", active: true).unscope(where: :name)
+    == User.where(active: true)
+
+ +

This method is similar to except, but unlike except, it persists across merges:

+ +
User.order('email').merge(User.except(:order))
+    == User.order('email')
+
+User.order('email').merge(User.unscope(:order))
+    == User.all
+
+ +

This means it can be used in association definitions:

+ +
has_many :comments, -> { unscope(where: :trashed) }
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 542
+def unscope(*args)
+  check_if_method_has_arguments!(__callee__, args)
+  spawn.unscope!(*args)
+end
+
+
+ +
+ +
+

+ + where(*args) + +

+ + +
+

Returns a new relation, which is the result of filtering the current relation according to the conditions in the arguments.

+ +

where accepts conditions in one of several formats. In the examples below, the resulting SQL is given as an illustration; the actual query generated may be different depending on the database adapter.

+ +

string

+ +

A single string, without additional arguments, is passed to the query constructor as an SQL fragment, and used in the where clause of the query.

+ +
Client.where("orders_count = '2'")
+# SELECT * from clients where orders_count = '2';
+
+ +

Note that building your own string from user input may expose your application to injection attacks if not done properly. As an alternative, it is recommended to use one of the following methods.

+ +

array

+ +

If an array is passed, then the first element of the array is treated as a template, and the remaining elements are inserted into the template to generate the condition. Active Record takes care of building the query to avoid injection attacks, and will convert from the ruby type to the database type where needed. Elements are inserted into the string in the order in which they appear.

+ +
User.where(["name = ? and email = ?", "Joe", "joe@example.com"])
+# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
+
+ +

Alternatively, you can use named placeholders in the template, and pass a hash as the second element of the array. The names in the template are replaced with the corresponding values from the hash.

+ +
User.where(["name = :name and email = :email", { name: "Joe", email: "joe@example.com" }])
+# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
+
+ +

This can make for more readable code in complex queries.

+ +

Lastly, you can use sprintf-style % escapes in the template. This works slightly differently than the previous methods; you are responsible for ensuring that the values in the template are properly quoted. The values are passed to the connector for quoting, but the caller is responsible for ensuring they are enclosed in quotes in the resulting SQL. After quoting, the values are inserted using the same escapes as the Ruby core method Kernel::sprintf.

+ +
User.where(["name = '%s' and email = '%s'", "Joe", "joe@example.com"])
+# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
+
+ +

If where is called with multiple arguments, these are treated as if they were passed as the elements of a single array.

+ +
User.where("name = :name and email = :email", { name: "Joe", email: "joe@example.com" })
+# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com';
+
+ +

When using strings to specify conditions, you can use any operator available from the database. While this provides the most flexibility, you can also unintentionally introduce dependencies on the underlying database. If your code is intended for general consumption, test with multiple database backends.

+ +

hash

+ +

where will also accept a hash condition, in which the keys are fields and the values are values to be searched for.

+ +

Fields can be symbols or strings. Values can be single values, arrays, or ranges.

+ +
User.where(name: "Joe", email: "joe@example.com")
+# SELECT * FROM users WHERE name = 'Joe' AND email = 'joe@example.com'
+
+User.where(name: ["Alice", "Bob"])
+# SELECT * FROM users WHERE name IN ('Alice', 'Bob')
+
+User.where(created_at: (Time.now.midnight - 1.day)..Time.now.midnight)
+# SELECT * FROM users WHERE (created_at BETWEEN '2012-06-09 07:00:00.000000' AND '2012-06-10 07:00:00.000000')
+
+ +

In the case of a belongs_to relationship, an association key can be used to specify the model if an ActiveRecord object is used as the value.

+ +
author = Author.find(1)
+
+# The following queries will be equivalent:
+Post.where(author: author)
+Post.where(author_id: author)
+
+ +

This also works with polymorphic belongs_to relationships:

+ +
treasure = Treasure.create(name: 'gold coins')
+treasure.price_estimates << PriceEstimate.create(price: 125)
+
+# The following queries will be equivalent:
+PriceEstimate.where(estimate_of: treasure)
+PriceEstimate.where(estimate_of_type: 'Treasure', estimate_of_id: treasure)
+
+ +

Joins

+ +

If the relation is the result of a join, you may create a condition which uses any of the tables in the join. For string and array conditions, use the table name in the condition.

+ +
User.joins(:posts).where("posts.created_at < ?", Time.now)
+
+ +

For hash conditions, you can either use the table name in the key, or use a sub-hash.

+ +
User.joins(:posts).where("posts.published" => true)
+User.joins(:posts).where(posts: { published: true })
+
+ +

no argument

+ +

If no argument is passed, where returns a new instance of WhereChain, that can be chained with WhereChain#not, WhereChain#missing, or WhereChain#associated.

+ +

Chaining with WhereChain#not:

+ +
User.where.not(name: "Jon")
+# SELECT * FROM users WHERE name != 'Jon'
+
+ +

Chaining with WhereChain#associated:

+ +
Post.where.associated(:author)
+# SELECT "posts".* FROM "posts"
+# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# WHERE "authors"."id" IS NOT NULL
+
+ +

Chaining with WhereChain#missing:

+ +
Post.where.missing(:author)
+# SELECT "posts".* FROM "posts"
+# LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# WHERE "authors"."id" IS NULL
+
+ +

blank condition

+ +

If the condition is any blank-ish object, then where is a no-op and returns the current relation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 763
+def where(*args)
+  if args.empty?
+    WhereChain.new(spawn)
+  elsif args.length == 1 && args.first.blank?
+    self
+  else
+    spawn.where!(*args)
+  end
+end
+
+
+ +
+ +
+

+ + without(*records) + +

+ + +
+ +
+ + + + + +
+ Alias for: excluding +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/QueryMethods/WhereChain.html b/src/7.0/classes/ActiveRecord/QueryMethods/WhereChain.html new file mode 100644 index 0000000000..ae44287380 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/QueryMethods/WhereChain.html @@ -0,0 +1,278 @@ +--- +title: ActiveRecord::QueryMethods::WhereChain +layout: default +--- +
+ +
+
+ +
+ +

WhereChain objects act as placeholder for queries in which where does not have any parameter. In this case, where can be chained to return a new relation.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + associated(*associations) + +

+ + +
+

Returns a new relation with joins and where clause to identify associated relations.

+ +

For example, posts that are associated to a related author:

+ +
Post.where.associated(:author)
+# SELECT "posts".* FROM "posts"
+# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# WHERE "authors"."id" IS NOT NULL
+
+ +

Additionally, multiple relations can be combined. This will return posts associated to both an author and any comments:

+ +
Post.where.associated(:author, :comments)
+# SELECT "posts".* FROM "posts"
+# INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# INNER JOIN "comments" ON "comments"."post_id" = "posts"."id"
+# WHERE "authors"."id" IS NOT NULL AND "comments"."id" IS NOT NULL
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 76
+def associated(*associations)
+  associations.each do |association|
+    reflection = scope_association_reflection(association)
+    @scope.joins!(association)
+    if reflection.options[:class_name]
+      self.not(association => { reflection.association_primary_key => nil })
+    else
+      self.not(reflection.table_name => { reflection.association_primary_key => nil })
+    end
+  end
+
+  @scope
+end
+
+
+ +
+ +
+

+ + missing(*associations) + +

+ + +
+

Returns a new relation with left outer joins and where clause to identify missing relations.

+ +

For example, posts that are missing a related author:

+ +
Post.where.missing(:author)
+# SELECT "posts".* FROM "posts"
+# LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# WHERE "authors"."id" IS NULL
+
+ +

Additionally, multiple relations can be combined. This will return posts that are missing both an author and any comments:

+ +
Post.where.missing(:author, :comments)
+# SELECT "posts".* FROM "posts"
+# LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
+# LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id"
+# WHERE "authors"."id" IS NULL AND "comments"."id" IS NULL
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 108
+def missing(*associations)
+  associations.each do |association|
+    reflection = scope_association_reflection(association)
+    @scope.left_outer_joins!(association)
+    if reflection.options[:class_name]
+      @scope.where!(association => { reflection.association_primary_key => nil })
+    else
+      @scope.where!(reflection.table_name => { reflection.association_primary_key => nil })
+    end
+  end
+
+  @scope
+end
+
+
+ +
+ +
+

+ + not(opts, *rest) + +

+ + +
+

Returns a new relation expressing WHERE + NOT condition according to the conditions in the arguments.

+ +

not accepts conditions as a string, array, or hash. See QueryMethods#where for more details on each format.

+ +
User.where.not("name = 'Jon'")
+# SELECT * FROM users WHERE NOT (name = 'Jon')
+
+User.where.not(["name = ?", "Jon"])
+# SELECT * FROM users WHERE NOT (name = 'Jon')
+
+User.where.not(name: "Jon")
+# SELECT * FROM users WHERE name != 'Jon'
+
+User.where.not(name: nil)
+# SELECT * FROM users WHERE name IS NOT NULL
+
+User.where.not(name: %w(Ko1 Nobu))
+# SELECT * FROM users WHERE name NOT IN ('Ko1', 'Nobu')
+
+User.where.not(name: "Jon", role: "admin")
+# SELECT * FROM users WHERE NOT (name == 'Jon' AND role == 'admin')
+
+ +

If there is a non-nil condition on a nullable column in the hash condition, the records that have nil values on the nullable column won’t be returned.

+ +
User.create!(nullable_country: nil)
+User.where.not(nullable_country: "UK")
+# SELECT * FROM users WHERE NOT (nullable_country = 'UK')
+# => []
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/query_methods.rb, line 50
+def not(opts, *rest)
+  where_clause = @scope.send(:build_where_clause, opts, rest)
+
+  @scope.where_clause += where_clause.invert
+
+  @scope
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Querying.html b/src/7.0/classes/ActiveRecord/Querying.html new file mode 100644 index 0000000000..19d1811106 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Querying.html @@ -0,0 +1,166 @@ +--- +title: ActiveRecord::Querying +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + count_by_sql(sql) + +

+ + +
+

Returns the result of an SQL statement that should only include a COUNT(*) in the SELECT part. The use of this method should be restricted to complicated SQL queries that can’t be executed using the ActiveRecord::Calculations class methods. Look into those before using this method, as it could lock you into a specific database engine or require a code change to switch database engines.

+ +
Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
+# => 12
+
+ +

Parameters

+
  • +

    sql - An SQL statement which should return a count query from the database, see the example above.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/querying.rb, line 93
+def count_by_sql(sql)
+  connection.select_value(sanitize_sql(sql), "#{name} Count").to_i
+end
+
+
+ +
+ +
+

+ + find_by_sql(sql, binds = [], preparable: nil, &block) + +

+ + +
+

Executes a custom SQL query against your database and returns all the results. The results will be returned as an array, with the requested columns encapsulated as attributes of the model you call this method from. For example, if you call Product.find_by_sql, then the results will be returned in a Product object with the attributes you specified in the SQL query.

+ +

If you call a complicated SQL query which spans multiple tables, the columns specified by the SELECT will be attributes of the model, whether or not they are columns of the corresponding table.

+ +

The sql parameter is a full SQL query as a string. It will be called as is; there will be no database agnostic conversions performed. This should be a last resort because using database-specific terms will lock you into using that particular database engine, or require you to change your call if you switch engines.

+ +
# A simple SQL query spanning multiple tables
+Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id"
+# => [#<Post:0x36bff9c @attributes={"title"=>"Ruby Meetup", "author"=>"Quentin"}>, ...]
+
+ +

You can use the same string replacement techniques as you can with ActiveRecord::QueryMethods#where :

+ +
Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
+Post.find_by_sql ["SELECT body FROM comments WHERE author = :user_id OR approved_by = :user_id", { :user_id => user_id }]
+
+ +

Note that building your own SQL query string from user input may expose your application to injection attacks (guides.rubyonrails.org/security.html#sql-injection).

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/querying.rb, line 49
+def find_by_sql(sql, binds = [], preparable: nil, &block)
+  _load_from_sql(_query_by_sql(sql, binds, preparable: preparable), &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RangeError.html b/src/7.0/classes/ActiveRecord/RangeError.html new file mode 100644 index 0000000000..1db0fb3be1 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RangeError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::RangeError +layout: default +--- +
+ +
+
+ +
+ +

Raised when values that executed are out of range.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ReadOnlyError.html b/src/7.0/classes/ActiveRecord/ReadOnlyError.html new file mode 100644 index 0000000000..7d603472ba --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ReadOnlyError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ReadOnlyError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a write to the database is attempted on a read only connection.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ReadOnlyRecord.html b/src/7.0/classes/ActiveRecord/ReadOnlyRecord.html new file mode 100644 index 0000000000..0771122580 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ReadOnlyRecord.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ReadOnlyRecord +layout: default +--- +
+ +
+
+ +
+ +

Raised on attempt to update record that is instantiated as read only.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ReadonlyAttributes.html b/src/7.0/classes/ActiveRecord/ReadonlyAttributes.html new file mode 100644 index 0000000000..72c4e63006 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ReadonlyAttributes.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::ReadonlyAttributes +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html b/src/7.0/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html new file mode 100644 index 0000000000..656c9f92ff --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html @@ -0,0 +1,152 @@ +--- +title: ActiveRecord::ReadonlyAttributes::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attr_readonly(*attributes) + +

+ + +
+

Attributes listed as readonly will be used to create a new record but update operations will ignore these fields.

+ +

You can assign a new value to a readonly attribute, but it will be ignored when the record is updated.

+ +

Examples

+ +
class Post < ActiveRecord::Base
+  attr_readonly :title
+end
+
+post = Post.create!(title: "Introducing Ruby on Rails!")
+post.update(title: "a different title") # change to title will be ignored
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/readonly_attributes.rb, line 25
+def attr_readonly(*attributes)
+  self._attr_readonly = Set.new(attributes.map(&:to_s)) + (_attr_readonly || [])
+end
+
+
+ +
+ +
+

+ + readonly_attributes() + +

+ + +
+

Returns an array of all the attributes that have been specified as readonly.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/readonly_attributes.rb, line 30
+def readonly_attributes
+  _attr_readonly
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RecordInvalid.html b/src/7.0/classes/ActiveRecord/RecordInvalid.html new file mode 100644 index 0000000000..d96d42127c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RecordInvalid.html @@ -0,0 +1,144 @@ +--- +title: ActiveRecord::RecordInvalid +layout: default +--- +
+ +
+
+ +
+ +

Active Record RecordInvalid

+ +

Raised by ActiveRecord::Base#save! and ActiveRecord::Base#create! when the record is invalid. Use the record method to retrieve the record which did not validate.

+ +
begin
+  complex_operation_that_internally_calls_save!
+rescue ActiveRecord::RecordInvalid => invalid
+  puts invalid.record.errors
+end
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(record = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations.rb, line 18
+def initialize(record = nil)
+  if record
+    @record = record
+    errors = @record.errors.full_messages.join(", ")
+    message = I18n.t(:"#{@record.class.i18n_scope}.errors.messages.record_invalid", errors: errors, default: :"errors.messages.record_invalid")
+  else
+    message = "Record invalid"
+  end
+
+  super(message)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RecordNotDestroyed.html b/src/7.0/classes/ActiveRecord/RecordNotDestroyed.html new file mode 100644 index 0000000000..24ac376fbe --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RecordNotDestroyed.html @@ -0,0 +1,135 @@ +--- +title: ActiveRecord::RecordNotDestroyed +layout: default +--- +
+ +
+
+ +
+ +

Raised by ActiveRecord::Base#destroy! when a call to #destroy would return false.

+ +
begin
+  complex_operation_that_internally_calls_destroy!
+rescue ActiveRecord::RecordNotDestroyed => invalid
+  puts invalid.record.errors
+end
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(message = nil, record = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 139
+def initialize(message = nil, record = nil)
+  @record = record
+  super(message)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RecordNotFound.html b/src/7.0/classes/ActiveRecord/RecordNotFound.html new file mode 100644 index 0000000000..8a6fe8e7ca --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RecordNotFound.html @@ -0,0 +1,147 @@ +--- +title: ActiveRecord::RecordNotFound +layout: default +--- +
+ +
+
+ +
+ +

Raised when Active Record cannot find a record by given id or set of ids.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + id
+ [R] + model
+ [R] + primary_key
+ + + + +

Class Public methods

+ +
+

+ + new(message = nil, model = nil, primary_key = nil, id = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 105
+def initialize(message = nil, model = nil, primary_key = nil, id = nil)
+  @primary_key = primary_key
+  @model = model
+  @id = id
+
+  super(message)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RecordNotSaved.html b/src/7.0/classes/ActiveRecord/RecordNotSaved.html new file mode 100644 index 0000000000..f873f5d48a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RecordNotSaved.html @@ -0,0 +1,128 @@ +--- +title: ActiveRecord::RecordNotSaved +layout: default +--- +
+ +
+
+ +
+ +

Raised by ActiveRecord::Base#save! and ActiveRecord::Base.create! methods when a record is invalid and cannot be saved.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(message = nil, record = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 120
+def initialize(message = nil, record = nil)
+  @record = record
+  super(message)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/RecordNotUnique.html b/src/7.0/classes/ActiveRecord/RecordNotUnique.html new file mode 100644 index 0000000000..8105d43d68 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/RecordNotUnique.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::RecordNotUnique +layout: default +--- +
+ +
+
+ +
+ +

Raised when a record cannot be inserted or updated because it would violate a uniqueness constraint.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Reflection.html b/src/7.0/classes/ActiveRecord/Reflection.html new file mode 100644 index 0000000000..81b4c72c9d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Reflection.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::Reflection +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Reflection/ClassMethods.html b/src/7.0/classes/ActiveRecord/Reflection/ClassMethods.html new file mode 100644 index 0000000000..b1df1b66a7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Reflection/ClassMethods.html @@ -0,0 +1,337 @@ +--- +title: ActiveRecord::Reflection::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Reflection enables the ability to examine the associations and aggregations of Active Record classes and objects. This information, for example, can be used in a form builder that takes an Active Record object and creates input fields for all of the attributes depending on their type and displays the associations to other objects.

+ +

MacroReflection class has info for AggregateReflection and AssociationReflection classes.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + reflect_on_aggregation(aggregation) + +

+ + +
+

Returns the AggregateReflection object for the named aggregation (use the symbol).

+ +
Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 67
+def reflect_on_aggregation(aggregation)
+  aggregate_reflections[aggregation.to_s]
+end
+
+
+ +
+ +
+

+ + reflect_on_all_aggregations() + +

+ + +
+

Returns an array of AggregateReflection objects for all the aggregations in the class.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 59
+def reflect_on_all_aggregations
+  aggregate_reflections.values
+end
+
+
+ +
+ +
+

+ + reflect_on_all_associations(macro = nil) + +

+ + +
+

Returns an array of AssociationReflection objects for all the associations in the class. If you only want to reflect on a certain association type, pass in the symbol (:has_many, :has_one, :belongs_to) as the first parameter.

+ +

Example:

+ +
Account.reflect_on_all_associations             # returns an array of all associations
+Account.reflect_on_all_associations(:has_many)  # returns an array of all has_many associations
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 104
+def reflect_on_all_associations(macro = nil)
+  association_reflections = reflections.values
+  association_reflections.select! { |reflection| reflection.macro == macro } if macro
+  association_reflections
+end
+
+
+ +
+ +
+

+ + reflect_on_all_autosave_associations() + +

+ + +
+

Returns an array of AssociationReflection objects for all associations which have :autosave enabled.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 124
+def reflect_on_all_autosave_associations
+  reflections.values.select { |reflection| reflection.options[:autosave] }
+end
+
+
+ +
+ +
+

+ + reflect_on_association(association) + +

+ + +
+

Returns the AssociationReflection object for the association (use the symbol).

+ +
Account.reflect_on_association(:owner)             # returns the owner AssociationReflection
+Invoice.reflect_on_association(:line_items).macro  # returns :has_many
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 115
+def reflect_on_association(association)
+  reflections[association.to_s]
+end
+
+
+ +
+ +
+

+ + reflections() + +

+ + +
+

Returns a Hash of name of the reflection as the key and an AssociationReflection as the value.

+ +
Account.reflections # => {"balance" => AggregateReflection}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 75
+def reflections
+  @__reflections ||= begin
+    ref = {}
+
+    _reflections.each do |name, reflection|
+      parent_reflection = reflection.parent_reflection
+
+      if parent_reflection
+        parent_name = parent_reflection.name
+        ref[parent_name.to_s] = parent_reflection
+      else
+        ref[name] = reflection
+      end
+    end
+
+    ref
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Reflection/MacroReflection.html b/src/7.0/classes/ActiveRecord/Reflection/MacroReflection.html new file mode 100644 index 0000000000..1c56899790 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Reflection/MacroReflection.html @@ -0,0 +1,379 @@ +--- +title: ActiveRecord::Reflection::MacroReflection +layout: default +--- +
+ +
+
+ +
+ +

Base class for AggregateReflection and AssociationReflection. Objects of AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + active_record
+ [R] + name

Returns the name of the macro.

+ +

composed_of :balance, class_name: 'Money' returns :balance has_many :clients returns :clients

+ [R] + options

Returns the hash of options used for the macro.

+ +

composed_of :balance, class_name: 'Money' returns { class_name: "Money" } has_many :clients returns {}

+ [R] + scope
+ + + + +

Class Public methods

+ +
+

+ + new(name, scope, options, active_record) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 348
+def initialize(name, scope, options, active_record)
+  @name          = name
+  @scope         = scope
+  @options       = options
+  @active_record = active_record
+  @klass         = options[:anonymous_class]
+  @plural_name   = active_record.pluralize_table_names ?
+                      name.to_s.pluralize : name.to_s
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other_aggregation) + +

+ + +
+

Returns true if self and other_aggregation have the same name attribute, active_record attribute, and other_aggregation has an options hash assigned to it.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 391
+def ==(other_aggregation)
+  super ||
+    other_aggregation.kind_of?(self.class) &&
+    name == other_aggregation.name &&
+    !other_aggregation.options.nil? &&
+    active_record == other_aggregation.active_record
+end
+
+
+ +
+ +
+

+ + autosave=(autosave) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 358
+def autosave=(autosave)
+  @options[:autosave] = autosave
+  parent_reflection = self.parent_reflection
+  if parent_reflection
+    parent_reflection.autosave = autosave
+  end
+end
+
+
+ +
+ +
+

+ + compute_class(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 385
+def compute_class(name)
+  name.constantize
+end
+
+
+ +
+ +
+

+ + klass() + +

+ + +
+

Returns the class for the macro.

+ +

composed_of :balance, class_name: 'Money' returns the Money class has_many :clients returns the Client class

+ +
class Company < ActiveRecord::Base
+  has_many :clients
+end
+
+Company.reflect_on_association(:clients).klass
+# => Client
+
+ +

Note: Do not call klass.new or klass.create to instantiate a new association object. Use build_association or create_association instead. This allows plugins to hook into association object creation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 381
+def klass
+  @klass ||= compute_class(class_name)
+end
+
+
+ +
+ +
+

+ + scope_for(relation, owner = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/reflection.rb, line 399
+def scope_for(relation, owner = nil)
+  relation.instance_exec(owner, &scope) || relation
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Relation.html b/src/7.0/classes/ActiveRecord/Relation.html new file mode 100644 index 0000000000..e46767fa7d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Relation.html @@ -0,0 +1,2455 @@ +--- +title: ActiveRecord::Relation +layout: default +--- +
+ +
+
+ +
+ +

Active Record Relation

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CLAUSE_METHODS=[:where, :having, :from]
 
INVALID_METHODS_FOR_DELETE_ALL=[:distinct]
 
MULTI_VALUE_METHODS=[:includes, :eager_load, :preload, :select, :group, +:order, :joins, :left_outer_joins, :references, +:extending, :unscope, :optimizer_hints, :annotate]
 
SINGLE_VALUE_METHODS=[:limit, :offset, :lock, :readonly, :reordering, :strict_loading, +:reverse_order, :distinct, :create_with, :skip_query_cache]
 
VALUE_METHODS=MULTI_VALUE_METHODS + SINGLE_VALUE_METHODS + CLAUSE_METHODS
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + klass
+ [R] + loaded
+ [R] + loaded?
+ [R] + model
+ [R] + predicate_builder
+ [RW] + skip_preloading_value
+ [R] + table
+ + + + +

Class Public methods

+ +
+

+ + new(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 27
+def initialize(klass, table: klass.arel_table, predicate_builder: klass.predicate_builder, values: {})
+  @klass  = klass
+  @table  = table
+  @values = values
+  @loaded = false
+  @predicate_builder = predicate_builder
+  @delegate_to_klass = false
+  @future_result = nil
+  @records = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other) + +

+ + +
+

Compares two relations for equality.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 766
+def ==(other)
+  case other
+  when Associations::CollectionProxy, AssociationRelation
+    self == other.records
+  when Relation
+    other.to_sql == to_sql
+  when Array
+    records == other
+  end
+end
+
+
+ +
+ +
+

+ + any?() + +

+ + +
+

Returns true if there are any records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 284
+def any?
+  return super if block_given?
+  !empty?
+end
+
+
+ +
+ +
+

+ + blank?() + +

+ + +
+

Returns true if relation is blank.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 782
+def blank?
+  records.blank?
+end
+
+
+ +
+ +
+

+ + build(attributes = nil, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: new +
+ + + +
+ +
+

+ + cache_key(timestamp_column = "updated_at") + +

+ + +
+

Returns a stable cache key that can be used to identify this query. The cache key is built with a fingerprint of the SQL query.

+ +
Product.where("name like ?", "%Cosmic Encounter%").cache_key
+# => "products/query-1850ab3d302391b85b8693e941286659"
+
+ +

If ActiveRecord::Base.collection_cache_versioning is turned off, as it was in Rails 6.0 and earlier, the cache key will also include a version.

+ +
ActiveRecord::Base.collection_cache_versioning = false
+Product.where("name like ?", "%Cosmic Encounter%").cache_key
+# => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
+
+ +

You can also pass a custom timestamp column to fetch the timestamp of the last updated record.

+ +
Product.where("name like ?", "%Game%").cache_key(:last_reviewed_at)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 320
+def cache_key(timestamp_column = "updated_at")
+  @cache_keys ||= {}
+  @cache_keys[timestamp_column] ||= klass.collection_cache_key(self, timestamp_column)
+end
+
+
+ +
+ +
+

+ + cache_key_with_version() + +

+ + +
+

Returns a cache key along with the version.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 399
+def cache_key_with_version
+  if version = cache_version
+    "#{cache_key}-#{version}"
+  else
+    cache_key
+  end
+end
+
+
+ +
+ +
+

+ + cache_version(timestamp_column = :updated_at) + +

+ + +
+

Returns a cache version that can be used together with the cache key to form a recyclable caching scheme. The cache version is built with the number of records matching the query, and the timestamp of the last updated record. When a new record comes to match the query, or any of the existing records is updated or deleted, the cache version changes.

+ +

If the collection is loaded, the method will iterate through the records to generate the timestamp, otherwise it will trigger one SQL query like:

+ +
SELECT COUNT(*), MAX("products"."updated_at") FROM "products" WHERE (name like '%Cosmic Encounter%')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 347
+def cache_version(timestamp_column = :updated_at)
+  if collection_cache_versioning
+    @cache_versions ||= {}
+    @cache_versions[timestamp_column] ||= compute_cache_version(timestamp_column)
+  end
+end
+
+
+ +
+ +
+

+ + create(attributes = nil, &block) + +

+ + +
+

Tries to create a new record with the same scoped attributes defined in the relation. Returns the initialized object if validation fails.

+ +

Expects arguments in the same format as ActiveRecord::Base.create.

+ +

Examples

+ +
users = User.where(name: 'Oscar')
+users.create # => #<User id: 3, name: "Oscar", ...>
+
+users.create(name: 'fxn')
+users.create # => #<User id: 4, name: "fxn", ...>
+
+users.create { |user| user.name = 'tenderlove' }
+# => #<User id: 5, name: "tenderlove", ...>
+
+users.create(name: nil) # validation on name
+# => #<User id: nil, name: nil, ...>
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 95
+def create(attributes = nil, &block)
+  if attributes.is_a?(Array)
+    attributes.collect { |attr| create(attr, &block) }
+  else
+    block = current_scope_restoring_block(&block)
+    scoping { _create(attributes, &block) }
+  end
+end
+
+
+ +
+ +
+

+ + create!(attributes = nil, &block) + +

+ + +
+

Similar to create, but calls create! on the base class. Raises an exception if a validation error occurs.

+ +

Expects arguments in the same format as ActiveRecord::Base.create!.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 110
+def create!(attributes = nil, &block)
+  if attributes.is_a?(Array)
+    attributes.collect { |attr| create!(attr, &block) }
+  else
+    block = current_scope_restoring_block(&block)
+    scoping { _create!(attributes, &block) }
+  end
+end
+
+
+ +
+ +
+

+ + create_or_find_by(attributes, &block) + +

+ + +
+

Attempts to create a record with the given attributes in a table that has a unique database constraint on one or several of its columns. If a row already exists with one or several of these unique constraints, the exception such an insertion would normally raise is caught, and the existing record with those attributes is found using find_by!.

+ +

This is similar to find_or_create_by, but avoids the problem of stale reads between the SELECT and the INSERT, as that method needs to first query the table, then attempt to insert a row if none is found.

+ +

There are several drawbacks to create_or_find_by, though:

+
  • +

    The underlying table must have the relevant columns defined with unique database constraints.

    +
  • +

    A unique constraint violation may be triggered by only one, or at least less than all, of the given attributes. This means that the subsequent find_by! may fail to find a matching record, which will then raise an ActiveRecord::RecordNotFound exception, rather than a record with the given attributes.

    +
  • +

    While we avoid the race condition between SELECT -> INSERT from find_or_create_by, we actually have another race condition between INSERT -> SELECT, which can be triggered if a DELETE between those two statements is run by another client. But for most applications, that’s a significantly less likely condition to hit.

    +
  • +

    It relies on exception handling to handle control flow, which may be marginally slower.

    +
  • +

    The primary key may auto-increment on each create, even if it fails. This can accelerate the problem of running out of integers, if the underlying table is still stuck on a primary key of type int (note: All Rails apps since 5.1+ have defaulted to bigint, which is not liable to this problem).

    +
+ +

This method will return a record if all given attributes are covered by unique constraints (unless the INSERT -> DELETE -> SELECT race condition is triggered), but if creation was attempted and failed due to validation errors it won’t be persisted, you get what create returns in such situation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 209
+def create_or_find_by(attributes, &block)
+  transaction(requires_new: true) { create(attributes, &block) }
+rescue ActiveRecord::RecordNotUnique
+  find_by!(attributes)
+end
+
+
+ +
+ +
+

+ + create_or_find_by!(attributes, &block) + +

+ + +
+

Like create_or_find_by, but calls create! so an exception is raised if the created record is invalid.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 218
+def create_or_find_by!(attributes, &block)
+  transaction(requires_new: true) { create!(attributes, &block) }
+rescue ActiveRecord::RecordNotUnique
+  find_by!(attributes)
+end
+
+
+ +
+ +
+

+ + delete_all() + +

+ + +
+

Deletes the records without instantiating the records first, and hence not calling the #destroy method nor invoking callbacks. This is a single SQL DELETE statement that goes straight to the database, much more efficient than destroy_all. Be careful with relations though, in particular :dependent rules defined on associations are not honored. Returns the number of rows affected.

+ +
Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
+
+ +

Both calls delete the affected posts all at once with a single DELETE statement. If you need to destroy dependent associations or call your before_* or after_destroy callbacks, use the destroy_all method instead.

+ +

If an invalid method is supplied, delete_all raises an ActiveRecordError:

+ +
Post.distinct.delete_all
+# => ActiveRecord::ActiveRecordError: delete_all doesn't support distinct
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 601
+def delete_all
+  invalid_methods = INVALID_METHODS_FOR_DELETE_ALL.select do |method|
+    value = @values[method]
+    method == :distinct ? value : value&.any?
+  end
+  if invalid_methods.any?
+    raise ActiveRecordError.new("delete_all doesn't support #{invalid_methods.join(', ')}")
+  end
+
+  arel = eager_loading? ? apply_join_dependency.arel : build_arel
+  arel.source.left = table
+
+  group_values_arel_columns = arel_columns(group_values.uniq)
+  having_clause_ast = having_clause.ast unless having_clause.empty?
+  stmt = arel.compile_delete(table[primary_key], having_clause_ast, group_values_arel_columns)
+
+  klass.connection.delete(stmt, "#{klass} Delete All").tap { reset }
+end
+
+
+ +
+ +
+

+ + delete_by(*args) + +

+ + +
+

Finds and deletes all records matching the specified conditions. This is short-hand for relation.where(condition).delete_all. Returns the number of rows affected.

+ +

If no record is found, returns 0 as zero rows were affected.

+ +
Person.delete_by(id: 13)
+Person.delete_by(name: 'Spartacus', rating: 4)
+Person.delete_by("published_at < ?", 2.weeks.ago)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 642
+def delete_by(*args)
+  where(*args).delete_all
+end
+
+
+ +
+ +
+

+ + destroy_all() + +

+ + +
+

Destroys the records by instantiating each record and calling its #destroy method. Each object’s callbacks are executed (including :dependent association options). Returns the collection of objects that were destroyed; each will be frozen, to reflect that no changes should be made (since they can’t be persisted).

+ +

Note: Instantiation, callback execution, and deletion of each record can be time consuming when you’re removing many records at once. It generates at least one SQL DELETE query per record (or possibly more, to enforce your callbacks). If you want to delete many rows quickly, without concern for their associations or callbacks, use delete_all instead.

+ +

Examples

+ +
Person.where(age: 0..18).destroy_all
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 579
+def destroy_all
+  records.each(&:destroy).tap { reset }
+end
+
+
+ +
+ +
+

+ + destroy_by(*args) + +

+ + +
+

Finds and destroys all records matching the specified conditions. This is short-hand for relation.where(condition).destroy_all. Returns the collection of objects that were destroyed.

+ +

If no record is found, returns empty array.

+ +
Person.destroy_by(id: 13)
+Person.destroy_by(name: 'Spartacus', rating: 4)
+Person.destroy_by("published_at < ?", 2.weeks.ago)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 629
+def destroy_by(*args)
+  where(*args).destroy_all
+end
+
+
+ +
+ +
+

+ + eager_loading?() + +

+ + +
+

Returns true if relation needs eager loading.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 751
+def eager_loading?
+  @should_eager_load ||=
+    eager_load_values.any? ||
+    includes_values.any? && (joined_includes_values.any? || references_eager_loaded_tables?)
+end
+
+
+ +
+ +
+

+ + empty?() + +

+ + +
+

Returns true if there are no records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 269
+def empty?
+  if loaded?
+    records.empty?
+  else
+    !exists?
+  end
+end
+
+
+ +
+ +
+

+ + encode_with(coder) + +

+ + +
+

Serializes the relation objects Array.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 255
+def encode_with(coder)
+  coder.represent_seq(nil, records)
+end
+
+
+ +
+ +
+

+ + explain() + +

+ + +
+

Runs EXPLAIN on the query or queries triggered by this relation and returns the result as a string. The string is formatted imitating the ones printed by the database shell.

+ +

Note that this method actually runs the queries, since the results of some are needed by the next ones when eager loading is going on.

+ +

Please see further details in the Active Record Query Interface guide.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 239
+def explain
+  exec_explain(collecting_queries_for_explain { exec_queries })
+end
+
+
+ +
+ +
+

+ + find_or_create_by(attributes, &block) + +

+ + +
+

Finds the first record with the given attributes, or creates a record with the attributes if one is not found:

+ +
# Find the first user named "Penélope" or create a new one.
+User.find_or_create_by(first_name: 'Penélope')
+# => #<User id: 1, first_name: "Penélope", last_name: nil>
+
+# Find the first user named "Penélope" or create a new one.
+# We already have one so the existing record will be returned.
+User.find_or_create_by(first_name: 'Penélope')
+# => #<User id: 1, first_name: "Penélope", last_name: nil>
+
+# Find the first user named "Scarlett" or create a new one with
+# a particular last name.
+User.create_with(last_name: 'Johansson').find_or_create_by(first_name: 'Scarlett')
+# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
+
+ +

This method accepts a block, which is passed down to create. The last example above can be alternatively written this way:

+ +
# Find the first user named "Scarlett" or create a new one with a
+# particular last name.
+User.find_or_create_by(first_name: 'Scarlett') do |user|
+  user.last_name = 'Johansson'
+end
+# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
+
+ +

This method always returns a record, but if creation was attempted and failed due to validation errors it won’t be persisted, you get what create returns in such situation.

+ +

Please note this method is not atomic, it runs first a SELECT, and if there are no results an INSERT is attempted. If there are other threads or processes there is a race condition between both calls and it could be the case that you end up with two similar records.

+ +

If this might be a problem for your application, please see create_or_find_by.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 168
+def find_or_create_by(attributes, &block)
+  find_by(attributes) || create(attributes, &block)
+end
+
+
+ +
+ +
+

+ + find_or_create_by!(attributes, &block) + +

+ + +
+

Like find_or_create_by, but calls create! so an exception is raised if the created record is invalid.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 175
+def find_or_create_by!(attributes, &block)
+  find_by(attributes) || create!(attributes, &block)
+end
+
+
+ +
+ +
+

+ + find_or_initialize_by(attributes, &block) + +

+ + +
+

Like find_or_create_by, but calls new instead of create.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 226
+def find_or_initialize_by(attributes, &block)
+  find_by(attributes) || new(attributes, &block)
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 38
+def initialize_copy(other)
+  @values = @values.dup
+  reset
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 794
+def inspect
+  subject = loaded? ? records : annotate("loading for inspect")
+  entries = subject.take([limit_value, 11].compact.min).map!(&:inspect)
+
+  entries[10] = "..." if entries.size == 11
+
+  "#<#{self.class.name} [#{entries.join(', ')}]>"
+end
+
+
+ +
+ +
+

+ + joined_includes_values() + +

+ + +
+

Joins that are also marked for preloading. In which case we should just eager load them. Note that this is a naive implementation because we could have strings and symbols which represent the same association, but that aren’t matched by this. Also, we could have nested hashes which partially match, e.g. { a: :b } & { a: [:b, :c] }

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 761
+def joined_includes_values
+  includes_values & joins_values
+end
+
+
+ +
+ +
+

+ + load(&block) + +

+ + +
+

Causes the records to be loaded from the database if they have not been loaded already. You can use this if for some reason you need to explicitly load some records before actually using them. The return value is the relation itself, not the records.

+ +
Post.where(published: true).load # => #<ActiveRecord::Relation>
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 693
+def load(&block)
+  if !loaded? || scheduled?
+    @records = exec_queries(&block)
+    @loaded = true
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + load_async() + +

+ + +
+

Schedule the query to be performed from a background thread pool.

+ +
Post.where(published: true).load_async # => #<ActiveRecord::Relation>
+
+ +

When the Relation is iterated, if the background query wasn’t executed yet, it will be performed by the foreground thread.

+ +

Note that config.active_record.async_query_executor must be configured for queries to actually be executed concurrently. Otherwise it defaults to executing them in the foreground.

+ +

load_async will also fall back to executing in the foreground in the test environment when transactional fixtures are enabled.

+ +

If the query was actually executed in the background, the Active Record logs will show it by prefixing the log line with ASYNC:

+ +
ASYNC Post Load (0.0ms) (db time 2ms)  SELECT "posts".* FROM "posts" LIMIT 100
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 664
+def load_async
+  return load if !connection.async_enabled?
+
+  unless loaded?
+    result = exec_main_query(async: connection.current_transaction.closed?)
+
+    if result.is_a?(Array)
+      @records = result
+    else
+      @future_result = result
+    end
+    @loaded = true
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + many?() + +

+ + +
+

Returns true if there is more than one record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 297
+def many?
+  return super if block_given?
+  return records.many? if loaded?
+  limited_count > 1
+end
+
+
+ +
+ +
+

+ + new(attributes = nil, &block) + +

+ + +
+

Initializes new record from relation while maintaining the current scope.

+ +

Expects arguments in the same format as ActiveRecord::Base.new.

+ +
users = User.where(name: 'DHH')
+user = users.new # => #<User id: nil, name: "DHH", created_at: nil, updated_at: nil>
+
+ +

You can also pass a block to new with the new record as argument:

+ +
user = users.new { |user| user.name = 'Oscar' }
+user.name # => Oscar
+
+
+ + + +
+ Also aliased as: build +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 66
+def new(attributes = nil, &block)
+  if attributes.is_a?(Array)
+    attributes.collect { |attr| new(attr, &block) }
+  else
+    block = current_scope_restoring_block(&block)
+    scoping { _new(attributes, &block) }
+  end
+end
+
+
+ +
+ +
+

+ + none?() + +

+ + +
+

Returns true if there are no records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 278
+def none?
+  return super if block_given?
+  empty?
+end
+
+
+ +
+ +
+

+ + one?() + +

+ + +
+

Returns true if there is exactly one record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 290
+def one?
+  return super if block_given?
+  return records.one? if loaded?
+  limited_count == 1
+end
+
+
+ +
+ +
+

+ + pretty_print(q) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 777
+def pretty_print(q)
+  q.pp(records)
+end
+
+
+ +
+ +
+

+ + reload() + +

+ + +
+

Forces reloading of relation.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 703
+def reload
+  reset
+  load
+end
+
+
+ +
+ +
+

+ + reset() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 708
+def reset
+  @future_result&.cancel
+  @future_result = nil
+  @delegate_to_klass = false
+  @to_sql = @arel = @loaded = @should_eager_load = nil
+  @offsets = @take = nil
+  @cache_keys = nil
+  @cache_versions = nil
+  @records = nil
+  self
+end
+
+
+ +
+ +
+

+ + scheduled?() + +

+ + +
+

Returns true if the relation was scheduled on the background thread pool.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 683
+def scheduled?
+  !!@future_result
+end
+
+
+ +
+ +
+

+ + scope_for_create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 744
+def scope_for_create
+  hash = where_clause.to_h(klass.table_name, equality_only: true)
+  create_with_value.each { |k, v| hash[k.to_s] = v } unless create_with_value.empty?
+  hash
+end
+
+
+ +
+ +
+

+ + scoping(all_queries: nil, &block) + +

+ + +
+

Scope all queries to the current scope.

+ +
Comment.where(post_id: 1).scoping do
+  Comment.first
+end
+# => SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = 1 ORDER BY "comments"."id" ASC LIMIT 1
+
+ +

If all_queries: true is passed, scoping will apply to all queries for the relation including update and delete on instances. Once all_queries is set to true it cannot be set to false in a nested block.

+ +

Please check unscoped if you want to remove all previous scopes (including the default_scope) during the execution of a block.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 421
+def scoping(all_queries: nil, &block)
+  registry = klass.scope_registry
+  if global_scope?(registry) && all_queries == false
+    raise ArgumentError, "Scoping is set to apply to all queries and cannot be unset in a nested block."
+  elsif already_in_scope?(registry)
+    yield
+  else
+    _scoping(self, registry, all_queries, &block)
+  end
+end
+
+
+ +
+ +
+

+ + size() + +

+ + +
+

Returns size of the records.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 260
+def size
+  if loaded?
+    records.length
+  else
+    count(:all)
+  end
+end
+
+
+ +
+ +
+

+ + to_a() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_ary +
+ + + +
+ +
+

+ + to_ary() + +

+ + +
+

Converts relation objects to Array.

+
+ + + +
+ Also aliased as: to_a +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 244
+def to_ary
+  records.dup
+end
+
+
+ +
+ +
+

+ + to_sql() + +

+ + +
+

Returns sql statement for the relation.

+ +
User.where(name: 'Oscar').to_sql
+# => SELECT "users".* FROM "users"  WHERE "users"."name" = 'Oscar'
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 724
+def to_sql
+  @to_sql ||= if eager_loading?
+    apply_join_dependency do |relation, join_dependency|
+      relation = join_dependency.apply_column_aliases(relation)
+      relation.to_sql
+    end
+  else
+    conn = klass.connection
+    conn.unprepared_statement { conn.to_sql(arel) }
+  end
+end
+
+
+ +
+ +
+

+ + touch_all(*names, time: nil) + +

+ + +
+

Touches all records in the current relation, setting the updated_at/updated_on attributes to the current time or the time specified. It does not instantiate the involved models, and it does not trigger Active Record callbacks or validations. This method can be passed attribute names and an optional time argument. If attribute names are passed, they are updated along with updated_at/updated_on attributes. If no time argument is passed, the current time is used as default.

+ +

Examples

+ +
# Touch all records
+Person.all.touch_all
+# => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670'"
+
+# Touch multiple records with a custom attribute
+Person.all.touch_all(:created_at)
+# => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670', \"created_at\" = '2018-01-04 22:55:23.132670'"
+
+# Touch multiple records with a specified time
+Person.all.touch_all(time: Time.new(2020, 5, 16, 0, 0, 0))
+# => "UPDATE \"people\" SET \"updated_at\" = '2020-05-16 00:00:00'"
+
+# Touch records with scope
+Person.where(name: 'David').touch_all
+# => "UPDATE \"people\" SET \"updated_at\" = '2018-01-04 22:55:23.132670' WHERE \"people\".\"name\" = 'David'"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 559
+def touch_all(*names, time: nil)
+  update_all klass.touch_attributes_with_time(*names, time: time)
+end
+
+
+ +
+ +
+

+ + update_all(updates) + +

+ + +
+

Updates all records in the current relation with details given. This method constructs a single SQL UPDATE statement and sends it straight to the database. It does not instantiate the involved models and it does not trigger Active Record callbacks or validations. However, values passed to update_all will still go through Active Record’s normal type casting and serialization. Returns the number of rows affected.

+ +

Note: As Active Record callbacks are not triggered, this method will not automatically update updated_at/updated_on columns.

+ +

Parameters

+
  • +

    updates - A string, array, or hash representing the SET part of an SQL statement.

    +
+ +

Examples

+ +
# Update all customers with the given attributes
+Customer.update_all wants_email: true
+
+# Update all books with 'Rails' in their title
+Book.where('title LIKE ?', '%Rails%').update_all(author: 'David')
+
+# Update all books that match conditions, but limit it to 5 ordered by date
+Book.where('title LIKE ?', '%Rails%').order(:created_at).limit(5).update_all(author: 'David')
+
+# Update all invoices and set the number column to its id value.
+Invoice.update_all('number = id')
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 464
+def update_all(updates)
+  raise ArgumentError, "Empty list of attributes to change" if updates.blank?
+
+  if updates.is_a?(Hash)
+    if klass.locking_enabled? &&
+        !updates.key?(klass.locking_column) &&
+        !updates.key?(klass.locking_column.to_sym)
+      attr = table[klass.locking_column]
+      updates[attr.name] = _increment_attribute(attr)
+    end
+    values = _substitute_values(updates)
+  else
+    values = Arel.sql(klass.sanitize_sql_for_assignment(updates, table.name))
+  end
+
+  arel = eager_loading? ? apply_join_dependency.arel : build_arel
+  arel.source.left = table
+
+  group_values_arel_columns = arel_columns(group_values.uniq)
+  having_clause_ast = having_clause.ast unless having_clause.empty?
+  stmt = arel.compile_update(values, table[primary_key], having_clause_ast, group_values_arel_columns)
+  klass.connection.update(stmt, "#{klass} Update All").tap { reset }
+end
+
+
+ +
+ +
+

+ + update_counters(counters) + +

+ + +
+

Updates the counters of the records in the current relation.

+ +

Parameters

+
  • +

    counter - A Hash containing the names of the fields to update as keys and the amount to update as values.

    +
  • +

    :touch option - Touch the timestamp columns when updating.

    +
  • +

    If attributes names are passed, they are updated along with update_at/on attributes.

    +
+ +

Examples

+ +
# For Posts by a given author increment the comment_count by 1.
+Post.where(author_id: author.id).update_counters(comment_count: 1)
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 516
+def update_counters(counters)
+  touch = counters.delete(:touch)
+
+  updates = {}
+  counters.each do |counter_name, value|
+    attr = table[counter_name]
+    updates[attr.name] = _increment_attribute(attr, value)
+  end
+
+  if touch
+    names = touch if touch != true
+    names = Array.wrap(names)
+    options = names.extract_options!
+    touch_updates = klass.touch_attributes_with_time(*names, **options)
+    updates.merge!(touch_updates) unless touch_updates.empty?
+  end
+
+  update_all updates
+end
+
+
+ +
+ +
+

+ + values() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 786
+def values
+  @values.dup
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + load_records(records) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation.rb, line 835
+def load_records(records)
+  @records = records.freeze
+  @loaded = true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Relation/RecordFetchWarning.html b/src/7.0/classes/ActiveRecord/Relation/RecordFetchWarning.html new file mode 100644 index 0000000000..f9dc62c2bc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Relation/RecordFetchWarning.html @@ -0,0 +1,111 @@ +--- +title: ActiveRecord::Relation::RecordFetchWarning +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + exec_queries() + +

+ + +
+

When this module is prepended to ActiveRecord::Relation and config.active_record.warn_on_records_fetched_greater_than is set to an integer, if the number of records a query returns is greater than the value of warn_on_records_fetched_greater_than, a warning is logged. This allows for the detection of queries that return a large number of records, which could cause memory bloat.

+ +

In most cases, fetching large number of records can be performed efficiently using the ActiveRecord::Batches methods. See ActiveRecord::Batches for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/record_fetch_warning.rb, line 16
+def exec_queries
+  QueryRegistry.reset
+
+  super.tap do |records|
+    if logger && ActiveRecord.warn_on_records_fetched_greater_than
+      if records.length > ActiveRecord.warn_on_records_fetched_greater_than
+        logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
+      end
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Result.html b/src/7.0/classes/ActiveRecord/Result.html new file mode 100644 index 0000000000..9585f8c331 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Result.html @@ -0,0 +1,543 @@ +--- +title: ActiveRecord::Result +layout: default +--- +
+ +
+
+ +
+ +

This class encapsulates a result returned from calling #exec_query on any database connection adapter. For example:

+ +
result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts')
+result # => #<ActiveRecord::Result:0xdeadbeef>
+
+# Get the column names of the result:
+result.columns
+# => ["id", "title", "body"]
+
+# Get the record values of the result:
+result.rows
+# => [[1, "title_1", "body_1"],
+      [2, "title_2", "body_2"],
+      ...
+     ]
+
+# Get an array of hashes representing the result (column => value):
+result.to_a
+# => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
+      {"id" => 2, "title" => "title_2", "body" => "body_2"},
+      ...
+     ]
+
+# ActiveRecord::Result also includes Enumerable.
+result.each do |row|
+  puts row['title'] + " " + row['body']
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + column_types
+ [R] + columns
+ [R] + rows
+ + + + +

Class Public methods

+ +
+

+ + new(columns, rows, column_types = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 43
+def initialize(columns, rows, column_types = {})
+  @columns      = columns
+  @rows         = rows
+  @hash_rows    = nil
+  @column_types = column_types
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](idx) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 87
+def [](idx)
+  hash_rows[idx]
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+

Calls the given block once for each element in row collection, passing row as parameter.

+ +

Returns an Enumerator if no block is given.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 67
+def each(&block)
+  if block_given?
+    hash_rows.each(&block)
+  else
+    hash_rows.to_enum { @rows.size }
+  end
+end
+
+
+ +
+ +
+

+ + empty?() + +

+ + +
+

Returns true if there are no records, otherwise false.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 76
+def empty?
+  rows.empty?
+end
+
+
+ +
+ +
+

+ + includes_column?(name) + +

+ + +
+

Returns true if this result set includes the column named name

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 54
+def includes_column?(name)
+  @columns.include? name
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 130
+def initialize_copy(other)
+  @columns      = columns.dup
+  @rows         = rows.dup
+  @column_types = column_types.dup
+  @hash_rows    = nil
+end
+
+
+ +
+ +
+

+ + last(n = nil) + +

+ + +
+

Returns the last record from the rows collection.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 92
+def last(n = nil)
+  n ? hash_rows.last(n) : hash_rows.last
+end
+
+
+ +
+ +
+

+ + length() + +

+ + +
+

Returns the number of elements in the rows array.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 59
+def length
+  @rows.length
+end
+
+
+ +
+ +
+

+ + to_a() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_ary +
+ + + +
+ +
+

+ + to_ary() + +

+ + +
+

Returns an array of hashes representing each row record.

+
+ + + +
+ Also aliased as: to_a +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/result.rb, line 81
+def to_ary
+  hash_rows
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Rollback.html b/src/7.0/classes/ActiveRecord/Rollback.html new file mode 100644 index 0000000000..d290b99f2d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Rollback.html @@ -0,0 +1,88 @@ +--- +title: ActiveRecord::Rollback +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::Base.transaction uses this exception to distinguish a deliberate rollback from other exceptional situations. Normally, raising an exception will cause the .transaction method to rollback the database transaction and pass on the exception. But if you raise an ActiveRecord::Rollback exception, then the database transaction will be rolled back, without passing on the exception.

+ +

For example, you could do this in your controller to rollback a transaction:

+ +
class BooksController < ActionController::Base
+  def create
+    Book.transaction do
+      book = Book.new(params[:book])
+      book.save!
+      if today_is_friday?
+        # The system must fail on Friday so that our support department
+        # won't be out of job. We silently rollback this transaction
+        # without telling the user.
+        raise ActiveRecord::Rollback
+      end
+    end
+    # ActiveRecord::Rollback is the only exception that won't be passed on
+    # by ActiveRecord::Base.transaction, so this line will still be reached
+    # even on Friday.
+    redirect_to root_url
+  end
+end
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Sanitization.html b/src/7.0/classes/ActiveRecord/Sanitization.html new file mode 100644 index 0000000000..f556fe67b6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Sanitization.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::Sanitization +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Sanitization/ClassMethods.html b/src/7.0/classes/ActiveRecord/Sanitization/ClassMethods.html new file mode 100644 index 0000000000..42dd1e2040 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Sanitization/ClassMethods.html @@ -0,0 +1,427 @@ +--- +title: ActiveRecord::Sanitization::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + sanitize_sql(condition) + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + sanitize_sql_array(ary) + +

+ + +
+

Accepts an array of conditions. The array has each value sanitized and interpolated into the SQL statement.

+ +
sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
+# => "name='foo''bar' and group_id=4"
+
+sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
+# => "name='foo''bar' and group_id=4"
+
+sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
+# => "name='foo''bar' and group_id='4'"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 125
+def sanitize_sql_array(ary)
+  statement, *values = ary
+  if values.first.is_a?(Hash) && /:\w+/.match?(statement)
+    replace_named_bind_variables(statement, values.first)
+  elsif statement.include?("?")
+    replace_bind_variables(statement, values)
+  elsif statement.blank?
+    statement
+  else
+    statement % values.collect { |value| connection.quote_string(value.to_s) }
+  end
+end
+
+
+ +
+ +
+

+ + sanitize_sql_for_assignment(assignments, default_table_name = table_name) + +

+ + +
+

Accepts an array, hash, or string of SQL conditions and sanitizes them into a valid SQL fragment for a SET clause.

+ +
sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
+# => "name=NULL and group_id=4"
+
+sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
+# => "name=NULL and group_id=4"
+
+Post.sanitize_sql_for_assignment({ name: nil, group_id: 4 })
+# => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
+
+sanitize_sql_for_assignment("name=NULL and group_id='4'")
+# => "name=NULL and group_id='4'"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 46
+def sanitize_sql_for_assignment(assignments, default_table_name = table_name)
+  case assignments
+  when Array; sanitize_sql_array(assignments)
+  when Hash;  sanitize_sql_hash_for_assignment(assignments, default_table_name)
+  else        assignments
+  end
+end
+
+
+ +
+ +
+

+ + sanitize_sql_for_conditions(condition) + +

+ + +
+

Accepts an array or string of SQL conditions and sanitizes them into a valid SQL fragment for a WHERE clause.

+ +
sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
+# => "name='foo''bar' and group_id=4"
+
+sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
+# => "name='foo''bar' and group_id='4'"
+
+sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
+# => "name='foo''bar' and group_id='4'"
+
+sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
+# => "name='foo''bar' and group_id='4'"
+
+
+ + + +
+ Also aliased as: sanitize_sql +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 22
+def sanitize_sql_for_conditions(condition)
+  return nil if condition.blank?
+
+  case condition
+  when Array; sanitize_sql_array(condition)
+  else        condition
+  end
+end
+
+
+ +
+ +
+

+ + sanitize_sql_for_order(condition) + +

+ + +
+

Accepts an array, or string of SQL conditions and sanitizes them into a valid SQL fragment for an ORDER clause.

+ +
sanitize_sql_for_order([Arel.sql("field(id, ?)"), [1,3,2]])
+# => "field(id, 1,3,2)"
+
+sanitize_sql_for_order("id ASC")
+# => "id ASC"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 62
+def sanitize_sql_for_order(condition)
+  if condition.is_a?(Array) && condition.first.to_s.include?("?")
+    disallow_raw_sql!(
+      [condition.first],
+      permit: connection.column_name_with_order_matcher
+    )
+
+    # Ensure we aren't dealing with a subclass of String that might
+    # override methods we use (e.g. Arel::Nodes::SqlLiteral).
+    if condition.first.kind_of?(String) && !condition.first.instance_of?(String)
+      condition = [String.new(condition.first), *condition[1..-1]]
+    end
+
+    Arel.sql(sanitize_sql_array(condition))
+  else
+    condition
+  end
+end
+
+
+ +
+ +
+

+ + sanitize_sql_hash_for_assignment(attrs, table) + +

+ + +
+

Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.

+ +
sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
+# => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 85
+def sanitize_sql_hash_for_assignment(attrs, table)
+  c = connection
+  attrs.map do |attr, value|
+    type = type_for_attribute(attr)
+    value = type.serialize(type.cast(value))
+    "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
+  end.join(", ")
+end
+
+
+ +
+ +
+

+ + sanitize_sql_like(string, escape_character = "\\") + +

+ + +
+

Sanitizes a string so that it is safe to use within an SQL LIKE statement. This method uses escape_character to escape all occurrences of itself, “_” and “%”.

+ +
sanitize_sql_like("100% true!")
+# => "100\\% true!"
+
+sanitize_sql_like("snake_cased_string")
+# => "snake\\_cased\\_string"
+
+sanitize_sql_like("100% true!", "!")
+# => "100!% true!!"
+
+sanitize_sql_like("snake_cased_string", "!")
+# => "snake!_cased!_string"
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/sanitization.rb, line 109
+def sanitize_sql_like(string, escape_character = "\\")
+  pattern = Regexp.union(escape_character, "%", "_")
+  string.gsub(pattern) { |x| [escape_character, x].join }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Schema.html b/src/7.0/classes/ActiveRecord/Schema.html new file mode 100644 index 0000000000..ccd1b5cceb --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Schema.html @@ -0,0 +1,167 @@ +--- +title: ActiveRecord::Schema +layout: default +--- +
+ +
+
+ +
+ +

Active Record Schema

+ +

Allows programmers to programmatically define a schema in a portable DSL. This means you can define tables, indexes, etc. without using SQL directly, so your applications can more easily support multiple databases.

+ +

Usage:

+ +
ActiveRecord::Schema[7.0].define do
+  create_table :authors do |t|
+    t.string :name, null: false
+  end
+
+  add_index :authors, :name, :unique
+
+  create_table :posts do |t|
+    t.integer :author_id, null: false
+    t.string :subject
+    t.text :body
+    t.boolean :private, default: false
+  end
+
+  add_index :posts, :author_id
+end
+
+ +

ActiveRecord::Schema is only supported by database adapters that also support migrations, the two features being very similar.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+
    + +
  • + [] +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + [](version) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/schema.rb, line 69
+def self.[](version)
+  @class_for_version ||= {}
+  @class_for_version[version] ||= Class.new(Migration::Compatibility.find(version)) do
+    include Definition
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Schema/Definition.html b/src/7.0/classes/ActiveRecord/Schema/Definition.html new file mode 100644 index 0000000000..4c90ebbabd --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Schema/Definition.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::Schema::Definition +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Schema/Definition/ClassMethods.html b/src/7.0/classes/ActiveRecord/Schema/Definition/ClassMethods.html new file mode 100644 index 0000000000..0d60adb8f2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Schema/Definition/ClassMethods.html @@ -0,0 +1,108 @@ +--- +title: ActiveRecord::Schema::Definition::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + define(info = {}, &block) + +

+ + +
+

Eval the given block. All methods available to the current connection adapter are available within the block, so you can easily use the database definition DSL to build up your schema ( create_table, add_index, etc.).

+ +

The info hash is optional, and if given is used to define metadata about the current schema (currently, only the schema’s version):

+ +
ActiveRecord::Schema[7.0].define(version: 2038_01_19_000001) do
+  ...
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/schema.rb, line 49
+def define(info = {}, &block)
+  new.define(info, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Scoping.html b/src/7.0/classes/ActiveRecord/Scoping.html new file mode 100644 index 0000000000..dc31939691 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Scoping.html @@ -0,0 +1,101 @@ +--- +title: ActiveRecord::Scoping +layout: default +--- +
+ +
+
+ +
+ +

Active Record Named Scopes

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Scoping/Default.html b/src/7.0/classes/ActiveRecord/Scoping/Default.html new file mode 100644 index 0000000000..121d1e5c49 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Scoping/Default.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::Scoping::Default +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Scoping/Default/ClassMethods.html b/src/7.0/classes/ActiveRecord/Scoping/Default/ClassMethods.html new file mode 100644 index 0000000000..1ec6d8681d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Scoping/Default/ClassMethods.html @@ -0,0 +1,265 @@ +--- +title: ActiveRecord::Scoping::Default::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + default_scopes?(all_queries: false) + +

+ + +
+

Checks if the model has any default scopes. If all_queries is set to true, the method will check if there are any default_scopes for the model where all_queries is true.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/default.rb, line 54
+def default_scopes?(all_queries: false)
+  if all_queries
+    self.default_scopes.any?(&:all_queries)
+  else
+    self.default_scopes.any?
+  end
+end
+
+
+ +
+ +
+

+ + unscoped(&block) + +

+ + +
+

Returns a scope for the model without the previously set scopes.

+ +
class Post < ActiveRecord::Base
+  def self.default_scope
+    where(published: true)
+  end
+end
+
+Post.all                                  # Fires "SELECT * FROM posts WHERE published = true"
+Post.unscoped.all                         # Fires "SELECT * FROM posts"
+Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts"
+
+ +

This method also accepts a block. All queries inside the block will not use the previously set scopes.

+ +
Post.unscoped {
+  Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
+}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/default.rb, line 42
+def unscoped(&block)
+  block_given? ? relation.scoping(&block) : relation
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + default_scope(scope = nil, all_queries: nil, &block) + +

+ + +
+

Use this macro in your model to set a default scope for all operations on the model.

+ +
class Article < ActiveRecord::Base
+  default_scope { where(published: true) }
+end
+
+Article.all # => SELECT * FROM articles WHERE published = true
+
+ +

The default_scope is also applied while creating/building a record. It is not applied while updating or deleting a record.

+ +
Article.new.published    # => true
+Article.create.published # => true
+
+ +

To apply a default_scope when updating or deleting a record, add all_queries: true:

+ +
class Article < ActiveRecord::Base
+  default_scope -> { where(blog_id: 1) }, all_queries: true
+end
+
+ +

Applying a default scope to all queries will ensure that records are always queried by the additional conditions. Note that only where clauses apply, as it does not make sense to add order to queries that return a single object by primary key.

+ +
Article.find(1).destroy
+=> DELETE ... FROM `articles` where ID = 1 AND blog_id = 1;
+
+ +

(You can also pass any object which responds to call to the default_scope macro, and it will be called when building the default scope.)

+ +

If you use multiple default_scope declarations in your model then they will be merged together:

+ +
class Article < ActiveRecord::Base
+  default_scope { where(published: true) }
+  default_scope { where(rating: 'G') }
+end
+
+Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
+
+ +

This is also the case with inheritance and module includes where the parent or module defines a default_scope and the child or including class defines a second one.

+ +

If you need to do more complex things with a default scope, you can alternatively define it as a class method:

+ +
class Article < ActiveRecord::Base
+  def self.default_scope
+    # Should return a scope, you can call 'super' here etc.
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/default.rb, line 119
+def default_scope(scope = nil, all_queries: nil, &block) # :doc:
+  scope = block if block_given?
+
+  if scope.is_a?(Relation) || !scope.respond_to?(:call)
+    raise ArgumentError,
+      "Support for calling #default_scope without a block is removed. For example instead " \
+      "of `default_scope where(color: 'red')`, please use " \
+      "`default_scope { where(color: 'red') }`. (Alternatively you can just redefine " \
+      "self.default_scope.)"
+  end
+
+  default_scope = DefaultScope.new(scope, all_queries)
+
+  self.default_scopes += [default_scope]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Scoping/Named.html b/src/7.0/classes/ActiveRecord/Scoping/Named.html new file mode 100644 index 0000000000..9380a9aed1 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Scoping/Named.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::Scoping::Named +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Scoping/Named/ClassMethods.html b/src/7.0/classes/ActiveRecord/Scoping/Named/ClassMethods.html new file mode 100644 index 0000000000..af4a7bf930 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Scoping/Named/ClassMethods.html @@ -0,0 +1,308 @@ +--- +title: ActiveRecord::Scoping::Named::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + all() + +

+ + +
+

Returns an ActiveRecord::Relation scope object.

+ +
posts = Post.all
+posts.size # Fires "select count(*) from  posts" and returns the count
+posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
+
+fruits = Fruit.all
+fruits = fruits.where(color: 'red') if options[:red_only]
+fruits = fruits.limit(10) if limited?
+
+ +

You can define a scope that applies to all finders using default_scope.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/named.rb, line 22
+def all
+  scope = current_scope
+
+  if scope
+    if self == scope.klass
+      scope.clone
+    else
+      relation.merge!(scope)
+    end
+  else
+    default_scoped
+  end
+end
+
+
+ +
+ +
+

+ + default_scoped(scope = relation, all_queries: nil) + +

+ + +
+

Returns a scope for the model with default scopes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/named.rb, line 45
+def default_scoped(scope = relation, all_queries: nil)
+  build_default_scope(scope, all_queries: all_queries) || scope
+end
+
+
+ +
+ +
+

+ + scope(name, body, &block) + +

+ + +
+

Adds a class method for retrieving and querying objects. The method is intended to return an ActiveRecord::Relation object, which is composable with other scopes. If it returns nil or false, an all scope is returned instead.

+ +

A scope represents a narrowing of a database query, such as where(color: :red).select('shirts.*').includes(:washing_instructions).

+ +
class Shirt < ActiveRecord::Base
+  scope :red, -> { where(color: 'red') }
+  scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
+end
+
+ +

The above calls to scope define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red, in effect, represents the query Shirt.where(color: 'red').

+ +

Note that this is simply ‘syntactic sugar’ for defining an actual class method:

+ +
class Shirt < ActiveRecord::Base
+  def self.red
+    where(color: 'red')
+  end
+end
+
+ +

Unlike Shirt.find(...), however, the object returned by Shirt.red is not an Array but an ActiveRecord::Relation, which is composable with other scopes; it resembles the association object constructed by a has_many declaration. For instance, you can invoke Shirt.red.first, Shirt.red.count, Shirt.red.where(size: 'small'). Also, just as with the association objects, named scopes act like an Array, implementing Enumerable; Shirt.red.each(&block), Shirt.red.first, and Shirt.red.inject(memo, &block) all behave as if Shirt.red really was an array.

+ +

These named scopes are composable. For instance, Shirt.red.dry_clean_only will produce all shirts that are both red and dry clean only. Nested finds and calculations also work with these compositions: Shirt.red.dry_clean_only.count returns the number of garments for which these criteria obtain. Similarly with Shirt.red.dry_clean_only.average(:thread_count).

+ +

All scopes are available as class methods on the ActiveRecord::Base descendant upon which the scopes were defined. But they are also available to has_many associations. If,

+ +
class Person < ActiveRecord::Base
+  has_many :shirts
+end
+
+ +

then elton.shirts.red.dry_clean_only will return all of Elton’s red, dry clean only shirts.

+ +

Named scopes can also have extensions, just as with has_many declarations:

+ +
class Shirt < ActiveRecord::Base
+  scope :red, -> { where(color: 'red') } do
+    def dom_id
+      'red_shirts'
+    end
+  end
+end
+
+ +

Scopes can also be used while creating/building a record.

+ +
class Article < ActiveRecord::Base
+  scope :published, -> { where(published: true) }
+end
+
+Article.published.new.published    # => true
+Article.published.create.published # => true
+
+ +

Class methods on your model are automatically available on scopes. Assuming the following setup:

+ +
class Article < ActiveRecord::Base
+  scope :published, -> { where(published: true) }
+  scope :featured, -> { where(featured: true) }
+
+  def self.latest_article
+    order('published_at desc').first
+  end
+
+  def self.titles
+    pluck(:title)
+  end
+end
+
+ +

We are able to call the methods like this:

+ +
Article.published.featured.latest_article
+Article.featured.titles
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/scoping/named.rb, line 154
+def scope(name, body, &block)
+  unless body.respond_to?(:call)
+    raise ArgumentError, "The scope body needs to be callable."
+  end
+
+  if dangerous_class_method?(name)
+    raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
+      "on the model \"#{self.name}\", but Active Record already defined " \
+      "a class method with the same name."
+  end
+
+  if method_defined_within?(name, Relation)
+    raise ArgumentError, "You tried to define a scope named \"#{name}\" " \
+      "on the model \"#{self.name}\", but ActiveRecord::Relation already defined " \
+      "an instance method with the same name."
+  end
+
+  extension = Module.new(&block) if block
+
+  if body.respond_to?(:to_proc)
+    singleton_class.define_method(name) do |*args|
+      scope = all._exec_scope(*args, &body)
+      scope = scope.extending(extension) if extension
+      scope
+    end
+  else
+    singleton_class.define_method(name) do |*args|
+      scope = body.call(*args) || all
+      scope = scope.extending(extension) if extension
+      scope
+    end
+  end
+  singleton_class.send(:ruby2_keywords, name)
+
+  generate_relation_method(name)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SecureToken.html b/src/7.0/classes/ActiveRecord/SecureToken.html new file mode 100644 index 0000000000..2da9215c0c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SecureToken.html @@ -0,0 +1,92 @@ +--- +title: ActiveRecord::SecureToken +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MINIMUM_TOKEN_LENGTH=24
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SecureToken/ClassMethods.html b/src/7.0/classes/ActiveRecord/SecureToken/ClassMethods.html new file mode 100644 index 0000000000..ffe902bbea --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SecureToken/ClassMethods.html @@ -0,0 +1,165 @@ +--- +title: ActiveRecord::SecureToken::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/secure_token.rb, line 43
+def generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
+  SecureRandom.base58(length)
+end
+
+
+ +
+ +
+

+ + has_secure_token(attribute = :token, length: MINIMUM_TOKEN_LENGTH) + +

+ + +
+

Example using has_secure_token

+ +
# Schema: User(token:string, auth_token:string)
+class User < ActiveRecord::Base
+  has_secure_token
+  has_secure_token :auth_token, length: 36
+end
+
+user = User.new
+user.save
+user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
+user.auth_token # => "tU9bLuZseefXQ4yQxQo8wjtBvsAfPc78os6R"
+user.regenerate_token # => true
+user.regenerate_auth_token # => true
+
+ +

SecureRandom::base58 is used to generate at minimum a 24-character unique token, so collisions are highly unlikely.

+ +

Note that it’s still possible to generate a race condition in the database in the same way that validates_uniqueness_of can. You’re encouraged to add a unique index in the database to deal with this even more unlikely scenario.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/secure_token.rb, line 32
+def has_secure_token(attribute = :token, length: MINIMUM_TOKEN_LENGTH)
+  if length < MINIMUM_TOKEN_LENGTH
+    raise MinimumLengthError, "Token requires a minimum length of #{MINIMUM_TOKEN_LENGTH} characters."
+  end
+
+  # Load securerandom only when has_secure_token is used.
+  require "active_support/core_ext/securerandom"
+  define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token(length: length) }
+  before_create { send("#{attribute}=", self.class.generate_unique_secure_token(length: length)) unless send("#{attribute}?") }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SecureToken/MinimumLengthError.html b/src/7.0/classes/ActiveRecord/SecureToken/MinimumLengthError.html new file mode 100644 index 0000000000..92a3cdaca8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SecureToken/MinimumLengthError.html @@ -0,0 +1,60 @@ +--- +title: ActiveRecord::SecureToken::MinimumLengthError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Serialization.html b/src/7.0/classes/ActiveRecord/Serialization.html new file mode 100644 index 0000000000..afad4cd1d7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Serialization.html @@ -0,0 +1,128 @@ +--- +title: ActiveRecord::Serialization +layout: default +--- +
+ +
+
+ +
+ +

Active Record Serialization

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + serializable_hash(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/serialization.rb, line 13
+def serializable_hash(options = nil)
+  if self.class._has_attribute?(self.class.inheritance_column)
+    options = options ? options.dup : {}
+
+    options[:except] = Array(options[:except]).map(&:to_s)
+    options[:except] |= Array(self.class.inheritance_column)
+  end
+
+  super(options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SerializationFailure.html b/src/7.0/classes/ActiveRecord/SerializationFailure.html new file mode 100644 index 0000000000..83f2f305ad --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SerializationFailure.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::SerializationFailure +layout: default +--- +
+ +
+
+ +
+ +

SerializationFailure will be raised when a transaction is rolled back by the database due to a serialization failure.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SerializationTypeMismatch.html b/src/7.0/classes/ActiveRecord/SerializationTypeMismatch.html new file mode 100644 index 0000000000..10d5344354 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SerializationTypeMismatch.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::SerializationTypeMismatch +layout: default +--- +
+ +
+
+ +
+ +

Raised when unserialized object’s type mismatches one specified for serializable field.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SignedId.html b/src/7.0/classes/ActiveRecord/SignedId.html new file mode 100644 index 0000000000..a83a94997d --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SignedId.html @@ -0,0 +1,168 @@ +--- +title: ActiveRecord::SignedId +layout: default +--- +
+ +
+
+ +
+ +

Active Record Signed Id

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + signed_id_verifier_secret + +

+ + +
+

Set the secret used for the signed id verifier instance when using Active Record outside of Rails. Within Rails, this is automatically set using the Rails application key generator.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 13
+class_attribute :signed_id_verifier_secret, instance_writer: false
+
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + signed_id(expires_in: nil, purpose: nil) + +

+ + +
+

Returns a signed id that’s generated using a preconfigured ActiveSupport::MessageVerifier instance. This signed id is tamper proof, so it’s safe to send in an email or otherwise share with the outside world. It can furthermore be set to expire (the default is not to expire), and scoped down with a specific purpose. If the expiration date has been exceeded before find_signed is called, the id won’t find the designated record. If a purpose is set, this too must match.

+ +

If you accidentally let a signed id out in the wild that you wish to retract sooner than its expiration date (or maybe you forgot to set an expiration date while meaning to!), you can use the purpose to essentially version the signed_id, like so:

+ +
user.signed_id purpose: :v2
+
+ +

And you then change your find_signed calls to require this new purpose. Any old signed ids that were not created with the purpose will no longer find the record.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 112
+def signed_id(expires_in: nil, purpose: nil)
+  self.class.signed_id_verifier.generate id, expires_in: expires_in, purpose: self.class.combine_signed_id_purposes(purpose)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SignedId/ClassMethods.html b/src/7.0/classes/ActiveRecord/SignedId/ClassMethods.html new file mode 100644 index 0000000000..bdb22f39e5 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SignedId/ClassMethods.html @@ -0,0 +1,259 @@ +--- +title: ActiveRecord::SignedId::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + find_signed(signed_id, purpose: nil) + +

+ + +
+

Lets you find a record based on a signed id that’s safe to put into the world without risk of tampering. This is particularly useful for things like password reset or email verification, where you want the bearer of the signed id to be able to interact with the underlying record, but usually only within a certain time period.

+ +

You set the time period that the signed id is valid for during generation, using the instance method signed_id(expires_in: 15.minutes). If the time has elapsed before a signed find is attempted, the signed id will no longer be valid, and nil is returned.

+ +

It’s possible to further restrict the use of a signed id with a purpose. This helps when you have a general base model, like a User, which might have signed ids for several things, like password reset or email verification. The purpose that was set during generation must match the purpose set when finding. If there’s a mismatch, nil is again returned.

+ +

Examples

+ +
signed_id = User.first.signed_id expires_in: 15.minutes, purpose: :password_reset
+
+User.find_signed signed_id # => nil, since the purpose does not match
+
+travel 16.minutes
+User.find_signed signed_id, purpose: :password_reset # => nil, since the signed id has expired
+
+travel_back
+User.find_signed signed_id, purpose: :password_reset # => User.first
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 42
+def find_signed(signed_id, purpose: nil)
+  raise UnknownPrimaryKey.new(self) if primary_key.nil?
+
+  if id = signed_id_verifier.verified(signed_id, purpose: combine_signed_id_purposes(purpose))
+    find_by primary_key => id
+  end
+end
+
+
+ +
+ +
+

+ + find_signed!(signed_id, purpose: nil) + +

+ + +
+

Works like find_signed, but will raise an ActiveSupport::MessageVerifier::InvalidSignature exception if the signed_id has either expired, has a purpose mismatch, is for another record, or has been tampered with. It will also raise an ActiveRecord::RecordNotFound exception if the valid signed id can’t find a record.

+ +

Examples

+ +
User.find_signed! "bad data" # => ActiveSupport::MessageVerifier::InvalidSignature
+
+signed_id = User.first.signed_id
+User.first.destroy
+User.find_signed! signed_id # => ActiveRecord::RecordNotFound
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 62
+def find_signed!(signed_id, purpose: nil)
+  if id = signed_id_verifier.verify(signed_id, purpose: combine_signed_id_purposes(purpose))
+    find(id)
+  end
+end
+
+
+ +
+ +
+

+ + signed_id_verifier() + +

+ + +
+

The verifier instance that all signed ids are generated and verified from. By default, it’ll be initialized with the class-level signed_id_verifier_secret, which within Rails comes from the Rails.application.key_generator. By default, it’s SHA256 for the digest and JSON for the serialization.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 71
+def signed_id_verifier
+  @signed_id_verifier ||= begin
+    secret = signed_id_verifier_secret
+    secret = secret.call if secret.respond_to?(:call)
+
+    if secret.nil?
+      raise ArgumentError, "You must set ActiveRecord::Base.signed_id_verifier_secret to use signed ids"
+    else
+      ActiveSupport::MessageVerifier.new secret, digest: "SHA256", serializer: JSON
+    end
+  end
+end
+
+
+ +
+ +
+

+ + signed_id_verifier=(verifier) + +

+ + +
+

Allows you to pass in a custom verifier used for the signed ids. This also allows you to use different verifiers for different classes. This is also helpful if you need to rotate keys, as you can prepare your custom verifier for that in advance. See ActiveSupport::MessageVerifier for details.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/signed_id.rb, line 87
+def signed_id_verifier=(verifier)
+  @signed_id_verifier = verifier
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SoleRecordExceeded.html b/src/7.0/classes/ActiveRecord/SoleRecordExceeded.html new file mode 100644 index 0000000000..4315130bfc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SoleRecordExceeded.html @@ -0,0 +1,128 @@ +--- +title: ActiveRecord::SoleRecordExceeded +layout: default +--- +
+ +
+
+ +
+ +

Raised when Active Record finds multiple records but only expected one.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(record = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 149
+def initialize(record = nil)
+  @record = record
+  super "Wanted only one #{record&.name || "record"}"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SpawnMethods.html b/src/7.0/classes/ActiveRecord/SpawnMethods.html new file mode 100644 index 0000000000..b27eb89966 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SpawnMethods.html @@ -0,0 +1,210 @@ +--- +title: ActiveRecord::SpawnMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + except(*skips) + +

+ + +
+

Removes from the query the condition(s) specified in skips.

+ +
Post.order('id asc').except(:order)                  # discards the order condition
+Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/spawn_methods.rb, line 58
+def except(*skips)
+  relation_with values.except(*skips)
+end
+
+
+ +
+ +
+

+ + merge(other, *rest) + +

+ + +
+

Merges in the conditions from other, if other is an ActiveRecord::Relation. Returns an array representing the intersection of the resulting records with other, if other is an array.

+ +
Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
+# Performs a single join query with both where conditions.
+
+recent_posts = Post.order('created_at DESC').first(5)
+Post.where(published: true).merge(recent_posts)
+# Returns the intersection of all published posts with the 5 most recently created posts.
+# (This is just an example. You'd probably want to do this with a single query!)
+
+ +

Procs will be evaluated by merge:

+ +
Post.where(published: true).merge(-> { joins(:comments) })
+# => Post.where(published: true).joins(:comments)
+
+ +

This is mainly intended for sharing common conditions between multiple associations.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/spawn_methods.rb, line 31
+def merge(other, *rest)
+  if other.is_a?(Array)
+    records & other
+  elsif other
+    spawn.merge!(other, *rest)
+  else
+    raise ArgumentError, "invalid argument: #{other.inspect}."
+  end
+end
+
+
+ +
+ +
+

+ + only(*onlies) + +

+ + +
+

Removes any condition from the query other than the one(s) specified in onlies.

+ +
Post.order('id asc').only(:where)         # discards the order condition
+Post.order('id asc').only(:where, :order) # uses the specified order
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/relation/spawn_methods.rb, line 66
+def only(*onlies)
+  relation_with values.slice(*onlies)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StaleObjectError.html b/src/7.0/classes/ActiveRecord/StaleObjectError.html new file mode 100644 index 0000000000..6e2310e37a --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StaleObjectError.html @@ -0,0 +1,143 @@ +--- +title: ActiveRecord::StaleObjectError +layout: default +--- +
+ +
+
+ +
+ +

Raised on attempt to save stale record. Record is stale when it’s being saved in another query after instantiation, for example, when two users edit the same wiki page and one starts editing and saves the page before the other.

+ +

Read more about optimistic locking in ActiveRecord::Locking module documentation.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + attempted_action
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(record = nil, attempted_action = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 283
+def initialize(record = nil, attempted_action = nil)
+  if record && attempted_action
+    @record = record
+    @attempted_action = attempted_action
+    super("Attempted to #{attempted_action} a stale object: #{record.class.name}.")
+  else
+    super("Stale object error.")
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StatementCache.html b/src/7.0/classes/ActiveRecord/StatementCache.html new file mode 100644 index 0000000000..a340955ea1 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StatementCache.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::StatementCache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StatementCache/PartialQueryCollector.html b/src/7.0/classes/ActiveRecord/StatementCache/PartialQueryCollector.html new file mode 100644 index 0000000000..ac888ec705 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StatementCache/PartialQueryCollector.html @@ -0,0 +1,289 @@ +--- +title: ActiveRecord::StatementCache::PartialQueryCollector +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + preparable
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/statement_cache.rb, line 67
+def initialize
+  @parts = []
+  @binds = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(str) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/statement_cache.rb, line 72
+def <<(str)
+  @parts << str
+  self
+end
+
+
+ +
+ +
+

+ + add_bind(obj) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/statement_cache.rb, line 77
+def add_bind(obj)
+  @binds << obj
+  @parts << Substitute.new
+  self
+end
+
+
+ +
+ +
+

+ + add_binds(binds, proc_for_binds = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/statement_cache.rb, line 83
+def add_binds(binds, proc_for_binds = nil)
+  @binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
+  binds.size.times do |i|
+    @parts << ", " unless i == 0
+    @parts << Substitute.new
+  end
+  self
+end
+
+
+ +
+ +
+

+ + value() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/statement_cache.rb, line 92
+def value
+  [@parts, @binds]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StatementInvalid.html b/src/7.0/classes/ActiveRecord/StatementInvalid.html new file mode 100644 index 0000000000..e057bad415 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StatementInvalid.html @@ -0,0 +1,139 @@ +--- +title: ActiveRecord::StatementInvalid +layout: default +--- +
+ +
+
+ +
+ +

Superclass for all database execution errors.

+ +

Wraps the underlying database error as cause.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + binds
+ [R] + sql
+ + + + +

Class Public methods

+ +
+

+ + new(message = nil, sql: nil, binds: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 159
+def initialize(message = nil, sql: nil, binds: nil)
+  super(message || $!&.message)
+  @sql = sql
+  @binds = binds
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StatementTimeout.html b/src/7.0/classes/ActiveRecord/StatementTimeout.html new file mode 100644 index 0000000000..dd253bfddc --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StatementTimeout.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::StatementTimeout +layout: default +--- +
+ +
+
+ +
+ +

StatementTimeout will be raised when statement timeout exceeded.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Store.html b/src/7.0/classes/ActiveRecord/Store.html new file mode 100644 index 0000000000..6ea10a2211 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Store.html @@ -0,0 +1,252 @@ +--- +title: ActiveRecord::Store +layout: default +--- +
+ +
+
+ +
+ +

Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column. It’s like a simple key/value store baked into your record when you don’t care about being able to query that store outside the context of a single record.

+ +

You can then declare accessors to this store that are then accessible just like any other attribute of the model. This is very helpful for easily exposing store keys to a form or elsewhere that’s already built around just accessing attributes on the model.

+ +

Every accessor comes with dirty tracking methods (key_changed?, key_was and key_change) and methods to access the changes made during the last save (saved_change_to_key?, saved_change_to_key and key_before_last_save).

+ +

NOTE: There is no key_will_change! method for accessors, use store_will_change! instead.

+ +

Make sure that you declare the database column used for the serialized store as a text, so there’s plenty of room.

+ +

You can set custom coder to encode/decode your serialized attributes to/from different formats. JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides load and dump.

+ +

NOTE: If you are using structured database data types (e.g. PostgreSQL hstore/json, or MySQL 5.7+ json) there is no need for the serialization provided by .store. Simply use .store_accessor instead to generate the accessor methods. Be aware that these columns use a string keyed hash and do not allow access using a symbol.

+ +

NOTE: The default validations with the exception of uniqueness will work. For example, if you want to check for uniqueness with hstore you will need to use a custom validation to handle it.

+ +

Examples:

+ +
class User < ActiveRecord::Base
+  store :settings, accessors: [ :color, :homepage ], coder: JSON
+  store :parent, accessors: [ :name ], coder: JSON, prefix: true
+  store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
+  store :settings, accessors: [ :two_factor_auth ], suffix: true
+  store :settings, accessors: [ :login_retry ], suffix: :config
+end
+
+u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
+u.color                          # Accessor stored attribute
+u.parent_name                    # Accessor stored attribute with prefix
+u.partner_name                   # Accessor stored attribute with custom prefix
+u.two_factor_auth_settings       # Accessor stored attribute with suffix
+u.login_retry_config             # Accessor stored attribute with custom suffix
+u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
+
+# There is no difference between strings and symbols for accessing custom attributes
+u.settings[:country]  # => 'Denmark'
+u.settings['country'] # => 'Denmark'
+
+# Dirty tracking
+u.color = 'green'
+u.color_changed? # => true
+u.color_was # => 'black'
+u.color_change # => ['black', 'green']
+
+# Add additional accessors to an existing store through store_accessor
+class SuperUser < User
+  store_accessor :settings, :privileges, :servants
+  store_accessor :parent, :birthday, prefix: true
+  store_accessor :settings, :secret_question, suffix: :config
+end
+
+ +

The stored attribute names can be retrieved using .stored_attributes.

+ +
User.stored_attributes[:settings] # => [:color, :homepage, :two_factor_auth, :login_retry]
+
+ +

Overwriting default accessors

+ +

All stored values are automatically available through accessors on the Active Record object, but sometimes you want to specialize this behavior. This can be done by overwriting the default accessors (using the same name as the attribute) and calling super to actually change things.

+ +
class Song < ActiveRecord::Base
+  # Uses a stored integer to hold the volume adjustment of the song
+  store :settings, accessors: [:volume_adjustment]
+
+  def volume_adjustment=(decibels)
+    super(decibels.to_i)
+  end
+
+  def volume_adjustment
+    super.to_i
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + local_stored_attributes
+ + + + + +

Instance Private methods

+ +
+

+ + read_store_attribute(store_attribute, key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/store.rb, line 206
+def read_store_attribute(store_attribute, key) # :doc:
+  accessor = store_accessor_for(store_attribute)
+  accessor.read(self, store_attribute, key)
+end
+
+
+ +
+ +
+

+ + write_store_attribute(store_attribute, key, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/store.rb, line 211
+def write_store_attribute(store_attribute, key, value) # :doc:
+  accessor = store_accessor_for(store_attribute)
+  accessor.write(self, store_attribute, key, value)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Store/ClassMethods.html b/src/7.0/classes/ActiveRecord/Store/ClassMethods.html new file mode 100644 index 0000000000..845d34ae81 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Store/ClassMethods.html @@ -0,0 +1,259 @@ +--- +title: ActiveRecord::Store::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + store(store_attribute, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/store.rb, line 104
+def store(store_attribute, options = {})
+  serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
+  store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
+end
+
+
+ +
+ +
+

+ + store_accessor(store_attribute, *keys, prefix: nil, suffix: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/store.rb, line 109
+def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
+  keys = keys.flatten
+
+  accessor_prefix =
+    case prefix
+    when String, Symbol
+      "#{prefix}_"
+    when TrueClass
+      "#{store_attribute}_"
+    else
+      ""
+    end
+  accessor_suffix =
+    case suffix
+    when String, Symbol
+      "_#{suffix}"
+    when TrueClass
+      "_#{store_attribute}"
+    else
+      ""
+    end
+
+  _store_accessors_module.module_eval do
+    keys.each do |key|
+      accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
+
+      define_method("#{accessor_key}=") do |value|
+        write_store_attribute(store_attribute, key, value)
+      end
+
+      define_method(accessor_key) do
+        read_store_attribute(store_attribute, key)
+      end
+
+      define_method("#{accessor_key}_changed?") do
+        return false unless attribute_changed?(store_attribute)
+        prev_store, new_store = changes[store_attribute]
+        prev_store&.dig(key) != new_store&.dig(key)
+      end
+
+      define_method("#{accessor_key}_change") do
+        return unless attribute_changed?(store_attribute)
+        prev_store, new_store = changes[store_attribute]
+        [prev_store&.dig(key), new_store&.dig(key)]
+      end
+
+      define_method("#{accessor_key}_was") do
+        return unless attribute_changed?(store_attribute)
+        prev_store, _new_store = changes[store_attribute]
+        prev_store&.dig(key)
+      end
+
+      define_method("saved_change_to_#{accessor_key}?") do
+        return false unless saved_change_to_attribute?(store_attribute)
+        prev_store, new_store = saved_change_to_attribute(store_attribute)
+        prev_store&.dig(key) != new_store&.dig(key)
+      end
+
+      define_method("saved_change_to_#{accessor_key}") do
+        return unless saved_change_to_attribute?(store_attribute)
+        prev_store, new_store = saved_change_to_attribute(store_attribute)
+        [prev_store&.dig(key), new_store&.dig(key)]
+      end
+
+      define_method("#{accessor_key}_before_last_save") do
+        return unless saved_change_to_attribute?(store_attribute)
+        prev_store, _new_store = saved_change_to_attribute(store_attribute)
+        prev_store&.dig(key)
+      end
+    end
+  end
+
+  # assign new store attribute and create new hash to ensure that each class in the hierarchy
+  # has its own hash of stored attributes.
+  self.local_stored_attributes ||= {}
+  self.local_stored_attributes[store_attribute] ||= []
+  self.local_stored_attributes[store_attribute] |= keys
+end
+
+
+ +
+ +
+

+ + stored_attributes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/store.rb, line 196
+def stored_attributes
+  parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
+  if local_stored_attributes
+    parent.merge!(local_stored_attributes) { |k, a, b| a | b }
+  end
+  parent
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/StrictLoadingViolationError.html b/src/7.0/classes/ActiveRecord/StrictLoadingViolationError.html new file mode 100644 index 0000000000..ff5981aa54 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/StrictLoadingViolationError.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::StrictLoadingViolationError +layout: default +--- +
+ +
+
+ +
+ +

Raised on attempt to lazily load records that are marked as strict loading.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/SubclassNotFound.html b/src/7.0/classes/ActiveRecord/SubclassNotFound.html new file mode 100644 index 0000000000..9fc1a3b18c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/SubclassNotFound.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::SubclassNotFound +layout: default +--- +
+ +
+
+ +
+ +

Raised when the single-table inheritance mechanism fails to locate the subclass (for example due to improper usage of column that ActiveRecord::Base.inheritance_column points to).

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Suppressor.html b/src/7.0/classes/ActiveRecord/Suppressor.html new file mode 100644 index 0000000000..c2c373a817 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Suppressor.html @@ -0,0 +1,94 @@ +--- +title: ActiveRecord::Suppressor +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::Suppressor prevents the receiver from being saved during a given block.

+ +

For example, here’s a pattern of creating notifications when new comments are posted. (The notification may in turn trigger an email, a push notification, or just appear in the UI somewhere):

+ +
class Comment < ActiveRecord::Base
+  belongs_to :commentable, polymorphic: true
+  after_create -> { Notification.create! comment: self,
+    recipients: commentable.recipients }
+end
+
+ +

That’s what you want the bulk of the time. New comment creates a new Notification. But there may well be off cases, like copying a commentable and its comments, where you don’t want that. So you’d have a concern something like this:

+ +
module Copyable
+  def copy_to(destination)
+    Notification.suppress do
+      # Copy logic that creates new comments that we do not want
+      # triggering notifications.
+    end
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Suppressor/ClassMethods.html b/src/7.0/classes/ActiveRecord/Suppressor/ClassMethods.html new file mode 100644 index 0000000000..c9728c4ca0 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Suppressor/ClassMethods.html @@ -0,0 +1,105 @@ +--- +title: ActiveRecord::Suppressor::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + suppress(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/suppressor.rb, line 40
+def suppress(&block)
+  previous_state = Suppressor.registry[name]
+  Suppressor.registry[name] = true
+  yield
+ensure
+  Suppressor.registry[name] = previous_state
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/TableNotSpecified.html b/src/7.0/classes/ActiveRecord/TableNotSpecified.html new file mode 100644 index 0000000000..ec0d8a610c --- /dev/null +++ b/src/7.0/classes/ActiveRecord/TableNotSpecified.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::TableNotSpecified +layout: default +--- +
+ +
+
+ +
+ +

Raised when a model makes a query but it has not specified an associated table.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Tasks.html b/src/7.0/classes/ActiveRecord/Tasks.html new file mode 100644 index 0000000000..232e6ffb48 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Tasks.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::Tasks +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Tasks/DatabaseTasks.html b/src/7.0/classes/ActiveRecord/Tasks/DatabaseTasks.html new file mode 100644 index 0000000000..72c60ad7b7 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Tasks/DatabaseTasks.html @@ -0,0 +1,2094 @@ +--- +title: ActiveRecord::Tasks::DatabaseTasks +layout: default +--- +
+ +
+
+ +
+ +

ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates logic behind common tasks used to manage database and migrations.

+ +

The tasks defined here are used with Rails commands provided by Active Record.

+ +

In order to use DatabaseTasks, a few config values need to be set. All the needed config values are set by Rails already, so it’s necessary to do it only if you want to change the defaults or when you want to use Active Record outside of Rails (in such case after configuring the database tasks, you can also use the rake tasks defined in Active Record).

+ +

The possible config values are:

+
  • +

    env: current environment (like Rails.env).

    +
  • +

    database_configuration: configuration of your databases (as in config/database.yml).

    +
  • +

    db_dir: your db directory.

    +
  • +

    fixtures_path: a path to fixtures directory.

    +
  • +

    migrations_paths: a list of paths to directories with migrations.

    +
  • +

    seed_loader: an object which will load seeds, it needs to respond to the load_seed method.

    +
  • +

    root: a path to the root of the application.

    +
+ +

Example usage of DatabaseTasks outside Rails could look as such:

+ +
include ActiveRecord::Tasks
+DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
+DatabaseTasks.db_dir = 'db'
+# other settings...
+
+DatabaseTasks.create_current('production')
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
LOCAL_HOSTS=["127.0.0.1", "localhost"]
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + database_configuration
+ [W] + db_dir
+ [W] + env
+ [W] + fixtures_path
+ [W] + migrations_paths
+ [W] + root
+ [W] + seed_loader
+ + + + +

Class Public methods

+ +
+

+ + structure_dump_flags + +

+ + +
+

Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump It can be used as a string/array (the typical case) or a hash (when you use multiple adapters) Example:

+ +
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
+  mysql2: ['--no-defaults', '--skip-add-drop-table'],
+  postgres: '--no-tablespaces'
+}
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 48
+mattr_accessor :structure_dump_flags, instance_accessor: false
+
+
+
+ +
+ +
+

+ + structure_load_flags + +

+ + +
+

Extra flags passed to database CLI tool when calling db:schema:load It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 54
+mattr_accessor :structure_load_flags, instance_accessor: false
+
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cache_dump_filename(db_config_name, schema_cache_path: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 470
+def cache_dump_filename(db_config_name, schema_cache_path: nil)
+  filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
+    "schema_cache.yml"
+  else
+    "#{db_config_name}_schema_cache.yml"
+  end
+
+  schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
+end
+
+
+ +
+ +
+

+ + charset(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 324
+def charset(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  database_adapter_for(db_config, *arguments).charset
+end
+
+
+ +
+ +
+

+ + charset_current(env_name = env, db_name = name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 319
+def charset_current(env_name = env, db_name = name)
+  db_config = configs_for(env_name: env_name, name: db_name)
+  charset(db_config)
+end
+
+
+ +
+ +
+

+ + check_protected_environments!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 63
+def check_protected_environments!
+  unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
+    current = ActiveRecord::Base.connection.migration_context.current_environment
+    stored  = ActiveRecord::Base.connection.migration_context.last_stored_environment
+
+    if ActiveRecord::Base.connection.migration_context.protected_environment?
+      raise ActiveRecord::ProtectedEnvironmentError.new(stored)
+    end
+
+    if stored && stored != current
+      raise ActiveRecord::EnvironmentMismatchError.new(current: current, stored: stored)
+    end
+  end
+rescue ActiveRecord::NoDatabaseError
+end
+
+
+ +
+ +
+

+ + check_schema_file(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 487
+def check_schema_file(filename)
+  unless File.exist?(filename)
+    message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
+    message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
+    Kernel.abort message
+  end
+end
+
+
+ +
+ +
+

+ + check_target_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 309
+def check_target_version
+  if target_version && !(Migration::MigrationFilenameRegexp.match?(ENV["VERSION"]) || /\A\d+\z/.match?(ENV["VERSION"]))
+    raise "Invalid format of target version: `VERSION=#{ENV['VERSION']}`"
+  end
+end
+
+
+ +
+ +
+

+ + clear_schema_cache(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 513
+def clear_schema_cache(filename)
+  FileUtils.rm_f filename, verbose: false
+end
+
+
+ +
+ +
+

+ + collation(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 334
+def collation(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  database_adapter_for(db_config, *arguments).collation
+end
+
+
+ +
+ +
+

+ + collation_current(env_name = env, db_name = name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 329
+def collation_current(env_name = env, db_name = name)
+  db_config = configs_for(env_name: env_name, name: db_name)
+  collation(db_config)
+end
+
+
+ +
+ +
+

+ + create(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 120
+def create(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  database_adapter_for(db_config, *arguments).create
+  $stdout.puts "Created database '#{db_config.database}'" if verbose?
+rescue DatabaseAlreadyExists
+  $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
+rescue Exception => error
+  $stderr.puts error
+  $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
+  raise
+end
+
+
+ +
+ +
+

+ + create_all() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 132
+def create_all
+  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
+  each_local_configuration { |db_config| create(db_config) }
+  if old_pool
+    ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
+  end
+end
+
+
+ +
+ +
+

+ + create_current(environment = env, name = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 183
+def create_current(environment = env, name = nil)
+  each_current_configuration(environment, name) { |db_config| create(db_config) }
+  ActiveRecord::Base.establish_connection(environment.to_sym)
+end
+
+
+ +
+ +
+

+ + db_dir() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 88
+def db_dir
+  @db_dir ||= Rails.application.config.paths["db"].first
+end
+
+
+ +
+ +
+

+ + drop(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 222
+def drop(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  database_adapter_for(db_config, *arguments).drop
+  $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
+rescue ActiveRecord::NoDatabaseError
+  $stderr.puts "Database '#{db_config.database}' does not exist"
+rescue Exception => error
+  $stderr.puts error
+  $stderr.puts "Couldn't drop database '#{db_config.database}'"
+  raise
+end
+
+
+ +
+ +
+

+ + drop_all() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 234
+def drop_all
+  each_local_configuration { |db_config| drop(db_config) }
+end
+
+
+ +
+ +
+

+ + drop_current(environment = env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 238
+def drop_current(environment = env)
+  each_current_configuration(environment) { |db_config| drop(db_config) }
+end
+
+
+ +
+ +
+

+ + dump_schema_cache(conn, filename) + +

+ + +
+

Dumps the schema cache in YAML format for the connection into the file

+ +

Examples:

+ +
ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 509
+def dump_schema_cache(conn, filename)
+  conn.schema_cache.dump_to(filename)
+end
+
+
+ +
+ +
+

+ + env() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 108
+def env
+  @env ||= Rails.env
+end
+
+
+ +
+ +
+

+ + fixtures_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 96
+def fixtures_path
+  @fixtures_path ||= if ENV["FIXTURES_PATH"]
+    File.join(root, ENV["FIXTURES_PATH"])
+  else
+    File.join(root, "test", "fixtures")
+  end
+end
+
+
+ +
+ +
+

+ + for_each(databases) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 154
+def for_each(databases)
+  return {} unless defined?(Rails)
+
+  database_configs = ActiveRecord::DatabaseConfigurations.new(databases).configs_for(env_name: Rails.env)
+
+  # if this is a single database application we don't want tasks for each primary database
+  return if database_configs.count == 1
+
+  database_configs.each do |db_config|
+    next unless db_config.database_tasks?
+
+    yield db_config.name
+  end
+end
+
+
+ +
+ +
+

+ + load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 480
+def load_schema_current(format = ActiveRecord.schema_format, file = nil, environment = env)
+  each_current_configuration(environment) do |db_config|
+    load_schema(db_config, format, file)
+  end
+  ActiveRecord::Base.establish_connection(environment.to_sym)
+end
+
+
+ +
+ +
+

+ + load_seed() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 495
+def load_seed
+  if seed_loader
+    seed_loader.load_seed
+  else
+    raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
+          "loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
+          "Seed loader should respond to load_seed method"
+  end
+end
+
+
+ +
+ +
+

+ + migrate(version = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 256
+def migrate(version = nil)
+  check_target_version
+
+  scope = ENV["SCOPE"]
+  verbose_was, Migration.verbose = Migration.verbose, verbose?
+
+  Base.connection.migration_context.migrate(target_version) do |migration|
+    if version.blank?
+      scope.blank? || scope == migration.scope
+    else
+      migration.version == version
+    end
+  end.tap do |migrations_ran|
+    Migration.write("No migrations ran. (using #{scope} scope)") if scope.present? && migrations_ran.empty?
+  end
+
+  ActiveRecord::Base.clear_cache!
+ensure
+  Migration.verbose = verbose_was
+end
+
+
+ +
+ +
+

+ + migrate_status() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 294
+def migrate_status
+  unless ActiveRecord::Base.connection.schema_migration.table_exists?
+    Kernel.abort "Schema migrations table does not exist yet."
+  end
+
+  # output
+  puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
+  puts "#{'Status'.center(8)}  #{'Migration ID'.ljust(14)}  Migration Name"
+  puts "-" * 50
+  ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
+    puts "#{status.center(8)}  #{version.ljust(14)}  #{name}"
+  end
+  puts
+end
+
+
+ +
+ +
+

+ + migrations_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 92
+def migrations_paths
+  @migrations_paths ||= Rails.application.paths["db/migrate"].to_a
+end
+
+
+ +
+ +
+

+ + name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 112
+def name
+  @name ||= "primary"
+end
+
+
+ +
+ +
+

+ + prepare_all() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 188
+def prepare_all
+  seed = false
+
+  each_current_configuration(env) do |db_config|
+    ActiveRecord::Base.establish_connection(db_config)
+
+    begin
+      # Skipped when no database
+      migrate
+
+      if ActiveRecord.dump_schema_after_migration
+        dump_schema(db_config, ActiveRecord.schema_format)
+      end
+    rescue ActiveRecord::NoDatabaseError
+      create(db_config)
+
+      if File.exist?(schema_dump_path(db_config))
+        load_schema(
+          db_config,
+          ActiveRecord.schema_format,
+          nil
+        )
+      else
+        migrate
+      end
+
+      seed = true
+    end
+  end
+
+  ActiveRecord::Base.establish_connection
+  load_seed if seed
+end
+
+
+ +
+ +
+

+ + purge(configuration) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 339
+def purge(configuration)
+  db_config = resolve_configuration(configuration)
+  database_adapter_for(db_config).purge
+end
+
+
+ +
+ +
+

+ + purge_all() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 344
+def purge_all
+  each_local_configuration { |db_config| purge(db_config) }
+end
+
+
+ +
+ +
+

+ + purge_current(environment = env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 348
+def purge_current(environment = env)
+  each_current_configuration(environment) { |db_config| purge(db_config) }
+  ActiveRecord::Base.establish_connection(environment.to_sym)
+end
+
+
+ +
+ +
+

+ + raise_for_multi_db(environment = env, command:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 169
+def raise_for_multi_db(environment = env, command:)
+  db_configs = configs_for(env_name: environment)
+
+  if db_configs.count > 1
+    dbs_list = []
+
+    db_configs.each do |db|
+      dbs_list << "#{command}:#{db.name}"
+    end
+
+    raise "You're using a multiple database application. To use `#{command}` you must run the namespaced task with a VERSION. Available tasks are #{dbs_list.to_sentence}."
+  end
+end
+
+
+ +
+ +
+

+ + register_task(pattern, task) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 79
+def register_task(pattern, task)
+  @tasks ||= {}
+  @tasks[pattern] = task
+end
+
+
+ +
+ +
+

+ + root() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 104
+def root
+  @root ||= Rails.root
+end
+
+
+ +
+ +
+

+ + schema_dump_path(db_config, format = ActiveRecord.schema_format) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 457
+def schema_dump_path(db_config, format = ActiveRecord.schema_format)
+  return ENV["SCHEMA"] if ENV["SCHEMA"]
+
+  filename = db_config.schema_dump(format)
+  return unless filename
+
+  if File.dirname(filename) == ActiveRecord::Tasks::DatabaseTasks.db_dir
+    filename
+  else
+    File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
+  end
+end
+
+
+ +
+ +
+

+ + schema_file_type(format = ActiveRecord.schema_format) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 447
+def schema_file_type(format = ActiveRecord.schema_format)
+  case format
+  when :ruby
+    "schema.rb"
+  when :sql
+    "structure.sql"
+  end
+end
+
+
+ +
+ +
+

+ + schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 390
+def schema_up_to_date?(configuration, format = ActiveRecord.schema_format, file = nil)
+  db_config = resolve_configuration(configuration)
+
+  file ||= schema_dump_path(db_config)
+
+  return true unless file && File.exist?(file)
+
+  ActiveRecord::Base.establish_connection(db_config)
+
+  return false unless ActiveRecord::InternalMetadata.enabled?
+  return false unless ActiveRecord::InternalMetadata.table_exists?
+
+  ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
+end
+
+
+ +
+ +
+

+ + seed_loader() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 116
+def seed_loader
+  @seed_loader ||= Rails.application
+end
+
+
+ +
+ +
+

+ + setup_initial_database_yaml() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 140
+def setup_initial_database_yaml
+  return {} unless defined?(Rails)
+
+  begin
+    Rails.application.config.load_database_yaml
+  rescue
+    unless ActiveRecord.suppress_multiple_database_warning
+      $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
+    end
+
+    {}
+  end
+end
+
+
+ +
+ +
+

+ + structure_dump(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 353
+def structure_dump(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  filename = arguments.delete_at(0)
+  flags = structure_dump_flags_for(db_config.adapter)
+  database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
+end
+
+
+ +
+ +
+

+ + structure_load(configuration, *arguments) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 360
+def structure_load(configuration, *arguments)
+  db_config = resolve_configuration(configuration)
+  filename = arguments.delete_at(0)
+  flags = structure_load_flags_for(db_config.adapter)
+  database_adapter_for(db_config, *arguments).structure_load(filename, flags)
+end
+
+
+ +
+ +
+

+ + target_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 315
+def target_version
+  ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
+end
+
+
+ +
+ +
+

+ + truncate_all(environment = env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/tasks/database_tasks.rb, line 250
+def truncate_all(environment = env)
+  configs_for(env_name: environment).each do |db_config|
+    truncate_tables(db_config)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/TestFixtures.html b/src/7.0/classes/ActiveRecord/TestFixtures.html new file mode 100644 index 0000000000..6b67068527 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/TestFixtures.html @@ -0,0 +1,307 @@ +--- +title: ActiveRecord::TestFixtures +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + enlist_fixture_connections() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 189
+def enlist_fixture_connections
+  setup_shared_connection_pool
+
+  ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
+end
+
+
+ +
+ +
+

+ + run_in_transaction?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 103
+def run_in_transaction?
+  use_transactional_tests &&
+    !self.class.uses_transaction?(name)
+end
+
+
+ +
+ +
+

+ + setup_fixtures(config = ActiveRecord::Base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 108
+def setup_fixtures(config = ActiveRecord::Base)
+  if pre_loaded_fixtures && !use_transactional_tests
+    raise RuntimeError, "pre_loaded_fixtures requires use_transactional_tests"
+  end
+
+  @fixture_cache = {}
+  @fixture_connections = []
+  @@already_loaded_fixtures ||= {}
+  @connection_subscriber = nil
+  @legacy_saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
+  @saved_pool_configs = Hash.new { |hash, key| hash[key] = {} }
+
+  # Load fixtures once and begin transaction.
+  if run_in_transaction?
+    if @@already_loaded_fixtures[self.class]
+      @loaded_fixtures = @@already_loaded_fixtures[self.class]
+    else
+      @loaded_fixtures = load_fixtures(config)
+      @@already_loaded_fixtures[self.class] = @loaded_fixtures
+    end
+
+    # Begin transactions for connections already established
+    @fixture_connections = enlist_fixture_connections
+    @fixture_connections.each do |connection|
+      connection.begin_transaction joinable: false, _lazy: false
+      connection.pool.lock_thread = true if lock_threads
+    end
+
+    # When connections are established in the future, begin a transaction too
+    @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
+      spec_name = payload[:spec_name] if payload.key?(:spec_name)
+      shard = payload[:shard] if payload.key?(:shard)
+      setup_shared_connection_pool if ActiveRecord.legacy_connection_handling
+
+      if spec_name
+        begin
+          connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
+        rescue ConnectionNotEstablished
+          connection = nil
+        end
+
+        if connection
+          setup_shared_connection_pool unless ActiveRecord.legacy_connection_handling
+
+          if !@fixture_connections.include?(connection)
+            connection.begin_transaction joinable: false, _lazy: false
+            connection.pool.lock_thread = true if lock_threads
+            @fixture_connections << connection
+          end
+        end
+      end
+    end
+
+  # Load fixtures for every test.
+  else
+    ActiveRecord::FixtureSet.reset_cache
+    @@already_loaded_fixtures[self.class] = nil
+    @loaded_fixtures = load_fixtures(config)
+  end
+
+  # Instantiate fixtures for every test if requested.
+  instantiate_fixtures if use_instantiated_fixtures
+end
+
+
+ +
+ +
+

+ + teardown_fixtures() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 172
+def teardown_fixtures
+  # Rollback changes if a transaction is active.
+  if run_in_transaction?
+    ActiveSupport::Notifications.unsubscribe(@connection_subscriber) if @connection_subscriber
+    @fixture_connections.each do |connection|
+      connection.rollback_transaction if connection.transaction_open?
+      connection.pool.lock_thread = false
+    end
+    @fixture_connections.clear
+    teardown_shared_connection_pool
+  else
+    ActiveRecord::FixtureSet.reset_cache
+  end
+
+  ActiveRecord::Base.clear_active_connections!
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/TestFixtures/ClassMethods.html b/src/7.0/classes/ActiveRecord/TestFixtures/ClassMethods.html new file mode 100644 index 0000000000..e5a40e71e6 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/TestFixtures/ClassMethods.html @@ -0,0 +1,306 @@ +--- +title: ActiveRecord::TestFixtures::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fixtures(*fixture_set_names) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 42
+def fixtures(*fixture_set_names)
+  if fixture_set_names.first == :all
+    raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
+    fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
+    fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
+    fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
+  else
+    fixture_set_names = fixture_set_names.flatten.map(&:to_s)
+  end
+
+  self.fixture_table_names |= fixture_set_names
+  setup_fixture_accessors(fixture_set_names)
+end
+
+
+ +
+ +
+

+ + set_fixture_class(class_names = {}) + +

+ + +
+

Sets the model class for a fixture when the class name cannot be inferred from the fixture name.

+ +

Examples:

+ +
set_fixture_class some_fixture:        SomeModel,
+                  'namespaced/fixture' => Another::Model
+
+ +

The keys must be the fixture names, that coincide with the short paths to the fixture files.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 38
+def set_fixture_class(class_names = {})
+  self.fixture_class_names = fixture_class_names.merge(class_names.stringify_keys)
+end
+
+
+ +
+ +
+

+ + setup_fixture_accessors(fixture_set_names = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 56
+def setup_fixture_accessors(fixture_set_names = nil)
+  fixture_set_names = Array(fixture_set_names || fixture_table_names)
+  methods = Module.new do
+    fixture_set_names.each do |fs_name|
+      fs_name = fs_name.to_s
+      accessor_name = fs_name.tr("/", "_").to_sym
+
+      define_method(accessor_name) do |*fixture_names|
+        force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
+        return_single_record = fixture_names.size == 1
+        fixture_names = @loaded_fixtures[fs_name].fixtures.keys if fixture_names.empty?
+
+        @fixture_cache[fs_name] ||= {}
+
+        instances = fixture_names.map do |f_name|
+          f_name = f_name.to_s if f_name.is_a?(Symbol)
+          @fixture_cache[fs_name].delete(f_name) if force_reload
+
+          if @loaded_fixtures[fs_name][f_name]
+            @fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
+          else
+            raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
+          end
+        end
+
+        return_single_record ? instances.first : instances
+      end
+      private accessor_name
+    end
+  end
+  include methods
+end
+
+
+ +
+ +
+

+ + uses_transaction(*methods) + +

+ + +
+

Prevents automatically wrapping each specified test in a transaction, to allow application logic transactions to be tested in a top-level (non-nested) context.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 92
+def uses_transaction(*methods)
+  @uses_transaction = [] unless defined?(@uses_transaction)
+  @uses_transaction.concat methods.map(&:to_s)
+end
+
+
+ +
+ +
+

+ + uses_transaction?(method) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/test_fixtures.rb, line 97
+def uses_transaction?(method)
+  @uses_transaction = [] unless defined?(@uses_transaction)
+  @uses_transaction.include?(method.to_s)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Timestamp.html b/src/7.0/classes/ActiveRecord/Timestamp.html new file mode 100644 index 0000000000..334a5f12b2 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Timestamp.html @@ -0,0 +1,98 @@ +--- +title: ActiveRecord::Timestamp +layout: default +--- +
+ +
+
+ +
+ +

Active Record Timestamp

+ +

Active Record automatically timestamps create and update operations if the table has fields named created_at/created_on or updated_at/updated_on.

+ +

Timestamping can be turned off by setting:

+ +
config.active_record.record_timestamps = false
+
+ +

Timestamps are in UTC by default but you can use the local timezone by setting:

+ +
config.active_record.default_timezone = :local
+
+ +

Time Zone aware attributes

+ +

Active Record keeps all the datetime and time columns timezone aware. By default, these values are stored in the database as UTC and converted back to the current Time.zone when pulled from the database.

+ +

This feature can be turned off completely by setting:

+ +
config.active_record.time_zone_aware_attributes = false
+
+ +

You can also specify that only datetime columns should be time-zone aware (while time should not) by setting:

+ +
ActiveRecord::Base.time_zone_aware_types = [:datetime]
+
+ +

You can also add database specific timezone aware types. For example, for PostgreSQL:

+ +
ActiveRecord::Base.time_zone_aware_types += [:tsrange, :tstzrange]
+
+ +

Finally, you can indicate specific attributes of a model for which time zone conversion should not applied, for instance by setting:

+ +
class Topic < ActiveRecord::Base
+  self.skip_time_zone_conversion_for_attributes = [:written_on]
+end
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/TransactionIsolationError.html b/src/7.0/classes/ActiveRecord/TransactionIsolationError.html new file mode 100644 index 0000000000..3650a0cc7e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/TransactionIsolationError.html @@ -0,0 +1,75 @@ +--- +title: ActiveRecord::TransactionIsolationError +layout: default +--- +
+ +
+
+ +
+ +

TransactionIsolationError will be raised under the following conditions:

+
  • +

    The adapter does not support setting the isolation level

    +
  • +

    You are joining an existing open transaction

    +
  • +

    You are creating a nested (savepoint) transaction

    +
+ +

The mysql2 and postgresql adapters support setting the transaction isolation level.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/TransactionRollbackError.html b/src/7.0/classes/ActiveRecord/TransactionRollbackError.html new file mode 100644 index 0000000000..67d93f1454 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/TransactionRollbackError.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::TransactionRollbackError +layout: default +--- +
+ +
+
+ +
+ +

TransactionRollbackError will be raised when a transaction is rolled back by the database due to a serialization failure or a deadlock.

+ +

See the following:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Transactions.html b/src/7.0/classes/ActiveRecord/Transactions.html new file mode 100644 index 0000000000..6e43ac0251 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Transactions.html @@ -0,0 +1,73 @@ +--- +title: ActiveRecord::Transactions +layout: default +--- +
+ +
+
+ +
+ +

See ActiveRecord::Transactions::ClassMethods for documentation.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Transactions/ClassMethods.html b/src/7.0/classes/ActiveRecord/Transactions/ClassMethods.html new file mode 100644 index 0000000000..70826d46ca --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Transactions/ClassMethods.html @@ -0,0 +1,492 @@ +--- +title: ActiveRecord::Transactions::ClassMethods +layout: default +--- +
+ +
+
+ +
+ +

Active Record Transactions

+ +

Transactions are protective blocks where SQL statements are only permanent if they can all succeed as one atomic action. The classic example is a transfer between two accounts where you can only have a deposit if the withdrawal succeeded and vice versa. Transactions enforce the integrity of the database and guard the data against program errors or database break-downs. So basically you should use transaction blocks whenever you have a number of statements that must be executed together or not at all.

+ +

For example:

+ +
ActiveRecord::Base.transaction do
+  david.withdrawal(100)
+  mary.deposit(100)
+end
+
+ +

This example will only take money from David and give it to Mary if neither withdrawal nor deposit raise an exception. Exceptions will force a ROLLBACK that returns the database to the state before the transaction began. Be aware, though, that the objects will not have their instance data returned to their pre-transactional state.

+ +

Different Active Record classes in a single transaction

+ +

Though the transaction class method is called on some Active Record class, the objects within the transaction block need not all be instances of that class. This is because transactions are per-database connection, not per-model.

+ +

In this example a balance record is transactionally saved even though transaction is called on the Account class:

+ +
Account.transaction do
+  balance.save!
+  account.save!
+end
+
+ +

The transaction method is also available as a model instance method. For example, you can also do this:

+ +
balance.transaction do
+  balance.save!
+  account.save!
+end
+
+ +

Transactions are not distributed across database connections

+ +

A transaction acts on a single database connection. If you have multiple class-specific databases, the transaction will not protect interaction among them. One workaround is to begin a transaction on each class whose models you alter:

+ +
Student.transaction do
+  Course.transaction do
+    course.enroll(student)
+    student.units += course.units
+  end
+end
+
+ +

This is a poor solution, but fully distributed transactions are beyond the scope of Active Record.

+ +

save and destroy are automatically wrapped in a transaction

+ +

Both #save and #destroy come wrapped in a transaction that ensures that whatever you do in validations or callbacks will happen under its protected cover. So you can use validations to check for values that the transaction depends on or you can raise exceptions in the callbacks to rollback, including after_* callbacks.

+ +

As a consequence changes to the database are not seen outside your connection until the operation is complete. For example, if you try to update the index of a search engine in after_save the indexer won’t see the updated record. The after_commit callback is the only one that is triggered once the update is committed. See below.

+ +

Exception handling and rolling back

+ +

Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you should be ready to catch those in your application code.

+ +

One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised, but not be re-raised by the transaction block.

+ +

Warning: one should not catch ActiveRecord::StatementInvalid exceptions inside a transaction block. ActiveRecord::StatementInvalid exceptions indicate that an error occurred at the database level, for example when a unique constraint is violated. On some database systems, such as PostgreSQL, database errors inside a transaction cause the entire transaction to become unusable until it’s restarted from the beginning. Here is an example which demonstrates the problem:

+ +
# Suppose that we have a Number model with a unique column called 'i'.
+Number.transaction do
+  Number.create(i: 0)
+  begin
+    # This will raise a unique constraint error...
+    Number.create(i: 0)
+  rescue ActiveRecord::StatementInvalid
+    # ...which we ignore.
+  end
+
+  # On PostgreSQL, the transaction is now unusable. The following
+  # statement will cause a PostgreSQL error, even though the unique
+  # constraint is no longer violated:
+  Number.create(i: 1)
+  # => "PG::Error: ERROR:  current transaction is aborted, commands
+  #     ignored until end of transaction block"
+end
+
+ +

One should restart the entire transaction if an ActiveRecord::StatementInvalid occurred.

+ +

Nested transactions

+ +

transaction calls can be nested. By default, this makes all database statements in the nested transaction block become part of the parent transaction. For example, the following behavior may be surprising:

+ +
User.transaction do
+  User.create(username: 'Kotori')
+  User.transaction do
+    User.create(username: 'Nemu')
+    raise ActiveRecord::Rollback
+  end
+end
+
+ +

creates both “Kotori” and “Nemu”. Reason is the ActiveRecord::Rollback exception in the nested block does not issue a ROLLBACK. Since these exceptions are captured in transaction blocks, the parent block does not see it and the real transaction is committed.

+ +

In order to get a ROLLBACK for the nested transaction you may ask for a real sub-transaction by passing requires_new: true. If anything goes wrong, the database rolls back to the beginning of the sub-transaction without rolling back the parent transaction. If we add it to the previous example:

+ +
User.transaction do
+  User.create(username: 'Kotori')
+  User.transaction(requires_new: true) do
+    User.create(username: 'Nemu')
+    raise ActiveRecord::Rollback
+  end
+end
+
+ +

only “Kotori” is created.

+ +

Most databases don’t support true nested transactions. At the time of writing, the only database that we’re aware of that supports true nested transactions, is MS-SQL. Because of this, Active Record emulates nested transactions by using savepoints. See dev.mysql.com/doc/refman/en/savepoint.html for more information about savepoints.

+ +

Callbacks

+ +

There are two types of callbacks associated with committing and rolling back transactions: after_commit and after_rollback.

+ +

after_commit callbacks are called on every record saved or destroyed within a transaction immediately after the transaction is committed. after_rollback callbacks are called on every record saved or destroyed within a transaction immediately after the transaction or savepoint is rolled back.

+ +

These callbacks are useful for interacting with other systems since you will be guaranteed that the callback is only executed when the database is in a permanent state. For example, after_commit is a good spot to put in a hook to clearing a cache since clearing it from within a transaction could trigger the cache to be regenerated before the database is updated.

+ +

Caveats

+ +

If you’re on MySQL, then do not use Data Definition Language (DDL) operations in nested transactions blocks that are emulated with savepoints. That is, do not execute statements like ‘CREATE TABLE’ inside such blocks. This is because MySQL automatically releases all savepoints upon executing a DDL operation. When transaction is finished and tries to release the savepoint it created earlier, a database error will occur because the savepoint has already been automatically released. The following example demonstrates the problem:

+ +
Model.connection.transaction do                           # BEGIN
+  Model.connection.transaction(requires_new: true) do     # CREATE SAVEPOINT active_record_1
+    Model.connection.create_table(...)                    # active_record_1 now automatically released
+  end                                                     # RELEASE SAVEPOINT active_record_1
+                                                          # ^^^^ BOOM! database error!
+end
+
+ +

Note that “TRUNCATE” is also a MySQL DDL statement!

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_commit(*args, &block) + +

+ + +
+

This callback is called after a record has been created, updated, or destroyed.

+ +

You can specify that the callback should only be fired by a certain action with the :on option:

+ +
after_commit :do_foo, on: :create
+after_commit :do_bar, on: :update
+after_commit :do_baz, on: :destroy
+
+after_commit :do_foo_bar, on: [:create, :update]
+after_commit :do_bar_baz, on: [:update, :destroy]
+
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 229
+def after_commit(*args, &block)
+  set_options_for_callbacks!(args)
+  set_callback(:commit, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + after_create_commit(*args, &block) + +

+ + +
+

Shortcut for after_commit :hook, on: :create.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 241
+def after_create_commit(*args, &block)
+  set_options_for_callbacks!(args, on: :create)
+  set_callback(:commit, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + after_destroy_commit(*args, &block) + +

+ + +
+

Shortcut for after_commit :hook, on: :destroy.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 253
+def after_destroy_commit(*args, &block)
+  set_options_for_callbacks!(args, on: :destroy)
+  set_callback(:commit, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + after_rollback(*args, &block) + +

+ + +
+

This callback is called after a create, update, or destroy are rolled back.

+ +

Please check the documentation of after_commit for options.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 261
+def after_rollback(*args, &block)
+  set_options_for_callbacks!(args)
+  set_callback(:rollback, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + after_save_commit(*args, &block) + +

+ + +
+

Shortcut for after_commit :hook, on: [ :create, :update ].

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 235
+def after_save_commit(*args, &block)
+  set_options_for_callbacks!(args, on: [ :create, :update ])
+  set_callback(:commit, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + after_update_commit(*args, &block) + +

+ + +
+

Shortcut for after_commit :hook, on: :update.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 247
+def after_update_commit(*args, &block)
+  set_options_for_callbacks!(args, on: :update)
+  set_callback(:commit, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + transaction(**options, &block) + +

+ + + + + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/transactions.rb, line 208
+def transaction(**options, &block)
+  connection.transaction(**options, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Translation.html b/src/7.0/classes/ActiveRecord/Translation.html new file mode 100644 index 0000000000..b9387c03ee --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Translation.html @@ -0,0 +1,68 @@ +--- +title: ActiveRecord::Translation +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type.html b/src/7.0/classes/ActiveRecord/Type.html new file mode 100644 index 0000000000..326f1e46c8 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type.html @@ -0,0 +1,296 @@ +--- +title: ActiveRecord::Type +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BigInteger=ActiveModel::Type::BigInteger
 
Binary=ActiveModel::Type::Binary
 
Boolean=ActiveModel::Type::Boolean
 

Active Model Type Boolean

+ +

A class that behaves like a boolean type, including rules for coercion of user input.

+ +

Coercion

+ +

Values set from user input will first be coerced into the appropriate ruby type. Coercion behavior is roughly mapped to Ruby’s boolean semantics.

+
  • +

    “false”, “f” , “0”, 0 or any other value in FALSE_VALUES will be coerced to false

    +
  • +

    Empty strings are coerced to nil

    +
  • +

    All other values will be coerced to true

    +
Decimal=ActiveModel::Type::Decimal
 
Float=ActiveModel::Type::Float
 
ImmutableString=ActiveModel::Type::ImmutableString
 
Integer=ActiveModel::Type::Integer
 
String=ActiveModel::Type::String
 
Value=ActiveModel::Type::Value
 
+ + + + + + +

Class Public methods

+ +
+

+ + register(type_name, klass = nil, **options, &block) + +

+ + +
+

Add a new type to the registry, allowing it to be referenced as a symbol by ActiveRecord::Base.attribute. If your type is only meant to be used with a specific database adapter, you can do so by passing adapter: :postgresql. If your type has the same name as a native type for the current adapter, an exception will be raised unless you specify an :override option. override: true will cause your type to be used instead of the native type. override: false will cause the native type to be used over yours if one exists.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type.rb, line 37
+def register(type_name, klass = nil, **options, &block)
+  registry.register(type_name, klass, **options, &block)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/Date.html b/src/7.0/classes/ActiveRecord/Type/Date.html new file mode 100644 index 0000000000..d22b7c4f06 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/Date.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::Type::Date +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/DateTime.html b/src/7.0/classes/ActiveRecord/Type/DateTime.html new file mode 100644 index 0000000000..89e2d2acea --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/DateTime.html @@ -0,0 +1,74 @@ +--- +title: ActiveRecord::Type::DateTime +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/Internal.html b/src/7.0/classes/ActiveRecord/Type/Internal.html new file mode 100644 index 0000000000..4a9d4d830b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/Internal.html @@ -0,0 +1,67 @@ +--- +title: ActiveRecord::Type::Internal +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/Internal/Timezone.html b/src/7.0/classes/ActiveRecord/Type/Internal/Timezone.html new file mode 100644 index 0000000000..632dcadf41 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/Internal/Timezone.html @@ -0,0 +1,140 @@ +--- +title: ActiveRecord::Type::Internal::Timezone +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + default_timezone() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/internal/timezone.rb, line 11
+def default_timezone
+  ActiveRecord.default_timezone
+end
+
+
+ +
+ +
+

+ + is_utc?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/internal/timezone.rb, line 7
+def is_utc?
+  ActiveRecord.default_timezone == :utc
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/Json.html b/src/7.0/classes/ActiveRecord/Type/Json.html new file mode 100644 index 0000000000..8e6743f96f --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/Json.html @@ -0,0 +1,278 @@ +--- +title: ActiveRecord::Type::Json +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + accessor() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/json.rb, line 25
+def accessor
+  ActiveRecord::Store::StringKeyedHashAccessor
+end
+
+
+ +
+ +
+

+ + changed_in_place?(raw_old_value, new_value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/json.rb, line 21
+def changed_in_place?(raw_old_value, new_value)
+  deserialize(raw_old_value) != new_value
+end
+
+
+ +
+ +
+

+ + deserialize(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/json.rb, line 12
+def deserialize(value)
+  return value unless value.is_a?(::String)
+  ActiveSupport::JSON.decode(value) rescue nil
+end
+
+
+ +
+ +
+

+ + serialize(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/json.rb, line 17
+def serialize(value)
+  ActiveSupport::JSON.encode(value) unless value.nil?
+end
+
+
+ +
+ +
+

+ + type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/json.rb, line 8
+def type
+  :json
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Type/Time.html b/src/7.0/classes/ActiveRecord/Type/Time.html new file mode 100644 index 0000000000..c87f5c4f0b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Type/Time.html @@ -0,0 +1,126 @@ +--- +title: ActiveRecord::Type::Time +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + serialize(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/type/time.rb, line 11
+def serialize(value)
+  case value = super
+  when ::Time
+    Value.new(value)
+  else
+    value
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/UnknownAttributeReference.html b/src/7.0/classes/ActiveRecord/UnknownAttributeReference.html new file mode 100644 index 0000000000..0a001f99ff --- /dev/null +++ b/src/7.0/classes/ActiveRecord/UnknownAttributeReference.html @@ -0,0 +1,80 @@ +--- +title: ActiveRecord::UnknownAttributeReference +layout: default +--- +
+ +
+
+ +
+ +

UnknownAttributeReference is raised when an unknown and potentially unsafe value is passed to a query method. For example, passing a non column name value to a relation’s order method might cause this exception.

+ +

When working around this exception, caution should be taken to avoid SQL injection vulnerabilities when passing user-provided values to query methods. Known-safe values can be passed to query methods by wrapping them in Arel.sql.

+ +

For example, the following code would raise this exception:

+ +
Post.order("REPLACE(title, 'misc', 'zzzz') asc").pluck(:id)
+
+ +

The desired result can be accomplished by wrapping the known-safe string in Arel.sql:

+ +
Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz') asc")).pluck(:id)
+
+ +

Again, such a workaround should not be used when passing user-provided values, such as request parameters or model attributes to query methods.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/UnknownPrimaryKey.html b/src/7.0/classes/ActiveRecord/UnknownPrimaryKey.html new file mode 100644 index 0000000000..a585b087ad --- /dev/null +++ b/src/7.0/classes/ActiveRecord/UnknownPrimaryKey.html @@ -0,0 +1,134 @@ +--- +title: ActiveRecord::UnknownPrimaryKey +layout: default +--- +
+ +
+
+ +
+ +

Raised when a primary key is needed, but not specified in the schema or model.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + model
+ + + + +

Class Public methods

+ +
+

+ + new(model = nil, description = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/errors.rb, line 378
+def initialize(model = nil, description = nil)
+  if model
+    message = "Unknown primary key for table #{model.table_name} in model #{model}."
+    message += "\n#{description}" if description
+    @model = model
+    super(message)
+  else
+    super("Unknown primary key.")
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/VERSION.html b/src/7.0/classes/ActiveRecord/VERSION.html new file mode 100644 index 0000000000..242df7a85e --- /dev/null +++ b/src/7.0/classes/ActiveRecord/VERSION.html @@ -0,0 +1,122 @@ +--- +title: ActiveRecord::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Validations.html b/src/7.0/classes/ActiveRecord/Validations.html new file mode 100644 index 0000000000..fa495cc98b --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Validations.html @@ -0,0 +1,266 @@ +--- +title: ActiveRecord::Validations +layout: default +--- +
+ +
+
+ +
+ +

Active Record Validations

+ +

Active Record includes the majority of its validations from ActiveModel::Validations all of which accept the :on argument to define the context where the validations are active. Active Record will always supply either the context of :create or :update dependent on whether the model is a new_record?.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + save(**options) + +

+ + +
+

The validation process on save can be skipped by passing validate: false. The validation context can be changed by passing context: context. The regular ActiveRecord::Base#save method is replaced with this when the validations module is mixed in, which it is by default.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations.rb, line 46
+def save(**options)
+  perform_validations(options) ? super : false
+end
+
+
+ +
+ +
+

+ + save!(**options) + +

+ + +
+

Attempts to save the record just like ActiveRecord::Base#save but will raise an ActiveRecord::RecordInvalid exception instead of returning false if the record is not valid.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations.rb, line 52
+def save!(**options)
+  perform_validations(options) ? super : raise_validation_error
+end
+
+
+ +
+ +
+

+ + valid?(context = nil) + +

+ + +
+

Runs all the validations within the specified context. Returns true if no errors are found, false otherwise.

+ +

Aliased as validate.

+ +

If the argument is false (default is nil), the context is set to :create if new_record? is true, and to :update if it is not.

+ +

Validations with no :on option will run no matter the context. Validations with some :on option will only run in the specified context.

+
+ + + +
+ Also aliased as: validate +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations.rb, line 66
+def valid?(context = nil)
+  context ||= default_validation_context
+  output = super(context)
+  errors.empty? && output
+end
+
+
+ +
+ +
+

+ + validate(context = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: valid? +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/Validations/ClassMethods.html b/src/7.0/classes/ActiveRecord/Validations/ClassMethods.html new file mode 100644 index 0000000000..0670760b79 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/Validations/ClassMethods.html @@ -0,0 +1,500 @@ +--- +title: ActiveRecord::Validations::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + validates_absence_of(*attr_names) + +

+ + +
+

Validates that the specified attributes are not present (as defined by Object#present?). If the attribute is an association, the associated object is considered absent if it was marked for destruction.

+ +

See ActiveModel::Validations::HelperMethods.validates_absence_of for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/absence.rb, line 20
+def validates_absence_of(*attr_names)
+  validates_with AbsenceValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_associated(*attr_names) + +

+ + +
+

Validates whether the associated object or objects are all valid. Works with any kind of association.

+ +
class Book < ActiveRecord::Base
+  has_many :pages
+  belongs_to :library
+
+  validates_associated :pages, :library
+end
+
+ +

WARNING: This validation must not be used on both ends of an association. Doing so will lead to a circular dependency and cause infinite recursion.

+ +

NOTE: This validation will not fail if the association hasn’t been assigned. If you want to ensure that the association is both present and guaranteed to be valid, you also need to use validates_presence_of.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “is invalid”).

    +
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/associated.rb, line 54
+def validates_associated(*attr_names)
+  validates_with AssociatedValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_length_of(*attr_names) + +

+ + +
+

Validates that the specified attributes match the length restrictions supplied. If the attribute is an association, records that are marked for destruction are not counted.

+ +

See ActiveModel::Validations::HelperMethods.validates_length_of for more information.

+
+ + + +
+ Also aliased as: validates_size_of +
+ + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/length.rb, line 19
+def validates_length_of(*attr_names)
+  validates_with LengthValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_numericality_of(*attr_names) + +

+ + +
+

Validates whether the value of the specified attribute is numeric by trying to convert it to a float with Kernel.Float (if only_integer is false) or applying it to the regular expression /\A[+\-]?\d+\z/ (if only_integer is set to true). Kernel.Float precision defaults to the column’s precision value or 15.

+ +

See ActiveModel::Validations::HelperMethods.validates_numericality_of for more information.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/numericality.rb, line 30
+def validates_numericality_of(*attr_names)
+  validates_with NumericalityValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_presence_of(*attr_names) + +

+ + +
+

Validates that the specified attributes are not blank (as defined by Object#blank?), and, if the attribute is an association, that the associated object is not marked for destruction. Happens by default on save.

+ +
class Person < ActiveRecord::Base
+  has_one :face
+  validates_presence_of :face
+end
+
+ +

The face attribute must be in the object and it cannot be blank or marked for destruction.

+ +

If you want to validate the presence of a boolean field (where the real values are true and false), you will want to use validates_inclusion_of :field_name, in: [true, false].

+ +

This is due to the way Object#blank? handles boolean values: false.blank? # => true.

+ +

This validator defers to the Active Model validation for presence, adding the check to see that an associated object is not marked for destruction. This prevents the parent object from validating successfully and saving, which then deletes the associated object, thus putting the parent object into an invalid state.

+ +

NOTE: This validation will not fail while using it with an association if the latter was assigned but not valid. If you want to ensure that it is both present and valid, you also need to use validates_associated.

+ +

Configuration options:

+
  • +

    :message - A custom error message (default is: “can’t be blank”).

    +
  • +

    :on - Specifies the contexts where this validation is active. Runs in all validation contexts by default nil. You can pass a symbol or an array of symbols. (e.g. on: :create or on: :custom_validation_context or on: [:create, :custom_validation_context])

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :strict - Specifies whether validation should be strict. See ActiveModel::Validations#validates! for more information.

    +
+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/presence.rb, line 63
+def validates_presence_of(*attr_names)
+  validates_with PresenceValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ +
+

+ + validates_size_of(*attr_names) + +

+ + +
+ +
+ + + + + +
+ Alias for: validates_length_of +
+ + + +
+ +
+

+ + validates_uniqueness_of(*attr_names) + +

+ + +
+

Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user can be named “davidhh”.

+ +
class Person < ActiveRecord::Base
+  validates_uniqueness_of :user_name
+end
+
+ +

It can also validate whether the value of the specified attributes are unique based on a :scope parameter:

+ +
class Person < ActiveRecord::Base
+  validates_uniqueness_of :user_name, scope: :account_id
+end
+
+ +

Or even multiple scope parameters. For example, making sure that a teacher can only be on the schedule once per semester for a particular class.

+ +
class TeacherSchedule < ActiveRecord::Base
+  validates_uniqueness_of :teacher_id, scope: [:semester_id, :class_id]
+end
+
+ +

It is also possible to limit the uniqueness constraint to a set of records matching certain conditions. In this example archived articles are not being taken into consideration when validating uniqueness of the title attribute:

+ +
class Article < ActiveRecord::Base
+  validates_uniqueness_of :title, conditions: -> { where.not(status: 'archived') }
+end
+
+ +

To build conditions based on the record’s state, define the conditions callable with a parameter, which will be the record itself. This example validates the title is unique for the year of publication:

+ +
class Article < ActiveRecord::Base
+  validates_uniqueness_of :title, conditions: ->(article) {
+    published_at = article.published_at
+    where(published_at: published_at.beginning_of_year..published_at.end_of_year)
+  }
+end
+
+ +

When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.

+ +

Configuration options:

+
  • +

    :message - Specifies a custom error message (default is: “has already been taken”).

    +
  • +

    :scope - One or more columns by which to limit the scope of the uniqueness constraint.

    +
  • +

    :conditions - Specify the conditions to be included as a WHERE SQL fragment to limit the uniqueness constraint lookup (e.g. conditions: -> { where(status: 'active') }).

    +
  • +

    :case_sensitive - Looks for an exact match. Ignored by non-text columns. The default behavior respects the default database collation.

    +
  • +

    :allow_nil - If set to true, skips this validation if the attribute is nil (default is false).

    +
  • +

    :allow_blank - If set to true, skips this validation if the attribute is blank (default is false).

    +
  • +

    :if - Specifies a method, proc, or string to call to determine if the validation should occur (e.g. if: :allow_validation, or if: Proc.new { |user| user.signup_step > 2 }). The method, proc or string should return or evaluate to a true or false value.

    +
  • +

    :unless - Specifies a method, proc, or string to call to determine if the validation should not occur (e.g. unless: :skip_validation, or unless: Proc.new { |user| user.signup_step <= 2 }). The method, proc, or string should return or evaluate to a true or false value.

    +
+ +

Concurrency and integrity

+ +

Using this validation method in conjunction with ActiveRecord::Base#save does not guarantee the absence of duplicate record insertions, because uniqueness checks on the application level are inherently prone to race conditions. For example, suppose that two users try to post a Comment at the same time, and a Comment’s title must be unique. At the database-level, the actions performed by these users could be interleaved in the following manner:

+ +
             User 1                 |               User 2
+------------------------------------+--------------------------------------
+# User 1 checks whether there's     |
+# already a comment with the title  |
+# 'My Post'. This is not the case.  |
+SELECT * FROM comments              |
+WHERE title = 'My Post'             |
+                                    |
+                                    | # User 2 does the same thing and also
+                                    | # infers that their title is unique.
+                                    | SELECT * FROM comments
+                                    | WHERE title = 'My Post'
+                                    |
+# User 1 inserts their comment.     |
+INSERT INTO comments                |
+(title, content) VALUES             |
+('My Post', 'hi!')                  |
+                                    |
+                                    | # User 2 does the same thing.
+                                    | INSERT INTO comments
+                                    | (title, content) VALUES
+                                    | ('My Post', 'hello!')
+                                    |
+                                    | # ^^^^^^
+                                    | # Boom! We now have a duplicate
+                                    | # title!
+
+ +

The best way to work around this problem is to add a unique index to the database table using connection.add_index. In the rare case that a race condition occurs, the database will guarantee the field’s uniqueness.

+ +

When the database catches such a duplicate insertion, ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid exception. You can either choose to let this error propagate (which will result in the default Rails exception page being shown), or you can catch it and restart the transaction (e.g. by telling the user that the title already exists, and asking them to re-enter the title). This technique is also known as optimistic concurrency control.

+ +

The bundled ActiveRecord::ConnectionAdapters distinguish unique index constraint errors from other types of database errors by throwing an ActiveRecord::RecordNotUnique exception. For other adapters you will have to parse the (database-specific) exception message to detect such a case.

+ +

The following bundled adapters throw the ActiveRecord::RecordNotUnique exception:

+ +
+ + + + + + + + +
+ + +
+
# File activerecord/lib/active_record/validations/uniqueness.rb, line 241
+def validates_uniqueness_of(*attr_names)
+  validates_with UniquenessValidator, _merge_attributes(attr_names)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/ValueTooLong.html b/src/7.0/classes/ActiveRecord/ValueTooLong.html new file mode 100644 index 0000000000..dc9762bb96 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/ValueTooLong.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::ValueTooLong +layout: default +--- +
+ +
+
+ +
+ +

Raised when a record cannot be inserted or updated because a value too long for a column type.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveRecord/WrappedDatabaseException.html b/src/7.0/classes/ActiveRecord/WrappedDatabaseException.html new file mode 100644 index 0000000000..d7d07fd519 --- /dev/null +++ b/src/7.0/classes/ActiveRecord/WrappedDatabaseException.html @@ -0,0 +1,66 @@ +--- +title: ActiveRecord::WrappedDatabaseException +layout: default +--- +
+ +
+
+ +
+ +

Defunct wrapper class kept for compatibility. StatementInvalid wraps the original exception now.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage.html b/src/7.0/classes/ActiveStorage.html new file mode 100644 index 0000000000..63cdc34858 --- /dev/null +++ b/src/7.0/classes/ActiveStorage.html @@ -0,0 +1,370 @@ +--- +title: ActiveStorage +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Active Storage as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Active Storage as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/AnalyzeJob.html b/src/7.0/classes/ActiveStorage/AnalyzeJob.html new file mode 100644 index 0000000000..ed261a0826 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/AnalyzeJob.html @@ -0,0 +1,113 @@ +--- +title: ActiveStorage::AnalyzeJob +layout: default +--- +
+ +
+
+ +
+ +

Provides asynchronous analysis of ActiveStorage::Blob records via ActiveStorage::Blob#analyze_later.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/jobs/active_storage/analyze_job.rb, line 10
+def perform(blob)
+  blob.analyze
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer.html b/src/7.0/classes/ActiveStorage/Analyzer.html new file mode 100644 index 0000000000..6270e50a14 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer.html @@ -0,0 +1,437 @@ +--- +title: ActiveStorage::Analyzer +layout: default +--- +
+ +
+
+ +
+ +

This is an abstract base class for analyzers, which extract metadata from blobs. See ActiveStorage::Analyzer::VideoAnalyzer for an example of a concrete subclass.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + blob
+ + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+

Implement this method in a concrete subclass. Have it return true when given a blob from which the analyzer can extract metadata.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 11
+def self.accept?(blob)
+  false
+end
+
+
+ +
+ +
+

+ + analyze_later?() + +

+ + +
+

Implement this method in concrete subclasses. It will determine if blob analysis should be done in a job or performed inline. By default, analysis is enqueued in a job.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 17
+def self.analyze_later?
+  true
+end
+
+
+ +
+ +
+

+ + new(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 21
+def initialize(blob)
+  @blob = blob
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + metadata() + +

+ + +
+

Override this method in a concrete subclass. Have it return a Hash of metadata.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 26
+def metadata
+  raise NotImplementedError
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + download_blob_to_tempfile(&block) + +

+ + +
+

Downloads the blob to a tempfile on disk. Yields the tempfile.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 32
+def download_blob_to_tempfile(&block) # :doc:
+  blob.open tmpdir: tmpdir, &block
+end
+
+
+ +
+ +
+

+ + instrument(analyzer, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 44
+def instrument(analyzer, &block) # :doc:
+  ActiveSupport::Notifications.instrument("analyze.active_storage", analyzer: analyzer, &block)
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 36
+def logger # :doc:
+  ActiveStorage.logger
+end
+
+
+ +
+ +
+

+ + tmpdir() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer.rb, line 40
+def tmpdir # :doc:
+  Dir.tmpdir
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer/AudioAnalyzer.html b/src/7.0/classes/ActiveStorage/Analyzer/AudioAnalyzer.html new file mode 100644 index 0000000000..ce21410628 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer/AudioAnalyzer.html @@ -0,0 +1,163 @@ +--- +title: ActiveStorage::Analyzer::AudioAnalyzer +layout: default +--- +
+ +
+
+ +
+ +

Extracts duration (seconds) and bit_rate (bits/s) from an audio blob.

+ +

Example:

+ +
ActiveStorage::Analyzer::AudioAnalyzer.new(blob).metadata
+# => { duration: 5.0, bit_rate: 320340 }
+
+ +

This analyzer requires the FFmpeg system library, which is not provided by Rails.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/audio_analyzer.rb, line 13
+def self.accept?(blob)
+  blob.audio?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + metadata() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/audio_analyzer.rb, line 17
+def metadata
+  { duration: duration, bit_rate: bit_rate }.compact
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer.html b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer.html new file mode 100644 index 0000000000..142d9138db --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer.html @@ -0,0 +1,190 @@ +--- +title: ActiveStorage::Analyzer::ImageAnalyzer +layout: default +--- +
+ +
+
+ +
+ +

This is an abstract base class for image analyzers, which extract width and height from an image blob.

+ +

If the image contains EXIF data indicating its angle is 90 or 270 degrees, its width and height are swapped for convenience.

+ +

Example:

+ +
ActiveStorage::Analyzer::ImageAnalyzer::ImageMagick.new(blob).metadata
+# => { width: 4104, height: 2736 }
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/image_analyzer.rb, line 13
+def self.accept?(blob)
+  blob.image?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + metadata() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/image_analyzer.rb, line 17
+def metadata
+  read_image do |image|
+    if rotated_image?(image)
+      { width: image.height, height: image.width }
+    else
+      { width: image.width, height: image.height }
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/ImageMagick.html b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/ImageMagick.html new file mode 100644 index 0000000000..9948e6568d --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/ImageMagick.html @@ -0,0 +1,113 @@ +--- +title: ActiveStorage::Analyzer::ImageAnalyzer::ImageMagick +layout: default +--- +
+ +
+
+ +
+ +

This analyzer relies on the third-party MiniMagick gem. MiniMagick requires the ImageMagick system library.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/image_analyzer/image_magick.rb, line 7
+def self.accept?(blob)
+  super && ActiveStorage.variant_processor == :mini_magick
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/Vips.html b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/Vips.html new file mode 100644 index 0000000000..926831fe7e --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer/ImageAnalyzer/Vips.html @@ -0,0 +1,131 @@ +--- +title: ActiveStorage::Analyzer::ImageAnalyzer::Vips +layout: default +--- +
+ +
+
+ +
+ +

This analyzer relies on the third-party ruby-vips gem. Ruby-vips requires the libvips system library.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ROTATIONS=/Right-top|Left-bottom|Top-right|Bottom-left/
 
+ + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/image_analyzer/vips.rb, line 7
+def self.accept?(blob)
+  super && ActiveStorage.variant_processor == :vips
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Analyzer/VideoAnalyzer.html b/src/7.0/classes/ActiveStorage/Analyzer/VideoAnalyzer.html new file mode 100644 index 0000000000..794c39153c --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Analyzer/VideoAnalyzer.html @@ -0,0 +1,180 @@ +--- +title: ActiveStorage::Analyzer::VideoAnalyzer +layout: default +--- +
+ +
+
+ +
+ +

Extracts the following from a video blob:

+
  • +

    Width (pixels)

    +
  • +

    Height (pixels)

    +
  • +

    Duration (seconds)

    +
  • +

    Angle (degrees)

    +
  • +

    Display aspect ratio

    +
  • +

    Audio (true if file has an audio channel, false if not)

    +
  • +

    Video (true if file has an video channel, false if not)

    +
+ +

Example:

+ +
ActiveStorage::Analyzer::VideoAnalyzer.new(blob).metadata
+# => { width: 640.0, height: 480.0, duration: 5.0, angle: 0, display_aspect_ratio: [4, 3], audio: true, video: true }
+
+ +

When a video’s angle is 90, -90, 270 or -270 degrees, its width and height are automatically swapped for convenience.

+ +

This analyzer requires the FFmpeg system library, which is not provided by Rails.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/video_analyzer.rb, line 23
+def self.accept?(blob)
+  blob.video?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + metadata() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/analyzer/video_analyzer.rb, line 27
+def metadata
+  { width: width, height: height, duration: duration, angle: angle, display_aspect_ratio: display_aspect_ratio, audio: audio?, video: video? }.compact
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Attached.html b/src/7.0/classes/ActiveStorage/Attached.html new file mode 100644 index 0000000000..e3658b735e --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Attached.html @@ -0,0 +1,183 @@ +--- +title: ActiveStorage::Attached +layout: default +--- +
+ +
+
+ +
+ +

Abstract base class for the concrete ActiveStorage::Attached::One and ActiveStorage::Attached::Many classes that both provide proxy access to the blob association for a record.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + name
+ [R] + record
+ + + + +

Class Public methods

+ +
+

+ + new(name, record) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached.rb, line 11
+def initialize(name, record)
+  @name, @record = name, record
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Attached/Many.html b/src/7.0/classes/ActiveStorage/Attached/Many.html new file mode 100644 index 0000000000..32df8d00b5 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Attached/Many.html @@ -0,0 +1,366 @@ +--- +title: ActiveStorage::Attached::Many +layout: default +--- +
+ +
+
+ +
+ +

Decorated proxy object representing of multiple attachments to a model.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attach(*attachables) + +

+ + +
+

Attaches one or more attachables to the record.

+ +

If the record is persisted and unchanged, the attachments are saved to the database immediately. Otherwise, they’ll be saved to the DB when the record is next saved.

+ +
document.images.attach(params[:images]) # Array of ActionDispatch::Http::UploadedFile objects
+document.images.attach(params[:signed_blob_id]) # Signed reference to blob from direct upload
+document.images.attach(io: File.open("/path/to/racecar.jpg"), filename: "racecar.jpg", content_type: "image/jpeg")
+document.images.attach([ first_blob, second_blob ])
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 49
+def attach(*attachables)
+  if record.persisted? && !record.changed?
+    record.public_send("#{name}=", blobs + attachables.flatten)
+    record.save
+  else
+    record.public_send("#{name}=", (change&.attachables || blobs) + attachables.flatten)
+  end
+end
+
+
+ +
+ +
+

+ + attached?() + +

+ + +
+

Returns true if any attachments have been made.

+ +
class Gallery < ApplicationRecord
+  has_many_attached :photos
+end
+
+Gallery.new.photos.attached? # => false
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 65
+def attached?
+  attachments.any?
+end
+
+
+ +
+ +
+

+ + attachments() + +

+ + +
+

Returns all the associated attachment records.

+ +

All methods called on this proxy object that aren’t listed here will automatically be delegated to attachments.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 30
+def attachments
+  change.present? ? change.attachments : record.public_send("#{name}_attachments")
+end
+
+
+ +
+ +
+

+ + blobs() + +

+ + +
+

Returns all attached blobs.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 35
+def blobs
+  change.present? ? change.blobs : record.public_send("#{name}_blobs")
+end
+
+
+ +
+ +
+

+ + detach + +

+ + +
+

Deletes associated attachments without purging them, leaving their respective blobs in place.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 23
+delegate :detach, to: :detach_many
+
+
+
+ +
+ +
+

+ + purge + +

+ + +
+

Directly purges each associated attachment (i.e. destroys the blobs and attachments and deletes the files on the service).

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 11
+delegate :purge, to: :purge_many
+
+
+
+ +
+ +
+

+ + purge_later + +

+ + +
+

Purges each associated attachment through the queuing system.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/many.rb, line 17
+delegate :purge_later, to: :purge_many
+
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Attached/Model.html b/src/7.0/classes/ActiveStorage/Attached/Model.html new file mode 100644 index 0000000000..b9bddb1981 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Attached/Model.html @@ -0,0 +1,494 @@ +--- +title: ActiveStorage::Attached::Model +layout: default +--- +
+ +
+
+ +
+ +

Provides the class-level DSL for declaring an Active Record model’s attachments.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deprecate(action) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 178
+          def deprecate(action)
+            reflection_name = proxy_association.reflection.name
+            attached_name = reflection_name.to_s.partition("_").first
+            ActiveSupport::Deprecation.warn(<<-MSG.squish)
+              Calling `#{action}` from `#{reflection_name}` is deprecated and will be removed in Rails 7.1.
+              To migrate to Rails 7.1's behavior call `#{action}` from `#{attached_name}` instead: `#{attached_name}.#{action}`.
+            MSG
+          end
+
+
+ +
+ +
+

+ + has_many_attached(name, dependent: :purge_later, service: nil, strict_loading: false) + +

+ + +
+

Specifies the relation between multiple attachments and the model.

+ +
class Gallery < ApplicationRecord
+  has_many_attached :photos
+end
+
+ +

There are no columns defined on the model side, Active Storage takes care of the mapping between your records and the attachments.

+ +

To avoid N+1 queries, you can include the attached blobs in your query like so:

+ +
Gallery.where(user: Current.user).with_attached_photos
+
+ +

Under the covers, this relationship is implemented as a has_many association to a ActiveStorage::Attachment record and a has_many-through association to a ActiveStorage::Blob record. These associations are available as photos_attachments and photos_blobs. But you shouldn’t need to work with these associations directly in most circumstances.

+ +

The system has been designed to having you go through the ActiveStorage::Attached::Many proxy that provides the dynamic proxy to the associations and factory methods, like #attach.

+ +

If the :dependent option isn’t set, all the attachments will be purged (i.e. destroyed) whenever the record is destroyed.

+ +

If you need the attachment to use a service which differs from the globally configured one, pass the :service option. For instance:

+ +
class Gallery < ActiveRecord::Base
+  has_many_attached :photos, service: :s3
+end
+
+ +

If you need to enable strict_loading to prevent lazy loading of attachments, pass the :strict_loading option. You can do:

+ +
class Gallery < ApplicationRecord
+  has_many_attached :photos, strict_loading: true
+end
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 129
+      def has_many_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
+        validate_service_configuration(name, service)
+
+        generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
+          # frozen_string_literal: true
+          def #{name}
+            @active_storage_attached ||= {}
+            @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::Many.new("#{name}", self)
+          end
+
+          def #{name}=(attachables)
+            attachables = Array(attachables).compact_blank
+
+            if ActiveStorage.replace_on_assign_to_many
+              attachment_changes["#{name}"] =
+                if attachables.none?
+                  ActiveStorage::Attached::Changes::DeleteMany.new("#{name}", self)
+                else
+                  ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, attachables)
+                end
+            else
+              ActiveSupport::Deprecation.warn \
+                "config.active_storage.replace_on_assign_to_many is deprecated and will be removed in Rails 7.1. " \
+                "Make sure that your code works well with config.active_storage.replace_on_assign_to_many set to true before upgrading. " \
+                "To append new attachables to the Active Storage association, prefer using `attach`. " \
+                "Using association setter would result in purging the existing attached attachments and replacing them with new ones."
+
+              if attachables.any?
+                attachment_changes["#{name}"] =
+                  ActiveStorage::Attached::Changes::CreateMany.new("#{name}", self, #{name}.blobs + attachables)
+              end
+            end
+          end
+        CODE
+
+        has_many :"#{name}_attachments", -> { where(name: name) }, as: :record, class_name: "ActiveStorage::Attachment", inverse_of: :record, dependent: :destroy, strict_loading: strict_loading do
+          def purge
+            deprecate(:purge)
+            each(&:purge)
+            reset
+          end
+
+          def purge_later
+            deprecate(:purge_later)
+            each(&:purge_later)
+            reset
+          end
+
+          private
+          def deprecate(action)
+            reflection_name = proxy_association.reflection.name
+            attached_name = reflection_name.to_s.partition("_").first
+            ActiveSupport::Deprecation.warn(<<-MSG.squish)
+              Calling `#{action}` from `#{reflection_name}` is deprecated and will be removed in Rails 7.1.
+              To migrate to Rails 7.1's behavior call `#{action}` from `#{attached_name}` instead: `#{attached_name}.#{action}`.
+            MSG
+          end
+        end
+        has_many :"#{name}_blobs", through: :"#{name}_attachments", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
+
+        scope :"with_attached_#{name}", -> {
+          if ActiveStorage.track_variants
+            includes("#{name}_attachments": { blob: :variant_records })
+          else
+            includes("#{name}_attachments": :blob)
+          end
+        }
+
+        after_save { attachment_changes[name.to_s]&.save }
+
+        after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
+
+        reflection = ActiveRecord::Reflection.create(
+          :has_many_attached,
+          name,
+          nil,
+          { dependent: dependent, service_name: service },
+          self
+        )
+        yield reflection if block_given?
+        ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
+      end
+
+
+ +
+ +
+

+ + has_one_attached(name, dependent: :purge_later, service: nil, strict_loading: false) + +

+ + +
+

Specifies the relation between a single attachment and the model.

+ +
class User < ApplicationRecord
+  has_one_attached :avatar
+end
+
+ +

There is no column defined on the model side, Active Storage takes care of the mapping between your records and the attachment.

+ +

To avoid N+1 queries, you can include the attached blobs in your query like so:

+ +
User.with_attached_avatar
+
+ +

Under the covers, this relationship is implemented as a has_one association to a ActiveStorage::Attachment record and a has_one-through association to a ActiveStorage::Blob record. These associations are available as avatar_attachment and avatar_blob. But you shouldn’t need to work with these associations directly in most circumstances.

+ +

The system has been designed to having you go through the ActiveStorage::Attached::One proxy that provides the dynamic proxy to the associations and factory methods, like attach.

+ +

If the :dependent option isn’t set, the attachment will be purged (i.e. destroyed) whenever the record is destroyed.

+ +

If you need the attachment to use a service which differs from the globally configured one, pass the :service option. For instance:

+ +
class User < ActiveRecord::Base
+  has_one_attached :avatar, service: :s3
+end
+
+ +

If you need to enable strict_loading to prevent lazy loading of attachment, pass the :strict_loading option. You can do:

+ +
class User < ApplicationRecord
+  has_one_attached :avatar, strict_loading: true
+end
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 50
+      def has_one_attached(name, dependent: :purge_later, service: nil, strict_loading: false)
+        validate_service_configuration(name, service)
+
+        generated_association_methods.class_eval <<-CODE, __FILE__, __LINE__ + 1
+          # frozen_string_literal: true
+          def #{name}
+            @active_storage_attached ||= {}
+            @active_storage_attached[:#{name}] ||= ActiveStorage::Attached::One.new("#{name}", self)
+          end
+
+          def #{name}=(attachable)
+            attachment_changes["#{name}"] =
+              if attachable.nil?
+                ActiveStorage::Attached::Changes::DeleteOne.new("#{name}", self)
+              else
+                ActiveStorage::Attached::Changes::CreateOne.new("#{name}", self, attachable)
+              end
+          end
+        CODE
+
+        has_one :"#{name}_attachment", -> { where(name: name) }, class_name: "ActiveStorage::Attachment", as: :record, inverse_of: :record, dependent: :destroy, strict_loading: strict_loading
+        has_one :"#{name}_blob", through: :"#{name}_attachment", class_name: "ActiveStorage::Blob", source: :blob, strict_loading: strict_loading
+
+        scope :"with_attached_#{name}", -> { includes("#{name}_attachment": :blob) }
+
+        after_save { attachment_changes[name.to_s]&.save }
+
+        after_commit(on: %i[ create update ]) { attachment_changes.delete(name.to_s).try(:upload) }
+
+        reflection = ActiveRecord::Reflection.create(
+          :has_one_attached,
+          name,
+          nil,
+          { dependent: dependent, service_name: service },
+          self
+        )
+        yield reflection if block_given?
+        ActiveRecord::Reflection.add_attachment_reflection(self, name, reflection)
+      end
+
+
+ +
+ +
+

+ + purge() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 165
+def purge
+  deprecate(:purge)
+  each(&:purge)
+  reset
+end
+
+
+ +
+ +
+

+ + purge_later() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 171
+def purge_later
+  deprecate(:purge_later)
+  each(&:purge_later)
+  reset
+end
+
+
+ +
+ +
+

+ + validate_service_configuration(association_name, service) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/model.rb, line 213
+def validate_service_configuration(association_name, service)
+  if service.present?
+    ActiveStorage::Blob.services.fetch(service) do
+      raise ArgumentError, "Cannot configure service :#{service} for #{name}##{association_name}"
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Attached/One.html b/src/7.0/classes/ActiveStorage/Attached/One.html new file mode 100644 index 0000000000..6210f7ab31 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Attached/One.html @@ -0,0 +1,373 @@ +--- +title: ActiveStorage::Attached::One +layout: default +--- +
+ +
+
+ +
+ +

Representation of a single attachment to a model.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + attach(attachable) + +

+ + +
+

Attaches an attachable to the record.

+ +

If the record is persisted and unchanged, the attachment is saved to the database immediately. Otherwise, it’ll be saved to the DB when the record is next saved.

+ +
person.avatar.attach(params[:avatar]) # ActionDispatch::Http::UploadedFile object
+person.avatar.attach(params[:signed_blob_id]) # Signed reference to blob from direct upload
+person.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg")
+person.avatar.attach(avatar_blob) # ActiveStorage::Blob object
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 56
+def attach(attachable)
+  if record.persisted? && !record.changed?
+    record.public_send("#{name}=", attachable)
+    record.save
+  else
+    record.public_send("#{name}=", attachable)
+  end
+end
+
+
+ +
+ +
+

+ + attached?() + +

+ + +
+

Returns true if an attachment has been made.

+ +
class User < ApplicationRecord
+  has_one_attached :avatar
+end
+
+User.new.avatar.attached? # => false
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 72
+def attached?
+  attachment.present?
+end
+
+
+ +
+ +
+

+ + attachment() + +

+ + +
+

Returns the associated attachment record.

+ +

You don’t have to call this method to access the attachment’s methods as they are all available at the model level.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 31
+def attachment
+  change.present? ? change.attachment : record.public_send("#{name}_attachment")
+end
+
+
+ +
+ +
+

+ + blank?() + +

+ + +
+

Returns true if an attachment is not attached.

+ +
class User < ApplicationRecord
+  has_one_attached :avatar
+end
+
+User.new.avatar.blank? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 42
+def blank?
+  !attached?
+end
+
+
+ +
+ +
+

+ + detach + +

+ + +
+

Deletes the attachment without purging it, leaving its blob in place.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 23
+delegate :detach, to: :detach_one
+
+
+
+ +
+ +
+

+ + purge + +

+ + +
+

Directly purges the attachment (i.e. destroys the blob and attachment and deletes the file on the service).

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 11
+delegate :purge, to: :purge_one
+
+
+
+ +
+ +
+

+ + purge_later + +

+ + +
+

Purges the attachment through the queuing system.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/attached/one.rb, line 17
+delegate :purge_later, to: :purge_one
+
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Attachment.html b/src/7.0/classes/ActiveStorage/Attachment.html new file mode 100644 index 0000000000..ea9d12f4d1 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Attachment.html @@ -0,0 +1,221 @@ +--- +title: ActiveStorage::Attachment +layout: default +--- +
+ +
+
+ +
+ +

Attachments associate records with blobs. Usually that’s a one record-many blobs relationship, but it is possible to associate many different records with the same blob. A foreign-key constraint on the attachments table prevents blobs from being purged if they’re still attached to any records.

+ +

Attachments also have access to all methods from ActiveStorage::Blob.

+ +

If you wish to preload attachments or blobs, you can use these scopes:

+ +
# preloads attachments, their corresponding blobs, and variant records (if using `ActiveStorage.track_variants`)
+User.all.with_attached_avatars
+
+# preloads blobs and variant records (if using `ActiveStorage.track_variants`)
+User.first.avatars.with_all_variant_records
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + purge() + +

+ + +
+

Synchronously deletes the attachment and purges the blob.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/attachment.rb, line 33
+def purge
+  transaction do
+    delete
+    record.touch if record&.persisted?
+  end
+  blob&.purge
+end
+
+
+ +
+ +
+

+ + purge_later() + +

+ + +
+

Deletes the attachment and enqueues a background job to purge the blob.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/attachment.rb, line 42
+def purge_later
+  transaction do
+    delete
+    record.touch if record&.persisted?
+  end
+  blob&.purge_later
+end
+
+
+ +
+ +
+

+ + variant(transformations) + +

+ + +
+

Returns an ActiveStorage::Variant or ActiveStorage::VariantWithRecord instance for the attachment with the set of transformations provided. See ActiveStorage::Blob::Representable#variant for more information.

+ +

Raises an ArgumentError if transformations is a Symbol which is an unknown pre-defined variant of the attachment.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/attachment.rb, line 56
+def variant(transformations)
+  case transformations
+  when Symbol
+    variant_name = transformations
+    transformations = variants.fetch(variant_name) do
+      record_model_name = record.to_model.model_name.name
+      raise ArgumentError, "Cannot find variant :#{variant_name} for #{record_model_name}##{name}"
+    end
+  end
+
+  blob.variant(transformations)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/BaseController.html b/src/7.0/classes/ActiveStorage/BaseController.html new file mode 100644 index 0000000000..1390bc0053 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/BaseController.html @@ -0,0 +1,80 @@ +--- +title: ActiveStorage::BaseController +layout: default +--- +
+ +
+
+ +
+ +

The base class for all Active Storage controllers.

+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/BaseJob.html b/src/7.0/classes/ActiveStorage/BaseJob.html new file mode 100644 index 0000000000..555731bfbc --- /dev/null +++ b/src/7.0/classes/ActiveStorage/BaseJob.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::BaseJob +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blob.html b/src/7.0/classes/ActiveStorage/Blob.html new file mode 100644 index 0000000000..7a8e24232d --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blob.html @@ -0,0 +1,1293 @@ +--- +title: ActiveStorage::Blob +layout: default +--- +
+ +
+
+ +
+ +

A blob is a record that contains the metadata about a file and a key for where that file resides on the service. Blobs can be created in two ways:

+
  1. +

    Ahead of the file being uploaded server-side to the service, via create_and_upload!. A rewindable io with the file contents must be available at the server for this operation.

    +
  2. +

    Ahead of the file being directly uploaded client-side to the service, via create_before_direct_upload!.

    +
+ +

The first option doesn’t require any client-side JavaScript integration, and can be used by any other back-end service that deals with files. The second option is faster, since you’re not using your own server as a staging point for uploads, and can work with deployments like Heroku that do not provide large amounts of disk space.

+ +

Blobs are intended to be immutable in as-so-far as their reference to a specific file goes. You’re allowed to update a blob’s metadata on a subsequent pass, but you should not update the key or change the uploaded file. If you need to create a derivative or otherwise change the blob, simply create a new blob and purge the old one.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7=["image/jpg", "image/pjpeg", "image/bmp"]
 
INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7=["text/javascript"]
 
MINIMUM_TOKEN_LENGTH=28
 
+ + + + + + +

Class Public methods

+ +
+

+ + compose(blobs, filename:, content_type: nil, metadata: nil) + +

+ + +
+

Concatenate multiple blobs into a single “composed” blob.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 151
+def compose(blobs, filename:, content_type: nil, metadata: nil)
+  raise ActiveRecord::RecordNotSaved, "All blobs must be persisted." if blobs.any?(&:new_record?)
+
+  content_type ||= blobs.pluck(:content_type).compact.first
+
+  new(filename: filename, content_type: content_type, metadata: metadata, byte_size: blobs.sum(&:byte_size)).tap do |combined_blob|
+    combined_blob.compose(blobs.pluck(:key))
+    combined_blob.save!
+  end
+end
+
+
+ +
+ +
+

+ + create_and_upload!(key: nil, io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil) + +

+ + +
+

Creates a new blob instance and then uploads the contents of the given io to the service. The blob instance is going to be saved before the upload begins to prevent the upload clobbering another due to key collisions. When providing a content type, pass identify: false to bypass automatic content type inference.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 105
+def create_and_upload!(key: nil, io:, filename:, content_type: nil, metadata: nil, service_name: nil, identify: true, record: nil)
+  create_after_unfurling!(key: key, io: io, filename: filename, content_type: content_type, metadata: metadata, service_name: service_name, identify: identify).tap do |blob|
+    blob.upload_without_unfurling(io)
+  end
+end
+
+
+ +
+ +
+

+ + create_before_direct_upload!(key: nil, filename:, byte_size:, checksum:, content_type: nil, metadata: nil, service_name: nil, record: nil) + +

+ + +
+

Returns a saved blob without uploading a file to the service. This blob will point to a key where there is no file yet. It’s intended to be used together with a client-side upload, which will first create the blob in order to produce the signed URL for uploading. This signed URL points to the key generated by the blob. Once the form using the direct upload is submitted, the blob can be associated with the right record using the signed ID.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 116
+def create_before_direct_upload!(key: nil, filename:, byte_size:, checksum:, content_type: nil, metadata: nil, service_name: nil, record: nil)
+  create! key: key, filename: filename, byte_size: byte_size, checksum: checksum, content_type: content_type, metadata: metadata, service_name: service_name
+end
+
+
+ +
+ +
+

+ + find_signed(id, record: nil, purpose: :blob_id) + +

+ + +
+

You can use the signed ID of a blob to refer to it on the client side without fear of tampering. This is particularly helpful for direct uploads where the client-side needs to refer to the blob that was created ahead of the upload itself on form submission.

+ +

The signed ID is also used to create stable URLs for the blob through the BlobsController.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 78
+def find_signed(id, record: nil, purpose: :blob_id)
+  super(id, purpose: purpose)
+end
+
+
+ +
+ +
+

+ + find_signed!(id, record: nil, purpose: :blob_id) + +

+ + +
+

Works like find_signed, but will raise an ActiveSupport::MessageVerifier::InvalidSignature exception if the signed_id has either expired, has a purpose mismatch, is for another record, or has been tampered with. It will also raise an ActiveRecord::RecordNotFound exception if the valid signed id can’t find a record.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 86
+def find_signed!(id, record: nil, purpose: :blob_id)
+  super(id, purpose: purpose)
+end
+
+
+ +
+ +
+

+ + generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH) + +

+ + +
+

To prevent problems with case-insensitive filesystems, especially in combination with databases which treat indices as case-sensitive, all blob keys generated are going to only contain the base-36 character alphabet and will therefore be lowercase. To maintain the same or higher amount of entropy as in the base-58 encoding used by has_secure_token the number of bytes used is increased to 28 from the standard 24

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 125
+def generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
+  SecureRandom.base36(length)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + audio?() + +

+ + +
+

Returns true if the content_type of this blob is in the audio range, like audio/mpeg.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 198
+def audio?
+  content_type.start_with?("audio")
+end
+
+
+ +
+ +
+

+ + content_type=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 343
+  def content_type=(value)
+    unless ActiveStorage.silence_invalid_content_types_warning
+      if INVALID_VARIABLE_CONTENT_TYPES_DEPRECATED_IN_RAILS_7.include?(value)
+        ActiveSupport::Deprecation.warn(<<-MSG.squish)
+          #{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
+          If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.variable_content_types`.
+          Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
+        MSG
+      end
+
+      if INVALID_VARIABLE_CONTENT_TYPES_TO_SERVE_AS_BINARY_DEPRECATED_IN_RAILS_7.include?(value)
+        ActiveSupport::Deprecation.warn(<<-MSG.squish)
+          #{value} is not a valid content type, it should not be used when creating a blob, and support for it will be removed in Rails 7.1.
+          If you want to keep supporting this content type past Rails 7.1, add it to `config.active_storage.content_types_to_serve_as_binary`.
+          Dismiss this warning by setting `config.active_storage.silence_invalid_content_types_warning = true`.
+        MSG
+      end
+    end
+
+    super
+  end
+
+
+ +
+ +
+

+ + custom_metadata() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 184
+def custom_metadata
+  self[:metadata][:custom] || {}
+end
+
+
+ +
+ +
+

+ + custom_metadata=(metadata) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 188
+def custom_metadata=(metadata)
+  self[:metadata] = self[:metadata].merge(custom: metadata)
+end
+
+
+ +
+ +
+

+ + delete() + +

+ + +
+

Deletes the files on the service associated with the blob. This should only be done if the blob is going to be deleted as well or you will essentially have a dead reference. It’s recommended to use purge and purge_later methods in most circumstances.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 318
+def delete
+  service.delete(key)
+  service.delete_prefixed("variants/#{key}/") if image?
+end
+
+
+ +
+ +
+

+ + download(&block) + +

+ + +
+

Downloads the file associated with this blob. If no block is given, the entire file is read into memory and returned. That’ll use a lot of RAM for very large files. If a block is given, then the download is streamed and yielded in chunks.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 278
+def download(&block)
+  service.download key, &block
+end
+
+
+ +
+ +
+

+ + download_chunk(range) + +

+ + +
+

Downloads a part of the file associated with this blob.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 283
+def download_chunk(range)
+  service.download_chunk key, range
+end
+
+
+ +
+ +
+

+ + filename() + +

+ + +
+

Returns an ActiveStorage::Filename instance of the filename that can be queried for basename, extension, and a sanitized version of the filename that’s safe to use in URLs.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 180
+def filename
+  ActiveStorage::Filename.new(self[:filename])
+end
+
+
+ +
+ +
+

+ + image?() + +

+ + +
+

Returns true if the content_type of this blob is in the image range, like image/png.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 193
+def image?
+  content_type.start_with?("image")
+end
+
+
+ +
+ +
+

+ + key() + +

+ + +
+

Returns the key pointing to the file on the service that’s associated with this blob. The key is the secure-token format from Rails in lower case. So it’ll look like: xtapjjcjiudrlk3tmwyjgpuobabd. This key is not intended to be revealed directly to the user. Always refer to blobs using the signed_id or a verified form of the key.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 172
+def key
+  # We can't wait until the record is first saved to have a key for it
+  self[:key] ||= self.class.generate_unique_secure_token(length: MINIMUM_TOKEN_LENGTH)
+end
+
+
+ +
+ +
+

+ + open(tmpdir: nil, &block) + +

+ + +
+

Downloads the blob to a tempfile on disk. Yields the tempfile.

+ +

The tempfile’s name is prefixed with ActiveStorage- and the blob’s ID. Its extension matches that of the blob.

+ +

By default, the tempfile is created in Dir.tmpdir. Pass tmpdir: to create it in a different directory:

+ +
blob.open(tmpdir: "/path/to/tmp") do |file|
+  # ...
+end
+
+ +

The tempfile is automatically closed and unlinked after the given block is executed.

+ +

Raises ActiveStorage::IntegrityError if the downloaded data does not match the blob’s checksum.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 300
+def open(tmpdir: nil, &block)
+  service.open(
+    key,
+    checksum: checksum,
+    verify: !composed,
+    name: [ "ActiveStorage-#{id}-", filename.extension_with_delimiter ],
+    tmpdir: tmpdir,
+    &block
+  )
+end
+
+
+ +
+ +
+

+ + purge() + +

+ + +
+

Destroys the blob record and then deletes the file on the service. This is the recommended way to dispose of unwanted blobs. Note, though, that deleting the file off the service will initiate an HTTP connection to the service, which may be slow or prevented, so you should not use this method inside a transaction or in callbacks. Use purge_later instead.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 326
+def purge
+  destroy
+  delete if previously_persisted?
+rescue ActiveRecord::InvalidForeignKey
+end
+
+
+ +
+ +
+

+ + purge_later() + +

+ + +
+

Enqueues an ActiveStorage::PurgeJob to call purge. This is the recommended way to purge blobs from a transaction, an Active Record callback, or in any other real-time scenario.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 334
+def purge_later
+  ActiveStorage::PurgeJob.perform_later(self)
+end
+
+
+ +
+ +
+

+ + service() + +

+ + +
+

Returns an instance of service, which can be configured globally or per attachment

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 339
+def service
+  services.fetch(service_name)
+end
+
+
+ +
+ +
+

+ + service_headers_for_direct_upload() + +

+ + +
+

Returns a Hash of headers for service_url_for_direct_upload requests.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 228
+def service_headers_for_direct_upload
+  service.headers_for_direct_upload key, filename: filename, content_type: content_type, content_length: byte_size, checksum: checksum, custom_metadata: custom_metadata
+end
+
+
+ +
+ +
+

+ + service_url_for_direct_upload(expires_in: ActiveStorage.service_urls_expire_in) + +

+ + +
+

Returns a URL that can be used to directly upload a file for this blob on the service. This URL is intended to be short-lived for security and only generated on-demand by the client-side JavaScript responsible for doing the uploading.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 223
+def service_url_for_direct_upload(expires_in: ActiveStorage.service_urls_expire_in)
+  service.url_for_direct_upload key, expires_in: expires_in, content_type: content_type, content_length: byte_size, checksum: checksum, custom_metadata: custom_metadata
+end
+
+
+ +
+ +
+

+ + signed_id(purpose: :blob_id, expires_in: nil) + +

+ + +
+

Returns a signed ID for this blob that’s suitable for reference on the client-side without fear of tampering.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 164
+def signed_id(purpose: :blob_id, expires_in: nil)
+  super
+end
+
+
+ +
+ +
+

+ + text?() + +

+ + +
+

Returns true if the content_type of this blob is in the text range, like text/plain.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 208
+def text?
+  content_type.start_with?("text")
+end
+
+
+ +
+ +
+

+ + upload(io, identify: true) + +

+ + +
+

Uploads the io to the service on the key for this blob. Blobs are intended to be immutable, so you shouldn’t be using this method after a file has already been uploaded to fit with a blob. If you want to create a derivative blob, you should instead simply create a new blob based on the old one.

+ +

Prior to uploading, we compute the checksum, which is sent to the service for transit integrity validation. If the checksum does not match what the service receives, an exception will be raised. We also measure the size of the io and store that in byte_size on the blob record. The content type is automatically extracted from the io unless you specify a content_type and pass identify as false.

+ +

Normally, you do not have to call this method directly at all. Use the create_and_upload! class method instead. If you do use this method directly, make sure you are using it on a persisted Blob as otherwise another blob’s data might get overwritten on the service.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 255
+def upload(io, identify: true)
+  unfurl io, identify: identify
+  upload_without_unfurling io
+end
+
+
+ +
+ +
+

+ + url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline, filename: nil, **options) + +

+ + +
+

Returns the URL of the blob on the service. This returns a permanent URL for public files, and returns a short-lived URL for private files. Private files are signed, and not for public use. Instead, the URL should only be exposed as a redirect from a stable, possibly authenticated URL. Hiding the URL behind a redirect also allows you to change services without updating all URLs.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 216
+def url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline, filename: nil, **options)
+  service.url key, expires_in: expires_in, filename: ActiveStorage::Filename.wrap(filename || self.filename),
+    content_type: content_type_for_serving, disposition: forced_disposition_for_serving || disposition, **options
+end
+
+
+ +
+ +
+

+ + video?() + +

+ + +
+

Returns true if the content_type of this blob is in the video range, like video/mp4.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob.rb, line 203
+def video?
+  content_type.start_with?("video")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blob/Analyzable.html b/src/7.0/classes/ActiveStorage/Blob/Analyzable.html new file mode 100644 index 0000000000..1286b5a564 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blob/Analyzable.html @@ -0,0 +1,200 @@ +--- +title: ActiveStorage::Blob::Analyzable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + analyze() + +

+ + +
+

Extracts and stores metadata from the file associated with this blob using a relevant analyzer. Active Storage comes with built-in analyzers for images and videos. See ActiveStorage::Analyzer::ImageAnalyzer and ActiveStorage::Analyzer::VideoAnalyzer for information about the specific attributes they extract and the third-party libraries they require.

+ +

To choose the analyzer for a blob, Active Storage calls accept? on each registered analyzer in order. It uses the first analyzer for which accept? returns true when given the blob. If no registered analyzer accepts the blob, no metadata is extracted from it.

+ +

In a Rails application, add or remove analyzers by manipulating Rails.application.config.active_storage.analyzers in an initializer:

+ +
# Add a custom analyzer for Microsoft Office documents:
+Rails.application.config.active_storage.analyzers.append DOCXAnalyzer
+
+# Remove the built-in video analyzer:
+Rails.application.config.active_storage.analyzers.delete ActiveStorage::Analyzer::VideoAnalyzer
+
+ +

Outside of a Rails application, manipulate ActiveStorage.analyzers instead.

+ +

You won’t ordinarily need to call this method from a Rails application. New blobs are automatically and asynchronously analyzed via analyze_later when they’re attached for the first time.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/analyzable.rb, line 28
+def analyze
+  update! metadata: metadata.merge(extract_metadata_via_analyzer)
+end
+
+
+ +
+ +
+

+ + analyze_later() + +

+ + +
+

Enqueues an ActiveStorage::AnalyzeJob which calls analyze, or calls analyze inline based on analyzer class configuration.

+ +

This method is automatically called for a blob when it’s attached for the first time. You can call it to analyze a blob again (e.g. if you add a new analyzer or modify an existing one).

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/analyzable.rb, line 36
+def analyze_later
+  if analyzer_class.analyze_later?
+    ActiveStorage::AnalyzeJob.perform_later(self)
+  else
+    analyze
+  end
+end
+
+
+ +
+ +
+

+ + analyzed?() + +

+ + +
+

Returns true if the blob has been analyzed.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/analyzable.rb, line 45
+def analyzed?
+  analyzed
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blob/Identifiable.html b/src/7.0/classes/ActiveStorage/Blob/Identifiable.html new file mode 100644 index 0000000000..646ed16136 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blob/Identifiable.html @@ -0,0 +1,183 @@ +--- +title: ActiveStorage::Blob::Identifiable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + identified?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/identifiable.rb, line 16
+def identified?
+  identified
+end
+
+
+ +
+ +
+

+ + identify() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/identifiable.rb, line 4
+def identify
+  identify_without_saving
+  save!
+end
+
+
+ +
+ +
+

+ + identify_without_saving() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/identifiable.rb, line 9
+def identify_without_saving
+  unless identified?
+    self.content_type = identify_content_type
+    self.identified = true
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blob/Representable.html b/src/7.0/classes/ActiveStorage/Blob/Representable.html new file mode 100644 index 0000000000..4450de91af --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blob/Representable.html @@ -0,0 +1,342 @@ +--- +title: ActiveStorage::Blob::Representable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + preview(transformations) + +

+ + +
+

Returns an ActiveStorage::Preview instance with the set of transformations provided. A preview is an image generated from a non-image blob. Active Storage comes with built-in previewers for videos and PDF documents. The video previewer extracts the first frame from a video and the PDF previewer extracts the first page from a PDF document.

+ +
blob.preview(resize_to_limit: [100, 100]).processed.url
+
+ +

Avoid processing previews synchronously in views. Instead, link to a controller action that processes them on demand. Active Storage provides one, but you may want to create your own (for example, if you need authentication). Here’s how to use the built-in version:

+ +
<%= image_tag video.preview(resize_to_limit: [100, 100]) %>
+
+ +

This method raises ActiveStorage::UnpreviewableError if no previewer accepts the receiving blob. To determine whether a blob is accepted by any previewer, call ActiveStorage::Blob#previewable?.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 63
+def preview(transformations)
+  if previewable?
+    ActiveStorage::Preview.new(self, transformations)
+  else
+    raise ActiveStorage::UnpreviewableError
+  end
+end
+
+
+ +
+ +
+

+ + previewable?() + +

+ + +
+

Returns true if any registered previewer accepts the blob. By default, this will return true for videos and PDF documents.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 72
+def previewable?
+  ActiveStorage.previewers.any? { |klass| klass.accept?(self) }
+end
+
+
+ +
+ +
+

+ + representable?() + +

+ + +
+

Returns true if the blob is variable or previewable.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 97
+def representable?
+  variable? || previewable?
+end
+
+
+ +
+ +
+

+ + representation(transformations) + +

+ + +
+

Returns an ActiveStorage::Preview for a previewable blob or an ActiveStorage::Variant for a variable image blob.

+ +
blob.representation(resize_to_limit: [100, 100]).processed.url
+
+ +

Raises ActiveStorage::UnrepresentableError if the receiving blob is neither variable nor previewable. Call ActiveStorage::Blob#representable? to determine whether a blob is representable.

+ +

See ActiveStorage::Blob#preview and ActiveStorage::Blob#variant for more information.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 85
+def representation(transformations)
+  case
+  when previewable?
+    preview transformations
+  when variable?
+    variant transformations
+  else
+    raise ActiveStorage::UnrepresentableError
+  end
+end
+
+
+ +
+ +
+

+ + variable?() + +

+ + +
+

Returns true if the variant processor can transform the blob (its content type is in ActiveStorage.variable_content_types).

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 44
+def variable?
+  ActiveStorage.variable_content_types.include?(content_type)
+end
+
+
+ +
+ +
+

+ + variant(transformations) + +

+ + +
+

Returns an ActiveStorage::Variant or ActiveStorage::VariantWithRecord instance with the set of transformations provided. This is only relevant for image files, and it allows any image to be transformed for size, colors, and the like. Example:

+ +
avatar.variant(resize_to_limit: [100, 100]).processed.url
+
+ +

This will create and process a variant of the avatar blob that’s constrained to a height and width of 100px. Then it’ll upload said variant to the service according to a derivative key of the blob and the transformations.

+ +

Frequently, though, you don’t actually want to transform the variant right away. But rather simply refer to a specific variant that can be created by a controller on-demand. Like so:

+ +
<%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
+
+ +

This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController can then produce on-demand.

+ +

Raises ActiveStorage::InvariableError if the variant processor cannot transform the blob. To determine whether a blob is variable, call ActiveStorage::Blob#variable?.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/blob/representable.rb, line 34
+def variant(transformations)
+  if variable?
+    variant_class.new(self, ActiveStorage::Variation.wrap(transformations).default_to(default_variant_transformations))
+  else
+    raise ActiveStorage::InvariableError
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blobs.html b/src/7.0/classes/ActiveStorage/Blobs.html new file mode 100644 index 0000000000..96a0c1b040 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blobs.html @@ -0,0 +1,71 @@ +--- +title: ActiveStorage::Blobs +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blobs/ProxyController.html b/src/7.0/classes/ActiveStorage/Blobs/ProxyController.html new file mode 100644 index 0000000000..2f0ca3d7b0 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blobs/ProxyController.html @@ -0,0 +1,138 @@ +--- +title: ActiveStorage::Blobs::ProxyController +layout: default +--- +
+ +
+
+ +
+ +

Proxy files through application. This avoids having a redirect and makes files easier to cache.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/blobs/proxy_controller.rb, line 13
+def show
+  if request.headers["Range"].present?
+    send_blob_byte_range_data @blob, request.headers["Range"]
+  else
+    http_cache_forever public: true do
+      response.headers["Accept-Ranges"] = "bytes"
+      response.headers["Content-Length"] = @blob.byte_size.to_s
+
+      send_blob_stream @blob, disposition: params[:disposition]
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Blobs/RedirectController.html b/src/7.0/classes/ActiveStorage/Blobs/RedirectController.html new file mode 100644 index 0000000000..a5c091db90 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Blobs/RedirectController.html @@ -0,0 +1,116 @@ +--- +title: ActiveStorage::Blobs::RedirectController +layout: default +--- +
+ +
+
+ +
+ +

Take a signed permanent reference for a blob and turn it into an expiring service URL for download.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/blobs/redirect_controller.rb, line 12
+def show
+  expires_in ActiveStorage.service_urls_expire_in
+  redirect_to @blob.url(disposition: params[:disposition]), allow_other_host: true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/DirectUploadsController.html b/src/7.0/classes/ActiveStorage/DirectUploadsController.html new file mode 100644 index 0000000000..0d7a485bdb --- /dev/null +++ b/src/7.0/classes/ActiveStorage/DirectUploadsController.html @@ -0,0 +1,114 @@ +--- +title: ActiveStorage::DirectUploadsController +layout: default +--- +
+ +
+
+ +
+ +

Creates a new blob on the server side in anticipation of a direct-to-service upload from the client side. When the client-side upload is completed, the signed_blob_id can be submitted as part of the form to reference the blob that was created up front.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/direct_uploads_controller.rb, line 7
+def create
+  blob = ActiveStorage::Blob.create_before_direct_upload!(**blob_args)
+  render json: direct_upload_json(blob)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/DiskController.html b/src/7.0/classes/ActiveStorage/DiskController.html new file mode 100644 index 0000000000..49be0ab314 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/DiskController.html @@ -0,0 +1,169 @@ +--- +title: ActiveStorage::DiskController +layout: default +--- +
+ +
+
+ +
+ +

Serves files stored with the disk service in the same way that the cloud services do. This means using expiring, signed URLs that are meant for immediate access, not permanent linking. Always go through the BlobsController, or your own authenticated controller, rather than directly to the service URL.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/disk_controller.rb, line 12
+def show
+  if key = decode_verified_key
+    serve_file named_disk_service(key[:service_name]).path_for(key[:key]), content_type: key[:content_type], disposition: key[:disposition]
+  else
+    head :not_found
+  end
+rescue Errno::ENOENT
+  head :not_found
+end
+
+
+ +
+ +
+

+ + update() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/disk_controller.rb, line 22
+def update
+  if token = decode_verified_token
+    if acceptable_content?(token)
+      named_disk_service(token[:service_name]).upload token[:key], request.body, checksum: token[:checksum]
+      head :no_content
+    else
+      head :unprocessable_entity
+    end
+  else
+    head :not_found
+  end
+rescue ActiveStorage::IntegrityError
+  head :unprocessable_entity
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Error.html b/src/7.0/classes/ActiveStorage/Error.html new file mode 100644 index 0000000000..08540c5b8b --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Error.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::Error +layout: default +--- +
+ +
+
+ +
+ +

Generic base class for all Active Storage exceptions.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/FileNotFoundError.html b/src/7.0/classes/ActiveStorage/FileNotFoundError.html new file mode 100644 index 0000000000..986458f12d --- /dev/null +++ b/src/7.0/classes/ActiveStorage/FileNotFoundError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::FileNotFoundError +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveStorage::Blob#download is called on a blob where the backing file is no longer present in its service.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Filename.html b/src/7.0/classes/ActiveStorage/Filename.html new file mode 100644 index 0000000000..ef6b1f88cb --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Filename.html @@ -0,0 +1,532 @@ +--- +title: ActiveStorage::Filename +layout: default +--- +
+ +
+
+ +
+ +

Encapsulates a string representing a filename to provide convenient access to parts of it and sanitization. A Filename instance is returned by ActiveStorage::Blob#filename, and is comparable so it can be used for sorting.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Comparable + +
  • + +
+ + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(filename) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 16
+def initialize(filename)
+  @filename = filename
+end
+
+
+ +
+ +
+

+ + wrap(filename) + +

+ + +
+

Returns a Filename instance based on the given filename. If the filename is a Filename, it is returned unmodified. If it is a String, it is passed to ActiveStorage::Filename.new.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 11
+def wrap(filename)
+  filename.kind_of?(self) ? filename : new(filename)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 74
+def <=>(other)
+  to_s.downcase <=> other.to_s.downcase
+end
+
+
+ +
+ +
+

+ + as_json(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 66
+def as_json(*)
+  to_s
+end
+
+
+ +
+ +
+

+ + base() + +

+ + +
+

Returns the part of the filename preceding any extension.

+ +
ActiveStorage::Filename.new("racecar.jpg").base # => "racecar"
+ActiveStorage::Filename.new("racecar").base     # => "racecar"
+ActiveStorage::Filename.new(".gitignore").base  # => ".gitignore"
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 25
+def base
+  File.basename @filename, extension_with_delimiter
+end
+
+
+ +
+ +
+

+ + extension() + +

+ + +
+ +
+ + + + + + + + + +
+ +
+

+ + extension_with_delimiter() + +

+ + +
+

Returns the extension of the filename (i.e. the substring following the last dot, excluding a dot at the beginning) with the dot that precedes it. If the filename has no extension, an empty string is returned.

+ +
ActiveStorage::Filename.new("racecar.jpg").extension_with_delimiter # => ".jpg"
+ActiveStorage::Filename.new("racecar").extension_with_delimiter     # => ""
+ActiveStorage::Filename.new(".gitignore").extension_with_delimiter  # => ""
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 35
+def extension_with_delimiter
+  File.extname @filename
+end
+
+
+ +
+ +
+

+ + extension_without_delimiter() + +

+ + +
+

Returns the extension of the filename (i.e. the substring following the last dot, excluding a dot at the beginning). If the filename has no extension, an empty string is returned.

+ +
ActiveStorage::Filename.new("racecar.jpg").extension_without_delimiter # => "jpg"
+ActiveStorage::Filename.new("racecar").extension_without_delimiter     # => ""
+ActiveStorage::Filename.new(".gitignore").extension_without_delimiter  # => ""
+
+
+ + + +
+ Also aliased as: extension +
+ + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 45
+def extension_without_delimiter
+  extension_with_delimiter.from(1).to_s
+end
+
+
+ +
+ +
+

+ + sanitized() + +

+ + +
+

Returns the sanitized filename.

+ +
ActiveStorage::Filename.new("foo:bar.jpg").sanitized # => "foo-bar.jpg"
+ActiveStorage::Filename.new("foo/bar.jpg").sanitized # => "foo-bar.jpg"
+
+ +

Characters considered unsafe for storage (e.g. , $, and the RTL override character) are replaced with a dash.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 57
+def sanitized
+  @filename.encode(Encoding::UTF_8, invalid: :replace, undef: :replace, replace: "�").strip.tr("\u{202E}%$|:;/\t\r\n\\", "-")
+end
+
+
+ +
+ +
+

+ + to_json() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 70
+def to_json
+  to_s
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+

Returns the sanitized version of the filename.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/filename.rb, line 62
+def to_s
+  sanitized.to_s
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/FixtureSet.html b/src/7.0/classes/ActiveStorage/FixtureSet.html new file mode 100644 index 0000000000..79fcc6d7a5 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/FixtureSet.html @@ -0,0 +1,221 @@ +--- +title: ActiveStorage::FixtureSet +layout: default +--- +
+ +
+
+ +
+ +

Fixtures are a way of organizing data that you want to test against; in short, sample data.

+ +

To learn more about fixtures, read the ActiveRecord::FixtureSet documentation.

+ +

YAML

+ +

Like other Active Record-backed models, ActiveStorage::Attachment and ActiveStorage::Blob records inherit from ActiveRecord::Base instances and therefore can be populated by fixtures.

+ +

Consider a hypothetical Article model class, its related fixture data, as well as fixture data for related ActiveStorage::Attachment and ActiveStorage::Blob records:

+ +
# app/models/article.rb
+class Article < ApplicationRecord
+  has_one_attached :thumbnail
+end
+
+# fixtures/active_storage/blobs.yml
+first_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob filename: "first.png" %>
+
+# fixtures/active_storage/attachments.yml
+first_thumbnail_attachment:
+  name: thumbnail
+  record: first (Article)
+  blob: first_thumbnail_blob
+
+ +

When processed, Active Record will insert database records for each fixture entry and will ensure the Active Storage relationship is intact.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + blob(filename:, **attributes) + +

+ + +
+

Generate a YAML-encoded representation of an ActiveStorage::Blob instance’s attributes, resolve the file relative to the directory mentioned by ActiveSupport::Testing::FileFixtures.file_fixture, and upload the file to the Service

+ +

Examples

+ +
# tests/fixtures/action_text/blobs.yml
+second_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob(
+  filename: "second.svg",
+) %>
+
+third_thumbnail_blob: <%= ActiveStorage::FixtureSet.blob(
+  filename: "third.svg",
+  content_type: "image/svg+xml",
+  service_name: "public"
+) %>
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/fixture_set.rb, line 60
+def self.blob(filename:, **attributes)
+  new.prepare Blob.new(filename: filename, key: generate_unique_secure_token), **attributes
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + prepare(instance, **attributes) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/fixture_set.rb, line 64
+def prepare(instance, **attributes)
+  io = file_fixture(instance.filename.to_s).open
+  instance.unfurl(io)
+  instance.assign_attributes(attributes)
+  instance.upload_without_unfurling(io)
+
+  instance.attributes.transform_values { |value| value.is_a?(Hash) ? value.to_json : value }.compact.to_json
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/IntegrityError.html b/src/7.0/classes/ActiveStorage/IntegrityError.html new file mode 100644 index 0000000000..db7b87c5ff --- /dev/null +++ b/src/7.0/classes/ActiveStorage/IntegrityError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::IntegrityError +layout: default +--- +
+ +
+
+ +
+ +

Raised when uploaded or downloaded data does not match a precomputed checksum. Indicates that a network error or a software bug caused data corruption.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/InvariableError.html b/src/7.0/classes/ActiveStorage/InvariableError.html new file mode 100644 index 0000000000..e32d3b9ca5 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/InvariableError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::InvariableError +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveStorage::Blob#variant is called on a blob that isn’t variable. Use ActiveStorage::Blob#variable? to determine whether a blob is variable.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/LogSubscriber.html b/src/7.0/classes/ActiveStorage/LogSubscriber.html new file mode 100644 index 0000000000..993b9bfac4 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/LogSubscriber.html @@ -0,0 +1,416 @@ +--- +title: ActiveStorage::LogSubscriber +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 41
+def logger
+  ActiveStorage.logger
+end
+
+
+ +
+ +
+

+ + service_delete(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 19
+def service_delete(event)
+  info event, color("Deleted file from key: #{key_in(event)}", RED)
+end
+
+
+ +
+ +
+

+ + service_delete_prefixed(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 23
+def service_delete_prefixed(event)
+  info event, color("Deleted files by key prefix: #{event.payload[:prefix]}", RED)
+end
+
+
+ +
+ +
+

+ + service_download(event) + +

+ + +
+ +
+ + + +
+ Also aliased as: service_streaming_download +
+ + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 13
+def service_download(event)
+  info event, color("Downloaded file from key: #{key_in(event)}", BLUE)
+end
+
+
+ +
+ +
+

+ + service_exist(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 27
+def service_exist(event)
+  debug event, color("Checked if file exists at key: #{key_in(event)} (#{event.payload[:exist] ? "yes" : "no"})", BLUE)
+end
+
+
+ +
+ +
+

+ + service_mirror(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 35
+def service_mirror(event)
+  message = "Mirrored file at key: #{key_in(event)}"
+  message += " (checksum: #{event.payload[:checksum]})" if event.payload[:checksum]
+  debug event, color(message, GREEN)
+end
+
+
+ +
+ +
+

+ + service_streaming_download(event) + +

+ + +
+ +
+ + + + + +
+ Alias for: service_download +
+ + + +
+ +
+

+ + service_upload(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 7
+def service_upload(event)
+  message = "Uploaded file to key: #{key_in(event)}"
+  message += " (checksum: #{event.payload[:checksum]})" if event.payload[:checksum]
+  info event, color(message, GREEN)
+end
+
+
+ +
+ +
+

+ + service_url(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/log_subscriber.rb, line 31
+def service_url(event)
+  debug event, color("Generated URL for file at key: #{key_in(event)} (#{event.payload[:url]})", BLUE)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/MirrorJob.html b/src/7.0/classes/ActiveStorage/MirrorJob.html new file mode 100644 index 0000000000..3b98a46e55 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/MirrorJob.html @@ -0,0 +1,113 @@ +--- +title: ActiveStorage::MirrorJob +layout: default +--- +
+ +
+
+ +
+ +

Provides asynchronous mirroring of directly-uploaded blobs.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform(key, checksum:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/jobs/active_storage/mirror_job.rb, line 12
+def perform(key, checksum:)
+  ActiveStorage::Blob.service.try(:mirror, key, checksum: checksum)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Preview.html b/src/7.0/classes/ActiveStorage/Preview.html new file mode 100644 index 0000000000..1dbccf92fd --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Preview.html @@ -0,0 +1,384 @@ +--- +title: ActiveStorage::Preview +layout: default +--- +
+ +
+
+ +
+ +

Some non-image blobs can be previewed: that is, they can be presented as images. A video blob can be previewed by extracting its first frame, and a PDF blob can be previewed by extracting its first page.

+ +

A previewer extracts a preview image from a blob. Active Storage provides previewers for videos and PDFs. ActiveStorage::Previewer::VideoPreviewer is used for videos whereas ActiveStorage::Previewer::PopplerPDFPreviewer and ActiveStorage::Previewer::MuPDFPreviewer are used for PDFs. Build custom previewers by subclassing ActiveStorage::Previewer and implementing the requisite methods. Consult the ActiveStorage::Previewer documentation for more details on what’s required of previewers.

+ +

To choose the previewer for a blob, Active Storage calls accept? on each registered previewer in order. It uses the first previewer for which accept? returns true when given the blob. In a Rails application, add or remove previewers by manipulating Rails.application.config.active_storage.previewers in an initializer:

+ +
Rails.application.config.active_storage.previewers
+# => [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
+
+# Add a custom previewer for Microsoft Office documents:
+Rails.application.config.active_storage.previewers << DOCXPreviewer
+# => [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer, DOCXPreviewer ]
+
+ +

Outside of a Rails application, modify ActiveStorage.previewers instead.

+ +

The built-in previewers rely on third-party system libraries. Specifically, the built-in video previewer requires FFmpeg. Two PDF previewers are provided: one requires Poppler, and the other requires muPDF (version 1.8 or newer). To preview PDFs, install either Poppler or muPDF.

+ +

These libraries are not provided by Rails. You must install them yourself to use the built-in previewers. Before you install and use third-party software, make sure you understand the licensing implications of doing so.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + blob
+ [R] + variation
+ + + + +

Class Public methods

+ +
+

+ + new(blob, variation_or_variation_key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 36
+def initialize(blob, variation_or_variation_key)
+  @blob, @variation = blob, ActiveStorage::Variation.wrap(variation_or_variation_key)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + download(&block) + +

+ + +
+

Downloads the file associated with this preview’s variant. If no block is given, the entire file is read into memory and returned. That’ll use a lot of RAM for very large files. If a block is given, then the download is streamed and yielded in chunks. Raises ActiveStorage::Preview::UnprocessedError if the preview has not been processed yet.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 83
+def download(&block)
+  if processed?
+    variant.download(&block)
+  else
+    raise UnprocessedError
+  end
+end
+
+
+ +
+ +
+

+ + image() + +

+ + +
+

Returns the blob’s attached preview image.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 52
+def image
+  blob.preview_image
+end
+
+
+ +
+ +
+

+ + key() + +

+ + +
+

Returns a combination key of the blob and the variation that together identifies a specific variant.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 70
+def key
+  if processed?
+    variant.key
+  else
+    raise UnprocessedError
+  end
+end
+
+
+ +
+ +
+

+ + processed() + +

+ + +
+

Processes the preview if it has not been processed yet. Returns the receiving Preview instance for convenience:

+ +
blob.preview(resize_to_limit: [100, 100]).processed.url
+
+ +

Processing a preview generates an image from its blob and attaches the preview image to the blob. Because the preview image is stored with the blob, it is only generated once.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 46
+def processed
+  process unless processed?
+  self
+end
+
+
+ +
+ +
+

+ + url(**options) + +

+ + +
+

Returns the URL of the preview’s variant on the service. Raises ActiveStorage::Preview::UnprocessedError if the preview has not been processed yet.

+ +

This method synchronously processes a variant of the preview image, so do not call it in views. Instead, generate a stable URL that redirects to the URL returned by this method.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/preview.rb, line 61
+def url(**options)
+  if processed?
+    variant.url(**options)
+  else
+    raise UnprocessedError
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Preview/UnprocessedError.html b/src/7.0/classes/ActiveStorage/Preview/UnprocessedError.html new file mode 100644 index 0000000000..722ee88e66 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Preview/UnprocessedError.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::Preview::UnprocessedError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/PreviewError.html b/src/7.0/classes/ActiveStorage/PreviewError.html new file mode 100644 index 0000000000..9349a97399 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/PreviewError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::PreviewError +layout: default +--- +
+ +
+
+ +
+ +

Raised when a Previewer is unable to generate a preview image.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Previewer.html b/src/7.0/classes/ActiveStorage/Previewer.html new file mode 100644 index 0000000000..dc47347deb --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Previewer.html @@ -0,0 +1,409 @@ +--- +title: ActiveStorage::Previewer +layout: default +--- +
+ +
+
+ +
+ +

This is an abstract base class for previewers, which generate images from blobs. See ActiveStorage::Previewer::MuPDFPreviewer and ActiveStorage::Previewer::VideoPreviewer for examples of concrete subclasses.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + blob
+ + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+

Implement this method in a concrete subclass. Have it return true when given a blob from which the previewer can generate an image.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 12
+def self.accept?(blob)
+  false
+end
+
+
+ +
+ +
+

+ + new(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 16
+def initialize(blob)
+  @blob = blob
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + preview(**options) + +

+ + +
+

Override this method in a concrete subclass. Have it yield an attachable preview image (i.e. anything accepted by ActiveStorage::Attached::One#attach). Pass the additional options to the underlying blob that is created.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 23
+def preview(**options)
+  raise NotImplementedError
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + download_blob_to_tempfile(&block) + +

+ + +
+

Downloads the blob to a tempfile on disk. Yields the tempfile.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 29
+def download_blob_to_tempfile(&block) # :doc:
+  blob.open tmpdir: tmpdir, &block
+end
+
+
+ +
+ +
+

+ + draw(*argv) + +

+ + +
+

Executes a system command, capturing its binary output in a tempfile. Yields the tempfile.

+ +

Use this method to shell out to a system library (e.g. muPDF or FFmpeg) for preview image generation. The resulting tempfile can be used as the :io value in an attachable Hash:

+ +
def preview
+  download_blob_to_tempfile do |input|
+    draw "my-drawing-command", input.path, "--format", "png", "-" do |output|
+      yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png"
+    end
+  end
+end
+
+ +

The output tempfile is opened in the directory returned by tmpdir.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 47
+def draw(*argv) # :doc:
+  open_tempfile do |file|
+    instrument :preview, key: blob.key do
+      capture(*argv, to: file)
+    end
+
+    yield file
+  end
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 86
+def logger # :doc:
+  ActiveStorage.logger
+end
+
+
+ +
+ +
+

+ + tmpdir() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer.rb, line 90
+def tmpdir # :doc:
+  Dir.tmpdir
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Previewer/MuPDFPreviewer.html b/src/7.0/classes/ActiveStorage/Previewer/MuPDFPreviewer.html new file mode 100644 index 0000000000..b4d3919cdb --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Previewer/MuPDFPreviewer.html @@ -0,0 +1,235 @@ +--- +title: ActiveStorage::Previewer::MuPDFPreviewer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/mupdf_previewer.rb, line 6
+def accept?(blob)
+  blob.content_type == "application/pdf" && mutool_exists?
+end
+
+
+ +
+ +
+

+ + mutool_exists?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/mupdf_previewer.rb, line 14
+def mutool_exists?
+  return @mutool_exists if defined?(@mutool_exists) && !@mutool_exists.nil?
+
+  system mutool_path, out: File::NULL, err: File::NULL
+
+  @mutool_exists = $?.exitstatus == 1
+end
+
+
+ +
+ +
+

+ + mutool_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/mupdf_previewer.rb, line 10
+def mutool_path
+  ActiveStorage.paths[:mutool] || "mutool"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + preview(**options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/mupdf_previewer.rb, line 23
+def preview(**options)
+  download_blob_to_tempfile do |input|
+    draw_first_page_from input do |output|
+      yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png", **options
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Previewer/PopplerPDFPreviewer.html b/src/7.0/classes/ActiveStorage/Previewer/PopplerPDFPreviewer.html new file mode 100644 index 0000000000..bdc1eef7d8 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Previewer/PopplerPDFPreviewer.html @@ -0,0 +1,233 @@ +--- +title: ActiveStorage::Previewer::PopplerPDFPreviewer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb, line 6
+def accept?(blob)
+  blob.content_type == "application/pdf" && pdftoppm_exists?
+end
+
+
+ +
+ +
+

+ + pdftoppm_exists?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb, line 14
+def pdftoppm_exists?
+  return @pdftoppm_exists if defined?(@pdftoppm_exists)
+
+  @pdftoppm_exists = system(pdftoppm_path, "-v", out: File::NULL, err: File::NULL)
+end
+
+
+ +
+ +
+

+ + pdftoppm_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb, line 10
+def pdftoppm_path
+  ActiveStorage.paths[:pdftoppm] || "pdftoppm"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + preview(**options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/poppler_pdf_previewer.rb, line 21
+def preview(**options)
+  download_blob_to_tempfile do |input|
+    draw_first_page_from input do |output|
+      yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png", **options
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Previewer/VideoPreviewer.html b/src/7.0/classes/ActiveStorage/Previewer/VideoPreviewer.html new file mode 100644 index 0000000000..962264263e --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Previewer/VideoPreviewer.html @@ -0,0 +1,233 @@ +--- +title: ActiveStorage::Previewer::VideoPreviewer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + accept?(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/video_previewer.rb, line 8
+def accept?(blob)
+  blob.video? && ffmpeg_exists?
+end
+
+
+ +
+ +
+

+ + ffmpeg_exists?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/video_previewer.rb, line 12
+def ffmpeg_exists?
+  return @ffmpeg_exists if defined?(@ffmpeg_exists)
+
+  @ffmpeg_exists = system(ffmpeg_path, "-version", out: File::NULL, err: File::NULL)
+end
+
+
+ +
+ +
+

+ + ffmpeg_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/video_previewer.rb, line 18
+def ffmpeg_path
+  ActiveStorage.paths[:ffmpeg] || "ffmpeg"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + preview(**options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/previewer/video_previewer.rb, line 23
+def preview(**options)
+  download_blob_to_tempfile do |input|
+    draw_relevant_frame_from input do |output|
+      yield io: output, filename: "#{blob.filename.base}.jpg", content_type: "image/jpeg", **options
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/PurgeJob.html b/src/7.0/classes/ActiveStorage/PurgeJob.html new file mode 100644 index 0000000000..709a9116a2 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/PurgeJob.html @@ -0,0 +1,113 @@ +--- +title: ActiveStorage::PurgeJob +layout: default +--- +
+ +
+
+ +
+ +

Provides asynchronous purging of ActiveStorage::Blob records via ActiveStorage::Blob#purge_later.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + perform(blob) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/jobs/active_storage/purge_job.rb, line 10
+def perform(blob)
+  blob.purge
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Reflection.html b/src/7.0/classes/ActiveStorage/Reflection.html new file mode 100644 index 0000000000..8da5654c44 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Reflection.html @@ -0,0 +1,67 @@ +--- +title: ActiveStorage::Reflection +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions.html b/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions.html new file mode 100644 index 0000000000..c908e070e1 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions.html @@ -0,0 +1,67 @@ +--- +title: ActiveStorage::Reflection::ActiveRecordExtensions +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions/ClassMethods.html b/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions/ClassMethods.html new file mode 100644 index 0000000000..102ae8c37c --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Reflection/ActiveRecordExtensions/ClassMethods.html @@ -0,0 +1,144 @@ +--- +title: ActiveStorage::Reflection::ActiveRecordExtensions::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + reflect_on_all_attachments() + +

+ + +
+

Returns an array of reflection objects for all the attachments in the class.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/reflection.rb, line 59
+def reflect_on_all_attachments
+  attachment_reflections.values
+end
+
+
+ +
+ +
+

+ + reflect_on_attachment(attachment) + +

+ + +
+

Returns the reflection object for the named attachment.

+ +
User.reflect_on_attachment(:avatar)
+# => the avatar reflection
+
+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/reflection.rb, line 68
+def reflect_on_attachment(attachment)
+  attachment_reflections[attachment.to_s]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Representations.html b/src/7.0/classes/ActiveStorage/Representations.html new file mode 100644 index 0000000000..37cccea271 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Representations.html @@ -0,0 +1,73 @@ +--- +title: ActiveStorage::Representations +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Representations/ProxyController.html b/src/7.0/classes/ActiveStorage/Representations/ProxyController.html new file mode 100644 index 0000000000..404bb35f8d --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Representations/ProxyController.html @@ -0,0 +1,131 @@ +--- +title: ActiveStorage::Representations::ProxyController +layout: default +--- +
+ +
+
+ +
+ +

Proxy files through application. This avoids having a redirect and makes files easier to cache.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/representations/proxy_controller.rb, line 12
+def show
+  http_cache_forever public: true do
+    send_blob_stream @representation.image, disposition: params[:disposition]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Representations/RedirectController.html b/src/7.0/classes/ActiveStorage/Representations/RedirectController.html new file mode 100644 index 0000000000..c46a2a061f --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Representations/RedirectController.html @@ -0,0 +1,116 @@ +--- +title: ActiveStorage::Representations::RedirectController +layout: default +--- +
+ +
+
+ +
+ +

Take a signed permanent reference for a blob representation and turn it into an expiring service URL for download.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/active_storage/representations/redirect_controller.rb, line 10
+def show
+  expires_in ActiveStorage.service_urls_expire_in
+  redirect_to @representation.url(disposition: params[:disposition]), allow_other_host: true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service.html b/src/7.0/classes/ActiveStorage/Service.html new file mode 100644 index 0000000000..d035050280 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service.html @@ -0,0 +1,717 @@ +--- +title: ActiveStorage::Service +layout: default +--- +
+ +
+
+ +
+ +

Abstract class serving as an interface for concrete services.

+ +

The available services are:

+
  • +

    Disk, to manage attachments saved directly on the hard drive.

    +
  • +

    GCS, to manage attachments through Google Cloud Storage.

    +
  • +

    S3, to manage attachments through Amazon S3.

    +
  • +

    AzureStorage, to manage attachments through Microsoft Azure Storage.

    +
  • +

    Mirror, to be able to use several services to manage attachments.

    +
+ +

Inside a Rails application, you can set-up your services through the generated config/storage.yml file and reference one of the aforementioned constant under the service key. For example:

+ +
local:
+  service: Disk
+  root: <%= Rails.root.join("storage") %>
+
+ +

You can checkout the service’s constructor to know which keys are required.

+ +

Then, in your application’s configuration, you can specify the service to use like this:

+ +
config.active_storage.service = :local
+
+ +

If you are using Active Storage outside of a Ruby on Rails application, you can configure the service to use like this:

+ +
ActiveStorage::Blob.service = ActiveStorage::Service.configure(
+  :local,
+  { local: {service: "Disk",  root: Pathname("/tmp/foo/storage") } }
+)
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + name
+ + + + +

Class Public methods

+ +
+

+ + configure(service_name, configurations) + +

+ + +
+

Configure an Active Storage service by name from a set of configurations, typically loaded from a YAML file. The Active Storage engine uses this to set the global Active Storage service when the app boots.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 50
+def configure(service_name, configurations)
+  Configurator.build(service_name, configurations)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + +

+ + +
+

Concatenate multiple files into a single “composed” file.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 94
+def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {})
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+

Delete the file at the key.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 99
+def delete(key)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+

Delete files at keys starting with the prefix.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 104
+def delete_prefixed(prefix)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + download(key) + +

+ + +
+

Return the content of the file at the key.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 80
+def download(key)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + download_chunk(key, range) + +

+ + +
+

Return the partial content in the byte range of the file at the key.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 85
+def download_chunk(key, range)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + exist?(key) + +

+ + +
+

Return true if a file exists at the key.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 109
+def exist?(key)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + headers_for_direct_upload(key, filename:, content_type:, content_length:, checksum:, custom_metadata: {}) + +

+ + +
+

Returns a Hash of headers for url_for_direct_upload requests.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 141
+def headers_for_direct_upload(key, filename:, content_type:, content_length:, checksum:, custom_metadata: {})
+  {}
+end
+
+
+ +
+ +
+

+ + open(*args, **options, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 89
+def open(*args, **options, &block)
+  ActiveStorage::Downloader.new(self).open(*args, **options, &block)
+end
+
+
+ +
+ +
+

+ + public?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 145
+def public?
+  @public
+end
+
+
+ +
+ +
+

+ + update_metadata(key, **metadata) + +

+ + +
+

Update metadata for the file identified by key in the service. Override in subclasses only if the service needs to store specific metadata that has to be updated upon identification.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 76
+def update_metadata(key, **metadata)
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, **options) + +

+ + +
+

Upload the io to the key specified. If a checksum is provided, the service will ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 69
+def upload(key, io, checksum: nil, **options)
+  raise NotImplementedError
+end
+
+
+ +
+ +
+

+ + url(key, **options) + +

+ + +
+

Returns the URL for the file at the key. This returns a permanent URL for public files, and returns a short-lived URL for private files. For private files you can provide the disposition (:inline or :attachment), filename, and content_type that you wish the file to be served with on request. Additionally, you can also provide the amount of seconds the URL will be valid for, specified in expires_in.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 117
+def url(key, **options)
+  instrument :url, key: key do |payload|
+    generated_url =
+      if public?
+        public_url(key, **options)
+      else
+        private_url(key, **options)
+      end
+
+    payload[:url] = generated_url
+
+    generated_url
+  end
+end
+
+
+ +
+ +
+

+ + url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {}) + +

+ + +
+

Returns a signed, temporary URL that a direct upload file can be PUT to on the key. The URL will be valid for the amount of seconds specified in expires_in. You must also provide the content_type, content_length, and checksum of the file that will be uploaded. All these attributes will be validated by the service upon upload.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service.rb, line 136
+def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {})
+  raise NotImplementedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/AzureStorageService.html b/src/7.0/classes/ActiveStorage/Service/AzureStorageService.html new file mode 100644 index 0000000000..2fc85f3098 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/AzureStorageService.html @@ -0,0 +1,570 @@ +--- +title: ActiveStorage::Service::AzureStorageService +layout: default +--- +
+ +
+
+ +
+ +

Wraps the Microsoft Azure Storage Blob Service as an Active Storage service. See ActiveStorage::Service for the generic API documentation that applies to all services.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + client
+ [R] + container
+ [R] + signer
+ + + + +

Class Public methods

+ +
+

+ + new(storage_account_name:, storage_access_key:, container:, public: false, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 15
+def initialize(storage_account_name:, storage_access_key:, container:, public: false, **options)
+  @client = Azure::Storage::Blob::BlobService.create(storage_account_name: storage_account_name, storage_access_key: storage_access_key, **options)
+  @signer = Azure::Storage::Common::Core::Auth::SharedAccessSignature.new(storage_account_name, storage_access_key)
+  @container = container
+  @public = public
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 110
+def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {})
+  content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+
+  client.create_append_blob(
+    container,
+    destination_key,
+    content_type: content_type,
+    content_disposition: content_disposition,
+    metadata: custom_metadata,
+  ).tap do |blob|
+    source_keys.each do |source_key|
+      stream(source_key) do |chunk|
+        client.append_blob_block(container, blob.name, chunk)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 56
+def delete(key)
+  instrument :delete, key: key do
+    client.delete_blob(container, key)
+  rescue Azure::Core::Http::HTTPError => e
+    raise unless e.type == "BlobNotFound"
+    # Ignore files already deleted
+  end
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 65
+def delete_prefixed(prefix)
+  instrument :delete_prefixed, prefix: prefix do
+    marker = nil
+
+    loop do
+      results = client.list_blobs(container, prefix: prefix, marker: marker)
+
+      results.each do |blob|
+        client.delete_blob(container, blob.name)
+      end
+
+      break unless marker = results.continuation_token.presence
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download(key, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 32
+def download(key, &block)
+  if block_given?
+    instrument :streaming_download, key: key do
+      stream(key, &block)
+    end
+  else
+    instrument :download, key: key do
+      handle_errors do
+        _, io = client.get_blob(container, key)
+        io.force_encoding(Encoding::BINARY)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download_chunk(key, range) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 47
+def download_chunk(key, range)
+  instrument :download_chunk, key: key, range: range do
+    handle_errors do
+      _, io = client.get_blob(container, key, start_range: range.begin, end_range: range.exclude_end? ? range.end - 1 : range.end)
+      io.force_encoding(Encoding::BINARY)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + exist?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 81
+def exist?(key)
+  instrument :exist, key: key do |payload|
+    answer = blob_for(key).present?
+    payload[:exist] = answer
+    answer
+  end
+end
+
+
+ +
+ +
+

+ + headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 104
+def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **)
+  content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
+
+  { "Content-Type" => content_type, "Content-MD5" => checksum, "x-ms-blob-content-disposition" => content_disposition, "x-ms-blob-type" => "BlockBlob", **custom_metadata_headers(custom_metadata) }
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 22
+def upload(key, io, checksum: nil, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}, **)
+  instrument :upload, key: key, checksum: checksum do
+    handle_errors do
+      content_disposition = content_disposition_with(filename: filename, type: disposition) if disposition && filename
+
+      client.create_block_blob(container, key, IO.try_convert(io) || io, content_md5: checksum, content_type: content_type, content_disposition: content_disposition, metadata: custom_metadata)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/azure_storage_service.rb, line 89
+def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {})
+  instrument :url, key: key do |payload|
+    generated_url = signer.signed_uri(
+      uri_for(key), false,
+      service: "b",
+      permissions: "rw",
+      expiry: format_expiry(expires_in)
+    ).to_s
+
+    payload[:url] = generated_url
+
+    generated_url
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/DiskService.html b/src/7.0/classes/ActiveStorage/Service/DiskService.html new file mode 100644 index 0000000000..c52d2c2104 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/DiskService.html @@ -0,0 +1,536 @@ +--- +title: ActiveStorage::Service::DiskService +layout: default +--- +
+ +
+
+ +
+ +

Wraps a local disk path as an Active Storage service. See ActiveStorage::Service for the generic API documentation that applies to all services.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + root
+ + + + +

Class Public methods

+ +
+

+ + new(root:, public: false, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 14
+def initialize(root:, public: false, **options)
+  @root = root
+  @public = public
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose(source_keys, destination_key, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 103
+def compose(source_keys, destination_key, **)
+  File.open(make_path_for(destination_key), "w") do |destination_file|
+    source_keys.each do |source_key|
+      File.open(path_for(source_key), "rb") do |source_file|
+        IO.copy_stream(source_file, destination_file)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 51
+def delete(key)
+  instrument :delete, key: key do
+    File.delete path_for(key)
+  rescue Errno::ENOENT
+    # Ignore files already deleted
+  end
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 59
+def delete_prefixed(prefix)
+  instrument :delete_prefixed, prefix: prefix do
+    Dir.glob(path_for("#{prefix}*")).each do |path|
+      FileUtils.rm_rf(path)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download(key, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 26
+def download(key, &block)
+  if block_given?
+    instrument :streaming_download, key: key do
+      stream key, &block
+    end
+  else
+    instrument :download, key: key do
+      File.binread path_for(key)
+    rescue Errno::ENOENT
+      raise ActiveStorage::FileNotFoundError
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download_chunk(key, range) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 40
+def download_chunk(key, range)
+  instrument :download_chunk, key: key, range: range do
+    File.open(path_for(key), "rb") do |file|
+      file.seek range.begin
+      file.read range.size
+    end
+  rescue Errno::ENOENT
+    raise ActiveStorage::FileNotFoundError
+  end
+end
+
+
+ +
+ +
+

+ + exist?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 67
+def exist?(key)
+  instrument :exist, key: key do |payload|
+    answer = File.exist? path_for(key)
+    payload[:exist] = answer
+    answer
+  end
+end
+
+
+ +
+ +
+

+ + headers_for_direct_upload(key, content_type:, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 95
+def headers_for_direct_upload(key, content_type:, **)
+  { "Content-Type" => content_type }
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 19
+def upload(key, io, checksum: nil, **)
+  instrument :upload, key: key, checksum: checksum do
+    IO.copy_stream(io, make_path_for(key))
+    ensure_integrity_of(key, checksum) if checksum
+  end
+end
+
+
+ +
+ +
+

+ + url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/disk_service.rb, line 75
+def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {})
+  instrument :url, key: key do |payload|
+    verified_token_with_expiration = ActiveStorage.verifier.generate(
+      {
+        key: key,
+        content_type: content_type,
+        content_length: content_length,
+        checksum: checksum,
+        service_name: name
+      },
+      expires_in: expires_in,
+      purpose: :blob_token
+    )
+
+    url_helpers.update_rails_disk_service_url(verified_token_with_expiration, url_options).tap do |generated_url|
+      payload[:url] = generated_url
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/GCSService.html b/src/7.0/classes/ActiveStorage/Service/GCSService.html new file mode 100644 index 0000000000..5c8b3c42f8 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/GCSService.html @@ -0,0 +1,608 @@ +--- +title: ActiveStorage::Service::GCSService +layout: default +--- +
+ +
+
+ +
+ +

Wraps the Google Cloud Storage as an Active Storage service. See ActiveStorage::Service for the generic API documentation that applies to all services.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(public: false, **config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 14
+def initialize(public: false, **config)
+  @config = config
+  @public = public
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 137
+def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {})
+  bucket.compose(source_keys, destination_key).update do |file|
+    file.content_type = content_type
+    file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+    file.metadata = custom_metadata
+  end
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 64
+def delete(key)
+  instrument :delete, key: key do
+    file_for(key).delete
+  rescue Google::Cloud::NotFoundError
+    # Ignore files already deleted
+  end
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 72
+def delete_prefixed(prefix)
+  instrument :delete_prefixed, prefix: prefix do
+    bucket.files(prefix: prefix).all do |file|
+      file.delete
+    rescue Google::Cloud::NotFoundError
+      # Ignore concurrently-deleted files
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download(key, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 32
+def download(key, &block)
+  if block_given?
+    instrument :streaming_download, key: key do
+      stream(key, &block)
+    end
+  else
+    instrument :download, key: key do
+      file_for(key).download.string
+    rescue Google::Cloud::NotFoundError
+      raise ActiveStorage::FileNotFoundError
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download_chunk(key, range) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 56
+def download_chunk(key, range)
+  instrument :download_chunk, key: key, range: range do
+    file_for(key).download(range: range).string
+  rescue Google::Cloud::NotFoundError
+    raise ActiveStorage::FileNotFoundError
+  end
+end
+
+
+ +
+ +
+

+ + exist?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 82
+def exist?(key)
+  instrument :exist, key: key do |payload|
+    answer = file_for(key).exists?
+    payload[:exist] = answer
+    answer
+  end
+end
+
+
+ +
+ +
+

+ + headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 126
+def headers_for_direct_upload(key, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **)
+  content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
+
+  headers = { "Content-MD5" => checksum, "Content-Disposition" => content_disposition, **custom_metadata_headers(custom_metadata) }
+  if @config[:cache_control].present?
+    headers["Cache-Control"] = @config[:cache_control]
+  end
+
+  headers
+end
+
+
+ +
+ +
+

+ + update_metadata(key, content_type:, disposition: nil, filename: nil, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 46
+def update_metadata(key, content_type:, disposition: nil, filename: nil, custom_metadata: {})
+  instrument :update_metadata, key: key, content_type: content_type, disposition: disposition do
+    file_for(key).update do |file|
+      file.content_type = content_type
+      file.content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+      file.metadata = custom_metadata
+    end
+  end
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 19
+def upload(key, io, checksum: nil, content_type: nil, disposition: nil, filename: nil, custom_metadata: {})
+  instrument :upload, key: key, checksum: checksum do
+    # GCS's signed URLs don't include params such as response-content-type response-content_disposition
+    # in the signature, which means an attacker can modify them and bypass our effort to force these to
+    # binary and attachment when the file's content type requires it. The only way to force them is to
+    # store them as object's metadata.
+    content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+    bucket.create_file(io, key, md5: checksum, cache_control: @config[:cache_control], content_type: content_type, content_disposition: content_disposition, metadata: custom_metadata)
+  rescue Google::Cloud::InvalidArgumentError
+    raise ActiveStorage::IntegrityError
+  end
+end
+
+
+ +
+ +
+

+ + url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/gcs_service.rb, line 90
+def url_for_direct_upload(key, expires_in:, checksum:, custom_metadata: {}, **)
+  instrument :url, key: key do |payload|
+    headers = {}
+    version = :v2
+
+    if @config[:cache_control].present?
+      headers["Cache-Control"] = @config[:cache_control]
+      # v2 signing doesn't support non `x-goog-` headers. Only switch to v4 signing
+      # if necessary for back-compat; v4 limits the expiration of the URL to 7 days
+      # whereas v2 has no limit
+      version = :v4
+    end
+
+    headers.merge!(custom_metadata_headers(custom_metadata))
+
+    args = {
+      content_md5: checksum,
+      expires: expires_in,
+      headers: headers,
+      method: "PUT",
+      version: version,
+    }
+
+    if @config[:iam]
+      args[:issuer] = issuer
+      args[:signer] = signer
+    end
+
+    generated_url = bucket.signed_url(key, **args)
+
+    payload[:url] = generated_url
+
+    generated_url
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerError.html b/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerError.html new file mode 100644 index 0000000000..08284dc942 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerError.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::Service::GCSService::MetadataServerError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerNotFoundError.html b/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerNotFoundError.html new file mode 100644 index 0000000000..58b6fa9fb3 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/GCSService/MetadataServerNotFoundError.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::Service::GCSService::MetadataServerNotFoundError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/MirrorService.html b/src/7.0/classes/ActiveStorage/Service/MirrorService.html new file mode 100644 index 0000000000..aba4b6a189 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/MirrorService.html @@ -0,0 +1,317 @@ +--- +title: ActiveStorage::Service::MirrorService +layout: default +--- +
+ +
+
+ +
+ +

Wraps a set of mirror services and provides a single ActiveStorage::Service object that will all have the files uploaded to them. A primary service is designated to answer calls to:

+
  • +

    download

    +
  • +

    exists?

    +
  • +

    url

    +
  • +

    url_for_direct_upload

    +
  • +

    headers_for_direct_upload

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + mirrors
+ [R] + primary
+ + + + +

Class Public methods

+ +
+

+ + new(primary:, mirrors:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/mirror_service.rb, line 29
+def initialize(primary:, mirrors:)
+  @primary, @mirrors = primary, mirrors
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + delete(key) + +

+ + +
+

Delete the file at the key on all services.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/mirror_service.rb, line 43
+def delete(key)
+  perform_across_services :delete, key
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+

Delete files at keys starting with the prefix on all services.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/mirror_service.rb, line 48
+def delete_prefixed(prefix)
+  perform_across_services :delete_prefixed, prefix
+end
+
+
+ +
+ +
+

+ + mirror(key, checksum:) + +

+ + +
+

Copy the file at the key from the primary service to each of the mirrors where it doesn’t already exist.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/mirror_service.rb, line 54
+def mirror(key, checksum:)
+  instrument :mirror, key: key, checksum: checksum do
+    if (mirrors_in_need_of_mirroring = mirrors.select { |service| !service.exist?(key) }).any?
+      primary.open(key, checksum: checksum) do |io|
+        mirrors_in_need_of_mirroring.each do |service|
+          io.rewind
+          service.upload key, io, checksum: checksum
+        end
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, **options) + +

+ + +
+

Upload the io to the key specified to all services. If a checksum is provided, all services will ensure a match when the upload has completed or raise an ActiveStorage::IntegrityError.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/mirror_service.rb, line 35
+def upload(key, io, checksum: nil, **options)
+  each_service.collect do |service|
+    io.rewind
+    service.upload key, io, checksum: checksum, **options
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Service/S3Service.html b/src/7.0/classes/ActiveStorage/Service/S3Service.html new file mode 100644 index 0000000000..6d6c83dfaf --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Service/S3Service.html @@ -0,0 +1,596 @@ +--- +title: ActiveStorage::Service::S3Service +layout: default +--- +
+ +
+
+ +
+ +

Wraps the Amazon Simple Storage Service (S3) as an Active Storage service. See ActiveStorage::Service for the generic API documentation that applies to all services.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
MAXIMUM_UPLOAD_PARTS_COUNT=10000
 
MINIMUM_UPLOAD_PART_SIZE=5.megabytes
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + bucket
+ [R] + client
+ [R] + multipart_upload_threshold
+ [R] + upload_options
+ + + + +

Class Public methods

+ +
+

+ + new(bucket:, upload: {}, public: false, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 15
+def initialize(bucket:, upload: {}, public: false, **options)
+  @client = Aws::S3::Resource.new(**options)
+  @bucket = @client.bucket(bucket)
+
+  @multipart_upload_threshold = upload.delete(:multipart_threshold) || 100.megabytes
+  @public = public
+
+  @upload_options = upload
+  @upload_options[:acl] = "public-read" if public?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 98
+def compose(source_keys, destination_key, filename: nil, content_type: nil, disposition: nil, custom_metadata: {})
+  content_disposition = content_disposition_with(type: disposition, filename: filename) if disposition && filename
+
+  object_for(destination_key).upload_stream(
+    content_type: content_type,
+    content_disposition: content_disposition,
+    part_size: MINIMUM_UPLOAD_PART_SIZE,
+    metadata: custom_metadata,
+    **upload_options
+  ) do |out|
+    source_keys.each do |source_key|
+      stream(source_key) do |chunk|
+        IO.copy_stream(StringIO.new(chunk), out)
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 60
+def delete(key)
+  instrument :delete, key: key do
+    object_for(key).delete
+  end
+end
+
+
+ +
+ +
+

+ + delete_prefixed(prefix) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 66
+def delete_prefixed(prefix)
+  instrument :delete_prefixed, prefix: prefix do
+    bucket.objects(prefix: prefix).batch_delete!
+  end
+end
+
+
+ +
+ +
+

+ + download(key, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 38
+def download(key, &block)
+  if block_given?
+    instrument :streaming_download, key: key do
+      stream(key, &block)
+    end
+  else
+    instrument :download, key: key do
+      object_for(key).get.body.string.force_encoding(Encoding::BINARY)
+    rescue Aws::S3::Errors::NoSuchKey
+      raise ActiveStorage::FileNotFoundError
+    end
+  end
+end
+
+
+ +
+ +
+

+ + download_chunk(key, range) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 52
+def download_chunk(key, range)
+  instrument :download_chunk, key: key, range: range do
+    object_for(key).get(range: "bytes=#{range.begin}-#{range.exclude_end? ? range.end - 1 : range.end}").body.string.force_encoding(Encoding::BINARY)
+  rescue Aws::S3::Errors::NoSuchKey
+    raise ActiveStorage::FileNotFoundError
+  end
+end
+
+
+ +
+ +
+

+ + exist?(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 72
+def exist?(key)
+  instrument :exist, key: key do |payload|
+    answer = object_for(key).exists?
+    payload[:exist] = answer
+    answer
+  end
+end
+
+
+ +
+ +
+

+ + headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 92
+def headers_for_direct_upload(key, content_type:, checksum:, filename: nil, disposition: nil, custom_metadata: {}, **)
+  content_disposition = content_disposition_with(type: disposition, filename: filename) if filename
+
+  { "Content-Type" => content_type, "Content-MD5" => checksum, "Content-Disposition" => content_disposition, **custom_metadata_headers(custom_metadata) }
+end
+
+
+ +
+ +
+

+ + upload(key, io, checksum: nil, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}, **) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 26
+def upload(key, io, checksum: nil, filename: nil, content_type: nil, disposition: nil, custom_metadata: {}, **)
+  instrument :upload, key: key, checksum: checksum do
+    content_disposition = content_disposition_with(filename: filename, type: disposition) if disposition && filename
+
+    if io.size < multipart_upload_threshold
+      upload_with_single_part key, io, checksum: checksum, content_type: content_type, content_disposition: content_disposition, custom_metadata: custom_metadata
+    else
+      upload_with_multipart key, io, content_type: content_type, content_disposition: content_disposition, custom_metadata: custom_metadata
+    end
+  end
+end
+
+
+ +
+ +
+

+ + url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/service/s3_service.rb, line 80
+def url_for_direct_upload(key, expires_in:, content_type:, content_length:, checksum:, custom_metadata: {})
+  instrument :url, key: key do |payload|
+    generated_url = object_for(key).presigned_url :put, expires_in: expires_in.to_i,
+      content_type: content_type, content_length: content_length, content_md5: checksum,
+      metadata: custom_metadata, whitelist_headers: ["content-length"], **upload_options
+
+    payload[:url] = generated_url
+
+    generated_url
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/SetCurrent.html b/src/7.0/classes/ActiveStorage/SetCurrent.html new file mode 100644 index 0000000000..7bf9bbc7b9 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/SetCurrent.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::SetCurrent +layout: default +--- +
+ +
+
+ +
+ +

Sets the ActiveStorage::Current.url_options attribute, which the disk service uses to generate URLs. Include this concern in custom controllers that call ActiveStorage::Blob#url, ActiveStorage::Variant#url, or ActiveStorage::Preview#url so the disk service can generate URLs using the same host, protocol, and port as the current request.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Streaming.html b/src/7.0/classes/ActiveStorage/Streaming.html new file mode 100644 index 0000000000..786e266cc7 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Streaming.html @@ -0,0 +1,148 @@ +--- +title: ActiveStorage::Streaming +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_BLOB_STREAMING_DISPOSITION="inline"
 
+ + + + + + + +

Instance Private methods

+ +
+

+ + send_blob_stream(blob, disposition: nil) + +

+ + +
+

Stream the blob from storage directly to the response. The disposition can be controlled by setting disposition. The content type and filename is set directly from the blob.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/controllers/concerns/active_storage/streaming.rb, line 56
+def send_blob_stream(blob, disposition: nil) # :doc:
+  send_stream(
+      filename: blob.filename.sanitized,
+      disposition: blob.forced_disposition_for_serving || disposition || DEFAULT_BLOB_STREAMING_DISPOSITION,
+      type: blob.content_type_for_serving) do |stream|
+    blob.download do |chunk|
+      stream.write chunk
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Transformers.html b/src/7.0/classes/ActiveStorage/Transformers.html new file mode 100644 index 0000000000..df2dd5bc0f --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Transformers.html @@ -0,0 +1,71 @@ +--- +title: ActiveStorage::Transformers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer.html b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer.html new file mode 100644 index 0000000000..166b80f9ae --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer.html @@ -0,0 +1,75 @@ +--- +title: ActiveStorage::Transformers::ImageProcessingTransformer +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingArgument.html b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingArgument.html new file mode 100644 index 0000000000..48539a96c7 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingArgument.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::Transformers::ImageProcessingTransformer::UnsupportedImageProcessingArgument +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingMethod.html b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingMethod.html new file mode 100644 index 0000000000..5739ef296b --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Transformers/ImageProcessingTransformer/UnsupportedImageProcessingMethod.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::Transformers::ImageProcessingTransformer::UnsupportedImageProcessingMethod +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Transformers/Transformer.html b/src/7.0/classes/ActiveStorage/Transformers/Transformer.html new file mode 100644 index 0000000000..11ff567d48 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Transformers/Transformer.html @@ -0,0 +1,222 @@ +--- +title: ActiveStorage::Transformers::Transformer +layout: default +--- +
+ +
+
+ +
+ +

A Transformer applies a set of transformations to an image.

+ +

The following concrete subclasses are included in Active Storage:

+ + +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + transformations
+ + + + +

Class Public methods

+ +
+

+ + new(transformations) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/transformers/transformer.rb, line 14
+def initialize(transformations)
+  @transformations = transformations
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + transform(file, format:) + +

+ + +
+

Applies the transformations to the source image in file, producing a target image in the specified format. Yields an open Tempfile containing the target image. Closes and unlinks the output tempfile after yielding to the given block. Returns the result of the block.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/transformers/transformer.rb, line 21
+def transform(file, format:)
+  output = process(file, format: format)
+
+  begin
+    yield output
+  ensure
+    output.close!
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + process(file, format:) + +

+ + +
+

Returns an open Tempfile containing a transformed image in the given format. All subclasses implement this method.

+
+ + + + + + + + +
+ + +
+
# File activestorage/lib/active_storage/transformers/transformer.rb, line 34
+def process(file, format:) # :doc:
+  raise NotImplementedError
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/UnpreviewableError.html b/src/7.0/classes/ActiveStorage/UnpreviewableError.html new file mode 100644 index 0000000000..8fb76b54e8 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/UnpreviewableError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::UnpreviewableError +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveStorage::Blob#preview is called on a blob that isn’t previewable. Use ActiveStorage::Blob#previewable? to determine whether a blob is previewable.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/UnrepresentableError.html b/src/7.0/classes/ActiveStorage/UnrepresentableError.html new file mode 100644 index 0000000000..26a28008d7 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/UnrepresentableError.html @@ -0,0 +1,66 @@ +--- +title: ActiveStorage::UnrepresentableError +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveStorage::Blob#representation is called on a blob that isn’t representable. Use ActiveStorage::Blob#representable? to determine whether a blob is representable.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/VERSION.html b/src/7.0/classes/ActiveStorage/VERSION.html new file mode 100644 index 0000000000..20c5e14a36 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActiveStorage::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Variant.html b/src/7.0/classes/ActiveStorage/Variant.html new file mode 100644 index 0000000000..ec085dc18b --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Variant.html @@ -0,0 +1,416 @@ +--- +title: ActiveStorage::Variant +layout: default +--- +
+ +
+
+ +
+ +

Image blobs can have variants that are the result of a set of transformations applied to the original. These variants are used to create thumbnails, fixed-size avatars, or any other derivative image from the original.

+ +

Variants rely on ImageProcessing gem for the actual transformations of the file, so you must add gem "image_processing" to your Gemfile if you wish to use variants. By default, images will be processed with ImageMagick using the MiniMagick gem, but you can also switch to the libvips processor operated by the ruby-vips gem).

+ +
Rails.application.config.active_storage.variant_processor
+# => :mini_magick
+
+Rails.application.config.active_storage.variant_processor = :vips
+# => :vips
+
+ +

Note that to create a variant it’s necessary to download the entire blob file from the service. Because of this process, you also want to be considerate about when the variant is actually processed. You shouldn’t be processing variants inline in a template, for example. Delay the processing to an on-demand controller, like the one provided in ActiveStorage::RepresentationsController.

+ +

To refer to such a delayed on-demand variant, simply link to the variant through the resolved route provided by Active Storage like so:

+ +
<%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
+
+ +

This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController can then produce on-demand.

+ +

When you do want to actually produce the variant needed, call processed. This will check that the variant has already been processed and uploaded to the service, and, if so, just return that. Otherwise it will perform the transformations, upload the variant to the service, and return itself again. Example:

+ +
avatar.variant(resize_to_limit: [100, 100]).processed.url
+
+ +

This will create and process a variant of the avatar blob that’s constrained to a height and width of 100. Then it’ll upload said variant to the service according to a derivative key of the blob and the transformations.

+ +

You can combine any number of ImageMagick/libvips operations into a variant, as well as any macros provided by the ImageProcessing gem (such as resize_to_limit):

+ +
avatar.variant(resize_to_limit: [800, 800], colourspace: "b-w", rotate: "-90")
+
+ +

Visit the following links for a list of available ImageProcessing commands and ImageMagick/libvips operations:

+ + +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + blob
+ [R] + variation
+ + + + +

Class Public methods

+ +
+

+ + new(blob, variation_or_variation_key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 58
+def initialize(blob, variation_or_variation_key)
+  @blob, @variation = blob, ActiveStorage::Variation.wrap(variation_or_variation_key)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + download(&block) + +

+ + +
+

Downloads the file associated with this variant. If no block is given, the entire file is read into memory and returned. That’ll use a lot of RAM for very large files. If a block is given, then the download is streamed and yielded in chunks.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 84
+def download(&block)
+  service.download key, &block
+end
+
+
+ +
+ +
+

+ + filename() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 88
+def filename
+  ActiveStorage::Filename.new "#{blob.filename.base}.#{variation.format.downcase}"
+end
+
+
+ +
+ +
+

+ + image() + +

+ + +
+

Returns the receiving variant. Allows ActiveStorage::Variant and ActiveStorage::Preview instances to be used interchangeably.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 99
+def image
+  self
+end
+
+
+ +
+ +
+

+ + key() + +

+ + +
+

Returns a combination key of the blob and the variation that together identifies a specific variant.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 69
+def key
+  "variants/#{blob.key}/#{OpenSSL::Digest::SHA256.hexdigest(variation.key)}"
+end
+
+
+ +
+ +
+

+ + processed() + +

+ + +
+

Returns the variant instance itself after it’s been processed or an existing processing has been found on the service.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 63
+def processed
+  process unless processed?
+  self
+end
+
+
+ +
+ +
+

+ + url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline) + +

+ + +
+

Returns the URL of the blob variant on the service. See {ActiveStorage::Blob#url} for details.

+ +

Use url_for(variant) (or the implied form, like +link_to variant+ or +redirect_to variant+) to get the stable URL for a variant that points to the ActiveStorage::RepresentationsController, which in turn will use this service_call method for its redirection.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant.rb, line 78
+def url(expires_in: ActiveStorage.service_urls_expire_in, disposition: :inline)
+  service.url key, expires_in: expires_in, disposition: disposition, filename: filename, content_type: content_type
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/VariantRecord.html b/src/7.0/classes/ActiveStorage/VariantRecord.html new file mode 100644 index 0000000000..4bbc6f7d57 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/VariantRecord.html @@ -0,0 +1,60 @@ +--- +title: ActiveStorage::VariantRecord +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/VariantWithRecord.html b/src/7.0/classes/ActiveStorage/VariantWithRecord.html new file mode 100644 index 0000000000..e062ff6c24 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/VariantWithRecord.html @@ -0,0 +1,295 @@ +--- +title: ActiveStorage::VariantWithRecord +layout: default +--- +
+ +
+
+ +
+ +

Like an ActiveStorage::Variant, but keeps detail about the variant in the database as an ActiveStorage::VariantRecord. This is only used if ActiveStorage.track_variants is enabled.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + blob
+ [R] + variation
+ + + + +

Class Public methods

+ +
+

+ + new(blob, variation) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant_with_record.rb, line 9
+def initialize(blob, variation)
+  @blob, @variation = blob, ActiveStorage::Variation.wrap(variation)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + image() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant_with_record.rb, line 26
+def image
+  record&.image
+end
+
+
+ +
+ +
+

+ + process() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant_with_record.rb, line 18
+def process
+  transform_blob { |image| create_or_find_record(image: image) } unless processed?
+end
+
+
+ +
+ +
+

+ + processed() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant_with_record.rb, line 13
+def processed
+  process
+  self
+end
+
+
+ +
+ +
+

+ + processed?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variant_with_record.rb, line 22
+def processed?
+  record.present?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveStorage/Variation.html b/src/7.0/classes/ActiveStorage/Variation.html new file mode 100644 index 0000000000..a5b11ce5d2 --- /dev/null +++ b/src/7.0/classes/ActiveStorage/Variation.html @@ -0,0 +1,501 @@ +--- +title: ActiveStorage::Variation +layout: default +--- +
+ +
+
+ +
+ +

A set of transformations that can be applied to a blob to create a variant. This class is exposed via the ActiveStorage::Blob#variant method and should rarely be used directly.

+ +

In case you do need to use this directly, it’s instantiated using a hash of transformations where the key is the command and the value is the arguments. Example:

+ +
ActiveStorage::Variation.new(resize_to_limit: [100, 100], colourspace: "b-w", rotate: "-90", saver: { trim: true })
+
+ +

The options map directly to ImageProcessing commands.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + transformations
+ + + + +

Class Public methods

+ +
+

+ + decode(key) + +

+ + +
+

Returns a Variation instance with the transformations that were encoded by encode.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 33
+def decode(key)
+  new ActiveStorage.verifier.verify(key, purpose: :variation)
+end
+
+
+ +
+ +
+

+ + encode(transformations) + +

+ + +
+

Returns a signed key for the transformations, which can be used to refer to a specific variation in a URL or combined key (like ActiveStorage::Variant#key).

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 39
+def encode(transformations)
+  ActiveStorage.verifier.generate(transformations, purpose: :variation)
+end
+
+
+ +
+ +
+

+ + new(transformations) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 44
+def initialize(transformations)
+  @transformations = transformations.deep_symbolize_keys
+end
+
+
+ +
+ +
+

+ + wrap(variator) + +

+ + +
+

Returns a Variation instance based on the given variator. If the variator is a Variation, it is returned unmodified. If it is a String, it is passed to ActiveStorage::Variation.decode. Otherwise, it is assumed to be a transformations Hash and is passed directly to the constructor.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 21
+def wrap(variator)
+  case variator
+  when self
+    variator
+  when String
+    decode variator
+  else
+    new variator
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + content_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 68
+def content_type
+  MiniMime.lookup_by_extension(format.to_s).content_type
+end
+
+
+ +
+ +
+

+ + default_to(defaults) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 48
+def default_to(defaults)
+  self.class.new transformations.reverse_merge(defaults)
+end
+
+
+ +
+ +
+

+ + digest() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 77
+def digest
+  OpenSSL::Digest::SHA1.base64digest Marshal.dump(transformations)
+end
+
+
+ +
+ +
+

+ + format() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 60
+def format
+  transformations.fetch(:format, :png).tap do |format|
+    if MiniMime.lookup_by_extension(format.to_s).nil?
+      raise ArgumentError, "Invalid variant format (#{format.inspect})"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + key() + +

+ + +
+

Returns a signed key for all the transformations that this variation was instantiated with.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 73
+def key
+  self.class.encode(transformations)
+end
+
+
+ +
+ +
+

+ + transform(file, &block) + +

+ + +
+

Accepts a File object, performs the transformations against it, and saves the transformed image into a temporary file.

+
+ + + + + + + + +
+ + +
+
# File activestorage/app/models/active_storage/variation.rb, line 54
+def transform(file, &block)
+  ActiveSupport::Notifications.instrument("transform.active_storage") do
+    transformer.transform(file, format: format, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport.html b/src/7.0/classes/ActiveSupport.html new file mode 100644 index 0000000000..0698a2c4c2 --- /dev/null +++ b/src/7.0/classes/ActiveSupport.html @@ -0,0 +1,662 @@ +--- +title: ActiveSupport +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Active Support as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Active Support as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/version.rb, line 7
+def self.version
+  gem_version
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ActionableError.html b/src/7.0/classes/ActiveSupport/ActionableError.html new file mode 100644 index 0000000000..e7ac813ac3 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ActionableError.html @@ -0,0 +1,82 @@ +--- +title: ActiveSupport::ActionableError +layout: default +--- +
+ +
+
+ +
+ +

Actionable errors lets you define actions to resolve an error.

+ +

To make an error actionable, include the ActiveSupport::ActionableError module and invoke the action class macro to define the action. An action needs a name and a block to execute.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ActionableError/ClassMethods.html b/src/7.0/classes/ActiveSupport/ActionableError/ClassMethods.html new file mode 100644 index 0000000000..07b2111461 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ActionableError/ClassMethods.html @@ -0,0 +1,110 @@ +--- +title: ActiveSupport::ActionableError::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + action(name, &block) + +

+ + +
+

Defines an action that can resolve the error.

+ +
class PendingMigrationError < MigrationError
+  include ActiveSupport::ActionableError
+
+  action "Run pending migrations" do
+    ActiveRecord::Tasks::DatabaseTasks.migrate
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/actionable_error.rb, line 43
+def action(name, &block)
+  _actions[name] = block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ActionableError/NonActionable.html b/src/7.0/classes/ActiveSupport/ActionableError/NonActionable.html new file mode 100644 index 0000000000..3f958f6eae --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ActionableError/NonActionable.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::ActionableError::NonActionable +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ArrayInquirer.html b/src/7.0/classes/ActiveSupport/ArrayInquirer.html new file mode 100644 index 0000000000..dff32f6bbd --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ArrayInquirer.html @@ -0,0 +1,136 @@ +--- +title: ActiveSupport::ArrayInquirer +layout: default +--- +
+ +
+
+ +
+ +

Wrapping an array in an ArrayInquirer gives a friendlier way to check its string-like contents:

+ +
variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
+
+variants.phone?    # => true
+variants.tablet?   # => true
+variants.desktop?  # => false
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + any?(*candidates) + +

+ + +
+

Passes each element of candidates collection to ArrayInquirer collection. The method returns true if any element from the ArrayInquirer collection is equal to the stringified or symbolized form of any element in the candidates collection.

+ +

If candidates collection is not given, method returns true.

+ +
variants = ActiveSupport::ArrayInquirer.new([:phone, :tablet])
+
+variants.any?                      # => true
+variants.any?(:phone, :tablet)     # => true
+variants.any?('phone', 'desktop')  # => true
+variants.any?(:desktop, :watch)    # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/array_inquirer.rb, line 25
+def any?(*candidates)
+  if candidates.none?
+    super
+  else
+    candidates.any? do |candidate|
+      include?(candidate.to_sym) || include?(candidate.to_s)
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Autoload.html b/src/7.0/classes/ActiveSupport/Autoload.html new file mode 100644 index 0000000000..b9dcd1cf77 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Autoload.html @@ -0,0 +1,338 @@ +--- +title: ActiveSupport::Autoload +layout: default +--- +
+ +
+
+ +
+ +

Autoload and eager load conveniences for your library.

+ +

This module allows you to define autoloads based on Rails conventions (i.e. no need to define the path it is automatically guessed based on the filename) and also define a set of constants that needs to be eager loaded:

+ +
module MyLib
+  extend ActiveSupport::Autoload
+
+  autoload :Model
+
+  eager_autoload do
+    autoload :Cache
+  end
+end
+
+ +

Then your library can be eager loaded by simply calling:

+ +
MyLib.eager_load!
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + autoload(const_name, path = @_at_path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 37
+def autoload(const_name, path = @_at_path)
+  unless path
+    full = [name, @_under_path, const_name.to_s].compact.join("::")
+    path = Inflector.underscore(full)
+  end
+
+  if @_eager_autoload
+    @_autoloads[const_name] = path
+  end
+
+  super const_name, path
+end
+
+
+ +
+ +
+

+ + autoload_at(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 57
+def autoload_at(path)
+  @_at_path, old_path = path, @_at_path
+  yield
+ensure
+  @_at_path = old_path
+end
+
+
+ +
+ +
+

+ + autoload_under(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 50
+def autoload_under(path)
+  @_under_path, old_path = path, @_under_path
+  yield
+ensure
+  @_under_path = old_path
+end
+
+
+ +
+ +
+

+ + autoloads() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 75
+def autoloads
+  @_autoloads
+end
+
+
+ +
+ +
+

+ + eager_autoload() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 64
+def eager_autoload
+  old_eager, @_eager_autoload = @_eager_autoload, true
+  yield
+ensure
+  @_eager_autoload = old_eager
+end
+
+
+ +
+ +
+

+ + eager_load!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/autoload.rb, line 71
+def eager_load!
+  @_autoloads.each_value { |file| require file }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/BacktraceCleaner.html b/src/7.0/classes/ActiveSupport/BacktraceCleaner.html new file mode 100644 index 0000000000..f43da164db --- /dev/null +++ b/src/7.0/classes/ActiveSupport/BacktraceCleaner.html @@ -0,0 +1,393 @@ +--- +title: ActiveSupport::BacktraceCleaner +layout: default +--- +
+ +
+
+ +
+ +

Backtraces often include many lines that are not relevant for the context under review. This makes it hard to find the signal amongst the backtrace noise, and adds debugging time. With a BacktraceCleaner, filters and silencers are used to remove the noisy lines, so that only the most relevant lines remain.

+ +

Filters are used to modify lines of data, while silencers are used to remove lines entirely. The typical filter use case is to remove lengthy path information from the start of each line, and view file paths relevant to the app directory instead of the file system root. The typical silencer use case is to exclude the output of a noisy library from the backtrace, so that you can focus on the rest.

+ +
bc = ActiveSupport::BacktraceCleaner.new
+bc.add_filter   { |line| line.gsub(Rails.root.to_s, '') } # strip the Rails.root prefix
+bc.add_silencer { |line| /puma|rubygems/.match?(line) } # skip any lines from puma or rubygems
+bc.clean(exception.backtrace) # perform the cleanup
+
+ +

To reconfigure an existing BacktraceCleaner (like the default one in Rails) and show as much data as possible, you can always call BacktraceCleaner#remove_silencers!, which will restore the backtrace to a pristine state. If you need to reconfigure an existing BacktraceCleaner so that it does not filter or modify the paths of any lines of the backtrace, you can call BacktraceCleaner#remove_filters! These two methods will give you a completely untouched backtrace.

+ +

Inspired by the Quiet Backtrace gem by thoughtbot.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
FORMATTED_GEMS_PATTERN=/\A[^\/]+ \([\w.]+\) /
 
+ + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 32
+def initialize
+  @filters, @silencers = [], []
+  add_gem_filter
+  add_gem_silencer
+  add_stdlib_silencer
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + add_filter(&block) + +

+ + +
+

Adds a filter from the block provided. Each line in the backtrace will be mapped against this filter.

+ +
# Will turn "/my/rails/root/app/models/person.rb" into "/app/models/person.rb"
+backtrace_cleaner.add_filter { |line| line.gsub(Rails.root, '') }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 60
+def add_filter(&block)
+  @filters << block
+end
+
+
+ +
+ +
+

+ + add_silencer(&block) + +

+ + +
+

Adds a silencer from the block provided. If the silencer returns true for a given line, it will be excluded from the clean backtrace.

+ +
# Will reject all lines that include the word "puma", like "/gems/puma/server.rb" or "/app/my_puma_server/rb"
+backtrace_cleaner.add_silencer { |line| /puma/.match?(line) }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 69
+def add_silencer(&block)
+  @silencers << block
+end
+
+
+ +
+ +
+

+ + clean(backtrace, kind = :silent) + +

+ + +
+

Returns the backtrace after all filters and silencers have been run against it. Filters run first, then silencers.

+
+ + + +
+ Also aliased as: filter +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 41
+def clean(backtrace, kind = :silent)
+  filtered = filter_backtrace(backtrace)
+
+  case kind
+  when :silent
+    silence(filtered)
+  when :noise
+    noise(filtered)
+  else
+    filtered
+  end
+end
+
+
+ +
+ +
+

+ + filter(backtrace, kind = :silent) + +

+ + +
+ +
+ + + + + +
+ Alias for: clean +
+ + + +
+ +
+

+ + remove_filters!() + +

+ + +
+

Removes all filters, but leaves in the silencers. Useful if you suddenly need to see entire filepaths in the backtrace that you had already filtered out.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 83
+def remove_filters!
+  @filters = []
+end
+
+
+ +
+ +
+

+ + remove_silencers!() + +

+ + +
+

Removes all silencers, but leaves in the filters. Useful if your context of debugging suddenly expands as you suspect a bug in one of the libraries you use.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/backtrace_cleaner.rb, line 76
+def remove_silencers!
+  @silencers = []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Benchmarkable.html b/src/7.0/classes/ActiveSupport/Benchmarkable.html new file mode 100644 index 0000000000..db9ecf5881 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Benchmarkable.html @@ -0,0 +1,132 @@ +--- +title: ActiveSupport::Benchmarkable +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + benchmark(message = "Benchmarking", options = {}, &block) + +

+ + +
+

Allows you to measure the execution time of a block in a template and records the result to the log. Wrap this block around expensive operations or possible bottlenecks to get a time reading for the operation. For example, let’s say you thought your file processing method was taking too long; you could wrap it in a benchmark block.

+ +
<% benchmark 'Process data files' do %>
+  <%= expensive_files_operation %>
+<% end %>
+
+ +

That would add something like “Process data files (345.2ms)” to the log, which you can then use to compare timings when optimizing your code.

+ +

You may give an optional logger level (:debug, :info, :warn, :error) as the :level option. The default logger level value is :info.

+ +
<% benchmark 'Low-level files', level: :debug do %>
+  <%= lowlevel_files_operation %>
+<% end %>
+
+ +

Finally, you can pass true as the third argument to silence all log activity (other than the timing information) from inside the block. This is great for boiling down a noisy block to just a single statement that produces one log line:

+ +
<% benchmark 'Process data files', level: :info, silence: true do %>
+  <%= expensive_and_chatty_files_operation %>
+<% end %>
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/benchmarkable.rb, line 37
+def benchmark(message = "Benchmarking", options = {}, &block)
+  if logger
+    options.assert_valid_keys(:level, :silence)
+    options[:level] ||= :info
+
+    result = nil
+    ms = Benchmark.ms { result = options[:silence] ? logger.silence(&block) : yield }
+    logger.public_send(options[:level], "%s (%.1fms)" % [ message, ms ])
+    result
+  else
+    yield
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache.html b/src/7.0/classes/ActiveSupport/Cache.html new file mode 100644 index 0000000000..be5c5dd0af --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache.html @@ -0,0 +1,306 @@ +--- +title: ActiveSupport::Cache +layout: default +--- +
+ +
+
+ +
+ +

See ActiveSupport::Cache::Store for documentation.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_COMPRESS_LIMIT=1.kilobyte
 
OPTION_ALIASES={ +expires_in: [:expire_in, :expired_in] +}.freeze
 

Mapping of canonical option names to aliases that a store will recognize.

UNIVERSAL_OPTIONS=[:namespace, :compress, :compress_threshold, :expires_in, :expire_in, :expired_in, :race_condition_ttl, :coder, :skip_nil]
 

These options mean something to all cache implementations. Individual cache implementations may support additional options.

+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + format_version
+ + + + +

Class Public methods

+ +
+

+ + expand_cache_key(key, namespace = nil) + +

+ + +
+

Expands out the key argument into a key that can be used for the cache store. Optionally accepts a namespace, and all keys will be scoped within that namespace.

+ +

If the key argument provided is an array, or responds to to_a, then each of elements in the array will be turned into parameters/keys and concatenated into a single key. For example:

+ +
ActiveSupport::Cache.expand_cache_key([:foo, :bar])               # => "foo/bar"
+ActiveSupport::Cache.expand_cache_key([:foo, :bar], "namespace")  # => "namespace/foo/bar"
+
+ +

The key argument can also respond to cache_key or to_param.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 100
+def expand_cache_key(key, namespace = nil)
+  expanded_cache_key = namespace ? +"#{namespace}/" : +""
+
+  if prefix = ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
+    expanded_cache_key << "#{prefix}/"
+  end
+
+  expanded_cache_key << retrieve_cache_key(key)
+  expanded_cache_key
+end
+
+
+ +
+ +
+

+ + lookup_store(store = nil, *parameters) + +

+ + +
+

Creates a new Store object according to the given options.

+ +

If no arguments are passed to this method, then a new ActiveSupport::Cache::MemoryStore object will be returned.

+ +

If you pass a Symbol as the first argument, then a corresponding cache store class under the ActiveSupport::Cache namespace will be created. For example:

+ +
ActiveSupport::Cache.lookup_store(:memory_store)
+# => returns a new ActiveSupport::Cache::MemoryStore object
+
+ActiveSupport::Cache.lookup_store(:mem_cache_store)
+# => returns a new ActiveSupport::Cache::MemCacheStore object
+
+ +

Any additional arguments will be passed to the corresponding cache store class’s constructor:

+ +
ActiveSupport::Cache.lookup_store(:file_store, '/tmp/cache')
+# => same as: ActiveSupport::Cache::FileStore.new('/tmp/cache')
+
+ +

If the first argument is not a Symbol, then it will simply be returned:

+ +
ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
+# => returns MyOwnCacheStore.new
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 68
+def lookup_store(store = nil, *parameters)
+  case store
+  when Symbol
+    options = parameters.extract_options!
+    # clean this up once Ruby 2.7 support is dropped
+    # see https://github.com/rails/rails/pull/41522#discussion_r581186602
+    if options.empty?
+      retrieve_store_class(store).new(*parameters)
+    else
+      retrieve_store_class(store).new(*parameters, **options)
+    end
+  when Array
+    lookup_store(*store)
+  when nil
+    ActiveSupport::Cache::MemoryStore.new
+  else
+    store
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Coders.html b/src/7.0/classes/ActiveSupport/Cache/Coders.html new file mode 100644 index 0000000000..7b8ec57cdd --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Coders.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::Cache::Coders +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Coders/Loader.html b/src/7.0/classes/ActiveSupport/Cache/Coders/Loader.html new file mode 100644 index 0000000000..3f0818867b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Coders/Loader.html @@ -0,0 +1,116 @@ +--- +title: ActiveSupport::Cache::Coders::Loader +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + load(payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 854
+def load(payload)
+  if !payload.is_a?(String)
+    ActiveSupport::Cache::Store.logger&.warn %{Payload wasn't a string, was #{payload.class.name} - couldn't unmarshal, so returning nil."}
+
+    return nil
+  elsif payload.start_with?(MARK_70_UNCOMPRESSED)
+    members = Marshal.load(payload.byteslice(1..-1))
+  elsif payload.start_with?(MARK_70_COMPRESSED)
+    members = Marshal.load(Zlib::Inflate.inflate(payload.byteslice(1..-1)))
+  elsif payload.start_with?(MARK_61)
+    return Marshal.load(payload)
+  else
+    ActiveSupport::Cache::Store.logger&.warn %{Invalid cache prefix: #{payload.byteslice(0).inspect}, expected "\\x00" or "\\x01"}
+
+    return nil
+  end
+  Entry.unpack(members)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Coders/Rails61Coder.html b/src/7.0/classes/ActiveSupport/Cache/Coders/Rails61Coder.html new file mode 100644 index 0000000000..124c81db50 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Coders/Rails61Coder.html @@ -0,0 +1,154 @@ +--- +title: ActiveSupport::Cache::Coders::Rails61Coder +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + dump(entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 878
+def dump(entry)
+  Marshal.dump(entry)
+end
+
+
+ +
+ +
+

+ + dump_compressed(entry, threshold) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 882
+def dump_compressed(entry, threshold)
+  Marshal.dump(entry.compressed(threshold))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Coders/Rails70Coder.html b/src/7.0/classes/ActiveSupport/Cache/Coders/Rails70Coder.html new file mode 100644 index 0000000000..d6b39b25ed --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Coders/Rails70Coder.html @@ -0,0 +1,162 @@ +--- +title: ActiveSupport::Cache::Coders::Rails70Coder +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + dump(entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 891
+def dump(entry)
+  MARK_70_UNCOMPRESSED + Marshal.dump(entry.pack)
+end
+
+
+ +
+ +
+

+ + dump_compressed(entry, threshold) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 895
+def dump_compressed(entry, threshold)
+  payload = Marshal.dump(entry.pack)
+  if payload.bytesize >= threshold
+    compressed_payload = Zlib::Deflate.deflate(payload)
+    if compressed_payload.bytesize < payload.bytesize
+      return MARK_70_COMPRESSED + compressed_payload
+    end
+  end
+
+  MARK_70_UNCOMPRESSED + payload
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/ConnectionPoolLike.html b/src/7.0/classes/ActiveSupport/Cache/ConnectionPoolLike.html new file mode 100644 index 0000000000..78f88b0209 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/ConnectionPoolLike.html @@ -0,0 +1,101 @@ +--- +title: ActiveSupport::Cache::ConnectionPoolLike +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + with() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 27
+def with
+  yield self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/FileStore.html b/src/7.0/classes/ActiveSupport/Cache/FileStore.html new file mode 100644 index 0000000000..06ebcb563c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/FileStore.html @@ -0,0 +1,434 @@ +--- +title: ActiveSupport::Cache::FileStore +layout: default +--- +
+ +
+
+ +
+ +

A cache store implementation which stores everything on the filesystem.

+ +

FileStore implements the Strategy::LocalCache strategy which implements an in-memory cache inside of a block.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DIR_FORMATTER="%03X"
 
FILENAME_MAX_SIZE=226
 
FILEPATH_MAX_SIZE=900
 
GITKEEP_FILES=[".gitkeep", ".keep"].freeze
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + cache_path
+ + + + +

Class Public methods

+ +
+

+ + new(cache_path, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 21
+def initialize(cache_path, **options)
+  super(options)
+  @cache_path = cache_path.to_s
+end
+
+
+ +
+ +
+

+ + supports_cache_versioning?() + +

+ + +
+

Advertise cache versioning support.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 27
+def self.supports_cache_versioning?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cleanup(options = nil) + +

+ + +
+

Preemptively iterates through all stored keys and removes the ones which have expired.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 41
+def cleanup(options = nil)
+  options = merged_options(options)
+  search_dir(cache_path) do |fname|
+    entry = read_entry(fname, **options)
+    delete_entry(fname, **options) if entry && entry.expired?
+  end
+end
+
+
+ +
+ +
+

+ + clear(options = nil) + +

+ + +
+

Deletes all items from the cache. In this case it deletes all the entries in the specified file store directory except for .keep or .gitkeep. Be careful which directory is specified in your config file when using FileStore because everything in that directory will be deleted.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 34
+def clear(options = nil)
+  root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
+  FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
+rescue Errno::ENOENT, Errno::ENOTEMPTY
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+

Decrements an already existing integer value that is stored in the cache. If the key is not found nothing is done.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 57
+def decrement(name, amount = 1, options = nil)
+  modify_value(name, -amount, options)
+end
+
+
+ +
+ +
+

+ + delete_matched(matcher, options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 61
+def delete_matched(matcher, options = nil)
+  options = merged_options(options)
+  instrument(:delete_matched, matcher.inspect) do
+    matcher = key_matcher(matcher, options)
+    search_dir(cache_path) do |path|
+      key = file_path_key(path)
+      delete_entry(path, **options) if key.match(matcher)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+

Increments an already existing integer value that is stored in the cache. If the key is not found nothing is done.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/file_store.rb, line 51
+def increment(name, amount = 1, options = nil)
+  modify_value(name, amount, options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore.html new file mode 100644 index 0000000000..1e176d8ffc --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore.html @@ -0,0 +1,431 @@ +--- +title: ActiveSupport::Cache::MemCacheStore +layout: default +--- +
+ +
+
+ +
+ +

A cache store implementation which stores data in Memcached: memcached.org

+ +

This is currently the most popular cache store for production websites.

+ +

Special features:

+
  • +

    Clustering and load balancing. One can specify multiple memcached servers, and MemCacheStore will load balance between all available servers. If a server goes down, then MemCacheStore will ignore it until it comes back up.

    +
+ +

MemCacheStore implements the Strategy::LocalCache strategy which implements an in-memory cache inside of a block.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ESCAPE_KEY_CHARS=/[\x00-\x20%\x7F-\xFF]/n
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(*addresses) + +

+ + +
+

Creates a new MemCacheStore object, with the given memcached server addresses. Each address is either a host name, or a host-with-port string in the form of “host_name:port”. For example:

+ +
ActiveSupport::Cache::MemCacheStore.new("localhost", "server-downstairs.localnetwork:8229")
+
+ +

If no addresses are provided, but ENV['MEMCACHE_SERVERS'] is defined, it will be used instead. Otherwise, MemCacheStore will connect to localhost:11211 (the default memcached port).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 109
+def initialize(*addresses)
+  addresses = addresses.flatten
+  options = addresses.extract_options!
+  if options.key?(:cache_nils)
+    options[:skip_nil] = !options.delete(:cache_nils)
+  end
+  super(options)
+
+  unless [String, Dalli::Client, NilClass].include?(addresses.first.class)
+    raise ArgumentError, "First argument must be an empty array, an array of hosts or a Dalli::Client instance."
+  end
+  if addresses.first.is_a?(Dalli::Client)
+    @data = addresses.first
+  else
+    mem_cache_options = options.dup
+    # The value "compress: false" prevents duplicate compression within Dalli.
+    mem_cache_options[:compress] = false
+    (UNIVERSAL_OPTIONS - %i(compress)).each { |name| mem_cache_options.delete(name) }
+    @data = self.class.build_mem_cache(*(addresses + [mem_cache_options]))
+  end
+end
+
+
+ +
+ +
+

+ + supports_cache_versioning?() + +

+ + +
+

Advertise cache versioning support.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 30
+def self.supports_cache_versioning?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + clear(options = nil) + +

+ + +
+

Clear the entire cache on all memcached servers. This method should be used with care when shared cache is being used.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 175
+def clear(options = nil)
+  rescue_error_with(nil) { @data.with { |c| c.flush_all } }
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+

Decrement a cached value. This method uses the memcached decr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will initialize that value to zero.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 164
+def decrement(name, amount = 1, options = nil)
+  options = merged_options(options)
+  instrument(:decrement, name, amount: amount) do
+    rescue_error_with nil do
+      @data.with { |c| c.decr(normalize_key(name, options), amount, options[:expires_in]) }
+    end
+  end
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+

Increment a cached value. This method uses the memcached incr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will initialize that value to zero.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 151
+def increment(name, amount = 1, options = nil)
+  options = merged_options(options)
+  instrument(:increment, name, amount: amount) do
+    rescue_error_with nil do
+      @data.with { |c| c.incr(normalize_key(name, options), amount, options[:expires_in]) }
+    end
+  end
+end
+
+
+ +
+ +
+

+ + stats() + +

+ + +
+

Get the statistics from the memcached servers.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 180
+def stats
+  @data.with { |c| c.stats }
+end
+
+
+ +
+ +
+

+ + write(name, value, options = nil) + + +

+ + +
+

Behaves the same as ActiveSupport::Cache::Store#write, but supports additional options specific to memcached.

+ +

Additional Options

+
  • +

    raw: true - Sends the value directly to the server as raw bytes. The value must be a string or number. You can use memcached direct operations like increment and decrement only on raw values.

    +
  • +

    unless_exist: true - Prevents overwriting an existing cache entry.

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 132
+      
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders.html new file mode 100644 index 0000000000..445adf6e66 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders.html @@ -0,0 +1,71 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::Coders +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Loader.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Loader.html new file mode 100644 index 0000000000..122504b551 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Loader.html @@ -0,0 +1,105 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::Coders::Loader +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + load(payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 200
+def load(payload)
+  if payload.is_a?(Entry)
+    payload
+  else
+    Cache::Coders::Loader.load(payload)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails61Coder.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails61Coder.html new file mode 100644 index 0000000000..e7e9ded1cb --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails61Coder.html @@ -0,0 +1,154 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::Coders::Rails61Coder +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + dump(entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 213
+def dump(entry)
+  entry
+end
+
+
+ +
+ +
+

+ + dump_compressed(entry, threshold) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 217
+def dump_compressed(entry, threshold)
+  entry.compressed(threshold)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails70Coder.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails70Coder.html new file mode 100644 index 0000000000..d5b23dda0c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/Coders/Rails70Coder.html @@ -0,0 +1,76 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::Coders::Rails70Coder +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache.html new file mode 100644 index 0000000000..6789e35a9c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache.html @@ -0,0 +1,67 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::DupLocalCache +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache/DupLocalStore.html b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache/DupLocalStore.html new file mode 100644 index 0000000000..166556fc01 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemCacheStore/DupLocalCache/DupLocalStore.html @@ -0,0 +1,162 @@ +--- +title: ActiveSupport::Cache::MemCacheStore::DupLocalCache::DupLocalStore +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + fetch_entry(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 45
+def fetch_entry(key)
+  entry = super do
+    new_entry = yield
+    if entry.is_a?(Entry)
+      new_entry.dup_value!
+    end
+    new_entry
+  end
+  entry = entry.dup
+
+  if entry.is_a?(Entry)
+    entry.dup_value!
+  end
+
+  entry
+end
+
+
+ +
+ +
+

+ + write_entry(_key, entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/mem_cache_store.rb, line 38
+def write_entry(_key, entry)
+  if entry.is_a?(Entry)
+    entry.dup_value!
+  end
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/MemoryStore.html b/src/7.0/classes/ActiveSupport/Cache/MemoryStore.html new file mode 100644 index 0000000000..66ce546c62 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/MemoryStore.html @@ -0,0 +1,492 @@ +--- +title: ActiveSupport::Cache::MemoryStore +layout: default +--- +
+ +
+
+ +
+ +

A cache store implementation which stores everything into memory in the same process. If you’re running multiple Ruby on Rails server processes (which is the case if you’re using Phusion Passenger or puma clustered mode), then this means that Rails server process instances won’t be able to share cache data with each other and this may not be the most appropriate cache in that scenario.

+ +

This cache has a bounded size specified by the :size options to the initializer (default is 32Mb). When the cache exceeds the allotted size, a cleanup will occur which tries to prune the cache down to three quarters of the maximum size by removing the least recently used entries.

+ +

Unlike other Cache store implementations, MemoryStore does not compress values by default. MemoryStore does not benefit from compression as much as other Store implementations, as it does not send data over a network. However, when compression is enabled, it still pays the full cost of compression in terms of cpu use.

+ +

MemoryStore is thread-safe.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
PER_ENTRY_OVERHEAD=240
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 48
+def initialize(options = nil)
+  options ||= {}
+  # Disable compression by default.
+  options[:compress] ||= false
+  super(options)
+  @data = {}
+  @max_size = options[:size] || 32.megabytes
+  @max_prune_time = options[:max_prune_time] || 2
+  @cache_size = 0
+  @monitor = Monitor.new
+  @pruning = false
+end
+
+
+ +
+ +
+

+ + supports_cache_versioning?() + +

+ + +
+

Advertise cache versioning support.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 62
+def self.supports_cache_versioning?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cleanup(options = nil) + +

+ + +
+

Preemptively iterates through all stored keys and removes the ones which have expired.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 75
+def cleanup(options = nil)
+  options = merged_options(options)
+  instrument(:cleanup, size: @data.size) do
+    keys = synchronize { @data.keys }
+    keys.each do |key|
+      entry = @data[key]
+      delete_entry(key, **options) if entry && entry.expired?
+    end
+  end
+end
+
+
+ +
+ +
+

+ + clear(options = nil) + +

+ + +
+

Delete all data stored in a given cache store.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 67
+def clear(options = nil)
+  synchronize do
+    @data.clear
+    @cache_size = 0
+  end
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+

Decrement an integer value in the cache.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 117
+def decrement(name, amount = 1, options = nil)
+  modify_value(name, -amount, options)
+end
+
+
+ +
+ +
+

+ + delete_matched(matcher, options = nil) + +

+ + +
+

Deletes cache entries if the cache key matches a given pattern.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 122
+def delete_matched(matcher, options = nil)
+  options = merged_options(options)
+  instrument(:delete_matched, matcher.inspect) do
+    matcher = key_matcher(matcher, options)
+    keys = synchronize { @data.keys }
+    keys.each do |key|
+      delete_entry(key, **options) if key.match(matcher)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+

Increment an integer value in the cache.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 112
+def increment(name, amount = 1, options = nil)
+  modify_value(name, amount, options)
+end
+
+
+ +
+ +
+

+ + prune(target_size, max_time = nil) + +

+ + +
+

To ensure entries fit within the specified memory prune the cache by removing the least recently accessed entries.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 88
+def prune(target_size, max_time = nil)
+  return if pruning?
+  @pruning = true
+  begin
+    start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+    cleanup
+    instrument(:prune, target_size, from: @cache_size) do
+      keys = synchronize { @data.keys }
+      keys.each do |key|
+        delete_entry(key, **options)
+        return if @cache_size <= target_size || (max_time && Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time > max_time)
+      end
+    end
+  ensure
+    @pruning = false
+  end
+end
+
+
+ +
+ +
+

+ + pruning?() + +

+ + +
+

Returns true if the cache is currently being pruned.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/memory_store.rb, line 107
+def pruning?
+  @pruning
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/NullStore.html b/src/7.0/classes/ActiveSupport/Cache/NullStore.html new file mode 100644 index 0000000000..90398b2738 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/NullStore.html @@ -0,0 +1,308 @@ +--- +title: ActiveSupport::Cache::NullStore +layout: default +--- +
+ +
+
+ +
+ +

A cache store implementation which doesn’t actually store anything. Useful in development and test environments where you don’t want caching turned on but need to go through the caching interface.

+ +

This cache does implement the local cache strategy, so values will actually be cached inside blocks that utilize this strategy. See ActiveSupport::Cache::Strategy::LocalCache for more details.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + supports_cache_versioning?() + +

+ + +
+

Advertise cache versioning support.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 16
+def self.supports_cache_versioning?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cleanup(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 23
+def cleanup(options = nil)
+end
+
+
+ +
+ +
+

+ + clear(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 20
+def clear(options = nil)
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 29
+def decrement(name, amount = 1, options = nil)
+end
+
+
+ +
+ +
+

+ + delete_matched(matcher, options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 32
+def delete_matched(matcher, options = nil)
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/null_store.rb, line 26
+def increment(name, amount = 1, options = nil)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/RedisCacheStore.html b/src/7.0/classes/ActiveSupport/Cache/RedisCacheStore.html new file mode 100644 index 0000000000..5f0b14ee77 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/RedisCacheStore.html @@ -0,0 +1,713 @@ +--- +title: ActiveSupport::Cache::RedisCacheStore +layout: default +--- +
+ +
+
+ +
+ +

Redis cache store.

+ +

Deployment note: Take care to use a *dedicated Redis cache* rather than pointing this at your existing Redis server. It won’t cope well with mixed usage patterns and it won’t expire cache entries by default.

+ +

Redis cache server setup guide: redis.io/topics/lru-cache

+
  • +

    Supports vanilla Redis, hiredis, and Redis::Distributed.

    +
  • +

    Supports Memcached-like sharding across Redises with Redis::Distributed.

    +
  • +

    Fault tolerant. If the Redis server is unavailable, no exceptions are raised. Cache fetches are all misses and writes are dropped.

    +
  • +

    Local cache. Hot in-memory primary cache within block/middleware scope.

    +
  • +

    read_multi and write_multi support for Redis mget/mset. Use Redis::Distributed 4.0.1+ for distributed mget support.

    +
  • +

    delete_matched support for Redis KEYS globs.

    +
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_ERROR_HANDLER=-> (method:, returning:, exception:) do +if logger +logger.error { "RedisCacheStore: #{method} failed, returned #{returning.inspect}: #{exception.class}: #{exception.message}" } +end +end
 
DEFAULT_REDIS_OPTIONS={ +connect_timeout: 20, +read_timeout: 1, +write_timeout: 1, +reconnect_attempts: 0, +}
 
MAX_KEY_BYTESIZE=1024
 

Keys are truncated with the ActiveSupport digest if they exceed 1kB

+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + max_key_bytesize
+ [R] + redis_options
+ + + + +

Class Public methods

+ +
+

+ + new(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: default_coder, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options) + +

+ + +
+

Creates a new Redis cache store.

+ +

Handles four options: :redis block, :redis instance, single :url string, and multiple :url strings.

+ +
Option  Class       Result
+:redis  Proc    ->  options[:redis].call
+:redis  Object  ->  options[:redis]
+:url    String  ->  Redis.new(url: …)
+:url    Array   ->  Redis::Distributed.new([{ url: … }, { url: … }, …])
+
+ +

No namespace is set by default. Provide one if the Redis cache server is shared with other apps: namespace: 'myapp-cache'.

+ +

Compression is enabled by default with a 1kB threshold, so cached values larger than 1kB are automatically compressed. Disable by passing compress: false or change the threshold by passing compress_threshold: 4.kilobytes.

+ +

No expiry is set on cache entries by default. Redis is expected to be configured with an eviction policy that automatically deletes least-recently or -frequently used keys when it reaches max memory. See redis.io/topics/lru-cache for cache server setup.

+ +

Race condition TTL is not set by default. This can be used to avoid “thundering herd” cache writes when hot cache entries are expired. See ActiveSupport::Cache::Store#fetch for more.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 149
+def initialize(namespace: nil, compress: true, compress_threshold: 1.kilobyte, coder: default_coder, expires_in: nil, race_condition_ttl: nil, error_handler: DEFAULT_ERROR_HANDLER, **redis_options)
+  @redis_options = redis_options
+
+  @max_key_bytesize = MAX_KEY_BYTESIZE
+  @error_handler = error_handler
+
+  super namespace: namespace,
+    compress: compress, compress_threshold: compress_threshold,
+    expires_in: expires_in, race_condition_ttl: race_condition_ttl,
+    coder: coder
+end
+
+
+ +
+ +
+

+ + supports_cache_versioning?() + +

+ + +
+

Advertise cache versioning support.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 73
+def self.supports_cache_versioning?
+  true
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cleanup(options = nil) + +

+ + +
+

Cache Store API implementation.

+ +

Removes expired entries. Handled natively by Redis least-recently-/ least-frequently-used expiry, so manual cleanup is not supported.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 281
+def cleanup(options = nil)
+  super
+end
+
+
+ +
+ +
+

+ + clear(options = nil) + +

+ + +
+

Clear the entire cache on all Redis servers. Safe to use on shared servers if the cache is namespaced.

+ +

Failsafe: Raises errors.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 289
+def clear(options = nil)
+  failsafe :clear do
+    if namespace = merged_options(options)[:namespace]
+      delete_matched "*", namespace: namespace
+    else
+      redis.with { |c| c.flushdb }
+    end
+  end
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+

Cache Store API implementation.

+ +

Decrement a cached value. This method uses the Redis decr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will initialize that value to zero.

+ +

Failsafe: Raises errors.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 262
+def decrement(name, amount = 1, options = nil)
+  instrument :decrement, name, amount: amount do
+    failsafe :decrement do
+      options = merged_options(options)
+      key = normalize_key(name, options)
+
+      redis.with do |c|
+        c.decrby(key, amount).tap do
+          write_key_expiry(c, key, options)
+        end
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + delete_matched(matcher, options = nil) + +

+ + +
+

Cache Store API implementation.

+ +

Supports Redis KEYS glob patterns:

+ +
h?llo matches hello, hallo and hxllo
+h*llo matches hllo and heeeello
+h[ae]llo matches hello and hallo, but not hillo
+h[^e]llo matches hallo, hbllo, ... but not hello
+h[a-b]llo matches hallo and hbllo
+
+ +

Use \ to escape special characters if you want to match them verbatim.

+ +

See redis.io/commands/KEYS for more.

+ +

Failsafe: Raises errors.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 210
+def delete_matched(matcher, options = nil)
+  instrument :delete_matched, matcher do
+    unless String === matcher
+      raise ArgumentError, "Only Redis glob strings are supported: #{matcher.inspect}"
+    end
+    redis.with do |c|
+      pattern = namespace_key(matcher, options)
+      cursor = "0"
+      # Fetch keys in batches using SCAN to avoid blocking the Redis server.
+      nodes = c.respond_to?(:nodes) ? c.nodes : [c]
+
+      nodes.each do |node|
+        begin
+          cursor, keys = node.scan(cursor, match: pattern, count: SCAN_BATCH_SIZE)
+          node.del(*keys) unless keys.empty?
+        end until cursor == "0"
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+

Cache Store API implementation.

+ +

Increment a cached value. This method uses the Redis incr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will initialize that value to zero.

+ +

Failsafe: Raises errors.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 239
+def increment(name, amount = 1, options = nil)
+  instrument :increment, name, amount: amount do
+    failsafe :increment do
+      options = merged_options(options)
+      key = normalize_key(name, options)
+
+      redis.with do |c|
+        c.incrby(key, amount).tap do
+          write_key_expiry(c, key, options)
+        end
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 174
+def inspect
+  instance = @redis || @redis_options
+  "#<#{self.class} options=#{options.inspect} redis=#{instance.inspect}>"
+end
+
+
+ +
+ +
+

+ + read_multi(*names) + +

+ + +
+

Cache Store API implementation.

+ +

Read multiple values at once. Returns a hash of requested keys -> fetched values.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 183
+def read_multi(*names)
+  if mget_capable?
+    instrument(:read_multi, names, options) do |payload|
+      read_multi_mget(*names).tap do |results|
+        payload[:hits] = results.keys
+      end
+    end
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + redis() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 161
+def redis
+  @redis ||= begin
+    pool_options = self.class.send(:retrieve_pool_options, redis_options)
+
+    if pool_options.any?
+      self.class.send(:ensure_connection_pool_added!)
+      ::ConnectionPool.new(pool_options) { self.class.build_redis(**redis_options) }
+    else
+      self.class.build_redis(**redis_options)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + stats() + +

+ + +
+

Get info from redis servers.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/redis_cache_store.rb, line 300
+def stats
+  redis.with { |c| c.info }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Store.html b/src/7.0/classes/ActiveSupport/Cache/Store.html new file mode 100644 index 0000000000..689c1c6245 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Store.html @@ -0,0 +1,1119 @@ +--- +title: ActiveSupport::Cache::Store +layout: default +--- +
+ +
+
+ +
+ +

An abstract cache store class. There are multiple cache store implementations, each having its own additional features. See the classes under the ActiveSupport::Cache module, e.g. ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most popular cache store for large production websites.

+ +

Some implementations may not support all methods beyond the basic cache methods of fetch, write, read, exist?, and delete.

+ +

ActiveSupport::Cache::Store can store any Ruby object that is supported by its coder‘s dump and load methods.

+ +
cache = ActiveSupport::Cache::MemoryStore.new
+
+cache.read('city')   # => nil
+cache.write('city', "Duckburgh")
+cache.read('city')   # => "Duckburgh"
+
+cache.write('not serializable', Proc.new {}) # => TypeError
+
+ +

Keys are always translated into Strings and are case sensitive. When an object is specified as a key and has a cache_key method defined, this method will be called to define the key. Otherwise, the to_param method will be called. Hashes and Arrays can also be used as keys. The elements will be delimited by slashes, and the elements within a Hash will be sorted by key so they are consistent.

+ +
cache.read('city') == cache.read(:city)   # => true
+
+ +

Nil values can be cached.

+ +

If your cache is on a shared infrastructure, you can define a namespace for your cache entries. If a namespace is defined, it will be prefixed on to every key. The namespace can be either a static value or a Proc. If it is a Proc, it will be invoked when each key is evaluated so that you can use application logic to invalidate keys.

+ +
cache.namespace = -> { @last_mod_time }  # Set the namespace to a variable
+@last_mod_time = Time.now  # Invalidate the entire cache by changing namespace
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + options
+ [R] + silence
+ [R] + silence?
+ + + + +

Class Public methods

+ +
+

+ + new(options = nil) + +

+ + +
+

Creates a new cache.

+ +

Options

+
  • +

    :namespace - Sets the namespace for the cache. This option is especially useful if your application shares a cache with other applications.

    +
  • +

    :coder - Replaces the default cache entry serialization mechanism with a custom one. The coder must respond to dump and load. Using a custom coder disables automatic compression.

    +
+ +

Any other specified options are treated as default options for the relevant cache operations, such as read, write, and fetch.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 211
+def initialize(options = nil)
+  @options = options ? normalize_options(options) : {}
+  @options[:compress] = true unless @options.key?(:compress)
+  @options[:compress_threshold] = DEFAULT_COMPRESS_LIMIT unless @options.key?(:compress_threshold)
+
+  @coder = @options.delete(:coder) { default_coder } || NullCoder
+  @coder_supports_compression = @coder.respond_to?(:dump_compressed)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + cleanup(options = nil) + +

+ + +
+

Cleans up the cache by removing expired entries.

+ +

Options are passed to the underlying cache implementation.

+ +

Some implementations may not support this method.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 582
+def cleanup(options = nil)
+  raise NotImplementedError.new("#{self.class.name} does not support cleanup")
+end
+
+
+ +
+ +
+

+ + clear(options = nil) + +

+ + +
+

Clears the entire cache. Be careful with this method since it could affect other processes if shared cache is being used.

+ +

The options hash is passed to the underlying cache implementation.

+ +

Some implementations may not support this method.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 592
+def clear(options = nil)
+  raise NotImplementedError.new("#{self.class.name} does not support clear")
+end
+
+
+ +
+ +
+

+ + decrement(name, amount = 1, options = nil) + +

+ + +
+

Decrements an integer value in the cache.

+ +

Options are passed to the underlying cache implementation.

+ +

Some implementations may not support this method.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 573
+def decrement(name, amount = 1, options = nil)
+  raise NotImplementedError.new("#{self.class.name} does not support decrement")
+end
+
+
+ +
+ +
+

+ + delete(name, options = nil) + +

+ + +
+

Deletes an entry in the cache. Returns true if an entry is deleted.

+ +

Options are passed to the underlying cache implementation.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 514
+def delete(name, options = nil)
+  options = merged_options(options)
+
+  instrument(:delete, name) do
+    delete_entry(normalize_key(name, options), **options)
+  end
+end
+
+
+ +
+ +
+

+ + delete_matched(matcher, options = nil) + +

+ + +
+

Deletes all entries with keys matching the pattern.

+ +

Options are passed to the underlying cache implementation.

+ +

Some implementations may not support this method.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 555
+def delete_matched(matcher, options = nil)
+  raise NotImplementedError.new("#{self.class.name} does not support delete_matched")
+end
+
+
+ +
+ +
+

+ + delete_multi(names, options = nil) + +

+ + +
+

Deletes multiple entries in the cache.

+ +

Options are passed to the underlying cache implementation.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 525
+def delete_multi(names, options = nil)
+  options = merged_options(options)
+  names.map! { |key| normalize_key(key, options) }
+
+  instrument :delete_multi, names do
+    delete_multi_entries(names, **options)
+  end
+end
+
+
+ +
+ +
+

+ + exist?(name, options = nil) + +

+ + +
+

Returns true if the cache contains an entry for the given key.

+ +

Options are passed to the underlying cache implementation.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 537
+def exist?(name, options = nil)
+  options = merged_options(options)
+
+  instrument(:exist?, name) do |payload|
+    entry = read_entry(normalize_key(name, options), **options, event: payload)
+    (entry && !entry.expired? && !entry.mismatched?(normalize_version(name, options))) || false
+  end
+end
+
+
+ +
+ +
+

+ + fetch(name, options = nil, &block) + +

+ + +
+

Fetches data from the cache, using the given key. If there is data in the cache with the given key, then that data is returned.

+ +

If there is no such data in the cache (a cache miss), then nil will be returned. However, if a block has been passed, that block will be passed the key and executed in the event of a cache miss. The return value of the block will be written to the cache under the given cache key, and that return value will be returned.

+ +
cache.write('today', 'Monday')
+cache.fetch('today')  # => "Monday"
+
+cache.fetch('city')   # => nil
+cache.fetch('city') do
+  'Duckburgh'
+end
+cache.fetch('city')   # => "Duckburgh"
+
+ +

Options

+ +

Internally, fetch calls read_entry, and calls write_entry on a cache miss. Thus, fetch supports the same options as read and write. Additionally, fetch supports the following options:

+
  • +

    force: true - Forces a cache “miss,” meaning we treat the cache value as missing even if it’s present. Passing a block is required when force is true so this always results in a cache write.

    + +
    cache.write('today', 'Monday')
    +cache.fetch('today', force: true) { 'Tuesday' } # => 'Tuesday'
    +cache.fetch('today', force: true) # => ArgumentError
    +
    + +

    The :force option is useful when you’re calling some other method to ask whether you should force a cache write. Otherwise, it’s clearer to just call write.

    +
  • +

    skip_nil: true - Prevents caching a nil result:

    + +
    cache.fetch('foo') { nil }
    +cache.fetch('bar', skip_nil: true) { nil }
    +cache.exist?('foo') # => true
    +cache.exist?('bar') # => false
    +
    +
  • +

    :race_condition_ttl - Specifies the number of seconds during which an expired value can be reused while a new value is being generated. This can be used to prevent race conditions when cache entries expire, by preventing multiple processes from simultaneously regenerating the same entry (also known as the dog pile effect).

    + +

    When a process encounters a cache entry that has expired less than :race_condition_ttl seconds ago, it will bump the expiration time by :race_condition_ttl seconds before generating a new value. During this extended time window, while the process generates a new value, other processes will continue to use the old value. After the first process writes the new value, other processes will then use it.

    + +

    If the first process errors out while generating a new value, another process can try to generate a new value after the extended time window has elapsed.

    + +
    # Set all values to expire after one minute.
    +cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 1.minute)
    +
    +cache.write('foo', 'original value')
    +val_1 = nil
    +val_2 = nil
    +sleep 60
    +
    +Thread.new do
    +  val_1 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
    +    sleep 1
    +    'new value 1'
    +  end
    +end
    +
    +Thread.new do
    +  val_2 = cache.fetch('foo', race_condition_ttl: 10.seconds) do
    +    'new value 2'
    +  end
    +end
    +
    +cache.fetch('foo') # => "original value"
    +sleep 10 # First thread extended the life of cache by another 10 seconds
    +cache.fetch('foo') # => "new value 1"
    +val_1 # => "new value 1"
    +val_2 # => "original value"
    +
    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 321
+def fetch(name, options = nil, &block)
+  if block_given?
+    options = merged_options(options)
+    key = normalize_key(name, options)
+
+    entry = nil
+    instrument(:read, name, options) do |payload|
+      cached_entry = read_entry(key, **options, event: payload) unless options[:force]
+      entry = handle_expired_entry(cached_entry, key, options)
+      entry = nil if entry && entry.mismatched?(normalize_version(name, options))
+      payload[:super_operation] = :fetch if payload
+      payload[:hit] = !!entry if payload
+    end
+
+    if entry
+      get_entry_value(entry, name, options)
+    else
+      save_block_result_to_cache(name, options, &block)
+    end
+  elsif options && options[:force]
+    raise ArgumentError, "Missing block: Calling `Cache#fetch` with `force: true` requires a block."
+  else
+    read(name, options)
+  end
+end
+
+
+ +
+ +
+

+ + fetch_multi(*names) + +

+ + +
+

Fetches data from the cache, using the given keys. If there is data in the cache with the given keys, then that data is returned. Otherwise, the supplied block is called for each key for which there was no data, and the result will be written to the cache and returned. Therefore, you need to pass a block that returns the data to be written to the cache. If you do not want to write the cache when the cache is not found, use read_multi.

+ +

Returns a hash with the data for each of the names. For example:

+ +
cache.write("bim", "bam")
+cache.fetch_multi("bim", "unknown_key") do |key|
+  "Fallback value for key: #{key}"
+end
+# => { "bim" => "bam",
+#      "unknown_key" => "Fallback value for key: unknown_key" }
+
+ +

Options are passed to the underlying cache implementation. For example:

+ +
cache.fetch_multi("fizz", expires_in: 5.seconds) do |key|
+  "buzz"
+end
+# => {"fizz"=>"buzz"}
+cache.read("fizz")
+# => "buzz"
+sleep(6)
+cache.read("fizz")
+# => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 447
+def fetch_multi(*names)
+  raise ArgumentError, "Missing block: `Cache#fetch_multi` requires a block." unless block_given?
+
+  options = names.extract_options!
+  options = merged_options(options)
+
+  instrument :read_multi, names, options do |payload|
+    reads   = read_multi_entries(names, **options)
+    writes  = {}
+    ordered = names.index_with do |name|
+      reads.fetch(name) { writes[name] = yield(name) }
+    end
+
+    payload[:hits] = reads.keys
+    payload[:super_operation] = :fetch_multi
+
+    write_multi(writes, options)
+
+    ordered
+  end
+end
+
+
+ +
+ +
+

+ + increment(name, amount = 1, options = nil) + +

+ + +
+

Increments an integer value in the cache.

+ +

Options are passed to the underlying cache implementation.

+ +

Some implementations may not support this method.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 564
+def increment(name, amount = 1, options = nil)
+  raise NotImplementedError.new("#{self.class.name} does not support increment")
+end
+
+
+ +
+ +
+

+ + mute() + +

+ + +
+

Silences the logger within a block.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 227
+def mute
+  previous_silence, @silence = defined?(@silence) && @silence, true
+  yield
+ensure
+  @silence = previous_silence
+end
+
+
+ +
+ +
+

+ + read(name, options = nil) + +

+ + +
+

Reads data from the cache, using the given key. If there is data in the cache with the given key, then that data is returned. Otherwise, nil is returned.

+ +

Note, if data was written with the :expires_in or :version options, both of these conditions are applied before the data is returned.

+ +

Options

+
  • +

    :version - Specifies a version for the cache entry. If the cached version does not match the requested version, the read will be treated as a cache miss. This feature is used to support recyclable cache keys.

    +
+ +

Other options will be handled by the specific cache store implementation.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 362
+def read(name, options = nil)
+  options = merged_options(options)
+  key     = normalize_key(name, options)
+  version = normalize_version(name, options)
+
+  instrument(:read, name, options) do |payload|
+    entry = read_entry(key, **options, event: payload)
+
+    if entry
+      if entry.expired?
+        delete_entry(key, **options)
+        payload[:hit] = false if payload
+        nil
+      elsif entry.mismatched?(version)
+        payload[:hit] = false if payload
+        nil
+      else
+        payload[:hit] = true if payload
+        entry.value
+      end
+    else
+      payload[:hit] = false if payload
+      nil
+    end
+  end
+end
+
+
+ +
+ +
+

+ + read_multi(*names) + +

+ + +
+

Reads multiple values at once from the cache. Options can be passed in the last argument.

+ +

Some cache implementation may optimize this method.

+ +

Returns a hash mapping the names provided to the values found.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 395
+def read_multi(*names)
+  options = names.extract_options!
+  options = merged_options(options)
+
+  instrument :read_multi, names, options do |payload|
+    read_multi_entries(names, **options, event: payload).tap do |results|
+      payload[:hits] = results.keys
+    end
+  end
+end
+
+
+ +
+ +
+

+ + silence!() + +

+ + +
+

Silences the logger.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 221
+def silence!
+  @silence = true
+  self
+end
+
+
+ +
+ +
+

+ + write(name, value, options = nil) + +

+ + +
+

Writes the value to the cache with the key. The value must be supported by the coder‘s dump and load methods.

+ +

By default, cache entries larger than 1kB are compressed. Compression allows more data to be stored in the same memory footprint, leading to fewer cache evictions and higher hit rates.

+ +

Options

+
  • +

    compress: false - Disables compression of the cache entry.

    +
  • +

    :compress_threshold - The compression threshold, specified in bytes. Cache entries larger than this threshold will be compressed. Defaults to 1.kilobyte.

    +
  • +

    :expires_in - Sets a relative expiration time for the cache entry, specified in seconds. :expire_in and :expired_in are aliases for :expires_in.

    + +
    cache = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
    +cache.write(key, value, expires_in: 1.minute) # Set a lower value for one entry
    +
    +
  • +

    :expires_at - Sets an absolute expiration time for the cache entry.

    + +
    cache = ActiveSupport::Cache::MemoryStore.new
    +cache.write(key, value, expires_at: Time.now.at_end_of_hour)
    +
    +
  • +

    :version - Specifies a version for the cache entry. When reading from the cache, if the cached version does not match the requested version, the read will be treated as a cache miss. This feature is used to support recyclable cache keys.

    +
+ +

Other options will be handled by the specific cache store implementation.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 502
+def write(name, value, options = nil)
+  options = merged_options(options)
+
+  instrument(:write, name, options) do
+    entry = Entry.new(value, **options.merge(version: normalize_version(name, options)))
+    write_entry(normalize_key(name, options), entry, **options)
+  end
+end
+
+
+ +
+ +
+

+ + write_multi(hash, options = nil) + +

+ + +
+

Cache Storage API to write multiple values at once.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 407
+def write_multi(hash, options = nil)
+  options = merged_options(options)
+
+  instrument :write_multi, hash, options do |payload|
+    entries = hash.each_with_object({}) do |(name, value), memo|
+      memo[normalize_key(name, options)] = Entry.new(value, **options.merge(version: normalize_version(name, options)))
+    end
+
+    write_multi_entries entries, **options
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + key_matcher(pattern, options) + +

+ + +
+

Adds the namespace defined in the options to a pattern designed to match keys. Implementations that support delete_matched should call this method to translate a pattern that matches names into one that matches namespaced keys.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache.rb, line 605
+def key_matcher(pattern, options) # :doc:
+  prefix = options[:namespace].is_a?(Proc) ? options[:namespace].call : options[:namespace]
+  if prefix
+    source = pattern.source
+    if source.start_with?("^")
+      source = source[1, source.length]
+    else
+      source = ".*#{source[0, source.length]}"
+    end
+    Regexp.new("^#{Regexp.escape(prefix)}:#{source}", pattern.options)
+  else
+    pattern
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Strategy.html b/src/7.0/classes/ActiveSupport/Cache/Strategy.html new file mode 100644 index 0000000000..240a66900e --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Strategy.html @@ -0,0 +1,77 @@ +--- +title: ActiveSupport::Cache::Strategy +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache.html b/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache.html new file mode 100644 index 0000000000..5a9891e66f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache.html @@ -0,0 +1,163 @@ +--- +title: ActiveSupport::Cache::Strategy::LocalCache +layout: default +--- +
+ +
+
+ +
+ +

Caches that implement LocalCache will be backed by an in-memory cache for the duration of a block. Repeated calls to the cache for the same key will hit the in-memory cache for faster access.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + middleware() + +

+ + +
+

Middleware class can be inserted as a Rack handler to be local cache for the duration of request.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 69
+def middleware
+  @middleware ||= Middleware.new(
+    "ActiveSupport::Cache::Strategy::LocalCache",
+    local_cache_key)
+end
+
+
+ +
+ +
+

+ + with_local_cache(&block) + +

+ + +
+

Use a local cache for the duration of block.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 63
+def with_local_cache(&block)
+  use_temporary_local_cache(LocalStore.new, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache/LocalStore.html b/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache/LocalStore.html new file mode 100644 index 0000000000..ef9bfcbb48 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Cache/Strategy/LocalCache/LocalStore.html @@ -0,0 +1,312 @@ +--- +title: ActiveSupport::Cache::Strategy::LocalCache::LocalStore +layout: default +--- +
+ +
+
+ +
+ +

Simple memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 32
+def initialize
+  @data = {}
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + clear(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 36
+def clear(options = nil)
+  @data.clear
+end
+
+
+ +
+ +
+

+ + delete_entry(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 53
+def delete_entry(key)
+  !!@data.delete(key)
+end
+
+
+ +
+ +
+

+ + read_entry(key) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 40
+def read_entry(key)
+  @data[key]
+end
+
+
+ +
+ +
+

+ + read_multi_entries(keys) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 44
+def read_multi_entries(keys)
+  @data.slice(*keys)
+end
+
+
+ +
+ +
+

+ + write_entry(key, entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/cache/strategy/local_cache.rb, line 48
+def write_entry(key, entry)
+  @data[key] = entry
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/CachingKeyGenerator.html b/src/7.0/classes/ActiveSupport/CachingKeyGenerator.html new file mode 100644 index 0000000000..d1ca68ea7d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/CachingKeyGenerator.html @@ -0,0 +1,156 @@ +--- +title: ActiveSupport::CachingKeyGenerator +layout: default +--- +
+ +
+
+ +
+ +

CachingKeyGenerator is a wrapper around KeyGenerator which allows users to avoid re-executing the key generation process when it’s called using the same salt and key_size.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(key_generator) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 48
+def initialize(key_generator)
+  @key_generator = key_generator
+  @cache_keys = Concurrent::Map.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + generate_key(*args) + +

+ + +
+

Returns a derived key suitable for use.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 54
+def generate_key(*args)
+  @cache_keys[args.join("|")] ||= @key_generator.generate_key(*args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks.html b/src/7.0/classes/ActiveSupport/Callbacks.html new file mode 100644 index 0000000000..a76a040a90 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks.html @@ -0,0 +1,236 @@ +--- +title: ActiveSupport::Callbacks +layout: default +--- +
+ +
+
+ +
+ +

Callbacks are code hooks that are run at key points in an object’s life cycle. The typical use case is to have a base class define a set of callbacks relevant to the other functionality it supplies, so that subclasses can install callbacks that enhance or modify the base functionality without needing to override or redefine methods of the base class.

+ +

Mixing in this module allows you to define the events in the object’s life cycle that will support callbacks (via ClassMethods#define_callbacks), set the instance methods, procs, or callback objects to be called (via ClassMethods#set_callback), and run the installed callbacks at the appropriate times (via run_callbacks).

+ +

By default callbacks are halted by throwing :abort. See ClassMethods#define_callbacks for details.

+ +

Three kinds of callbacks are supported: before callbacks, run before a certain event; after callbacks, run after the event; and around callbacks, blocks that surround the event, triggering it when they yield. Callback code can be contained in instance methods, procs or lambdas, or callback objects that respond to certain predetermined methods. See ClassMethods#set_callback for details.

+ +
class Record
+  include ActiveSupport::Callbacks
+  define_callbacks :save
+
+  def save
+    run_callbacks :save do
+      puts "- save"
+    end
+  end
+end
+
+class PersonRecord < Record
+  set_callback :save, :before, :saving_message
+  def saving_message
+    puts "saving..."
+  end
+
+  set_callback :save, :after do |object|
+    puts "saved"
+  end
+end
+
+person = PersonRecord.new
+person.save
+
+ +

Output:

+ +
saving...
+- save
+saved
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
CALLBACK_FILTER_TYPES=[:before, :after, :around]
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + run_callbacks(kind) + +

+ + +
+

Runs the callbacks for the given event.

+ +

Calls the before and around callbacks in the order they were set, yields the block (if given one), and then runs the after callbacks in reverse order.

+ +

If the callback chain was halted, returns false. Otherwise returns the result of the block, nil if no callbacks have been set, or true if callbacks have been set but no block is given.

+ +
run_callbacks :save do
+  save
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 95
+def run_callbacks(kind)
+  callbacks = __callbacks[kind.to_sym]
+
+  if callbacks.empty?
+    yield if block_given?
+  else
+    env = Filters::Environment.new(self, false, nil)
+    next_sequence = callbacks.compile
+
+    # Common case: no 'around' callbacks defined
+    if next_sequence.final?
+      next_sequence.invoke_before(env)
+      env.value = !env.halted && (!block_given? || yield)
+      next_sequence.invoke_after(env)
+      env.value
+    else
+      invoke_sequence = Proc.new do
+        skipped = nil
+
+        while true
+          current = next_sequence
+          current.invoke_before(env)
+          if current.final?
+            env.value = !env.halted && (!block_given? || yield)
+          elsif current.skip?(env)
+            (skipped ||= []) << current
+            next_sequence = next_sequence.nested
+            next
+          else
+            next_sequence = next_sequence.nested
+            begin
+              target, block, method, *arguments = current.expand_call_template(env, invoke_sequence)
+              target.send(method, *arguments, &block)
+            ensure
+              next_sequence = current
+            end
+          end
+          current.invoke_after(env)
+          skipped.pop.invoke_after(env) while skipped&.first
+          break env.value
+        end
+      end
+
+      invoke_sequence.call
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate.html new file mode 100644 index 0000000000..ccbbd5305f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate.html @@ -0,0 +1,77 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec0.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec0.html new file mode 100644 index 0000000000..78d37d71ad --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec0.html @@ -0,0 +1,231 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::InstanceExec0 +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 435
+def initialize(block)
+  @override_block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 439
+def expand(target, value, block)
+  [target, @override_block, :instance_exec]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 449
+def inverted_lambda
+  lambda do |target, value, &block|
+    !target.instance_exec(&@override_block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 443
+def make_lambda
+  lambda do |target, value, &block|
+    target.instance_exec(&@override_block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec1.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec1.html new file mode 100644 index 0000000000..69691c396e --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec1.html @@ -0,0 +1,231 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::InstanceExec1 +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 457
+def initialize(block)
+  @override_block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 461
+def expand(target, value, block)
+  [target, @override_block, :instance_exec, target]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 471
+def inverted_lambda
+  lambda do |target, value, &block|
+    !target.instance_exec(target, &@override_block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 465
+def make_lambda
+  lambda do |target, value, &block|
+    target.instance_exec(target, &@override_block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec2.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec2.html new file mode 100644 index 0000000000..c3d0405cce --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/InstanceExec2.html @@ -0,0 +1,234 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::InstanceExec2 +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 479
+def initialize(block)
+  @override_block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 483
+def expand(target, value, block)
+  raise ArgumentError unless block
+  [target, @override_block || block, :instance_exec, target, block]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 495
+def inverted_lambda
+  lambda do |target, value, &block|
+    raise ArgumentError unless block
+    !target.instance_exec(target, block, &@override_block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 488
+def make_lambda
+  lambda do |target, value, &block|
+    raise ArgumentError unless block
+    target.instance_exec(target, block, &@override_block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/MethodCall.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/MethodCall.html new file mode 100644 index 0000000000..8f8546c2ea --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/MethodCall.html @@ -0,0 +1,243 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::MethodCall +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(method) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 377
+def initialize(method)
+  @method_name = method
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+

Return the parts needed to make this call, with the given input values.

+ +

Returns an array of the form:

+ +
[target, block, method, *arguments]
+
+ +

This array can be used as such:

+ +
target.send(method, *arguments, &block)
+
+ +

The actual invocation is left up to the caller to minimize call stack pollution.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 394
+def expand(target, value, block)
+  [target, block, @method_name]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 404
+def inverted_lambda
+  lambda do |target, value, &block|
+    !target.send(@method_name, &block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 398
+def make_lambda
+  lambda do |target, value, &block|
+    target.send(@method_name, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ObjectCall.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ObjectCall.html new file mode 100644 index 0000000000..ab6094e7ee --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ObjectCall.html @@ -0,0 +1,232 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::ObjectCall +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(target, method) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 412
+def initialize(target, method)
+  @override_target = target
+  @method_name = method
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 417
+def expand(target, value, block)
+  [@override_target || target, block, @method_name, target]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 427
+def inverted_lambda
+  lambda do |target, value, &block|
+    !(@override_target || target).send(@method_name, target, &block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 421
+def make_lambda
+  lambda do |target, value, &block|
+    (@override_target || target).send(@method_name, target, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ProcCall.html b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ProcCall.html new file mode 100644 index 0000000000..5937d57f90 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/CallTemplate/ProcCall.html @@ -0,0 +1,231 @@ +--- +title: ActiveSupport::Callbacks::CallTemplate::ProcCall +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(target) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 504
+def initialize(target)
+  @override_target = target
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + expand(target, value, block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 508
+def expand(target, value, block)
+  [@override_target || target, block, :call, target, value]
+end
+
+
+ +
+ +
+

+ + inverted_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 518
+def inverted_lambda
+  lambda do |target, value, &block|
+    !(@override_target || target).call(target, value, &block)
+  end
+end
+
+
+ +
+ +
+

+ + make_lambda() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 512
+def make_lambda
+  lambda do |target, value, &block|
+    (@override_target || target).call(target, value, &block)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/ClassMethods.html b/src/7.0/classes/ActiveSupport/Callbacks/ClassMethods.html new file mode 100644 index 0000000000..732ed8b4de --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/ClassMethods.html @@ -0,0 +1,412 @@ +--- +title: ActiveSupport::Callbacks::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + define_callbacks(*names) + +

+ + +
+

Define sets of events in the object life cycle that support callbacks.

+ +
define_callbacks :validate
+define_callbacks :initialize, :save, :destroy
+
+ +
Options
+
  • +

    :terminator - Determines when a before filter will halt the callback chain, preventing following before and around callbacks from being called and the event from being triggered. This should be a lambda to be executed. The current object and the result lambda of the callback will be provided to the terminator lambda.

    + +
    define_callbacks :validate, terminator: ->(target, result_lambda) { result_lambda.call == false }
    +
    + +

    In this example, if any before validate callbacks returns false, any successive before and around callback is not executed.

    + +

    The default terminator halts the chain when a callback throws :abort.

    +
  • +

    :skip_after_callbacks_if_terminated - Determines if after callbacks should be terminated by the :terminator option. By default after callbacks are executed no matter if callback chain was terminated or not. This option has no effect if :terminator option is set to nil.

    +
  • +

    :scope - Indicates which methods should be executed when an object is used as a callback.

    + +
    class Audit
    +  def before(caller)
    +    puts 'Audit: before is called'
    +  end
    +
    +  def before_save(caller)
    +    puts 'Audit: before_save is called'
    +  end
    +end
    +
    +class Account
    +  include ActiveSupport::Callbacks
    +
    +  define_callbacks :save
    +  set_callback :save, :before, Audit.new
    +
    +  def save
    +    run_callbacks :save do
    +      puts 'save in main'
    +    end
    +  end
    +end
    +
    + +

    In the above case whenever you save an account the method Audit#before will be called. On the other hand

    + +
    define_callbacks :save, scope: [:kind, :name]
    +
    + +

    would trigger Audit#before_save instead. That’s constructed by calling #{kind}_#{name} on the given instance. In this case “kind” is “before” and “name” is “save”. In this context :kind and :name have special meanings: :kind refers to the kind of callback (before/after/around) and :name refers to the method on which callbacks are being defined.

    + +

    A declaration like

    + +
    define_callbacks :save, scope: [:name]
    +
    + +

    would call Audit#save.

    +
+ +
Notes
+ +

names passed to define_callbacks must not end with !, ? or =.

+ +

Calling define_callbacks multiple times with the same names will overwrite previous callbacks registered with set_callback.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 917
+        def define_callbacks(*names)
+          options = names.extract_options!
+
+          names.each do |name|
+            name = name.to_sym
+
+            ([self] + self.descendants).each do |target|
+              target.set_callbacks name, CallbackChain.new(name, options)
+            end
+
+            module_eval <<-RUBY, __FILE__, __LINE__ + 1
+              def _run_#{name}_callbacks(&block)
+                run_callbacks #{name.inspect}, &block
+              end
+
+              def self._#{name}_callbacks
+                get_callbacks(#{name.inspect})
+              end
+
+              def self._#{name}_callbacks=(value)
+                set_callbacks(#{name.inspect}, value)
+              end
+
+              def _#{name}_callbacks
+                __callbacks[#{name.inspect}]
+              end
+            RUBY
+          end
+        end
+
+
+ +
+ +
+

+ + reset_callbacks(name) + +

+ + +
+

Remove all set callbacks for the given event.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 827
+def reset_callbacks(name)
+  callbacks = get_callbacks name
+
+  self.descendants.each do |target|
+    chain = target.get_callbacks(name).dup
+    callbacks.each { |c| chain.delete(c) }
+    target.set_callbacks name, chain
+  end
+
+  set_callbacks(name, callbacks.dup.clear)
+end
+
+
+ +
+ +
+

+ + set_callback(name, *filter_list, &block) + +

+ + +
+

Install a callback for the given event.

+ +
set_callback :save, :before, :before_method
+set_callback :save, :after,  :after_method, if: :condition
+set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
+
+ +

The second argument indicates whether the callback is to be run :before, :after, or :around the event. If omitted, :before is assumed. This means the first example above can also be written as:

+ +
set_callback :save, :before_method
+
+ +

The callback can be specified as a symbol naming an instance method; as a proc, lambda, or block; or as an object that responds to a certain method determined by the :scope argument to define_callbacks.

+ +

If a proc, lambda, or block is given, its body is evaluated in the context of the current object. It can also optionally accept the current object as an argument.

+ +

Before and around callbacks are called in the order that they are set; after callbacks are called in the reverse order.

+ +

Around callbacks can access the return value from the event, if it wasn’t halted, from the yield call.

+ +
Options
+
  • +

    :if - A symbol or an array of symbols, each naming an instance method or a proc; the callback will be called only when they all return a true value.

    + +

    If a proc is given, its body is evaluated in the context of the current object. It can also optionally accept the current object as an argument.

    +
  • +

    :unless - A symbol or an array of symbols, each naming an instance method or a proc; the callback will be called only when they all return a false value.

    + +

    If a proc is given, its body is evaluated in the context of the current object. It can also optionally accept the current object as an argument.

    +
  • +

    :prepend - If true, the callback will be prepended to the existing chain rather than appended.

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 756
+def set_callback(name, *filter_list, &block)
+  type, filters, options = normalize_callback_params(filter_list, block)
+
+  self_chain = get_callbacks name
+  mapped = filters.map do |filter|
+    Callback.build(self_chain, filter, type, options)
+  end
+
+  __update_callbacks(name) do |target, chain|
+    options[:prepend] ? chain.prepend(*mapped) : chain.append(*mapped)
+    target.set_callbacks name, chain
+  end
+end
+
+
+ +
+ +
+

+ + skip_callback(name, *filter_list, &block) + +

+ + +
+

Skip a previously set callback. Like set_callback, :if or :unless options may be passed in order to control when the callback is skipped.

+ +
class Writer < PersonRecord
+  attr_accessor :age
+  skip_callback :save, :before, :saving_message, if: -> { age > 18 }
+end
+
+ +

When if option returns true, callback is skipped.

+ +
writer = Writer.new
+writer.age = 20
+writer.save
+
+ +

Output:

+ +
- save
+saved
+
+ +

When if option returns false, callback is NOT skipped.

+ +
young_writer = Writer.new
+young_writer.age = 17
+young_writer.save
+
+ +

Output:

+ +
saving...
+- save
+saved
+
+ +

An ArgumentError will be raised if the callback has not already been set (unless the :raise option is set to false).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 802
+def skip_callback(name, *filter_list, &block)
+  type, filters, options = normalize_callback_params(filter_list, block)
+
+  options[:raise] = true unless options.key?(:raise)
+
+  __update_callbacks(name) do |target, chain|
+    filters.each do |filter|
+      callback = chain.find { |c| c.matches?(type, filter) }
+
+      if !callback && options[:raise]
+        raise ArgumentError, "#{type.to_s.capitalize} #{name} callback #{filter.inspect} has not been defined"
+      end
+
+      if callback && (options.key?(:if) || options.key?(:unless))
+        new_callback = callback.merge_conditional_options(chain, if_option: options[:if], unless_option: options[:unless])
+        chain.insert(chain.index(callback), new_callback)
+      end
+
+      chain.delete(callback)
+    end
+    target.set_callbacks name, chain
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/Conditionals.html b/src/7.0/classes/ActiveSupport/Callbacks/Conditionals.html new file mode 100644 index 0000000000..240a0d4d2a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/Conditionals.html @@ -0,0 +1,67 @@ +--- +title: ActiveSupport::Callbacks::Conditionals +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/Conditionals/Value.html b/src/7.0/classes/ActiveSupport/Callbacks/Conditionals/Value.html new file mode 100644 index 0000000000..09b200f52b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/Conditionals/Value.html @@ -0,0 +1,147 @@ +--- +title: ActiveSupport::Callbacks::Conditionals::Value +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 152
+def initialize(&block)
+  @block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(target, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 155
+def call(target, value); @block.call(value); end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/Filters.html b/src/7.0/classes/ActiveSupport/Callbacks/Filters.html new file mode 100644 index 0000000000..fb87c90914 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/Filters.html @@ -0,0 +1,87 @@ +--- +title: ActiveSupport::Callbacks::Filters +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
Environment=Struct.new(:target, :halted, :value)
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/Filters/After.html b/src/7.0/classes/ActiveSupport/Callbacks/Filters/After.html new file mode 100644 index 0000000000..da7623f14a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/Filters/After.html @@ -0,0 +1,119 @@ +--- +title: ActiveSupport::Callbacks::Filters::After +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + build(callback_sequence, user_callback, user_conditions, chain_config) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 213
+def self.build(callback_sequence, user_callback, user_conditions, chain_config)
+  if chain_config[:skip_after_callbacks_if_terminated]
+    if user_conditions.any?
+      halting_and_conditional(callback_sequence, user_callback, user_conditions)
+    else
+      halting(callback_sequence, user_callback)
+    end
+  else
+    if user_conditions.any?
+      conditional callback_sequence, user_callback, user_conditions
+    else
+      simple callback_sequence, user_callback
+    end
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Callbacks/Filters/Before.html b/src/7.0/classes/ActiveSupport/Callbacks/Filters/Before.html new file mode 100644 index 0000000000..6f513c3da7 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Callbacks/Filters/Before.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::Callbacks::Filters::Before +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + build(callback_sequence, user_callback, user_conditions, chain_config, filter, name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/callbacks.rb, line 163
+def self.build(callback_sequence, user_callback, user_conditions, chain_config, filter, name)
+  halted_lambda = chain_config[:terminator]
+
+  if user_conditions.any?
+    halting_and_conditional(callback_sequence, user_callback, user_conditions, halted_lambda, filter, name)
+  else
+    halting(callback_sequence, user_callback, halted_lambda, filter, name)
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/CodeGenerator.html b/src/7.0/classes/ActiveSupport/CodeGenerator.html new file mode 100644 index 0000000000..4c94eea3c3 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/CodeGenerator.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::CodeGenerator +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/CodeGenerator/MethodSet.html b/src/7.0/classes/ActiveSupport/CodeGenerator/MethodSet.html new file mode 100644 index 0000000000..fe99d5dfae --- /dev/null +++ b/src/7.0/classes/ActiveSupport/CodeGenerator/MethodSet.html @@ -0,0 +1,220 @@ +--- +title: ActiveSupport::CodeGenerator::MethodSet +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
METHOD_CACHES=Hash.new { |h, k| h[k] = Module.new }
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(namespace) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/code_generator.rb, line 8
+def initialize(namespace)
+  @cache = METHOD_CACHES[namespace]
+  @sources = []
+  @methods = {}
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + apply(owner, path, line) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/code_generator.rb, line 25
+def apply(owner, path, line)
+  unless @sources.empty?
+    @cache.module_eval("# frozen_string_literal: true\n" + @sources.join(";"), path, line)
+  end
+  @methods.each do |name, as|
+    owner.define_method(name, @cache.instance_method(as))
+  end
+end
+
+
+ +
+ +
+

+ + define_cached_method(name, as: name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/code_generator.rb, line 14
+def define_cached_method(name, as: name)
+  name = name.to_sym
+  as = as.to_sym
+  @methods.fetch(name) do
+    unless @cache.method_defined?(as)
+      yield @sources
+    end
+    @methods[name] = as
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/CompareWithRange.html b/src/7.0/classes/ActiveSupport/CompareWithRange.html new file mode 100644 index 0000000000..488c52dd57 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/CompareWithRange.html @@ -0,0 +1,188 @@ +--- +title: ActiveSupport::CompareWithRange +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + ===(value) + +

+ + +
+

Extends the default Range#=== to support range comparisons.

+ +
(1..5) === (1..5)  # => true
+(1..5) === (2..3)  # => true
+(1..5) === (1...6) # => true
+(1..5) === (2..6)  # => false
+
+ +

The native Range#=== behavior is untouched.

+ +
('a'..'f') === ('c') # => true
+(5..9) === (11) # => false
+
+ +

The given range must be fully bounded, with both start and end.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/range/compare_range.rb, line 16
+def ===(value)
+  if value.is_a?(::Range)
+    is_backwards_op = value.exclude_end? ? :>= : :>
+    return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
+    # 1...10 includes 1..9 but it does not include 1..10.
+    # 1..10 includes 1...11 but it does not include 1...12.
+    operator = exclude_end? && !value.exclude_end? ? :< : :<=
+    value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
+    super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + include?(value) + +

+ + +
+

Extends the default Range#include? to support range comparisons.

+ +
(1..5).include?(1..5)  # => true
+(1..5).include?(2..3)  # => true
+(1..5).include?(1...6) # => true
+(1..5).include?(2..6)  # => false
+
+ +

The native Range#include? behavior is untouched.

+ +
('a'..'f').include?('c') # => true
+(5..9).include?(11) # => false
+
+ +

The given range must be fully bounded, with both start and end.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/range/compare_range.rb, line 41
+def include?(value)
+  if value.is_a?(::Range)
+    is_backwards_op = value.exclude_end? ? :>= : :>
+    return false if value.begin && value.end && value.begin.public_send(is_backwards_op, value.end)
+    # 1...10 includes 1..9 but it does not include 1..10.
+    # 1..10 includes 1...11 but it does not include 1...12.
+    operator = exclude_end? && !value.exclude_end? ? :< : :<=
+    value_max = !exclude_end? && value.exclude_end? ? value.max : value.last
+    super(value.first) && (self.end.nil? || value_max.public_send(operator, last))
+  else
+    super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Concern.html b/src/7.0/classes/ActiveSupport/Concern.html new file mode 100644 index 0000000000..9ba3946f4e --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Concern.html @@ -0,0 +1,330 @@ +--- +title: ActiveSupport::Concern +layout: default +--- +
+ +
+
+ +
+ +

A typical module looks like this:

+ +
module M
+  def self.included(base)
+    base.extend ClassMethods
+    base.class_eval do
+      scope :disabled, -> { where(disabled: true) }
+    end
+  end
+
+  module ClassMethods
+    ...
+  end
+end
+
+ +

By using ActiveSupport::Concern the above module could instead be written as:

+ +
require "active_support/concern"
+
+module M
+  extend ActiveSupport::Concern
+
+  included do
+    scope :disabled, -> { where(disabled: true) }
+  end
+
+  class_methods do
+    ...
+  end
+end
+
+ +

Moreover, it gracefully handles module dependencies. Given a Foo module and a Bar module which depends on the former, we would typically write the following:

+ +
module Foo
+  def self.included(base)
+    base.class_eval do
+      def self.method_injected_by_foo
+        ...
+      end
+    end
+  end
+end
+
+module Bar
+  def self.included(base)
+    base.method_injected_by_foo
+  end
+end
+
+class Host
+  include Foo # We need to include this dependency for Bar
+  include Bar # Bar is the module that Host really needs
+end
+
+ +

But why should Host care about Bar‘s dependencies, namely Foo? We could try to hide these from Host directly including Foo in Bar:

+ +
module Bar
+  include Foo
+  def self.included(base)
+    base.method_injected_by_foo
+  end
+end
+
+class Host
+  include Bar
+end
+
+ +

Unfortunately this won’t work, since when Foo is included, its base is the Bar module, not the Host class. With ActiveSupport::Concern, module dependencies are properly resolved:

+ +
require "active_support/concern"
+
+module Foo
+  extend ActiveSupport::Concern
+  included do
+    def self.method_injected_by_foo
+      ...
+    end
+  end
+end
+
+module Bar
+  extend ActiveSupport::Concern
+  include Foo
+
+  included do
+    self.method_injected_by_foo
+  end
+end
+
+class Host
+  include Bar # It works, now Bar takes care of its dependencies
+end
+
+ +

Prepending concerns

+ +

Just like include, concerns also support prepend with a corresponding prepended do callback. module ClassMethods or class_methods do are prepended as well.

+ +

prepend is also used for any dependencies.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + class_methods(&class_methods_module_definition) + +

+ + +
+

Define class methods from given block. You can define private class methods as well.

+ +
module Example
+  extend ActiveSupport::Concern
+
+  class_methods do
+    def foo; puts 'foo'; end
+
+    private
+      def bar; puts 'bar'; end
+  end
+end
+
+class Buzz
+  include Example
+end
+
+Buzz.foo # => "foo"
+Buzz.bar # => private method 'bar' called for Buzz:Class(NoMethodError)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concern.rb, line 207
+def class_methods(&class_methods_module_definition)
+  mod = const_defined?(:ClassMethods, false) ?
+    const_get(:ClassMethods) :
+    const_set(:ClassMethods, Module.new)
+
+  mod.module_eval(&class_methods_module_definition)
+end
+
+
+ +
+ +
+

+ + included(base = nil, &block) + +

+ + +
+

Evaluate given block in context of base class, so that you can write class macros here. When you define more than one included block, it raises an exception.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concern.rb, line 156
+def included(base = nil, &block)
+  if base.nil?
+    if instance_variable_defined?(:@_included_block)
+      if @_included_block.source_location != block.source_location
+        raise MultipleIncludedBlocks
+      end
+    else
+      @_included_block = block
+    end
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + prepended(base = nil, &block) + +

+ + +
+

Evaluate given block in context of base class, so that you can write class macros here. When you define more than one prepended block, it raises an exception.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concern.rb, line 173
+def prepended(base = nil, &block)
+  if base.nil?
+    if instance_variable_defined?(:@_prepended_block)
+      if @_prepended_block.source_location != block.source_location
+        raise MultiplePrependBlocks
+      end
+    else
+      @_prepended_block = block
+    end
+  else
+    super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Concurrency.html b/src/7.0/classes/ActiveSupport/Concurrency.html new file mode 100644 index 0000000000..ff377aece1 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Concurrency.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::Concurrency +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Concurrency/LoadInterlockAwareMonitor.html b/src/7.0/classes/ActiveSupport/Concurrency/LoadInterlockAwareMonitor.html new file mode 100644 index 0000000000..bd6a9681e2 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Concurrency/LoadInterlockAwareMonitor.html @@ -0,0 +1,161 @@ +--- +title: ActiveSupport::Concurrency::LoadInterlockAwareMonitor +layout: default +--- +
+ +
+
+ +
+ +

A monitor that will permit dependency loading while blocked waiting for the lock.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + mon_enter() + +

+ + +
+

Enters an exclusive section, but allows dependency loading while blocked

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb, line 15
+def mon_enter
+  mon_try_enter ||
+    ActiveSupport::Dependencies.interlock.permit_concurrent_loads { super }
+end
+
+
+ +
+ +
+

+ + synchronize(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/load_interlock_aware_monitor.rb, line 20
+def synchronize(&block)
+  Thread.handle_interrupt(EXCEPTION_NEVER) do
+    mon_enter
+
+    begin
+      Thread.handle_interrupt(EXCEPTION_IMMEDIATE, &block)
+    ensure
+      mon_exit
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Concurrency/ShareLock.html b/src/7.0/classes/ActiveSupport/Concurrency/ShareLock.html new file mode 100644 index 0000000000..b345058a84 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Concurrency/ShareLock.html @@ -0,0 +1,503 @@ +--- +title: ActiveSupport::Concurrency::ShareLock +layout: default +--- +
+ +
+
+ +
+ +

A share/exclusive lock, otherwise known as a read/write lock.

+ +

en.wikipedia.org/wiki/Readers%E2%80%93writer_lock

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + MonitorMixin + +
  • + +
+ + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 50
+def initialize
+  super()
+
+  @cv = new_cond
+
+  @sharing = Hash.new(0)
+  @waiting = {}
+  @sleeping = {}
+  @exclusive_thread = nil
+  @exclusive_depth = 0
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false) + +

+ + +
+

Execute the supplied block while holding the Exclusive lock. If no_wait is set and the lock is not immediately available, returns nil without yielding. Otherwise, returns the result of the block.

+ +

See start_exclusive for other options.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 148
+def exclusive(purpose: nil, compatible: [], after_compatible: [], no_wait: false)
+  if start_exclusive(purpose: purpose, compatible: compatible, no_wait: no_wait)
+    begin
+      yield
+    ensure
+      stop_exclusive(compatible: after_compatible)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + sharing() + +

+ + +
+

Execute the supplied block while holding the Share lock.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 159
+def sharing
+  start_sharing
+  begin
+    yield
+  ensure
+    stop_sharing
+  end
+end
+
+
+ +
+ +
+

+ + start_exclusive(purpose: nil, compatible: [], no_wait: false) + +

+ + +
+

Returns false if no_wait is set and the lock is not immediately available. Otherwise, returns true after the lock has been acquired.

+ +

purpose and compatible work together; while this thread is waiting for the exclusive lock, it will yield its share (if any) to any other attempt whose purpose appears in this attempt’s compatible list. This allows a “loose” upgrade, which, being less strict, prevents some classes of deadlocks.

+ +

For many resources, loose upgrades are sufficient: if a thread is awaiting a lock, it is not running any other code. With purpose matching, it is possible to yield only to other threads whose activity will not interfere.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 76
+def start_exclusive(purpose: nil, compatible: [], no_wait: false)
+  synchronize do
+    unless @exclusive_thread == Thread.current
+      if busy_for_exclusive?(purpose)
+        return false if no_wait
+
+        yield_shares(purpose: purpose, compatible: compatible, block_share: true) do
+          wait_for(:start_exclusive) { busy_for_exclusive?(purpose) }
+        end
+      end
+      @exclusive_thread = Thread.current
+    end
+    @exclusive_depth += 1
+
+    true
+  end
+end
+
+
+ +
+ +
+

+ + start_sharing() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 114
+def start_sharing
+  synchronize do
+    if @sharing[Thread.current] > 0 || @exclusive_thread == Thread.current
+      # We already hold a lock; nothing to wait for
+    elsif @waiting[Thread.current]
+      # We're nested inside a +yield_shares+ call: we'll resume as
+      # soon as there isn't an exclusive lock in our way
+      wait_for(:start_sharing) { @exclusive_thread }
+    else
+      # This is an initial / outermost share call: any outstanding
+      # requests for an exclusive lock get to go first
+      wait_for(:start_sharing) { busy_for_sharing?(false) }
+    end
+    @sharing[Thread.current] += 1
+  end
+end
+
+
+ +
+ +
+

+ + stop_exclusive(compatible: []) + +

+ + +
+

Relinquish the exclusive lock. Must only be called by the thread that called start_exclusive (and currently holds the lock).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 96
+def stop_exclusive(compatible: [])
+  synchronize do
+    raise "invalid unlock" if @exclusive_thread != Thread.current
+
+    @exclusive_depth -= 1
+    if @exclusive_depth == 0
+      @exclusive_thread = nil
+
+      if eligible_waiters?(compatible)
+        yield_shares(compatible: compatible, block_share: true) do
+          wait_for(:stop_exclusive) { @exclusive_thread || eligible_waiters?(compatible) }
+        end
+      end
+      @cv.broadcast
+    end
+  end
+end
+
+
+ +
+ +
+

+ + stop_sharing() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 131
+def stop_sharing
+  synchronize do
+    if @sharing[Thread.current] > 1
+      @sharing[Thread.current] -= 1
+    else
+      @sharing.delete Thread.current
+      @cv.broadcast
+    end
+  end
+end
+
+
+ +
+ +
+

+ + yield_shares(purpose: nil, compatible: [], block_share: false) + +

+ + +
+

Temporarily give up all held Share locks while executing the supplied block, allowing any compatible exclusive lock request to proceed.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/concurrency/share_lock.rb, line 171
+def yield_shares(purpose: nil, compatible: [], block_share: false)
+  loose_shares = previous_wait = nil
+  synchronize do
+    if loose_shares = @sharing.delete(Thread.current)
+      if previous_wait = @waiting[Thread.current]
+        purpose = nil unless purpose == previous_wait[0]
+        compatible &= previous_wait[1]
+      end
+      compatible |= [false] unless block_share
+      @waiting[Thread.current] = [purpose, compatible]
+    end
+
+    @cv.broadcast
+  end
+
+  begin
+    yield
+  ensure
+    synchronize do
+      wait_for(:yield_shares) { @exclusive_thread && @exclusive_thread != Thread.current }
+
+      if previous_wait
+        @waiting[Thread.current] = previous_wait
+      else
+        @waiting.delete Thread.current
+      end
+      @sharing[Thread.current] = loose_shares if loose_shares
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Configurable.html b/src/7.0/classes/ActiveSupport/Configurable.html new file mode 100644 index 0000000000..a241fed69d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Configurable.html @@ -0,0 +1,142 @@ +--- +title: ActiveSupport::Configurable +layout: default +--- +
+ +
+
+ +
+ +

Configurable provides a config method to store and retrieve configuration options as an OrderedOptions.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + config() + +

+ + +
+

Reads and writes attributes from a configuration OrderedOptions.

+ +
require "active_support/configurable"
+
+class User
+  include ActiveSupport::Configurable
+end
+
+user = User.new
+
+user.config.allowed_access = true
+user.config.level = 1
+
+user.config.allowed_access # => true
+user.config.level          # => 1
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 145
+def config
+  @_config ||= self.class.config.inheritable_copy
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Configurable/ClassMethods.html b/src/7.0/classes/ActiveSupport/Configurable/ClassMethods.html new file mode 100644 index 0000000000..4b97a71ada --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Configurable/ClassMethods.html @@ -0,0 +1,272 @@ +--- +title: ActiveSupport::Configurable::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 28
+def config
+  @_config ||= if respond_to?(:superclass) && superclass.respond_to?(:config)
+    superclass.config.inheritable_copy
+  else
+    # create a new "anonymous" class that will host the compiled reader methods
+    Class.new(Configuration).new
+  end
+end
+
+
+ +
+ +
+

+ + configure() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 37
+def configure
+  yield config
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) + +

+ + +
+

Allows you to add shortcut so that you don’t have to refer to attribute through config. Also look at the example for config to contrast.

+ +

Defines both class and instance config accessors.

+ +
class User
+  include ActiveSupport::Configurable
+  config_accessor :allowed_access
+end
+
+User.allowed_access # => nil
+User.allowed_access = false
+User.allowed_access # => false
+
+user = User.new
+user.allowed_access # => false
+user.allowed_access = true
+user.allowed_access # => true
+
+User.allowed_access # => false
+
+ +

The attribute name must be a valid method name in Ruby.

+ +
class User
+  include ActiveSupport::Configurable
+  config_accessor :"1_Badname"
+end
+# => NameError: invalid config attribute name
+
+ +

To omit the instance writer method, pass instance_writer: false. To omit the instance reader method, pass instance_reader: false.

+ +
class User
+  include ActiveSupport::Configurable
+  config_accessor :allowed_access, instance_reader: false, instance_writer: false
+end
+
+User.allowed_access = false
+User.allowed_access # => false
+
+User.new.allowed_access = true # => NoMethodError
+User.new.allowed_access        # => NoMethodError
+
+ +

Or pass instance_accessor: false, to omit both instance methods.

+ +
class User
+  include ActiveSupport::Configurable
+  config_accessor :allowed_access, instance_accessor: false
+end
+
+User.allowed_access = false
+User.allowed_access # => false
+
+User.new.allowed_access = true # => NoMethodError
+User.new.allowed_access        # => NoMethodError
+
+ +

Also you can pass default or a block to set up the attribute with a default value.

+ +
class User
+  include ActiveSupport::Configurable
+  config_accessor :allowed_access, default: false
+  config_accessor :hair_colors do
+    [:brown, :black, :blonde, :red]
+  end
+end
+
+User.allowed_access # => false
+User.hair_colors # => [:brown, :black, :blonde, :red]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 109
+def config_accessor(*names, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) # :doc:
+  names.each do |name|
+    raise NameError.new("invalid config attribute name") unless /\A[_A-Za-z]\w*\z/.match?(name)
+
+    reader, reader_line = "def #{name}; config.#{name}; end", __LINE__
+    writer, writer_line = "def #{name}=(value); config.#{name} = value; end", __LINE__
+
+    singleton_class.class_eval reader, __FILE__, reader_line
+    singleton_class.class_eval writer, __FILE__, writer_line
+
+    if instance_accessor
+      class_eval reader, __FILE__, reader_line if instance_reader
+      class_eval writer, __FILE__, writer_line if instance_writer
+    end
+
+    send("#{name}=", block_given? ? yield : default)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Configurable/Configuration.html b/src/7.0/classes/ActiveSupport/Configurable/Configuration.html new file mode 100644 index 0000000000..bb89517aa8 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Configurable/Configuration.html @@ -0,0 +1,153 @@ +--- +title: ActiveSupport::Configurable::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + compile_methods!(keys) + +

+ + +
+

Compiles reader methods so we don’t have to go through method_missing.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 18
+      def self.compile_methods!(keys)
+        keys.reject { |m| method_defined?(m) }.each do |key|
+          class_eval <<-RUBY, __FILE__, __LINE__ + 1
+            def #{key}; _get(#{key.inspect}); end
+          RUBY
+        end
+      end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compile_methods!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/configurable.rb, line 13
+def compile_methods!
+  self.class.compile_methods!(keys)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ConfigurationFile.html b/src/7.0/classes/ActiveSupport/ConfigurationFile.html new file mode 100644 index 0000000000..9b0db3937b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ConfigurationFile.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::ConfigurationFile +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ConfigurationFile/FormatError.html b/src/7.0/classes/ActiveSupport/ConfigurationFile/FormatError.html new file mode 100644 index 0000000000..366bab266b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ConfigurationFile/FormatError.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::ConfigurationFile::FormatError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/CurrentAttributes.html b/src/7.0/classes/ActiveSupport/CurrentAttributes.html new file mode 100644 index 0000000000..5ab1db6d81 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/CurrentAttributes.html @@ -0,0 +1,533 @@ +--- +title: ActiveSupport::CurrentAttributes +layout: default +--- +
+ +
+
+ +
+ +

Abstract super class that provides a thread-isolated attributes singleton, which resets automatically before and after each request. This allows you to keep all the per-request attributes easily available to the whole system.

+ +

The following full app-like example demonstrates how to use a Current class to facilitate easy access to the global, per-request attributes without passing them deeply around everywhere:

+ +
# app/models/current.rb
+class Current < ActiveSupport::CurrentAttributes
+  attribute :account, :user
+  attribute :request_id, :user_agent, :ip_address
+
+  resets { Time.zone = nil }
+
+  def user=(user)
+    super
+    self.account = user.account
+    Time.zone    = user.time_zone
+  end
+end
+
+# app/controllers/concerns/authentication.rb
+module Authentication
+  extend ActiveSupport::Concern
+
+  included do
+    before_action :authenticate
+  end
+
+  private
+    def authenticate
+      if authenticated_user = User.find_by(id: cookies.encrypted[:user_id])
+        Current.user = authenticated_user
+      else
+        redirect_to new_session_url
+      end
+    end
+end
+
+# app/controllers/concerns/set_current_request_details.rb
+module SetCurrentRequestDetails
+  extend ActiveSupport::Concern
+
+  included do
+    before_action do
+      Current.request_id = request.uuid
+      Current.user_agent = request.user_agent
+      Current.ip_address = request.ip
+    end
+  end
+end
+
+class ApplicationController < ActionController::Base
+  include Authentication
+  include SetCurrentRequestDetails
+end
+
+class MessagesController < ApplicationController
+  def create
+    Current.account.messages.create(message_params)
+  end
+end
+
+class Message < ApplicationRecord
+  belongs_to :creator, default: -> { Current.user }
+  after_create { |message| Event.create(record: message) }
+end
+
+class Event < ApplicationRecord
+  before_create do
+    self.request_id = Current.request_id
+    self.user_agent = Current.user_agent
+    self.ip_address = Current.ip_address
+  end
+end
+
+ +

A word of caution: It’s easy to overdo a global singleton like Current and tangle your model as a result. Current should only be used for a few, top-level globals, like account, user, and request details. The attributes stuck in Current should be used by more or less all actions on all requests. If you start sticking controller-specific attributes in there, you’re going to create a mess.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + attributes
+ + + + +

Class Public methods

+ +
+

+ + after_reset(&block) + +

+ + +
+ +
+ + + + + +
+ Alias for: resets +
+ + + +
+ +
+

+ + attribute(*names) + +

+ + +
+

Declares one or more attributes that will be given both class and instance accessor methods.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 100
+def attribute(*names)
+  ActiveSupport::CodeGenerator.batch(generated_attribute_methods, __FILE__, __LINE__) do |owner|
+    names.each do |name|
+      owner.define_cached_method(name, namespace: :current_attributes) do |batch|
+        batch <<
+          "def #{name}" <<
+          "attributes[:#{name}]" <<
+          "end"
+      end
+      owner.define_cached_method("#{name}=", namespace: :current_attributes) do |batch|
+        batch <<
+          "def #{name}=(value)" <<
+          "attributes[:#{name}] = value" <<
+          "end"
+      end
+    end
+  end
+
+  ActiveSupport::CodeGenerator.batch(singleton_class, __FILE__, __LINE__) do |owner|
+    names.each do |name|
+      owner.define_cached_method(name, namespace: :current_attributes_delegation) do |batch|
+        batch <<
+          "def #{name}" <<
+          "instance.#{name}" <<
+          "end"
+      end
+      owner.define_cached_method("#{name}=", namespace: :current_attributes_delegation) do |batch|
+        batch <<
+          "def #{name}=(value)" <<
+          "instance.#{name} = value" <<
+          "end"
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + before_reset(&block) + +

+ + +
+

Calls this block before reset is called on the instance. Used for resetting external collaborators that depend on current values.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 137
+def before_reset(&block)
+  set_callback :reset, :before, &block
+end
+
+
+ +
+ +
+

+ + instance() + +

+ + +
+

Returns singleton instance for this class in this thread. If none exists, one is created.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 95
+def instance
+  current_instances[current_instances_key] ||= new
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 188
+def initialize
+  @attributes = {}
+end
+
+
+ +
+ +
+

+ + resets(&block) + +

+ + +
+

Calls this block after reset is called on the instance. Used for resetting external collaborators, like Time.zone.

+
+ + + +
+ Also aliased as: after_reset +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 142
+def resets(&block)
+  set_callback :reset, :after, &block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + reset() + +

+ + +
+

Reset all attributes. Should be called before and after actions, when used as a per-request singleton.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 211
+def reset
+  run_callbacks :reset do
+    self.attributes = {}
+  end
+end
+
+
+ +
+ +
+

+ + set(set_attributes) + +

+ + +
+

Expose one or more attributes within a block. Old values are returned after the block concludes. Example demonstrating the common use of needing to set Current attributes outside the request-cycle:

+ +
class Chat::PublicationJob < ApplicationJob
+  def perform(attributes, room_number, creator)
+    Current.set(person: creator) do
+      Chat::Publisher.publish(attributes: attributes, room_number: room_number)
+    end
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/current_attributes.rb, line 202
+def set(set_attributes)
+  old_attributes = compute_attributes(set_attributes.keys)
+  assign_attributes(set_attributes)
+  yield
+ensure
+  assign_attributes(old_attributes)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Dependencies.html b/src/7.0/classes/ActiveSupport/Dependencies.html new file mode 100644 index 0000000000..1238436245 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Dependencies.html @@ -0,0 +1,203 @@ +--- +title: ActiveSupport::Dependencies +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + load_interlock(&block) + +

+ + +
+

Execute the supplied block while holding an exclusive lock, preventing any other thread from being inside a run_interlock block at the same time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies.rb, line 24
+def self.load_interlock(&block)
+  interlock.loading(&block)
+end
+
+
+ +
+ +
+

+ + run_interlock(&block) + +

+ + +
+

Execute the supplied block without interference from any concurrent loads.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies.rb, line 17
+def self.run_interlock(&block)
+  interlock.running(&block)
+end
+
+
+ +
+ +
+

+ + unload_interlock(&block) + +

+ + +
+

Execute the supplied block while holding an exclusive lock, preventing any other thread from being inside a run_interlock block at the same time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies.rb, line 31
+def self.unload_interlock(&block)
+  interlock.unloading(&block)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Dependencies/Interlock.html b/src/7.0/classes/ActiveSupport/Dependencies/Interlock.html new file mode 100644 index 0000000000..f16e32eb1a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Dependencies/Interlock.html @@ -0,0 +1,380 @@ +--- +title: ActiveSupport::Dependencies::Interlock +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + done_running() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 32
+def done_running
+  @lock.stop_sharing
+end
+
+
+ +
+ +
+

+ + done_unloading() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 24
+def done_unloading
+  @lock.stop_exclusive(compatible: [:load, :unload])
+end
+
+
+ +
+ +
+

+ + loading(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 12
+def loading(&block)
+  @lock.exclusive(purpose: :load, compatible: [:load], after_compatible: [:load], &block)
+end
+
+
+ +
+ +
+

+ + permit_concurrent_loads(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 40
+def permit_concurrent_loads(&block)
+  @lock.yield_shares(compatible: [:load], &block)
+end
+
+
+ +
+ +
+

+ + running(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 36
+def running(&block)
+  @lock.sharing(&block)
+end
+
+
+ +
+ +
+

+ + start_running() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 28
+def start_running
+  @lock.start_sharing
+end
+
+
+ +
+ +
+

+ + start_unloading() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 20
+def start_unloading
+  @lock.start_exclusive(purpose: :unload, compatible: [:load, :unload])
+end
+
+
+ +
+ +
+

+ + unloading(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/interlock.rb, line 16
+def unloading(&block)
+  @lock.exclusive(purpose: :unload, compatible: [:load, :unload], after_compatible: [:load, :unload], &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Dependencies/RequireDependency.html b/src/7.0/classes/ActiveSupport/Dependencies/RequireDependency.html new file mode 100644 index 0000000000..715204c5cd --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Dependencies/RequireDependency.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::Dependencies::RequireDependency +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + require_dependency(filename) + +

+ + +
+

Warning: This method is obsolete. The semantics of the autoloader match Ruby’s and you do not need to be defensive with load order anymore. Just refer to classes and modules normally.

+ +

Engines that do not control the mode in which their parent application runs should call require_dependency where needed in case the runtime mode is :classic.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/dependencies/require_dependency.rb, line 11
+def require_dependency(filename)
+  filename = filename.to_path if filename.respond_to?(:to_path)
+
+  unless filename.is_a?(String)
+    raise ArgumentError, "the file name must be either a String or implement #to_path -- you passed #{filename.inspect}"
+  end
+
+  if abspath = ActiveSupport::Dependencies.search_for_file(filename)
+    require abspath
+  else
+    require filename
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation.html b/src/7.0/classes/ActiveSupport/Deprecation.html new file mode 100644 index 0000000000..d94c60c6ee --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation.html @@ -0,0 +1,280 @@ +--- +title: ActiveSupport::Deprecation +layout: default +--- +
+ +
+
+ +
+ +

Deprecation specifies the API used by Rails to deprecate methods, instance variables, objects, and constants.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DEFAULT_BEHAVIORS={ +raise: ->(message, callstack, deprecation_horizon, gem_name) { +e = DeprecationException.new(message) +e.set_backtrace(callstack.map(&:to_s)) +raise e +}, + +stderr: ->(message, callstack, deprecation_horizon, gem_name) { +$stderr.puts(message) +$stderr.puts callstack.join("\n ") if debug +}, + +log: ->(message, callstack, deprecation_horizon, gem_name) { +logger = +if defined?(Rails.logger) && Rails.logger +Rails.logger +else +require "active_support/logger" +ActiveSupport::Logger.new($stderr) +end +logger.warn message +logger.debug callstack.join("\n ") if debug +}, + +notify: ->(message, callstack, deprecation_horizon, gem_name) { +notification_name = "deprecation.#{gem_name.underscore.tr('/', '_')}" +ActiveSupport::Notifications.instrument(notification_name, +message: message, +callstack: callstack, +gem_name: gem_name, +deprecation_horizon: deprecation_horizon) +}, + +silence: ->(message, callstack, deprecation_horizon, gem_name) { }, +}
 

Default warning behaviors per Rails.env.

+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + deprecation_horizon

The version number in which the deprecated behavior will be removed, by default.

+ + + + +

Class Public methods

+ +
+

+ + new(deprecation_horizon = "7.1", gem_name = "Rails") + +

+ + +
+

It accepts two parameters on initialization. The first is a version of library and the second is a library name.

+ +
ActiveSupport::Deprecation.new('2.0', 'MyLibrary')
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation.rb, line 41
+def initialize(deprecation_horizon = "7.1", gem_name = "Rails")
+  self.gem_name = gem_name
+  self.deprecation_horizon = deprecation_horizon
+  # By default, warnings are not silenced and debugging is off.
+  self.silenced = false
+  self.debug = false
+  @silenced_thread = Concurrent::ThreadLocalVar.new(false)
+  @explicitly_allowed_warnings = Concurrent::ThreadLocalVar.new(nil)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/Behavior.html b/src/7.0/classes/ActiveSupport/Deprecation/Behavior.html new file mode 100644 index 0000000000..47762871d5 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/Behavior.html @@ -0,0 +1,286 @@ +--- +title: ActiveSupport::Deprecation::Behavior +layout: default +--- +
+ +
+
+ +
+ +

Behavior module allows to determine how to display deprecation messages. You can create a custom behavior or set any from the DEFAULT_BEHAVIORS constant. Available behaviors are:

+
raise +
+

Raise ActiveSupport::DeprecationException.

+
stderr +
+

Log all deprecation warnings to $stderr.

+
log +
+

Log all deprecation warnings to Rails.logger.

+
notify +
+

Use ActiveSupport::Notifications to notify deprecation.rails.

+
silence +
+

Do nothing. On Rails, set config.active_support.report_deprecations = false to disable all behaviors.

+
+ +

Setting behaviors only affects deprecations that happen after boot time. For more information you can read the documentation of the behavior= method.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + debug

Whether to print a backtrace along with the warning.

+ + + + + +

Instance Public methods

+ +
+

+ + behavior() + +

+ + +
+

Returns the current behavior or if one isn’t set, defaults to :stderr.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/behaviors.rb, line 66
+def behavior
+  @behavior ||= [DEFAULT_BEHAVIORS[:stderr]]
+end
+
+
+ +
+ +
+

+ + behavior=(behavior) + +

+ + +
+

Sets the behavior to the specified value. Can be a single value, array, or an object that responds to call.

+ +

Available behaviors:

+
raise +
+

Raise ActiveSupport::DeprecationException.

+
stderr +
+

Log all deprecation warnings to $stderr.

+
log +
+

Log all deprecation warnings to Rails.logger.

+
notify +
+

Use ActiveSupport::Notifications to notify deprecation.rails.

+
silence +
+

Do nothing.

+
+ +

Setting behaviors only affects deprecations that happen after boot time. Deprecation warnings raised by gems are not affected by this setting because they happen before Rails boots up.

+ +
ActiveSupport::Deprecation.behavior = :stderr
+ActiveSupport::Deprecation.behavior = [:stderr, :log]
+ActiveSupport::Deprecation.behavior = MyCustomHandler
+ActiveSupport::Deprecation.behavior = ->(message, callstack, deprecation_horizon, gem_name) {
+  # custom stuff
+}
+
+ +

If you are using Rails, you can set config.active_support.report_deprecations = false to disable all deprecation behaviors. This is similar to the silence option but more performant.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/behaviors.rb, line 99
+def behavior=(behavior)
+  @behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
+end
+
+
+ +
+ +
+

+ + disallowed_behavior() + +

+ + +
+

Returns the current behavior for disallowed deprecations or if one isn’t set, defaults to :raise.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/behaviors.rb, line 71
+def disallowed_behavior
+  @disallowed_behavior ||= [DEFAULT_BEHAVIORS[:raise]]
+end
+
+
+ +
+ +
+

+ + disallowed_behavior=(behavior) + +

+ + +
+

Sets the behavior for disallowed deprecations (those configured by ActiveSupport::Deprecation.disallowed_warnings=) to the specified value. As with behavior=, this can be a single value, array, or an object that responds to call.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/behaviors.rb, line 107
+def disallowed_behavior=(behavior)
+  @disallowed_behavior = Array(behavior).map { |b| DEFAULT_BEHAVIORS[b] || arity_coerce(b) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantAccessor.html b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantAccessor.html new file mode 100644 index 0000000000..a7e33dbd23 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantAccessor.html @@ -0,0 +1,231 @@ +--- +title: ActiveSupport::Deprecation::DeprecatedConstantAccessor +layout: default +--- +
+ +
+
+ +
+ +

DeprecatedConstantAccessor transforms a constant into a deprecated one by hooking const_missing.

+ +

It takes the names of an old (deprecated) constant and of a new constant (both in string form) and optionally a deprecator. The deprecator defaults to ActiveSupport::Deprecator if none is specified.

+ +

The deprecated constant now returns the same object as the new one rather than a proxy object, so it can be used transparently in rescue blocks etc.

+ +
PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
+
+# (In a later update, the original implementation of `PLANETS` has been removed.)
+
+PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
+include ActiveSupport::Deprecation::DeprecatedConstantAccessor
+deprecate_constant 'PLANETS', 'PLANETS_POST_2006'
+
+PLANETS.map { |planet| planet.capitalize }
+# => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
+     (Backtrace information…)
+     ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + included(base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 29
+def self.included(base)
+  require "active_support/inflector/methods"
+
+  extension = Module.new do
+    def const_missing(missing_const_name)
+      if class_variable_defined?(:@@_deprecated_constants)
+        if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
+          replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
+          return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
+        end
+      end
+      super
+    end
+
+    def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
+      class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
+      class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
+    end
+  end
+  base.singleton_class.prepend extension
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + const_missing(missing_const_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 33
+def const_missing(missing_const_name)
+  if class_variable_defined?(:@@_deprecated_constants)
+    if (replacement = class_variable_get(:@@_deprecated_constants)[missing_const_name.to_s])
+      replacement[:deprecator].warn(replacement[:message] || "#{name}::#{missing_const_name} is deprecated! Use #{replacement[:new]} instead.", caller_locations)
+      return ActiveSupport::Inflector.constantize(replacement[:new].to_s)
+    end
+  end
+  super
+end
+
+
+ +
+ +
+

+ + deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/constant_accessor.rb, line 43
+def deprecate_constant(const_name, new_constant, message: nil, deprecator: ActiveSupport::Deprecation.instance)
+  class_variable_set(:@@_deprecated_constants, {}) unless class_variable_defined?(:@@_deprecated_constants)
+  class_variable_get(:@@_deprecated_constants)[const_name.to_s] = { new: new_constant, message: message, deprecator: deprecator }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantProxy.html b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantProxy.html new file mode 100644 index 0000000000..aed81fb28f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedConstantProxy.html @@ -0,0 +1,259 @@ +--- +title: ActiveSupport::Deprecation::DeprecatedConstantProxy +layout: default +--- +
+ +
+
+ +
+ +

DeprecatedConstantProxy transforms a constant into a deprecated one. It takes the names of an old (deprecated) constant and of a new constant (both in string form) and optionally a deprecator. The deprecator defaults to ActiveSupport::Deprecator if none is specified. The deprecated constant now returns the value of the new one.

+ +
PLANETS = %w(mercury venus earth mars jupiter saturn uranus neptune pluto)
+
+# (In a later update, the original implementation of `PLANETS` has been removed.)
+
+PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
+PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
+
+PLANETS.map { |planet| planet.capitalize }
+# => DEPRECATION WARNING: PLANETS is deprecated! Use PLANETS_POST_2006 instead.
+     (Backtrace information…)
+     ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(*args, **options, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 124
+def self.new(*args, **options, &block)
+  object = args.first
+
+  return object unless object
+  super
+end
+
+
+ +
+ +
+

+ + new(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.") + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 131
+def initialize(old_const, new_const, deprecator = ActiveSupport::Deprecation.instance, message: "#{old_const} is deprecated! Use #{new_const} instead.")
+  Kernel.require "active_support/inflector/methods"
+
+  @old_const = old_const
+  @new_const = new_const
+  @deprecator = deprecator
+  @message = message
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + class() + +

+ + +
+

Returns the class of the new constant.

+ +
PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune)
+PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006')
+PLANETS.class # => Array
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 157
+def class
+  target.class
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+

Don’t give a deprecation warning on inspect since test/unit and error logs rely on it for diagnostics.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 144
+def inspect
+  target.inspect
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedInstanceVariableProxy.html b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedInstanceVariableProxy.html new file mode 100644 index 0000000000..d4b3cbee88 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedInstanceVariableProxy.html @@ -0,0 +1,144 @@ +--- +title: ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy +layout: default +--- +
+ +
+
+ +
+ +

DeprecatedInstanceVariableProxy transforms an instance variable into a deprecated one. It takes an instance of a class, a method on that class and an instance variable. It optionally takes a deprecator as the last argument. The deprecator defaults to ActiveSupport::Deprecator if none is specified.

+ +
class Example
+  def initialize
+    @request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request)
+    @_request = :special_request
+  end
+
+  def request
+    @_request
+  end
+
+  def old_request
+    @request
+  end
+end
+
+example = Example.new
+# => #<Example:0x007fb9b31090b8 @_request=:special_request, @request=:special_request>
+
+example.old_request.to_s
+# => DEPRECATION WARNING: @request is deprecated! Call request.to_s instead of
+   @request.to_s
+   (Backtrace information…)
+   "special_request"
+
+example.request.to_s
+# => "special_request"
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 89
+def initialize(instance, method, var = "@#{method}", deprecator = ActiveSupport::Deprecation.instance)
+  @instance = instance
+  @method = method
+  @var = var
+  @deprecator = deprecator
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedObjectProxy.html b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedObjectProxy.html new file mode 100644 index 0000000000..1ae77e1996 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/DeprecatedObjectProxy.html @@ -0,0 +1,124 @@ +--- +title: ActiveSupport::Deprecation::DeprecatedObjectProxy +layout: default +--- +
+ +
+
+ +
+ +

DeprecatedObjectProxy transforms an object into a deprecated one. It takes an object, a deprecation message, and optionally a deprecator. The deprecator defaults to ActiveSupport::Deprecator if none is specified.

+ +
deprecated_object = ActiveSupport::Deprecation::DeprecatedObjectProxy.new(Object.new, "This object is now deprecated")
+# => #<Object:0x007fb9b34c34b0>
+
+deprecated_object.to_s
+DEPRECATION WARNING: This object is now deprecated.
+(Backtrace)
+# => "#<Object:0x007fb9b34c34b0>"
+
+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(object, message, deprecator = ActiveSupport::Deprecation.instance) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/proxy_wrappers.rb, line 40
+def initialize(object, message, deprecator = ActiveSupport::Deprecation.instance)
+  @object = object
+  @message = message
+  @deprecator = deprecator
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/Disallowed.html b/src/7.0/classes/ActiveSupport/Deprecation/Disallowed.html new file mode 100644 index 0000000000..3c805e0ac6 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/Disallowed.html @@ -0,0 +1,119 @@ +--- +title: ActiveSupport::Deprecation::Disallowed +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [W] + disallowed_warnings

Sets the criteria used to identify deprecation messages which should be disallowed. Can be an array containing strings, symbols, or regular expressions. (Symbols are treated as strings.) These are compared against the text of the generated deprecation warning.

+ +

Additionally the scalar symbol :all may be used to treat all deprecations as disallowed.

+ +

Deprecations matching a substring or regular expression will be handled using the configured Behavior#disallowed_behavior rather than Behavior#behavior.

+ + + + + +

Instance Public methods

+ +
+

+ + disallowed_warnings() + +

+ + +
+

Returns the configured criteria used to identify deprecation messages which should be treated as disallowed.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/disallowed.rb, line 21
+def disallowed_warnings
+  @disallowed_warnings ||= []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/MethodWrapper.html b/src/7.0/classes/ActiveSupport/Deprecation/MethodWrapper.html new file mode 100644 index 0000000000..73f9388602 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/MethodWrapper.html @@ -0,0 +1,178 @@ +--- +title: ActiveSupport::Deprecation::MethodWrapper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + deprecate_methods(target_module, *method_names) + +

+ + +
+

Declare that a method has been deprecated.

+ +
class Fred
+  def aaa; end
+  def bbb; end
+  def ccc; end
+  def ddd; end
+  def eee; end
+end
+
+ +

Using the default deprecator:

+ +
ActiveSupport::Deprecation.deprecate_methods(Fred, :aaa, bbb: :zzz, ccc: 'use Bar#ccc instead')
+# => Fred
+
+Fred.new.aaa
+# DEPRECATION WARNING: aaa is deprecated and will be removed from Rails 5.1. (called from irb_binding at (irb):10)
+# => nil
+
+Fred.new.bbb
+# DEPRECATION WARNING: bbb is deprecated and will be removed from Rails 5.1 (use zzz instead). (called from irb_binding at (irb):11)
+# => nil
+
+Fred.new.ccc
+# DEPRECATION WARNING: ccc is deprecated and will be removed from Rails 5.1 (use Bar#ccc instead). (called from irb_binding at (irb):12)
+# => nil
+
+ +

Passing in a custom deprecator:

+ +
custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
+ActiveSupport::Deprecation.deprecate_methods(Fred, ddd: :zzz, deprecator: custom_deprecator)
+# => [:ddd]
+
+Fred.new.ddd
+DEPRECATION WARNING: ddd is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):15)
+# => nil
+
+ +

Using a custom deprecator directly:

+ +
custom_deprecator = ActiveSupport::Deprecation.new('next-release', 'MyGem')
+custom_deprecator.deprecate_methods(Fred, eee: :zzz)
+# => [:eee]
+
+Fred.new.eee
+DEPRECATION WARNING: eee is deprecated and will be removed from MyGem next-release (use zzz instead). (called from irb_binding at (irb):18)
+# => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/method_wrappers.rb, line 52
+def deprecate_methods(target_module, *method_names)
+  options = method_names.extract_options!
+  deprecator = options.delete(:deprecator) || self
+  method_names += options.keys
+  mod = nil
+
+  method_names.each do |method_name|
+    message = options[method_name]
+    if target_module.method_defined?(method_name) || target_module.private_method_defined?(method_name)
+      method = target_module.instance_method(method_name)
+      target_module.module_eval do
+        redefine_method(method_name) do |*args, &block|
+          deprecator.deprecation_warning(method_name, message)
+          method.bind_call(self, *args, &block)
+        end
+        ruby2_keywords(method_name)
+      end
+    else
+      mod ||= Module.new
+      mod.module_eval do
+        define_method(method_name) do |*args, &block|
+          deprecator.deprecation_warning(method_name, message)
+          super(*args, &block)
+        end
+        ruby2_keywords(method_name)
+      end
+    end
+  end
+
+  target_module.prepend(mod) if mod
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Deprecation/Reporting.html b/src/7.0/classes/ActiveSupport/Deprecation/Reporting.html new file mode 100644 index 0000000000..3219e9ff66 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Deprecation/Reporting.html @@ -0,0 +1,349 @@ +--- +title: ActiveSupport::Deprecation::Reporting +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RAILS_GEM_ROOT=File.expand_path("../../../..", __dir__) + "/"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [RW] + gem_name

Name of gem where method is deprecated

+ [W] + silenced

Whether to print a message (silent mode)

+ + + + + +

Instance Public methods

+ +
+

+ + allow(allowed_warnings = :all, if: true, &block) + +

+ + +
+

Allow previously disallowed deprecation warnings within the block. allowed_warnings can be an array containing strings, symbols, or regular expressions. (Symbols are treated as strings). These are compared against the text of deprecation warning messages generated within the block. Matching warnings will be exempt from the rules set by ActiveSupport::Deprecation.disallowed_warnings

+ +

The optional if: argument accepts a truthy/falsy value or an object that responds to .call. If truthy, then matching warnings will be allowed. If falsey then the method yields to the block without allowing the warning.

+ +
ActiveSupport::Deprecation.disallowed_behavior = :raise
+ActiveSupport::Deprecation.disallowed_warnings = [
+  "something broke"
+]
+
+ActiveSupport::Deprecation.warn('something broke!')
+# => ActiveSupport::DeprecationException
+
+ActiveSupport::Deprecation.allow ['something broke'] do
+  ActiveSupport::Deprecation.warn('something broke!')
+end
+# => nil
+
+ActiveSupport::Deprecation.allow ['something broke'], if: Rails.env.production? do
+  ActiveSupport::Deprecation.warn('something broke!')
+end
+# => ActiveSupport::DeprecationException for dev/test, nil for production
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/reporting.rb, line 72
+def allow(allowed_warnings = :all, if: true, &block)
+  conditional = binding.local_variable_get(:if)
+  conditional = conditional.call if conditional.respond_to?(:call)
+  if conditional
+    @explicitly_allowed_warnings.bind(allowed_warnings, &block)
+  else
+    yield
+  end
+end
+
+
+ +
+ +
+

+ + deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/reporting.rb, line 86
+def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
+  caller_backtrace ||= caller_locations(2)
+  deprecated_method_warning(deprecated_method_name, message).tap do |msg|
+    warn(msg, caller_backtrace)
+  end
+end
+
+
+ +
+ +
+

+ + silence(&block) + +

+ + +
+

Silence deprecation warnings within the block.

+ +
ActiveSupport::Deprecation.warn('something broke!')
+# => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
+
+ActiveSupport::Deprecation.silence do
+  ActiveSupport::Deprecation.warn('something broke!')
+end
+# => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/reporting.rb, line 40
+def silence(&block)
+  @silenced_thread.bind(true, &block)
+end
+
+
+ +
+ +
+

+ + silenced() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/reporting.rb, line 82
+def silenced
+  @silenced || @silenced_thread.value
+end
+
+
+ +
+ +
+

+ + warn(message = nil, callstack = nil) + +

+ + +
+

Outputs a deprecation warning to the output configured by ActiveSupport::Deprecation.behavior.

+ +
ActiveSupport::Deprecation.warn('something broke!')
+# => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/deprecation/reporting.rb, line 18
+def warn(message = nil, callstack = nil)
+  return if silenced
+
+  callstack ||= caller_locations(2)
+  deprecation_message(callstack, message).tap do |m|
+    if deprecation_disallowed?(message)
+      disallowed_behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
+    else
+      behavior.each { |b| b.call(m, callstack, deprecation_horizon, gem_name) }
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/DeprecationException.html b/src/7.0/classes/ActiveSupport/DeprecationException.html new file mode 100644 index 0000000000..e5abbbcaeb --- /dev/null +++ b/src/7.0/classes/ActiveSupport/DeprecationException.html @@ -0,0 +1,66 @@ +--- +title: ActiveSupport::DeprecationException +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveSupport::Deprecation::Behavior#behavior is set with :raise. You would set :raise, as a behavior to raise errors and proactively report exceptions from deprecations.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/DescendantsTracker.html b/src/7.0/classes/ActiveSupport/DescendantsTracker.html new file mode 100644 index 0000000000..858fb76320 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/DescendantsTracker.html @@ -0,0 +1,394 @@ +--- +title: ActiveSupport::DescendantsTracker +layout: default +--- +
+ +
+
+ +
+ +

This module provides an internal implementation to track descendants which is faster than iterating through ObjectSpace.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + descendants(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 62
+def descendants(klass)
+  klass.descendants
+end
+
+
+ +
+ +
+

+ + direct_descendants(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 11
+      def direct_descendants(klass)
+        ActiveSupport::Deprecation.warn(<<~MSG)
+          ActiveSupport::DescendantsTracker.direct_descendants is deprecated and will be removed in Rails 7.1.
+          Use ActiveSupport::DescendantsTracker.subclasses instead.
+        MSG
+        subclasses(klass)
+      end
+
+
+ +
+ +
+

+ + store_inherited(klass, descendant) + +

+ + +
+

This is the only method that is not thread safe, but is only ever called during the eager loading phase.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 138
+def store_inherited(klass, descendant)
+  (@@direct_descendants[klass] ||= DescendantsArray.new) << descendant
+end
+
+
+ +
+ +
+

+ + subclasses(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 58
+def subclasses(klass)
+  klass.subclasses
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + descendants() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 88
+def descendants
+  subclasses.concat(subclasses.flat_map(&:descendants))
+end
+
+
+ +
+ +
+

+ + direct_descendants() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 92
+      def direct_descendants
+        ActiveSupport::Deprecation.warn(<<~MSG)
+          ActiveSupport::DescendantsTracker#direct_descendants is deprecated and will be removed in Rails 7.1.
+          Use #subclasses instead.
+        MSG
+        subclasses
+      end
+
+
+ +
+ +
+

+ + inherited(base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 153
+def inherited(base)
+  DescendantsTracker.store_inherited(self, base)
+  super
+end
+
+
+ +
+ +
+

+ + subclasses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/descendants_tracker.rb, line 82
+def subclasses
+  subclasses = super
+  subclasses.reject! { |d| @@excluded_descendants[d] }
+  subclasses
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Duration.html b/src/7.0/classes/ActiveSupport/Duration.html new file mode 100644 index 0000000000..078a1a4349 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Duration.html @@ -0,0 +1,1385 @@ +--- +title: ActiveSupport::Duration +layout: default +--- +
+ +
+
+ +
+ +

Provides accurate date and time measurements using Date#advance and Time#advance, respectively. It mainly supports the methods on Numeric.

+ +
1.month.ago       # equivalent to Time.now.advance(months: -1)
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PARTS=[:years, :months, :weeks, :days, :hours, :minutes, :seconds].freeze
 
PARTS_IN_SECONDS={ +seconds: 1, +minutes: SECONDS_PER_MINUTE, +hours: SECONDS_PER_HOUR, +days: SECONDS_PER_DAY, +weeks: SECONDS_PER_WEEK, +months: SECONDS_PER_MONTH, +years: SECONDS_PER_YEAR +}.freeze
 
SECONDS_PER_DAY=86400
 
SECONDS_PER_HOUR=3600
 
SECONDS_PER_MINUTE=60
 
SECONDS_PER_MONTH=2629746
 
SECONDS_PER_WEEK=604800
 
SECONDS_PER_YEAR=31556952
 
VARIABLE_PARTS=[:years, :months, :weeks, :days].freeze
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + value
+ + + + +

Class Public methods

+ +
+

+ + build(value) + +

+ + +
+

Creates a new Duration from a seconds value that is converted to the individual parts:

+ +
ActiveSupport::Duration.build(31556952).parts # => {:years=>1}
+ActiveSupport::Duration.build(2716146).parts  # => {:months=>1, :days=>1}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 188
+def build(value)
+  unless value.is_a?(::Numeric)
+    raise TypeError, "can't build an #{self.name} from a #{value.class.name}"
+  end
+
+  parts = {}
+  remainder_sign = value <=> 0
+  remainder = value.round(9).abs
+  variable = false
+
+  PARTS.each do |part|
+    unless part == :seconds
+      part_in_seconds = PARTS_IN_SECONDS[part]
+      parts[part] = remainder.div(part_in_seconds) * remainder_sign
+      remainder %= part_in_seconds
+
+      unless parts[part].zero?
+        variable ||= VARIABLE_PARTS.include?(part)
+      end
+    end
+  end unless value == 0
+
+  parts[:seconds] = remainder * remainder_sign
+
+  new(value, parts, variable)
+end
+
+
+ +
+ +
+

+ + parse(iso8601duration) + +

+ + +
+

Creates a new Duration from string formatted according to ISO 8601 Duration.

+ +

See ISO 8601 for more information. This method allows negative parts to be present in pattern. If invalid string is provided, it will raise ActiveSupport::Duration::ISO8601Parser::ParsingError.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 143
+def parse(iso8601duration)
+  parts = ISO8601Parser.new(iso8601duration).parse!
+  new(calculate_total_seconds(parts), parts)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + %(other) + +

+ + +
+

Returns the modulo of this Duration by another Duration or Numeric. Numeric values are treated as seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 306
+def %(other)
+  if Duration === other || Scalar === other
+    Duration.build(value % other.value)
+  elsif Numeric === other
+    Duration.build(value % other)
+  else
+    raise_type_error(other)
+  end
+end
+
+
+ +
+ +
+

+ + *(other) + +

+ + +
+

Multiplies this Duration by a Numeric and returns a new Duration.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 281
+def *(other)
+  if Scalar === other || Duration === other
+    Duration.new(value * other.value, @parts.transform_values { |number| number * other.value }, @variable || other.variable?)
+  elsif Numeric === other
+    Duration.new(value * other, @parts.transform_values { |number| number * other }, @variable)
+  else
+    raise_type_error(other)
+  end
+end
+
+
+ +
+ +
+

+ + +(other) + +

+ + +
+

Adds another Duration or a Numeric to this Duration. Numeric values are treated as seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 262
+def +(other)
+  if Duration === other
+    parts = @parts.merge(other._parts) do |_key, value, other_value|
+      value + other_value
+    end
+    Duration.new(value + other.value, parts, @variable || other.variable?)
+  else
+    seconds = @parts.fetch(:seconds, 0) + other
+    Duration.new(value + other, @parts.merge(seconds: seconds), @variable)
+  end
+end
+
+
+ +
+ +
+

+ + -(other) + +

+ + +
+

Subtracts another Duration or a Numeric from this Duration. Numeric values are treated as seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 276
+def -(other)
+  self + (-other)
+end
+
+
+ +
+ +
+

+ + /(other) + +

+ + +
+

Divides this Duration by a Numeric and returns a new Duration.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 292
+def /(other)
+  if Scalar === other
+    Duration.new(value / other.value, @parts.transform_values { |number| number / other.value }, @variable)
+  elsif Duration === other
+    value / other.value
+  elsif Numeric === other
+    Duration.new(value / other, @parts.transform_values { |number| number / other }, @variable)
+  else
+    raise_type_error(other)
+  end
+end
+
+
+ +
+ +
+

+ + <=>(other) + +

+ + +
+

Compares one Duration with another or a Numeric to this Duration. Numeric values are treated as seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 252
+def <=>(other)
+  if Duration === other
+    value <=> other.value
+  elsif Numeric === other
+    value <=> other
+  end
+end
+
+
+ +
+ +
+

+ + ==(other) + +

+ + +
+

Returns true if other is also a Duration instance with the same value, or if other == value.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 335
+def ==(other)
+  if Duration === other
+    other.value == value
+  else
+    other == value
+  end
+end
+
+
+ +
+ +
+

+ + after(time = ::Time.current) + +

+ + +
+ +
+ + + + + +
+ Alias for: since +
+ + + +
+ +
+

+ + ago(time = ::Time.current) + +

+ + +
+

Calculates a new Time or Date that is as far in the past as this Duration represents.

+
+ + + +
+ Also aliased as: until, before +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 438
+def ago(time = ::Time.current)
+  sum(-1, time)
+end
+
+
+ +
+ +
+

+ + before(time = ::Time.current) + +

+ + +
+ +
+ + + + + +
+ Alias for: ago +
+ + + +
+ +
+

+ + eql?(other) + +

+ + +
+

Returns true if other is also a Duration instance, which has the same parts as this one.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 420
+def eql?(other)
+  Duration === other && other.value.eql?(value)
+end
+
+
+ +
+ +
+

+ + from_now(time = ::Time.current) + +

+ + +
+ +
+ + + + + +
+ Alias for: since +
+ + + +
+ +
+

+ + hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 424
+def hash
+  @value.hash
+end
+
+
+ +
+ +
+

+ + in_days() + +

+ + +
+

Returns the amount of days a duration covers as a float

+ +
12.hours.in_days # => 0.5
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 393
+def in_days
+  in_seconds / SECONDS_PER_DAY.to_f
+end
+
+
+ +
+ +
+

+ + in_hours() + +

+ + +
+

Returns the amount of hours a duration covers as a float

+ +
1.day.in_hours # => 24.0
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 386
+def in_hours
+  in_seconds / SECONDS_PER_HOUR.to_f
+end
+
+
+ +
+ +
+

+ + in_minutes() + +

+ + +
+

Returns the amount of minutes a duration covers as a float

+ +
1.day.in_minutes # => 1440.0
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 379
+def in_minutes
+  in_seconds / SECONDS_PER_MINUTE.to_f
+end
+
+
+ +
+ +
+

+ + in_months() + +

+ + +
+

Returns the amount of months a duration covers as a float

+ +
9.weeks.in_months # => 2.07
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 407
+def in_months
+  in_seconds / SECONDS_PER_MONTH.to_f
+end
+
+
+ +
+ +
+

+ + in_seconds() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_i +
+ + + +
+ +
+

+ + in_weeks() + +

+ + +
+

Returns the amount of weeks a duration covers as a float

+ +
2.months.in_weeks # => 8.696
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 400
+def in_weeks
+  in_seconds / SECONDS_PER_WEEK.to_f
+end
+
+
+ +
+ +
+

+ + in_years() + +

+ + +
+

Returns the amount of years a duration covers as a float

+ +
30.days.in_years # => 0.082
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 414
+def in_years
+  in_seconds / SECONDS_PER_YEAR.to_f
+end
+
+
+ +
+ +
+

+ + iso8601(precision: nil) + +

+ + +
+

Build ISO 8601 Duration string for this duration. The precision parameter can be used to limit seconds’ precision of duration.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 467
+def iso8601(precision: nil)
+  ISO8601Serializer.new(self, precision: precision).serialize
+end
+
+
+ +
+ +
+

+ + parts() + +

+ + +
+

Returns a copy of the parts hash that defines the duration

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 235
+def parts
+  @parts.dup
+end
+
+
+ +
+ +
+

+ + since(time = ::Time.current) + +

+ + +
+

Calculates a new Time or Date that is as far in the future as this Duration represents.

+
+ + + +
+ Also aliased as: from_now, after +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 430
+def since(time = ::Time.current)
+  sum(1, time)
+end
+
+
+ +
+ +
+

+ + to_i() + +

+ + +
+

Returns the number of seconds that this Duration represents.

+ +
1.minute.to_i   # => 60
+1.hour.to_i     # => 3600
+1.day.to_i      # => 86400
+
+ +

Note that this conversion makes some assumptions about the duration of some periods, e.g. months are always 1/12 of year and years are 365.2425 days:

+ +
# equivalent to (1.year / 12).to_i
+1.month.to_i    # => 2629746
+
+# equivalent to 365.2425.days.to_i
+1.year.to_i     # => 31556952
+
+ +

In such cases, Ruby’s core Date and Time should be used for precision date and time arithmetic.

+
+ + + +
+ Also aliased as: in_seconds +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 371
+def to_i
+  @value.to_i
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+

Returns the amount of seconds a duration covers as a string. For more information check to_i method.

+ +
1.day.to_s # => "86400"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/duration.rb, line 347
+def to_s
+  @value.to_s
+end
+
+
+ +
+ +
+

+ + until(time = ::Time.current) + +

+ + +
+ +
+ + + + + +
+ Alias for: ago +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser.html b/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser.html new file mode 100644 index 0000000000..5155611f79 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::Duration::ISO8601Parser +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser/ParsingError.html b/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser/ParsingError.html new file mode 100644 index 0000000000..7010f4a7f0 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Duration/ISO8601Parser/ParsingError.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::Duration::ISO8601Parser::ParsingError +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EncryptedConfiguration.html b/src/7.0/classes/ActiveSupport/EncryptedConfiguration.html new file mode 100644 index 0000000000..c7a1f5cd8d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EncryptedConfiguration.html @@ -0,0 +1,265 @@ +--- +title: ActiveSupport::EncryptedConfiguration +layout: default +--- +
+ +
+
+ +
+ +

Provides convenience methods on top of EncryptedFile to access values stored as encrypted YAML.

+ +

Values can be accessed via Hash methods, such as fetch and dig, or via dynamic accessor methods, similar to OrderedOptions.

+ +
my_config = ActiveSupport::EncryptedConfiguration.new(...)
+my_config.read # => "some_secret: 123\nsome_namespace:\n  another_secret: 456"
+
+my_config[:some_secret]
+# => 123
+my_config.some_secret
+# => 123
+my_config.dig(:some_namespace, :another_secret)
+# => 456
+my_config.some_namespace.another_secret
+# => 456
+my_config.fetch(:foo)
+# => KeyError
+my_config.foo!
+# => KeyError
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(config_path:, key_path:, env_key:, raise_if_missing_key:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_configuration.rb, line 36
+def initialize(config_path:, key_path:, env_key:, raise_if_missing_key:)
+  super content_path: config_path, key_path: key_path,
+    env_key: env_key, raise_if_missing_key: raise_if_missing_key
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + config() + +

+ + +
+

Returns the decrypted content as a Hash with symbolized keys.

+ +
my_config = ActiveSupport::EncryptedConfiguration.new(...)
+my_config.read # => "some_secret: 123\nsome_namespace:\n  another_secret: 456"
+
+my_config.config
+# => { some_secret: 123, some_namespace: { another_secret: 789 } }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_configuration.rb, line 63
+def config
+  @config ||= deserialize(read).deep_symbolize_keys
+end
+
+
+ +
+ +
+

+ + read() + +

+ + +
+

Reads the file and returns the decrypted content. See EncryptedFile#read.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_configuration.rb, line 42
+def read
+  super
+rescue ActiveSupport::EncryptedFile::MissingContentError
+  # Allow a config to be started without a file present
+  ""
+end
+
+
+ +
+ +
+

+ + write(contents) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_configuration.rb, line 49
+def write(contents)
+  deserialize(contents)
+
+  super
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EncryptedFile.html b/src/7.0/classes/ActiveSupport/EncryptedFile.html new file mode 100644 index 0000000000..53ab0a7401 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EncryptedFile.html @@ -0,0 +1,394 @@ +--- +title: ActiveSupport::EncryptedFile +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
CIPHER="aes-128-gcm"
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + content_path
+ [R] + env_key
+ [R] + key_path
+ [R] + raise_if_missing_key
+ + + + +

Class Public methods

+ +
+

+ + generate_key() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 31
+def self.generate_key
+  SecureRandom.hex(ActiveSupport::MessageEncryptor.key_len(CIPHER))
+end
+
+
+ +
+ +
+

+ + new(content_path:, key_path:, env_key:, raise_if_missing_key:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 42
+def initialize(content_path:, key_path:, env_key:, raise_if_missing_key:)
+  @content_path = Pathname.new(content_path).yield_self { |path| path.symlink? ? path.realpath : path }
+  @key_path = Pathname.new(key_path)
+  @env_key, @raise_if_missing_key = env_key, raise_if_missing_key
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + change(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 77
+def change(&block)
+  writing read, &block
+end
+
+
+ +
+ +
+

+ + key() + +

+ + +
+

Returns the encryption key, first trying the environment variable specified by env_key, then trying the key file specified by key_path. If raise_if_missing_key is true, raises MissingKeyError if the environment variable is not set and the key file does not exist.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 52
+def key
+  read_env_key || read_key_file || handle_missing_key
+end
+
+
+ +
+ +
+

+ + read() + +

+ + +
+

Reads the file and returns the decrypted content.

+ +

Raises:

+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 64
+def read
+  if !key.nil? && content_path.exist?
+    decrypt content_path.binread
+  else
+    raise MissingContentError, content_path
+  end
+end
+
+
+ +
+ +
+

+ + write(contents) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 72
+def write(contents)
+  IO.binwrite "#{content_path}.tmp", encrypt(contents)
+  FileUtils.mv "#{content_path}.tmp", content_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EncryptedFile/InvalidKeyLengthError.html b/src/7.0/classes/ActiveSupport/EncryptedFile/InvalidKeyLengthError.html new file mode 100644 index 0000000000..77703b4b5c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EncryptedFile/InvalidKeyLengthError.html @@ -0,0 +1,107 @@ +--- +title: ActiveSupport::EncryptedFile::InvalidKeyLengthError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 24
+def initialize
+  super "Encryption key must be exactly #{EncryptedFile.expected_key_length} characters."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EncryptedFile/MissingContentError.html b/src/7.0/classes/ActiveSupport/EncryptedFile/MissingContentError.html new file mode 100644 index 0000000000..fead959206 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EncryptedFile/MissingContentError.html @@ -0,0 +1,107 @@ +--- +title: ActiveSupport::EncryptedFile::MissingContentError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(content_path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 10
+def initialize(content_path)
+  super "Missing encrypted content file in #{content_path}."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EncryptedFile/MissingKeyError.html b/src/7.0/classes/ActiveSupport/EncryptedFile/MissingKeyError.html new file mode 100644 index 0000000000..64ab7e33d5 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EncryptedFile/MissingKeyError.html @@ -0,0 +1,109 @@ +--- +title: ActiveSupport::EncryptedFile::MissingKeyError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(key_path:, env_key:) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/encrypted_file.rb, line 16
+def initialize(key_path:, env_key:)
+  super \
+    "Missing encryption key to decrypt file with. " +
+    "Ask your team for your master key and write it to #{key_path} or put it in the ENV['#{env_key}']."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EnumerableCoreExt.html b/src/7.0/classes/ActiveSupport/EnumerableCoreExt.html new file mode 100644 index 0000000000..c495b69552 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EnumerableCoreExt.html @@ -0,0 +1,67 @@ +--- +title: ActiveSupport::EnumerableCoreExt +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EnumerableCoreExt/Constants.html b/src/7.0/classes/ActiveSupport/EnumerableCoreExt/Constants.html new file mode 100644 index 0000000000..2c764f1763 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EnumerableCoreExt/Constants.html @@ -0,0 +1,54 @@ +--- +title: ActiveSupport::EnumerableCoreExt::Constants +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ErrorReporter.html b/src/7.0/classes/ActiveSupport/ErrorReporter.html new file mode 100644 index 0000000000..bee26c4e9b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ErrorReporter.html @@ -0,0 +1,426 @@ +--- +title: ActiveSupport::ErrorReporter +layout: default +--- +
+ +
+
+ +
+ +

ActiveSupport::ErrorReporter is a common interface for error reporting services.

+ +

To rescue and report any unhandled error, you can use the handle method:

+ +
Rails.error.handle do
+  do_something!
+end
+
+ +

If an error is raised, it will be reported and swallowed.

+ +

Alternatively if you want to report the error but not swallow it, you can use record

+ +
Rails.error.record do
+  do_something!
+end
+
+ +

Both methods can be restricted to only handle a specific exception class

+ +
maybe_tags = Rails.error.handle(Redis::BaseError) { redis.get("tags") }
+
+ +

You can also pass some extra context information that may be used by the error subscribers:

+ +
Rails.error.handle(context: { section: "admin" }) do
+  # ...
+end
+
+ +

Additionally a severity can be passed along to communicate how important the error report is. severity can be one of :error, :warning, or :info. Handled errors default to the :warning severity, and unhandled ones to :error.

+ +

Both handle and record pass through the return value from the block. In the case of handle rescuing an error, a fallback can be provided. The fallback must be a callable whose result will be returned when the block raises and is handled:

+ +
user = Rails.error.handle(fallback: -> { User.anonymous }) do
+  User.find_by(params)
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
SEVERITIES=%i(error warning info)
 
+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + logger
+ + + + +

Class Public methods

+ +
+

+ + new(*subscribers, logger: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 46
+def initialize(*subscribers, logger: nil)
+  @subscribers = subscribers.flatten
+  @logger = logger
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + handle(error_class = StandardError, severity: :warning, context: {}, fallback: nil) + +

+ + +
+

Report any unhandled exception, and swallow it.

+ +
Rails.error.handle do
+  1 + '1'
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 57
+def handle(error_class = StandardError, severity: :warning, context: {}, fallback: nil)
+  yield
+rescue error_class => error
+  report(error, handled: true, severity: severity, context: context)
+  fallback.call if fallback
+end
+
+
+ +
+ +
+

+ + record(error_class = StandardError, severity: :error, context: {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 64
+def record(error_class = StandardError, severity: :error, context: {})
+  yield
+rescue error_class => error
+  report(error, handled: false, severity: severity, context: context)
+  raise
+end
+
+
+ +
+ +
+

+ + report(error, handled:, severity: handled ? :warning : :error, context: {}) + +

+ + +
+

When the block based handle and record methods are not suitable, you can directly use report

+ +
Rails.error.report(error, handled: true)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 95
+def report(error, handled:, severity: handled ? :warning : :error, context: {})
+  unless SEVERITIES.include?(severity)
+    raise ArgumentError, "severity must be one of #{SEVERITIES.map(&:inspect).join(", ")}, got: #{severity.inspect}"
+  end
+
+  full_context = ActiveSupport::ExecutionContext.to_h.merge(context)
+  @subscribers.each do |subscriber|
+    subscriber.report(error, handled: handled, severity: severity, context: full_context)
+  rescue => subscriber_error
+    if logger
+      logger.fatal(
+        "Error subscriber raised an error: #{subscriber_error.message} (#{subscriber_error.class})\n" +
+        subscriber_error.backtrace.join("\n")
+      )
+    else
+      raise
+    end
+  end
+
+  nil
+end
+
+
+ +
+ +
+

+ + set_context(...) + +

+ + +
+

Update the execution context that is accessible to error subscribers

+ +
Rails.error.set_context(section: "checkout", user_id: @user.id)
+
+ +

See ActiveSupport::ExecutionContext.set

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 88
+def set_context(...)
+  ActiveSupport::ExecutionContext.set(...)
+end
+
+
+ +
+ +
+

+ + subscribe(subscriber) + +

+ + +
+

Register a new error subscriber. The subscriber must respond to

+ +
report(Exception, handled: Boolean, context: Hash)
+
+ +

The report method should never raise an error.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/error_reporter.rb, line 76
+def subscribe(subscriber)
+  unless subscriber.respond_to?(:report)
+    raise ArgumentError, "Error subscribers must respond to #report"
+  end
+  @subscribers << subscriber
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker.html b/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker.html new file mode 100644 index 0000000000..56fd9e0272 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::EventedFileUpdateChecker +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker/Core.html b/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker/Core.html new file mode 100644 index 0000000000..82040a5dc8 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/EventedFileUpdateChecker/Core.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::EventedFileUpdateChecker::Core +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ExecutionWrapper.html b/src/7.0/classes/ActiveSupport/ExecutionWrapper.html new file mode 100644 index 0000000000..754538b610 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ExecutionWrapper.html @@ -0,0 +1,399 @@ +--- +title: ActiveSupport::ExecutionWrapper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + error_reporter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 111
+def self.error_reporter
+  @error_reporter ||= ActiveSupport::ErrorReporter.new
+end
+
+
+ +
+ +
+

+ + register_hook(hook, outer: false) + +

+ + +
+

Register an object to be invoked during both the run and complete steps.

+ +

hook.complete will be passed the value returned from hook.run, and will only be invoked if run has previously been called. (Mostly, this means it won’t be invoked if an exception occurs in a preceding to_run block; all ordinary to_complete blocks are invoked in that situation.)

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 51
+def self.register_hook(hook, outer: false)
+  if outer
+    to_run RunHook.new(hook), prepend: true
+    to_complete :after, CompleteHook.new(hook)
+  else
+    to_run RunHook.new(hook)
+    to_complete CompleteHook.new(hook)
+  end
+end
+
+
+ +
+ +
+

+ + run!(reset: false) + +

+ + +
+

Run this execution.

+ +

Returns an instance, whose complete! method must be invoked after the work has been performed.

+ +

Where possible, prefer wrap.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 67
+def self.run!(reset: false)
+  if reset
+    lost_instance = IsolatedExecutionState.delete(active_key)
+    lost_instance&.complete!
+  else
+    return Null if active?
+  end
+
+  new.tap do |instance|
+    success = nil
+    begin
+      instance.run!
+      success = true
+    ensure
+      instance.complete! unless success
+    end
+  end
+end
+
+
+ +
+ +
+

+ + to_complete(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 22
+def self.to_complete(*args, &block)
+  set_callback(:complete, *args, &block)
+end
+
+
+ +
+ +
+

+ + to_run(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 18
+def self.to_run(*args, &block)
+  set_callback(:run, *args, &block)
+end
+
+
+ +
+ +
+

+ + wrap() + +

+ + +
+

Perform the work in the supplied block as an execution.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 87
+def self.wrap
+  return yield if active?
+
+  instance = run!
+  begin
+    yield
+  rescue => error
+    error_reporter.report(error, handled: false)
+    raise
+  ensure
+    instance.complete!
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + complete!() + +

+ + +
+

Complete this in-flight execution. This method must be called exactly once on the result of any call to run!.

+ +

Where possible, prefer wrap.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/execution_wrapper.rb, line 136
+def complete!
+  complete
+ensure
+  IsolatedExecutionState.delete(self.class.active_key)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Executor.html b/src/7.0/classes/ActiveSupport/Executor.html new file mode 100644 index 0000000000..fbf2c40f47 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Executor.html @@ -0,0 +1,62 @@ +--- +title: ActiveSupport::Executor +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/FileUpdateChecker.html b/src/7.0/classes/ActiveSupport/FileUpdateChecker.html new file mode 100644 index 0000000000..89284f9f20 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/FileUpdateChecker.html @@ -0,0 +1,293 @@ +--- +title: ActiveSupport::FileUpdateChecker +layout: default +--- +
+ +
+
+ +
+ +

FileUpdateChecker specifies the API used by Rails to watch files and control reloading. The API depends on four methods:

+
  • +

    initialize which expects two parameters and one block as described below.

    +
  • +

    updated? which returns a boolean if there were updates in the filesystem or not.

    +
  • +

    execute which executes the given block on initialization and updates the latest watched files and timestamp.

    +
  • +

    execute_if_updated which just executes the block if it was updated.

    +
+ +

After initialization, a call to execute_if_updated must execute the block only if there was really a change in the filesystem.

+ +

This class is used by Rails to reload the I18n framework whenever they are changed upon a new request.

+ +
i18n_reloader = ActiveSupport::FileUpdateChecker.new(paths) do
+  I18n.reload!
+end
+
+ActiveSupport::Reloader.to_prepare do
+  i18n_reloader.execute_if_updated
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(files, dirs = {}, &block) + +

+ + +
+

It accepts two parameters on initialization. The first is an array of files and the second is an optional hash of directories. The hash must have directories as keys and the value is an array of extensions to be watched under that directory.

+ +

This method must also receive a block that will be called once a path changes. The array of files and list of directories cannot be changed after FileUpdateChecker has been initialized.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/file_update_checker.rb, line 42
+def initialize(files, dirs = {}, &block)
+  unless block
+    raise ArgumentError, "A block is required to initialize a FileUpdateChecker"
+  end
+
+  @files = files.freeze
+  @glob  = compile_glob(dirs)
+  @block = block
+
+  @watched    = nil
+  @updated_at = nil
+
+  @last_watched   = watched
+  @last_update_at = updated_at(@last_watched)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + execute() + +

+ + +
+

Executes the given block and updates the latest watched files and timestamp.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/file_update_checker.rb, line 80
+def execute
+  @last_watched   = watched
+  @last_update_at = updated_at(@last_watched)
+  @block.call
+ensure
+  @watched = nil
+  @updated_at = nil
+end
+
+
+ +
+ +
+

+ + execute_if_updated() + +

+ + +
+

Execute the block given if updated.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/file_update_checker.rb, line 90
+def execute_if_updated
+  if updated?
+    yield if block_given?
+    execute
+    true
+  else
+    false
+  end
+end
+
+
+ +
+ +
+

+ + updated?() + +

+ + +
+

Check if any of the entries were updated. If so, the watched and/or updated_at values are cached until the block is executed via execute or execute_if_updated.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/file_update_checker.rb, line 61
+def updated?
+  current_watched = watched
+  if @last_watched.size != current_watched.size
+    @watched = current_watched
+    true
+  else
+    current_updated_at = updated_at(current_watched)
+    if @last_update_at < current_updated_at
+      @watched    = current_watched
+      @updated_at = current_updated_at
+      true
+    else
+      false
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ForkTracker.html b/src/7.0/classes/ActiveSupport/ForkTracker.html new file mode 100644 index 0000000000..aebd966a24 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ForkTracker.html @@ -0,0 +1,71 @@ +--- +title: ActiveSupport::ForkTracker +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ForkTracker/CoreExt.html b/src/7.0/classes/ActiveSupport/ForkTracker/CoreExt.html new file mode 100644 index 0000000000..e208a7f239 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ForkTracker/CoreExt.html @@ -0,0 +1,54 @@ +--- +title: ActiveSupport::ForkTracker::CoreExt +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ForkTracker/CoreExtPrivate.html b/src/7.0/classes/ActiveSupport/ForkTracker/CoreExtPrivate.html new file mode 100644 index 0000000000..1802b1cb73 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ForkTracker/CoreExtPrivate.html @@ -0,0 +1,68 @@ +--- +title: ActiveSupport::ForkTracker::CoreExtPrivate +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ForkTracker/ModernCoreExt.html b/src/7.0/classes/ActiveSupport/ForkTracker/ModernCoreExt.html new file mode 100644 index 0000000000..c7d5994c32 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ForkTracker/ModernCoreExt.html @@ -0,0 +1,105 @@ +--- +title: ActiveSupport::ForkTracker::ModernCoreExt +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + _fork() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/fork_tracker.rb, line 6
+def _fork
+  pid = super
+  if pid == 0
+    ForkTracker.check!
+  end
+  pid
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Gzip.html b/src/7.0/classes/ActiveSupport/Gzip.html new file mode 100644 index 0000000000..420f5e5ee2 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Gzip.html @@ -0,0 +1,170 @@ +--- +title: ActiveSupport::Gzip +layout: default +--- +
+ +
+
+ +
+ +

A convenient wrapper for the zlib standard library that allows compression/decompression of strings with gzip.

+ +
gzip = ActiveSupport::Gzip.compress('compress me!')
+# => "\x1F\x8B\b\x00o\x8D\xCDO\x00\x03K\xCE\xCF-(J-.V\xC8MU\x04\x00R>n\x83\f\x00\x00\x00"
+
+ActiveSupport::Gzip.decompress(gzip)
+# => "compress me!"
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY) + +

+ + +
+

Compresses a string using gzip.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/gzip.rb, line 30
+def self.compress(source, level = Zlib::DEFAULT_COMPRESSION, strategy = Zlib::DEFAULT_STRATEGY)
+  output = Stream.new
+  gz = Zlib::GzipWriter.new(output, level, strategy)
+  gz.write(source)
+  gz.close
+  output.string
+end
+
+
+ +
+ +
+

+ + decompress(source) + +

+ + +
+

Decompresses a gzipped string.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/gzip.rb, line 25
+def self.decompress(source)
+  Zlib::GzipReader.wrap(StringIO.new(source), &:read)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Gzip/Stream.html b/src/7.0/classes/ActiveSupport/Gzip/Stream.html new file mode 100644 index 0000000000..bebebb6dae --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Gzip/Stream.html @@ -0,0 +1,148 @@ +--- +title: ActiveSupport::Gzip::Stream +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/gzip.rb, line 17
+def initialize(*)
+  super
+  set_encoding "BINARY"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + close() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/gzip.rb, line 21
+def close; rewind; end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/HashWithIndifferentAccess.html b/src/7.0/classes/ActiveSupport/HashWithIndifferentAccess.html new file mode 100644 index 0000000000..10ee0e539c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/HashWithIndifferentAccess.html @@ -0,0 +1,2075 @@ +--- +title: ActiveSupport::HashWithIndifferentAccess +layout: default +--- +
+ +
+
+ +
+ +

Implements a hash where keys :foo and "foo" are considered to be the same.

+ +
rgb = ActiveSupport::HashWithIndifferentAccess.new
+
+rgb[:black] = '#000000'
+rgb[:black]  # => '#000000'
+rgb['black'] # => '#000000'
+
+rgb['white'] = '#FFFFFF'
+rgb[:white]  # => '#FFFFFF'
+rgb['white'] # => '#FFFFFF'
+
+ +

Internally symbols are mapped to strings when used as keys in the entire writing interface (calling []=, merge, etc). This mapping belongs to the public interface. For example, given:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
+
+ +

You are guaranteed that the key is returned as a string:

+ +
hash.keys # => ["a"]
+
+ +

Technically other types of keys are accepted:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
+hash[0] = 0
+hash # => {"a"=>1, 0=>0}
+
+ +

but this class is intended for use cases where strings or symbols are the expected keys and it is convenient to understand both as the same. For example the params hash in Ruby on Rails.

+ +

Note that core extensions define Hash#with_indifferent_access:

+ +
rgb = { black: '#000000', white: '#FFFFFF' }.with_indifferent_access
+
+ +

which may be handy.

+ +

To access this class outside of Rails, require the core extension with:

+ +
require "active_support/core_ext/hash/indifferent_access"
+
+ +

which will, in turn, require this file.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + [](*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 83
+def self.[](*args)
+  new.merge!(Hash[*args])
+end
+
+
+ +
+ +
+

+ + new(constructor = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 68
+def initialize(constructor = nil)
+  if constructor.respond_to?(:to_hash)
+    super()
+    update(constructor)
+
+    hash = constructor.is_a?(Hash) ? constructor : constructor.to_hash
+    self.default = hash.default if hash.default
+    self.default_proc = hash.default_proc if hash.default_proc
+  elsif constructor.nil?
+    super()
+  else
+    super(constructor)
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](key) + +

+ + +
+

Same as Hash#[] where the key passed as argument can be either a string or a symbol:

+ +
counters = ActiveSupport::HashWithIndifferentAccess.new
+counters[:foo] = 1
+
+counters['foo'] # => 1
+counters[:foo]  # => 1
+counters[:zoo]  # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 166
+def [](key)
+  super(convert_key(key))
+end
+
+
+ +
+ +
+

+ + []=(key, value) + +

+ + +
+

Assigns a new value to the hash:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new
+hash[:key] = 'value'
+
+ +

This value can be later fetched using either :key or 'key'.

+
+ + + +
+ Also aliased as: regular_writer, store +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 96
+def []=(key, value)
+  regular_writer(convert_key(key), convert_value(value, conversion: :assignment))
+end
+
+
+ +
+ +
+

+ + assoc(key) + +

+ + +
+

Same as Hash#assoc where the key passed as argument can be either a string or a symbol:

+ +
counters = ActiveSupport::HashWithIndifferentAccess.new
+counters[:foo] = 1
+
+counters.assoc('foo') # => ["foo", 1]
+counters.assoc(:foo)  # => ["foo", 1]
+counters.assoc(:zoo)  # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 179
+def assoc(key)
+  super(convert_key(key))
+end
+
+
+ +
+ +
+

+ + compact() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 357
+def compact
+  dup.tap(&:compact!)
+end
+
+
+ +
+ +
+

+ + deep_stringify_keys() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 311
+def deep_stringify_keys; dup end
+
+
+ +
+ +
+

+ + deep_stringify_keys!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 309
+def deep_stringify_keys!; self end
+
+
+ +
+ +
+

+ + deep_symbolize_keys() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 316
+def deep_symbolize_keys; to_hash.deep_symbolize_keys! end
+
+
+ +
+ +
+

+ + default(*args) + +

+ + +
+

Same as Hash#default where the key passed as argument can be either a string or a symbol:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new(1)
+hash.default                   # => 1
+
+hash = ActiveSupport::HashWithIndifferentAccess.new { |hash, key| key }
+hash.default                   # => nil
+hash.default('foo')            # => 'foo'
+hash.default(:foo)             # => 'foo'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 221
+def default(*args)
+  super(*args.map { |arg| convert_key(arg) })
+end
+
+
+ +
+ +
+

+ + delete(key) + +

+ + +
+

Removes the specified key from the hash.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 295
+def delete(key)
+  super(convert_key(key))
+end
+
+
+ +
+ +
+

+ + dig(*args) + +

+ + +
+

Same as Hash#dig where the key passed as argument can be either a string or a symbol:

+ +
counters = ActiveSupport::HashWithIndifferentAccess.new
+counters[:foo] = { bar: 1 }
+
+counters.dig('foo', 'bar')     # => 1
+counters.dig(:foo, :bar)       # => 1
+counters.dig(:zoo)             # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 206
+def dig(*args)
+  args[0] = convert_key(args[0]) if args.size > 0
+  super(*args)
+end
+
+
+ +
+ +
+

+ + dup() + +

+ + +
+

Returns a shallow copy of the hash.

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new({ a: { b: 'b' } })
+dup  = hash.dup
+dup[:a][:c] = 'c'
+
+hash[:a][:c] # => "c"
+dup[:a][:c]  # => "c"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 256
+def dup
+  self.class.new(self).tap do |new_hash|
+    set_defaults(new_hash)
+  end
+end
+
+
+ +
+ +
+

+ + except(*keys) + +

+ + +
+

Returns a hash with indifferent access that includes everything except given keys.

+ +
hash = { a: "x", b: "y", c: 10 }.with_indifferent_access
+hash.except(:a, "b") # => {c: 10}.with_indifferent_access
+hash                 # => { a: "x", b: "y", c: 10 }.with_indifferent_access
+
+
+ + + +
+ Also aliased as: without +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 303
+def except(*keys)
+  slice(*self.keys - keys.map { |key| convert_key(key) })
+end
+
+
+ +
+ +
+

+ + extractable_options?() + +

+ + +
+

Returns true so that Array#extract_options! finds members of this class.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 56
+def extractable_options?
+  true
+end
+
+
+ +
+ +
+

+ + fetch(key, *extras) + +

+ + +
+

Same as Hash#fetch where the key passed as argument can be either a string or a symbol:

+ +
counters = ActiveSupport::HashWithIndifferentAccess.new
+counters[:foo] = 1
+
+counters.fetch('foo')          # => 1
+counters.fetch(:bar, 0)        # => 0
+counters.fetch(:bar) { |key| 0 } # => 0
+counters.fetch(:zoo)           # => KeyError: key not found: "zoo"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 193
+def fetch(key, *extras)
+  super(convert_key(key), *extras)
+end
+
+
+ +
+ +
+

+ + fetch_values(*indices, &block) + +

+ + +
+

Returns an array of the values at the specified indices, but also raises an exception when one of the keys can’t be found.

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new
+hash[:a] = 'x'
+hash[:b] = 'y'
+hash.fetch_values('a', 'b') # => ["x", "y"]
+hash.fetch_values('a', 'c') { |key| 'z' } # => ["x", "z"]
+hash.fetch_values('a', 'c') # => KeyError: key not found: "c"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 244
+def fetch_values(*indices, &block)
+  super(*indices.map { |key| convert_key(key) }, &block)
+end
+
+
+ +
+ +
+

+ + has_key?(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: key? +
+ + + +
+ +
+

+ + include?(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: key? +
+ + + +
+ +
+

+ + key?(key) + +

+ + +
+

Checks the hash for a key matching the argument passed in:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new
+hash['key'] = 'value'
+hash.key?(:key)  # => true
+hash.key?('key') # => true
+
+
+ + + +
+ Also aliased as: include?, has_key?, member? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 149
+def key?(key)
+  super(convert_key(key))
+end
+
+
+ +
+ +
+

+ + member?(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: key? +
+ + + +
+ +
+

+ + merge(*hashes, &block) + +

+ + +
+

This method has the same semantics of update, except it does not modify the receiver but rather returns a new hash with indifferent access with the result of the merge.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 265
+def merge(*hashes, &block)
+  dup.update(*hashes, &block)
+end
+
+
+ +
+ +
+

+ + merge!(*other_hashes, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: update +
+ + + +
+ +
+

+ + nested_under_indifferent_access() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 64
+def nested_under_indifferent_access
+  self
+end
+
+
+ +
+ +
+

+ + regular_update(*other_hashes, &block) + +

+ + +
+ +
+ + + + + +
+ Alias for: update +
+ + + +
+ +
+

+ + regular_writer(key, value) + +

+ + +
+ +
+ + + + + +
+ Alias for: []= +
+ + + +
+ +
+

+ + reject(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 324
+def reject(*args, &block)
+  return to_enum(:reject) unless block_given?
+  dup.tap { |hash| hash.reject!(*args, &block) }
+end
+
+
+ +
+ +
+

+ + replace(other_hash) + +

+ + +
+

Replaces the contents of this hash with other_hash.

+ +
h = { "a" => 100, "b" => 200 }
+h.replace({ "c" => 300, "d" => 400 }) # => {"c"=>300, "d"=>400}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 290
+def replace(other_hash)
+  super(self.class.new(other_hash))
+end
+
+
+ +
+ +
+

+ + reverse_merge(other_hash) + +

+ + +
+

Like merge but the other way around: Merges the receiver into the argument and returns a new hash with indifferent access as result:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new
+hash['a'] = nil
+hash.reverse_merge(a: 0, b: 1) # => {"a"=>nil, "b"=>1}
+
+
+ + + +
+ Also aliased as: with_defaults +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 275
+def reverse_merge(other_hash)
+  super(self.class.new(other_hash))
+end
+
+
+ +
+ +
+

+ + reverse_merge!(other_hash) + +

+ + +
+

Same semantics as reverse_merge but modifies the receiver in-place.

+
+ + + +
+ Also aliased as: with_defaults! +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 281
+def reverse_merge!(other_hash)
+  super(self.class.new(other_hash))
+end
+
+
+ +
+ +
+

+ + select(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 319
+def select(*args, &block)
+  return to_enum(:select) unless block_given?
+  dup.tap { |hash| hash.select!(*args, &block) }
+end
+
+
+ +
+ +
+

+ + slice(*keys) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 347
+def slice(*keys)
+  keys.map! { |key| convert_key(key) }
+  self.class.new(super)
+end
+
+
+ +
+ +
+

+ + slice!(*keys) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 352
+def slice!(*keys)
+  keys.map! { |key| convert_key(key) }
+  super
+end
+
+
+ +
+ +
+

+ + store(key, value) + +

+ + +
+ +
+ + + + + +
+ Alias for: []= +
+ + + +
+ +
+

+ + stringify_keys() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 310
+def stringify_keys; dup end
+
+
+ +
+ +
+

+ + stringify_keys!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 308
+def stringify_keys!; self end
+
+
+ +
+ +
+

+ + symbolize_keys() + +

+ + +
+ +
+ + + +
+ Also aliased as: to_options +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 314
+def symbolize_keys; to_hash.symbolize_keys! end
+
+
+ +
+ +
+

+ + to_hash() + +

+ + +
+

Convert to a regular hash with string keys.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 362
+def to_hash
+  _new_hash = Hash.new
+  set_defaults(_new_hash)
+
+  each do |key, value|
+    _new_hash[key] = convert_value(value, conversion: :to_hash)
+  end
+  _new_hash
+end
+
+
+ +
+ +
+

+ + to_options() + +

+ + +
+ +
+ + + + + +
+ Alias for: symbolize_keys +
+ + + +
+ +
+

+ + to_options!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 317
+def to_options!; self end
+
+
+ +
+ +
+

+ + transform_keys(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 334
+def transform_keys(*args, &block)
+  return to_enum(:transform_keys) unless block_given?
+  dup.tap { |hash| hash.transform_keys!(*args, &block) }
+end
+
+
+ +
+ +
+

+ + transform_keys!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 339
+def transform_keys!
+  return enum_for(:transform_keys!) { size } unless block_given?
+  keys.each do |key|
+    self[yield(key)] = delete(key)
+  end
+  self
+end
+
+
+ +
+ +
+

+ + transform_values(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 329
+def transform_values(*args, &block)
+  return to_enum(:transform_values) unless block_given?
+  dup.tap { |hash| hash.transform_values!(*args, &block) }
+end
+
+
+ +
+ +
+

+ + update(*other_hashes, &block) + +

+ + +
+

Updates the receiver in-place, merging in the hashes passed as arguments:

+ +
hash_1 = ActiveSupport::HashWithIndifferentAccess.new
+hash_1[:key] = 'value'
+
+hash_2 = ActiveSupport::HashWithIndifferentAccess.new
+hash_2[:key] = 'New Value!'
+
+hash_1.update(hash_2) # => {"key"=>"New Value!"}
+
+hash = ActiveSupport::HashWithIndifferentAccess.new
+hash.update({ "a" => 1 }, { "b" => 2 }) # => { "a" => 1, "b" => 2 }
+
+ +

The arguments can be either an ActiveSupport::HashWithIndifferentAccess or a regular Hash. In either case the merge respects the semantics of indifferent access.

+ +

If the argument is a regular hash with keys :key and "key" only one of the values end up in the receiver, but which one is unspecified.

+ +

When given a block, the value for duplicated keys will be determined by the result of invoking the block with the duplicated key, the value in the receiver, and the value in other_hash. The rules for duplicated keys follow the semantics of indifferent access:

+ +
hash_1[:key] = 10
+hash_2['key'] = 12
+hash_1.update(hash_2) { |key, old, new| old + new } # => {"key"=>22}
+
+
+ + + +
+ Also aliased as: regular_update, merge! +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 130
+def update(*other_hashes, &block)
+  if other_hashes.size == 1
+    update_with_single_argument(other_hashes.first, block)
+  else
+    other_hashes.each do |other_hash|
+      update_with_single_argument(other_hash, block)
+    end
+  end
+  self
+end
+
+
+ +
+ +
+

+ + values_at(*keys) + +

+ + +
+

Returns an array of the values at the specified indices:

+ +
hash = ActiveSupport::HashWithIndifferentAccess.new
+hash[:a] = 'x'
+hash[:b] = 'y'
+hash.values_at('a', 'b') # => ["x", "y"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 231
+def values_at(*keys)
+  super(*keys.map { |key| convert_key(key) })
+end
+
+
+ +
+ +
+

+ + with_defaults(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge +
+ + + +
+ +
+

+ + with_defaults!(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge! +
+ + + +
+ +
+

+ + with_indifferent_access() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/hash_with_indifferent_access.rb, line 60
+def with_indifferent_access
+  dup
+end
+
+
+ +
+ +
+

+ + without(*keys) + +

+ + +
+ +
+ + + + + +
+ Alias for: except +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Inflector.html b/src/7.0/classes/ActiveSupport/Inflector.html new file mode 100644 index 0000000000..736cd1bd68 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Inflector.html @@ -0,0 +1,1251 @@ +--- +title: ActiveSupport::Inflector +layout: default +--- +
+ +
+
+ +
+ +

The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without, and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept in inflections.rb.

+ +

The Rails core team has stated patches for the inflections library will not be accepted in order to avoid breaking legacy applications which may be relying on errant inflections. If you discover an incorrect inflection and require it for your application or wish to define rules for languages other than English, please correct or add them yourself (explained below).

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ALLOWED_ENCODINGS_FOR_TRANSLITERATE=[Encoding::UTF_8, Encoding::US_ASCII, Encoding::GB18030].freeze
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + camelize(term, uppercase_first_letter = true) + +

+ + +
+

Converts strings to UpperCamelCase. If the uppercase_first_letter parameter is set to false, then produces lowerCamelCase.

+ +

Also converts ‘/’ to ‘::’ which is useful for converting paths to namespaces.

+ +
camelize('active_model')                # => "ActiveModel"
+camelize('active_model', false)         # => "activeModel"
+camelize('active_model/errors')         # => "ActiveModel::Errors"
+camelize('active_model/errors', false)  # => "activeModel::Errors"
+
+ +

As a rule of thumb you can think of camelize as the inverse of underscore, though there are cases where that does not hold:

+ +
camelize(underscore('SSLError'))        # => "SslError"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 69
+def camelize(term, uppercase_first_letter = true)
+  string = term.to_s
+  # String#camelize takes a symbol (:upper or :lower), so here we also support :lower to keep the methods consistent.
+  if !uppercase_first_letter || uppercase_first_letter == :lower
+    string = string.sub(inflections.acronyms_camelize_regex) { |match| match.downcase! || match }
+  else
+    string = string.sub(/^[a-z\d]*/) { |match| inflections.acronyms[match] || match.capitalize! || match }
+  end
+  string.gsub!(/(?:_|(\/))([a-z\d]*)/i) do
+    word = $2
+    substituted = inflections.acronyms[word] || word.capitalize! || word
+    $1 ? "::#{substituted}" : substituted
+  end
+  string
+end
+
+
+ +
+ +
+

+ + classify(table_name) + +

+ + +
+

Creates a class name from a plural table name like Rails does for table names to models. Note that this returns a string and not a Class. (To convert to an actual class follow classify with constantize.)

+ +
classify('ham_and_eggs') # => "HamAndEgg"
+classify('posts')        # => "Post"
+
+ +

Singular names are not handled correctly:

+ +
classify('calculus')     # => "Calculu"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 206
+def classify(table_name)
+  # strip out any leading schema name
+  camelize(singularize(table_name.to_s.sub(/.*\./, "")))
+end
+
+
+ +
+ +
+

+ + constantize(camel_cased_word) + +

+ + +
+

Tries to find a constant with the name specified in the argument string.

+ +
constantize('Module')   # => Module
+constantize('Foo::Bar') # => Foo::Bar
+
+ +

The name is assumed to be the one of a top-level constant, no matter whether it starts with “::” or not. No lexical context is taken into account:

+ +
C = 'outside'
+module M
+  C = 'inside'
+  C                # => 'inside'
+  constantize('C') # => 'outside', same as ::C
+end
+
+ +

NameError is raised when the name is not in CamelCase or the constant is unknown.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 277
+def constantize(camel_cased_word)
+  Object.const_get(camel_cased_word)
+end
+
+
+ +
+ +
+

+ + dasherize(underscored_word) + +

+ + +
+

Replaces underscores with dashes in the string.

+ +
dasherize('puni_puni') # => "puni-puni"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 214
+def dasherize(underscored_word)
+  underscored_word.tr("_", "-")
+end
+
+
+ +
+ +
+

+ + deconstantize(path) + +

+ + +
+

Removes the rightmost segment from the constant expression in the string.

+ +
deconstantize('Net::HTTP')   # => "Net"
+deconstantize('::Net::HTTP') # => "::Net"
+deconstantize('String')      # => ""
+deconstantize('::String')    # => ""
+deconstantize('')            # => ""
+
+ +

See also demodulize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 244
+def deconstantize(path)
+  path.to_s[0, path.rindex("::") || 0] # implementation based on the one in facets' Module#spacename
+end
+
+
+ +
+ +
+

+ + demodulize(path) + +

+ + +
+

Removes the module part from the expression in the string.

+ +
demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
+demodulize('Inflections')                           # => "Inflections"
+demodulize('::Inflections')                         # => "Inflections"
+demodulize('')                                      # => ""
+
+ +

See also deconstantize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 226
+def demodulize(path)
+  path = path.to_s
+  if i = path.rindex("::")
+    path[(i + 2)..-1]
+  else
+    path
+  end
+end
+
+
+ +
+ +
+

+ + foreign_key(class_name, separate_class_name_and_id_with_underscore = true) + +

+ + +
+

Creates a foreign key name from a class name. separate_class_name_and_id_with_underscore sets whether the method should put ‘_’ between the name and ‘id’.

+ +
foreign_key('Message')        # => "message_id"
+foreign_key('Message', false) # => "messageid"
+foreign_key('Admin::Post')    # => "post_id"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 255
+def foreign_key(class_name, separate_class_name_and_id_with_underscore = true)
+  underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id")
+end
+
+
+ +
+ +
+

+ + humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false) + +

+ + +
+

Tweaks an attribute name for display to end users.

+ +

Specifically, performs these transformations:

+
  • +

    Applies human inflection rules to the argument.

    +
  • +

    Deletes leading underscores, if any.

    +
  • +

    Removes an “_id” suffix if present.

    +
  • +

    Replaces underscores with spaces, if any.

    +
  • +

    Downcases all words except acronyms.

    +
  • +

    Capitalizes the first word.

    +
+ +

The capitalization of the first word can be turned off by setting the :capitalize option to false (default is true).

+ +

The trailing ‘_id’ can be kept and capitalized by setting the optional parameter keep_id_suffix to true (default is false).

+ +
humanize('employee_salary')                  # => "Employee salary"
+humanize('author_id')                        # => "Author"
+humanize('author_id', capitalize: false)     # => "author"
+humanize('_id')                              # => "Id"
+humanize('author_id', keep_id_suffix: true)  # => "Author id"
+
+ +

If “SSL” was defined to be an acronym:

+ +
humanize('ssl_error') # => "SSL error"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 132
+def humanize(lower_case_and_underscored_word, capitalize: true, keep_id_suffix: false)
+  result = lower_case_and_underscored_word.to_s.dup
+
+  inflections.humans.each { |(rule, replacement)| break if result.sub!(rule, replacement) }
+
+  result.tr!("_", " ")
+  result.lstrip!
+  if !keep_id_suffix && lower_case_and_underscored_word&.end_with?("_id")
+    result.delete_suffix!(" id")
+  end
+
+  result.gsub!(/([a-z\d]+)/i) do |match|
+    match.downcase!
+    inflections.acronyms[match] || match
+  end
+
+  if capitalize
+    result.sub!(/\A\w/) do |match|
+      match.upcase!
+      match
+    end
+  end
+
+  result
+end
+
+
+ +
+ +
+

+ + inflections(locale = :en) + +

+ + +
+

Yields a singleton instance of Inflector::Inflections so you can specify additional inflector rules. If passed an optional locale, rules for other languages can be specified. If not specified, defaults to :en. Only rules for English are provided.

+ +
ActiveSupport::Inflector.inflections(:en) do |inflect|
+  inflect.uncountable 'rails'
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 263
+def inflections(locale = :en)
+  if block_given?
+    yield Inflections.instance(locale)
+  else
+    Inflections.instance_or_fallback(locale)
+  end
+end
+
+
+ +
+ +
+

+ + ordinal(number) + +

+ + +
+

Returns the suffix that should be added to a number to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th.

+ +
ordinal(1)     # => "st"
+ordinal(2)     # => "nd"
+ordinal(1002)  # => "nd"
+ordinal(1003)  # => "rd"
+ordinal(-11)   # => "th"
+ordinal(-1021) # => "st"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 322
+def ordinal(number)
+  I18n.translate("number.nth.ordinals", number: number)
+end
+
+
+ +
+ +
+

+ + ordinalize(number) + +

+ + +
+

Turns a number into an ordinal string used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th.

+ +
ordinalize(1)     # => "1st"
+ordinalize(2)     # => "2nd"
+ordinalize(1002)  # => "1002nd"
+ordinalize(1003)  # => "1003rd"
+ordinalize(-11)   # => "-11th"
+ordinalize(-1021) # => "-1021st"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 335
+def ordinalize(number)
+  I18n.translate("number.nth.ordinalized", number: number)
+end
+
+
+ +
+ +
+

+ + parameterize(string, separator: "-", preserve_case: false, locale: nil) + +

+ + +
+

Replaces special characters in a string so that it may be used as part of a ‘pretty’ URL.

+ +
parameterize("Donald E. Knuth") # => "donald-e-knuth"
+parameterize("^très|Jolie-- ")  # => "tres-jolie"
+
+ +

To use a custom separator, override the separator argument.

+ +
parameterize("Donald E. Knuth", separator: '_') # => "donald_e_knuth"
+parameterize("^très|Jolie__ ", separator: '_')  # => "tres_jolie"
+
+ +

To preserve the case of the characters in a string, use the preserve_case argument.

+ +
parameterize("Donald E. Knuth", preserve_case: true) # => "Donald-E-Knuth"
+parameterize("^très|Jolie-- ", preserve_case: true) # => "tres-Jolie"
+
+ +

It preserves dashes and underscores unless they are used as separators:

+ +
parameterize("^très|Jolie__ ")                 # => "tres-jolie__"
+parameterize("^très|Jolie-- ", separator: "_") # => "tres_jolie--"
+parameterize("^très_Jolie-- ", separator: ".") # => "tres_jolie--"
+
+ +

If the optional parameter locale is specified, the word will be parameterized as a word of that language. By default, this parameter is set to nil and it will use the configured I18n.locale.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/transliterate.rb, line 121
+def parameterize(string, separator: "-", preserve_case: false, locale: nil)
+  # Replace accented chars with their ASCII equivalents.
+  parameterized_string = transliterate(string, locale: locale)
+
+  # Turn unwanted chars into the separator.
+  parameterized_string.gsub!(/[^a-z0-9\-_]+/i, separator)
+
+  unless separator.nil? || separator.empty?
+    if separator == "-"
+      re_duplicate_separator        = /-{2,}/
+      re_leading_trailing_separator = /^-|-$/i
+    else
+      re_sep = Regexp.escape(separator)
+      re_duplicate_separator        = /#{re_sep}{2,}/
+      re_leading_trailing_separator = /^#{re_sep}|#{re_sep}$/i
+    end
+    # No more than one of the separator in a row.
+    parameterized_string.gsub!(re_duplicate_separator, separator)
+    # Remove leading/trailing separator.
+    parameterized_string.gsub!(re_leading_trailing_separator, "")
+  end
+
+  parameterized_string.downcase! unless preserve_case
+  parameterized_string
+end
+
+
+ +
+ +
+

+ + pluralize(word, locale = :en) + +

+ + +
+

Returns the plural form of the word in the string.

+ +

If passed an optional locale parameter, the word will be pluralized using rules defined for that language. By default, this parameter is set to :en.

+ +
pluralize('post')             # => "posts"
+pluralize('octopus')          # => "octopi"
+pluralize('sheep')            # => "sheep"
+pluralize('words')            # => "words"
+pluralize('CamelOctopus')     # => "CamelOctopi"
+pluralize('ley', :es)         # => "leyes"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 32
+def pluralize(word, locale = :en)
+  apply_inflections(word, inflections(locale).plurals, locale)
+end
+
+
+ +
+ +
+

+ + safe_constantize(camel_cased_word) + +

+ + +
+

Tries to find a constant with the name specified in the argument string.

+ +
safe_constantize('Module')   # => Module
+safe_constantize('Foo::Bar') # => Foo::Bar
+
+ +

The name is assumed to be the one of a top-level constant, no matter whether it starts with “::” or not. No lexical context is taken into account:

+ +
C = 'outside'
+module M
+  C = 'inside'
+  C                     # => 'inside'
+  safe_constantize('C') # => 'outside', same as ::C
+end
+
+ +

nil is returned when the name is not in CamelCase or the constant (or part of it) is unknown.

+ +
safe_constantize('blargle')                  # => nil
+safe_constantize('UnknownModule')            # => nil
+safe_constantize('UnknownModule::Foo::Bar')  # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 303
+def safe_constantize(camel_cased_word)
+  constantize(camel_cased_word)
+rescue NameError => e
+  raise if e.name && !(camel_cased_word.to_s.split("::").include?(e.name.to_s) ||
+    e.name.to_s == camel_cased_word.to_s)
+rescue LoadError => e
+  message = e.respond_to?(:original_message) ? e.original_message : e.message
+  raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(message)
+end
+
+
+ +
+ +
+

+ + singularize(word, locale = :en) + +

+ + +
+

The reverse of pluralize, returns the singular form of a word in a string.

+ +

If passed an optional locale parameter, the word will be singularized using rules defined for that language. By default, this parameter is set to :en.

+ +
singularize('posts')            # => "post"
+singularize('octopi')           # => "octopus"
+singularize('sheep')            # => "sheep"
+singularize('word')             # => "word"
+singularize('CamelOctopi')      # => "CamelOctopus"
+singularize('leyes', :es)       # => "ley"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 49
+def singularize(word, locale = :en)
+  apply_inflections(word, inflections(locale).singulars, locale)
+end
+
+
+ +
+ +
+

+ + tableize(class_name) + +

+ + +
+

Creates the name of a table like Rails does for models to table names. This method uses the pluralize method on the last word in the string.

+ +
tableize('RawScaledScorer') # => "raw_scaled_scorers"
+tableize('ham_and_egg')     # => "ham_and_eggs"
+tableize('fancyCategory')   # => "fancy_categories"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 192
+def tableize(class_name)
+  pluralize(underscore(class_name))
+end
+
+
+ +
+ +
+

+ + titleize(word, keep_id_suffix: false) + +

+ + +
+

Capitalizes all the words and replaces some characters in the string to create a nicer looking title. titleize is meant for creating pretty output. It is not used in the Rails internals.

+ +

The trailing ‘_id’,‘Id’.. can be kept and capitalized by setting the optional parameter keep_id_suffix to true. By default, this parameter is false.

+ +
titleize('man from the boondocks')                       # => "Man From The Boondocks"
+titleize('x-men: the last stand')                        # => "X Men: The Last Stand"
+titleize('TheManWithoutAPast')                           # => "The Man Without A Past"
+titleize('raiders_of_the_lost_ark')                      # => "Raiders Of The Lost Ark"
+titleize('string_ending_with_id', keep_id_suffix: true)  # => "String Ending With Id"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 180
+def titleize(word, keep_id_suffix: false)
+  humanize(underscore(word), keep_id_suffix: keep_id_suffix).gsub(/\b(?<!\w['’`()])[a-z]/) do |match|
+    match.capitalize
+  end
+end
+
+
+ +
+ +
+

+ + transliterate(string, replacement = "?", locale: nil) + +

+ + +
+

Replaces non-ASCII characters with an ASCII approximation, or if none exists, a replacement character which defaults to “?”.

+ +
transliterate('Ærøskøbing')
+# => "AEroskobing"
+
+ +

Default approximations are provided for Western/Latin characters, e.g, “ø”, “ñ”, “é”, “ß”, etc.

+ +

This method is I18n aware, so you can set up custom approximations for a locale. This can be useful, for example, to transliterate German’s “ü” and “ö” to “ue” and “oe”, or to add support for transliterating Russian to ASCII.

+ +

In order to make your custom transliterations available, you must set them as the i18n.transliterate.rule i18n key:

+ +
# Store the transliterations in locales/de.yml
+i18n:
+  transliterate:
+    rule:
+      ü: "ue"
+      ö: "oe"
+
+# Or set them using Ruby
+I18n.backend.store_translations(:de, i18n: {
+  transliterate: {
+    rule: {
+      'ü' => 'ue',
+      'ö' => 'oe'
+    }
+  }
+})
+
+ +

The value for i18n.transliterate.rule can be a simple Hash that maps characters to ASCII approximations as shown above, or, for more complex requirements, a Proc:

+ +
I18n.backend.store_translations(:de, i18n: {
+  transliterate: {
+    rule: ->(string) { MyTransliterator.transliterate(string) }
+  }
+})
+
+ +

Now you can have different transliterations for each locale:

+ +
transliterate('Jürgen', locale: :en)
+# => "Jurgen"
+
+transliterate('Jürgen', locale: :de)
+# => "Juergen"
+
+ +

Transliteration is restricted to UTF-8, US-ASCII, and GB18030 strings. Other encodings will raise an ArgumentError.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/transliterate.rb, line 64
+def transliterate(string, replacement = "?", locale: nil)
+  string = string.dup if string.frozen?
+  raise ArgumentError, "Can only transliterate strings. Received #{string.class.name}" unless string.is_a?(String)
+  raise ArgumentError, "Cannot transliterate strings with #{string.encoding} encoding" unless ALLOWED_ENCODINGS_FOR_TRANSLITERATE.include?(string.encoding)
+
+  input_encoding = string.encoding
+
+  # US-ASCII is a subset of UTF-8 so we'll force encoding as UTF-8 if
+  # US-ASCII is given. This way we can let tidy_bytes handle the string
+  # in the same way as we do for UTF-8
+  string.force_encoding(Encoding::UTF_8) if string.encoding == Encoding::US_ASCII
+
+  # GB18030 is Unicode compatible but is not a direct mapping so needs to be
+  # transcoded. Using invalid/undef :replace will result in loss of data in
+  # the event of invalid characters, but since tidy_bytes will replace
+  # invalid/undef with a "?" we're safe to do the same beforehand
+  string.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace) if string.encoding == Encoding::GB18030
+
+  transliterated = I18n.transliterate(
+    ActiveSupport::Multibyte::Unicode.tidy_bytes(string).unicode_normalize(:nfc),
+    replacement: replacement,
+    locale: locale
+  )
+
+  # Restore the string encoding of the input if it was not UTF-8.
+  # Apply invalid/undef :replace as tidy_bytes does
+  transliterated.encode!(input_encoding, invalid: :replace, undef: :replace) if input_encoding != transliterated.encoding
+
+  transliterated
+end
+
+
+ +
+ +
+

+ + underscore(camel_cased_word) + +

+ + +
+

Makes an underscored, lowercase form from the expression in the string.

+ +

Changes ‘::’ to ‘/’ to convert namespaces to paths.

+ +
underscore('ActiveModel')         # => "active_model"
+underscore('ActiveModel::Errors') # => "active_model/errors"
+
+ +

As a rule of thumb you can think of underscore as the inverse of camelize, though there are cases where that does not hold:

+ +
camelize(underscore('SSLError'))  # => "SslError"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 96
+def underscore(camel_cased_word)
+  return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
+  word = camel_cased_word.to_s.gsub("::", "/")
+  word.gsub!(inflections.acronyms_underscore_regex) { "#{$1 && '_' }#{$2.downcase}" }
+  word.gsub!(/([A-Z])(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { ($1 || $2) << "_" }
+  word.tr!("-", "_")
+  word.downcase!
+  word
+end
+
+
+ +
+ +
+

+ + upcase_first(string) + +

+ + +
+

Converts just the first character to uppercase.

+ +
upcase_first('what a Lovely Day') # => "What a Lovely Day"
+upcase_first('w')                 # => "W"
+upcase_first('')                  # => ""
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/methods.rb, line 163
+def upcase_first(string)
+  string.length > 0 ? string[0].upcase.concat(string[1..-1]) : ""
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Inflector/Inflections.html b/src/7.0/classes/ActiveSupport/Inflector/Inflections.html new file mode 100644 index 0000000000..6c57a374f7 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Inflector/Inflections.html @@ -0,0 +1,644 @@ +--- +title: ActiveSupport::Inflector::Inflections +layout: default +--- +
+ +
+
+ +
+ +

A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional inflection rules. If passed an optional locale, rules for other languages can be specified. The default locale is :en. Only rules for English are provided.

+ +
ActiveSupport::Inflector.inflections(:en) do |inflect|
+  inflect.plural /^(ox)$/i, '\1\2en'
+  inflect.singular /^(ox)en/i, '\1'
+
+  inflect.irregular 'cactus', 'cacti'
+
+  inflect.uncountable 'equipment'
+end
+
+ +

New rules are added at the top. So in the example above, the irregular rule for cactus will now be the first of the pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may already have been loaded.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + acronyms
+ [R] + humans
+ [R] + plurals
+ [R] + singulars
+ [R] + uncountables
+ + + + +

Class Public methods

+ +
+

+ + instance(locale = :en) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 63
+def self.instance(locale = :en)
+  @__instance__[locale] ||= new
+end
+
+
+ +
+ +
+

+ + instance_or_fallback(locale) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 67
+def self.instance_or_fallback(locale)
+  I18n.fallbacks[locale].each do |k|
+    return @__instance__[k] if @__instance__.key?(k)
+  end
+  instance(locale)
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 78
+def initialize
+  @plurals, @singulars, @uncountables, @humans, @acronyms = [], [], Uncountables.new, [], {}
+  define_acronym_regex_patterns
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + acronym(word) + +

+ + +
+

Specifies a new acronym. An acronym must be specified as it will appear in a camelized string. An underscore string that contains the acronym will retain the acronym when passed to camelize, humanize, or titleize. A camelized string that contains the acronym will maintain the acronym when titleized or humanized, and will convert the acronym into a non-delimited single lowercase word when passed to underscore.

+ +
acronym 'HTML'
+titleize 'html'     # => 'HTML'
+camelize 'html'     # => 'HTML'
+underscore 'MyHTML' # => 'my_html'
+
+ +

The acronym, however, must occur as a delimited unit and not be part of another word for conversions to recognize it:

+ +
acronym 'HTTP'
+camelize 'my_http_delimited' # => 'MyHTTPDelimited'
+camelize 'https'             # => 'Https', not 'HTTPs'
+underscore 'HTTPS'           # => 'http_s', not 'https'
+
+acronym 'HTTPS'
+camelize 'https'   # => 'HTTPS'
+underscore 'HTTPS' # => 'https'
+
+ +

Note: Acronyms that are passed to pluralize will no longer be recognized, since the acronym will not occur as a delimited unit in the pluralized result. To work around this, you must specify the pluralized form as an acronym as well:

+ +
acronym 'API'
+camelize(pluralize('api')) # => 'Apis'
+
+acronym 'APIs'
+camelize(pluralize('api')) # => 'APIs'
+
+ +

acronym may be used to specify any word that contains an acronym or otherwise needs to maintain a non-standard capitalization. The only restriction is that the word must begin with a capital letter.

+ +
acronym 'RESTful'
+underscore 'RESTful'           # => 'restful'
+underscore 'RESTfulController' # => 'restful_controller'
+titleize 'RESTfulController'   # => 'RESTful Controller'
+camelize 'restful'             # => 'RESTful'
+camelize 'restful_controller'  # => 'RESTfulController'
+
+acronym 'McDonald'
+underscore 'McDonald' # => 'mcdonald'
+camelize 'mcdonald'   # => 'McDonald'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 140
+def acronym(word)
+  @acronyms[word.downcase] = word
+  define_acronym_regex_patterns
+end
+
+
+ +
+ +
+

+ + clear(scope = :all) + +

+ + +
+

Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type, the options are: :plurals, :singulars, :uncountables, :humans, :acronyms.

+ +
clear :all
+clear :plurals
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 229
+def clear(scope = :all)
+  case scope
+  when :all
+    clear(:acronyms)
+    clear(:plurals)
+    clear(:singulars)
+    clear(:uncountables)
+    clear(:humans)
+  when :acronyms
+    @acronyms = {}
+    define_acronym_regex_patterns
+  when :uncountables
+    @uncountables = Uncountables.new
+  when :plurals, :singulars, :humans
+    instance_variable_set "@#{scope}", []
+  end
+end
+
+
+ +
+ +
+

+ + human(rule, replacement) + +

+ + +
+

Specifies a humanized form of a string by a regular expression rule or by a string mapping. When using a regular expression based replacement, the normal humanize formatting is called after the replacement. When a string is used, the human form should be specified as desired (example: ‘The name’, not ‘the_name’).

+ +
human /_cnt$/i, '\1_count'
+human 'legacy_col_person_name', 'Name'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 218
+def human(rule, replacement)
+  @humans.prepend([rule, replacement])
+end
+
+
+ +
+ +
+

+ + irregular(singular, plural) + +

+ + +
+

Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used for strings, not regular expressions. You simply pass the irregular in singular and plural form.

+ +
irregular 'cactus', 'cacti'
+irregular 'person', 'people'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 172
+def irregular(singular, plural)
+  @uncountables.delete(singular)
+  @uncountables.delete(plural)
+
+  s0 = singular[0]
+  srest = singular[1..-1]
+
+  p0 = plural[0]
+  prest = plural[1..-1]
+
+  if s0.upcase == p0.upcase
+    plural(/(#{s0})#{srest}$/i, '\1' + prest)
+    plural(/(#{p0})#{prest}$/i, '\1' + prest)
+
+    singular(/(#{s0})#{srest}$/i, '\1' + srest)
+    singular(/(#{p0})#{prest}$/i, '\1' + srest)
+  else
+    plural(/#{s0.upcase}(?i)#{srest}$/,   p0.upcase   + prest)
+    plural(/#{s0.downcase}(?i)#{srest}$/, p0.downcase + prest)
+    plural(/#{p0.upcase}(?i)#{prest}$/,   p0.upcase   + prest)
+    plural(/#{p0.downcase}(?i)#{prest}$/, p0.downcase + prest)
+
+    singular(/#{s0.upcase}(?i)#{srest}$/,   s0.upcase   + srest)
+    singular(/#{s0.downcase}(?i)#{srest}$/, s0.downcase + srest)
+    singular(/#{p0.upcase}(?i)#{prest}$/,   s0.upcase   + srest)
+    singular(/#{p0.downcase}(?i)#{prest}$/, s0.downcase + srest)
+  end
+end
+
+
+ +
+ +
+

+ + plural(rule, replacement) + +

+ + +
+

Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression. The replacement should always be a string that may include references to the matched data from the rule.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 149
+def plural(rule, replacement)
+  @uncountables.delete(rule) if rule.is_a?(String)
+  @uncountables.delete(replacement)
+  @plurals.prepend([rule, replacement])
+end
+
+
+ +
+ +
+

+ + singular(rule, replacement) + +

+ + +
+

Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression. The replacement should always be a string that may include references to the matched data from the rule.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 159
+def singular(rule, replacement)
+  @uncountables.delete(rule) if rule.is_a?(String)
+  @uncountables.delete(replacement)
+  @singulars.prepend([rule, replacement])
+end
+
+
+ +
+ +
+

+ + uncountable(*words) + +

+ + +
+

Specifies words that are uncountable and should not be inflected.

+ +
uncountable 'money'
+uncountable 'money', 'information'
+uncountable %w( money information rice )
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 206
+def uncountable(*words)
+  @uncountables.add(words)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Inflector/Inflections/Uncountables.html b/src/7.0/classes/ActiveSupport/Inflector/Inflections/Uncountables.html new file mode 100644 index 0000000000..6d48c01532 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Inflector/Inflections/Uncountables.html @@ -0,0 +1,271 @@ +--- +title: ActiveSupport::Inflector::Inflections::Uncountables +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 32
+def initialize
+  @regex_array = []
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(*word) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 42
+def <<(*word)
+  add(word)
+end
+
+
+ +
+ +
+

+ + add(words) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 46
+def add(words)
+  words = words.flatten.map(&:downcase)
+  concat(words)
+  @regex_array += words.map { |word| to_regex(word) }
+  self
+end
+
+
+ +
+ +
+

+ + delete(entry) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 37
+def delete(entry)
+  super entry
+  @regex_array.delete(to_regex(entry))
+end
+
+
+ +
+ +
+

+ + uncountable?(str) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/inflector/inflections.rb, line 53
+def uncountable?(str)
+  @regex_array.any? { |regex| regex.match? str }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/InheritableOptions.html b/src/7.0/classes/ActiveSupport/InheritableOptions.html new file mode 100644 index 0000000000..ec973cdc77 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/InheritableOptions.html @@ -0,0 +1,169 @@ +--- +title: ActiveSupport::InheritableOptions +layout: default +--- +
+ +
+
+ +
+ +

InheritableOptions provides a constructor to build an OrderedOptions hash inherited from another hash.

+ +

Use this if you already have some hash and you want to create a new one based on it.

+ +
h = ActiveSupport::InheritableOptions.new({ girl: 'Mary', boy: 'John' })
+h.girl # => 'Mary'
+h.boy  # => 'John'
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(parent = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 80
+def initialize(parent = nil)
+  if parent.kind_of?(OrderedOptions)
+    # use the faster _get when dealing with OrderedOptions
+    super() { |h, k| parent._get(k) }
+  elsif parent
+    super() { |h, k| parent[k] }
+  else
+    super()
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + inheritable_copy() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 91
+def inheritable_copy
+  self.class.new(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/JSON.html b/src/7.0/classes/ActiveSupport/JSON.html new file mode 100644 index 0000000000..4ff6ca32e9 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/JSON.html @@ -0,0 +1,234 @@ +--- +title: ActiveSupport::JSON +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DATETIME_REGEX=/\A(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?)\z/
 
DATE_REGEX=/\A\d{4}-\d{2}-\d{2}\z/
 

matches YAML-formatted dates

+ + + + + + +

Class Public methods

+ +
+

+ + decode(json) + +

+ + +
+

Parses a JSON string (JavaScript Object Notation) into a hash. See www.json.org for more info.

+ +
ActiveSupport::JSON.decode("{\"team\":\"rails\",\"players\":\"36\"}")
+=> {"team" => "rails", "players" => "36"}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/json/decoding.rb, line 22
+def decode(json)
+  data = ::JSON.parse(json, quirks_mode: true)
+
+  if ActiveSupport.parse_json_times
+    convert_dates_from(data)
+  else
+    data
+  end
+end
+
+
+ +
+ +
+

+ + encode(value, options = nil) + +

+ + +
+

Dumps objects in JSON (JavaScript Object Notation). See www.json.org for more info.

+ +
ActiveSupport::JSON.encode({ team: 'rails', players: '36' })
+# => "{\"team\":\"rails\",\"players\":\"36\"}"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/json/encoding.rb, line 21
+def self.encode(value, options = nil)
+  Encoding.json_encoder.new(options).encode(value)
+end
+
+
+ +
+ +
+

+ + parse_error() + +

+ + +
+

Returns the class of the error that will be raised when there is an error in decoding JSON. Using this method means you won’t directly depend on the ActiveSupport’s JSON implementation, in case it changes in the future.

+ +
begin
+  obj = ActiveSupport::JSON.decode(some_string)
+rescue ActiveSupport::JSON.parse_error
+  Rails.logger.warn("Attempted to decode invalid JSON: #{some_string}")
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/json/decoding.rb, line 42
+def parse_error
+  ::JSON::ParserError
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/KeyGenerator.html b/src/7.0/classes/ActiveSupport/KeyGenerator.html new file mode 100644 index 0000000000..777f8be9db --- /dev/null +++ b/src/7.0/classes/ActiveSupport/KeyGenerator.html @@ -0,0 +1,243 @@ +--- +title: ActiveSupport::KeyGenerator +layout: default +--- +
+ +
+
+ +
+ +

KeyGenerator is a simple wrapper around OpenSSL’s implementation of PBKDF2. It can be used to derive a number of keys for various purposes from a given secret. This lets Rails applications have a single secure secret, but avoid reusing that key in multiple incompatible contexts.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + hash_digest_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 21
+def hash_digest_class
+  @hash_digest_class ||= OpenSSL::Digest::SHA1
+end
+
+
+ +
+ +
+

+ + hash_digest_class=(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 13
+def hash_digest_class=(klass)
+  if klass.kind_of?(Class) && klass < OpenSSL::Digest
+    @hash_digest_class = klass
+  else
+    raise ArgumentError, "#{klass} is expected to be an OpenSSL::Digest subclass"
+  end
+end
+
+
+ +
+ +
+

+ + new(secret, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 26
+def initialize(secret, options = {})
+  @secret = secret
+  # The default iterations are higher than required for our key derivation uses
+  # on the off chance someone uses this for password storage
+  @iterations = options[:iterations] || 2**16
+  # Also allow configuration here so people can use this to build a rotation
+  # scheme when switching the digest class.
+  @hash_digest_class = options[:hash_digest_class] || self.class.hash_digest_class
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + generate_key(salt, key_size = 64) + +

+ + +
+

Returns a derived key suitable for use. The default key_size is chosen to be compatible with the default settings of ActiveSupport::MessageVerifier. i.e. OpenSSL::Digest::SHA1#block_length

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/key_generator.rb, line 39
+def generate_key(salt, key_size = 64)
+  OpenSSL::PKCS5.pbkdf2_hmac(@secret, salt, @iterations, key_size, @hash_digest_class.new)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/LazyLoadHooks.html b/src/7.0/classes/ActiveSupport/LazyLoadHooks.html new file mode 100644 index 0000000000..544b4e7d8d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/LazyLoadHooks.html @@ -0,0 +1,193 @@ +--- +title: ActiveSupport::LazyLoadHooks +layout: default +--- +
+ +
+
+ +
+ +

LazyLoadHooks allows Rails to lazily load a lot of components and thus making the app boot faster. Because of this feature now there is no need to require ActiveRecord::Base at boot time purely to apply configuration. Instead a hook is registered that applies configuration once ActiveRecord::Base is loaded. Here ActiveRecord::Base is used as example but this feature can be applied elsewhere too.

+ +

Here is an example where on_load method is called to register a hook.

+ +
initializer 'active_record.initialize_timezone' do
+  ActiveSupport.on_load(:active_record) do
+    self.time_zone_aware_attributes = true
+    self.default_timezone = :utc
+  end
+end
+
+ +

When the entirety of ActiveRecord::Base has been evaluated then run_load_hooks is invoked. The very last line of ActiveRecord::Base is:

+ +
ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
+
+ +

run_load_hooks will then execute all the hooks that were registered with the on_load method. In the case of the above example, it will execute the block of code that is in the initializer.

+ +

Registering a hook that has already run results in that hook executing immediately. This allows hooks to be nested for code that relies on multiple lazily loaded components:

+ +
initializer "action_text.renderer" do
+  ActiveSupport.on_load(:action_controller_base) do
+    ActiveSupport.on_load(:action_text_content) do
+      self.default_renderer = Class.new(ActionController::Base).renderer
+    end
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + on_load(name, options = {}, &block) + +

+ + +
+

Declares a block that will be executed when a Rails component is fully loaded. If the component has already loaded, the block is executed immediately.

+ +

Options:

+
  • +

    :yield - Yields the object that run_load_hooks to block.

    +
  • +

    :run_once - Given block will run only once.

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/lazy_load_hooks.rb, line 58
+def on_load(name, options = {}, &block)
+  @loaded[name].each do |base|
+    execute_hook(name, base, options, block)
+  end
+
+  @load_hooks[name] << [block, options]
+end
+
+
+ +
+ +
+

+ + run_load_hooks(name, base = Object) + +

+ + +
+

Executes all blocks registered to name via on_load, using base as the evaluation context.

+ +
ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Base)
+
+ +

In the case of the above example, it will execute all hooks registered for :active_record within the class ActiveRecord::Base.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/lazy_load_hooks.rb, line 73
+def run_load_hooks(name, base = Object)
+  @loaded[name] << base
+  @load_hooks[name].each do |hook, options|
+    execute_hook(name, base, options, hook)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/LogSubscriber.html b/src/7.0/classes/ActiveSupport/LogSubscriber.html new file mode 100644 index 0000000000..e382f56573 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/LogSubscriber.html @@ -0,0 +1,600 @@ +--- +title: ActiveSupport::LogSubscriber +layout: default +--- +
+ +
+
+ +
+ +

ActiveSupport::LogSubscriber is an object set to consume ActiveSupport::Notifications with the sole purpose of logging them. The log subscriber dispatches notifications to a registered object based on its given namespace.

+ +

An example would be Active Record log subscriber responsible for logging queries:

+ +
module ActiveRecord
+  class LogSubscriber < ActiveSupport::LogSubscriber
+    def sql(event)
+      info "#{event.payload[:name]} (#{event.duration}) #{event.payload[:sql]}"
+    end
+  end
+end
+
+ +

And it’s finally registered as:

+ +
ActiveRecord::LogSubscriber.attach_to :active_record
+
+ +

Since we need to know all instance methods before attaching the log subscriber, the line above should be called after your ActiveRecord::LogSubscriber definition.

+ +

A logger also needs to be set with ActiveRecord::LogSubscriber.logger=. This is assigned automatically in a Rails environment.

+ +

After configured, whenever a "sql.active_record" notification is published, it will properly dispatch the event (ActiveSupport::Notifications::Event) to the sql method.

+ +

Being an ActiveSupport::Notifications consumer, ActiveSupport::LogSubscriber exposes a simple interface to check if instrumented code raises an exception. It is common to log a different message in case of an error, and this can be achieved by extending the previous example:

+ +
module ActiveRecord
+  class LogSubscriber < ActiveSupport::LogSubscriber
+    def sql(event)
+      exception = event.payload[:exception]
+
+      if exception
+        exception_object = event.payload[:exception_object]
+
+        error "[ERROR] #{event.payload[:name]}: #{exception.join(', ')} " \
+              "(#{exception_object.backtrace.first})"
+      else
+        # standard logger code
+      end
+    end
+  end
+end
+
+ +

Log subscriber also has some helpers to deal with logging and automatically flushes all logs when the request finishes (via action_dispatch.callback notification) in a Rails environment.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BLACK="\e[30m"
 

Colors

BLUE="\e[34m"
 
BOLD="\e[1m"
 
CLEAR="\e[0m"
 

Embed in a String to clear all previous ANSI sequences.

CYAN="\e[36m"
 
GREEN="\e[32m"
 
MAGENTA="\e[35m"
 
RED="\e[31m"
 
WHITE="\e[37m"
 
YELLOW="\e[33m"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [W] + logger
+ + + + +

Class Public methods

+ +
+

+ + flush_all!() + +

+ + +
+

Flush all log_subscribers‘ logger.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 96
+def flush_all!
+  logger.flush if logger.respond_to?(:flush)
+end
+
+
+ +
+ +
+

+ + log_subscribers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 91
+def log_subscribers
+  subscribers
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 83
+def logger
+  @logger ||= if defined?(Rails) && Rails.respond_to?(:logger)
+    Rails.logger
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finish(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 114
+def finish(name, id, payload)
+  super if logger
+rescue => e
+  log_exception(name, e)
+end
+
+
+ +
+ +
+

+ + logger() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 106
+def logger
+  LogSubscriber.logger
+end
+
+
+ +
+ +
+

+ + publish_event(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 120
+def publish_event(event)
+  super if logger
+rescue => e
+  log_exception(event.name, e)
+end
+
+
+ +
+ +
+

+ + start(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 110
+def start(name, id, payload)
+  super if logger
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + color(text, color, bold = false) + +

+ + +
+

Set color by using a symbol or one of the defined constants. If a third option is set to true, it also adds bold to the string. This is based on the Highline implementation and will automatically append CLEAR to the end of the returned String.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber.rb, line 139
+def color(text, color, bold = false) # :doc:
+  return text unless colorize_logging
+  color = self.class.const_get(color.upcase) if color.is_a?(Symbol)
+  bold  = bold ? BOLD : ""
+  "#{bold}#{color}#{text}#{CLEAR}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper.html b/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper.html new file mode 100644 index 0000000000..4579dfa7d0 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper.html @@ -0,0 +1,185 @@ +--- +title: ActiveSupport::LogSubscriber::TestHelper +layout: default +--- +
+ +
+
+ +
+ +

Provides some helpers to deal with testing log subscribers by setting up notifications. Take for instance Active Record subscriber tests:

+ +
class SyncLogSubscriberTest < ActiveSupport::TestCase
+  include ActiveSupport::LogSubscriber::TestHelper
+
+  setup do
+    ActiveRecord::LogSubscriber.attach_to(:active_record)
+  end
+
+  def test_basic_query_logging
+    Developer.all.to_a
+    wait
+    assert_equal 1, @logger.logged(:debug).size
+    assert_match(/Developer Load/, @logger.logged(:debug).last)
+    assert_match(/SELECT \* FROM "developers"/, @logger.logged(:debug).last)
+  end
+end
+
+ +

All you need to do is to ensure that your log subscriber is added to Rails::Subscriber, as in the second line of the code above. The test helpers are responsible for setting up the queue and subscriptions, and turning colors in logs off.

+ +

The messages are available in the @logger instance, which is a logger with limited powers (it actually does not send anything to your output), and you can collect them doing @logger.logged(level), where level is the level used in logging, like info, debug, warn, and so on.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + set_logger(logger) + +

+ + +
+

Overwrite if you use another logger in your log subscriber.

+ +
def logger
+  ActiveRecord::Base.logger = @logger
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 101
+def set_logger(logger)
+  ActiveSupport::LogSubscriber.logger = logger
+end
+
+
+ +
+ +
+

+ + wait() + +

+ + +
+

Wait notifications to be published.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 92
+def wait
+  @notifier.wait
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper/MockLogger.html b/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper/MockLogger.html new file mode 100644 index 0000000000..ebd3f56e6f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/LogSubscriber/TestHelper/MockLogger.html @@ -0,0 +1,267 @@ +--- +title: ActiveSupport::LogSubscriber::TestHelper::MockLogger +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + ActiveSupport::Logger::Severity + +
  • + +
+ + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + flush_count
+ [RW] + level
+ + + + +

Class Public methods

+ +
+

+ + new(level = DEBUG) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 60
+def initialize(level = DEBUG)
+  @flush_count = 0
+  @level = level
+  @logged = Hash.new { |h, k| h[k] = [] }
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + flush() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 78
+def flush
+  @flush_count += 1
+end
+
+
+ +
+ +
+

+ + logged(level) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 74
+def logged(level)
+  @logged[level].compact.map { |l| l.to_s.strip }
+end
+
+
+ +
+ +
+

+ + method_missing(level, message = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/log_subscriber/test_helper.rb, line 66
+def method_missing(level, message = nil)
+  if block_given?
+    @logged[level] << yield
+  else
+    @logged[level] << message
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Logger.html b/src/7.0/classes/ActiveSupport/Logger.html new file mode 100644 index 0000000000..8166b38e68 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Logger.html @@ -0,0 +1,189 @@ +--- +title: ActiveSupport::Logger +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + logger_outputs_to?(logger, *sources) + +

+ + +
+

Returns true if the logger destination matches one of the sources

+ +
logger = Logger.new(STDOUT)
+ActiveSupport::Logger.logger_outputs_to?(logger, STDOUT)
+# => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/logger.rb, line 16
+def self.logger_outputs_to?(logger, *sources)
+  logdev = logger.instance_variable_get(:@logdev)
+  logger_source = logdev.dev if logdev.respond_to?(:dev)
+  sources.any? { |source| source == logger_source }
+end
+
+
+ +
+ +
+

+ + new(*args, **kwargs) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/logger.rb, line 80
+def initialize(*args, **kwargs)
+  super
+  @formatter = SimpleFormatter.new
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Logger/SimpleFormatter.html b/src/7.0/classes/ActiveSupport/Logger/SimpleFormatter.html new file mode 100644 index 0000000000..06945ac5c1 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Logger/SimpleFormatter.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::Logger::SimpleFormatter +layout: default +--- +
+ +
+
+ +
+ +

Simple formatter which only displays the message.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + call(severity, timestamp, progname, msg) + +

+ + +
+

This method is invoked when a log event occurs

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/logger.rb, line 88
+def call(severity, timestamp, progname, msg)
+  "#{String === msg ? msg : msg.inspect}\n"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/LoggerSilence.html b/src/7.0/classes/ActiveSupport/LoggerSilence.html new file mode 100644 index 0000000000..756e1bd3cd --- /dev/null +++ b/src/7.0/classes/ActiveSupport/LoggerSilence.html @@ -0,0 +1,101 @@ +--- +title: ActiveSupport::LoggerSilence +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + silence(severity = Logger::ERROR) + +

+ + +
+

Silences the logger for the duration of the block.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/logger_silence.rb, line 17
+def silence(severity = Logger::ERROR)
+  silencer ? log_at(severity) { yield self } : yield(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/MessageEncryptor.html b/src/7.0/classes/ActiveSupport/MessageEncryptor.html new file mode 100644 index 0000000000..4b08d65dc3 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/MessageEncryptor.html @@ -0,0 +1,353 @@ +--- +title: ActiveSupport::MessageEncryptor +layout: default +--- +
+ +
+
+ +
+ +

MessageEncryptor is a simple way to encrypt values which get stored somewhere you don’t trust.

+ +

The cipher text and initialization vector are base64 encoded and returned to you.

+ +

This can be used in situations similar to the MessageVerifier, but where you don’t want users to be able to determine the value of the payload.

+ +
len   = ActiveSupport::MessageEncryptor.key_len
+salt  = SecureRandom.random_bytes(len)
+key   = ActiveSupport::KeyGenerator.new('password').generate_key(salt, len) # => "\x89\xE0\x156\xAC..."
+crypt = ActiveSupport::MessageEncryptor.new(key)                            # => #<ActiveSupport::MessageEncryptor ...>
+encrypted_data = crypt.encrypt_and_sign('my secret data')                   # => "NlFBTTMwOUV5UlA1QlNEN2xkY2d6eThYWWh..."
+crypt.decrypt_and_verify(encrypted_data)                                    # => "my secret data"
+
+ +

The decrypt_and_verify method will raise an ActiveSupport::MessageEncryptor::InvalidMessage exception if the data provided cannot be decrypted or verified.

+ +
crypt.decrypt_and_verify('not encrypted data') # => ActiveSupport::MessageEncryptor::InvalidMessage
+
+ +

Confining messages to a specific purpose

+ +

By default any message can be used throughout your app. But they can also be confined to a specific :purpose.

+ +
token = crypt.encrypt_and_sign("this is the chair", purpose: :login)
+
+ +

Then that same purpose must be passed when verifying to get the data back out:

+ +
crypt.decrypt_and_verify(token, purpose: :login)    # => "this is the chair"
+crypt.decrypt_and_verify(token, purpose: :shipping) # => nil
+crypt.decrypt_and_verify(token)                     # => nil
+
+ +

Likewise, if a message has no purpose it won’t be returned when verifying with a specific purpose.

+ +
token = crypt.encrypt_and_sign("the conversation is lively")
+crypt.decrypt_and_verify(token, purpose: :scare_tactics) # => nil
+crypt.decrypt_and_verify(token)                          # => "the conversation is lively"
+
+ +

Making messages expire

+ +

By default messages last forever and verifying one year from now will still return the original value. But messages can be set to expire at a given time with :expires_in or :expires_at.

+ +
crypt.encrypt_and_sign(parcel, expires_in: 1.month)
+crypt.encrypt_and_sign(doowad, expires_at: Time.now.end_of_year)
+
+ +

Then the messages can be verified and returned up to the expire time. Thereafter, verifying returns nil.

+ +

Rotating keys

+ +

MessageEncryptor also supports rotating out old configurations by falling back to a stack of encryptors. Call rotate to build and add an encryptor so decrypt_and_verify will also try the fallback.

+ +

By default any rotated encryptors use the values of the primary encryptor unless specified otherwise.

+ +

You’d give your encryptor the new defaults:

+ +
crypt = ActiveSupport::MessageEncryptor.new(@secret, cipher: "aes-256-gcm")
+
+ +

Then gradually rotate the old values out by adding them as fallbacks. Any message generated with the old values will then work until the rotation is removed.

+ +
crypt.rotate old_secret            # Fallback to an old secret instead of @secret.
+crypt.rotate cipher: "aes-256-cbc" # Fallback to an old cipher instead of aes-256-gcm.
+
+ +

Though if both the secret and the cipher was changed at the same time, the above should be combined into:

+ +
crypt.rotate old_secret, cipher: "aes-256-cbc"
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
OpenSSLCipherError=OpenSSL::Cipher::CipherError
 
+ + + + + + +

Class Public methods

+ +
+

+ + key_len(cipher = default_cipher) + +

+ + +
+

Given a cipher, returns the key length of the cipher to help generate the key of desired size

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_encryptor.rb, line 164
+def self.key_len(cipher = default_cipher)
+  OpenSSL::Cipher.new(cipher).key_len
+end
+
+
+ +
+ +
+

+ + new(secret, sign_secret = nil, cipher: nil, digest: nil, serializer: nil) + +

+ + +
+

Initialize a new MessageEncryptor. secret must be at least as long as the cipher key size. For the default ‘aes-256-gcm’ cipher, this is 256 bits. If you are using a user-entered secret, you can generate a suitable key by using ActiveSupport::KeyGenerator or a similar key derivation function.

+ +

First additional parameter is used as the signature key for MessageVerifier. This allows you to specify keys to encrypt and sign data.

+ +
ActiveSupport::MessageEncryptor.new('secret', 'signature_secret')
+
+ +

Options:

+
  • +

    :cipher - Cipher to use. Can be any cipher returned by OpenSSL::Cipher.ciphers. Default is ‘aes-256-gcm’.

    +
  • +

    :digest - String of digest to use for signing. Default is SHA1. Ignored when using an AEAD cipher like ‘aes-256-gcm’.

    +
  • +

    :serializer - Object serializer to use. Default is Marshal.

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_encryptor.rb, line 142
+def initialize(secret, sign_secret = nil, cipher: nil, digest: nil, serializer: nil)
+  @secret = secret
+  @sign_secret = sign_secret
+  @cipher = cipher || self.class.default_cipher
+  @digest = digest || "SHA1" unless aead_mode?
+  @verifier = resolve_verifier
+  @serializer = serializer || Marshal
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + decrypt_and_verify(data, purpose: nil, **) + +

+ + +
+

Decrypt and verify a message. We need to verify the message in order to avoid padding attacks. Reference: www.limited-entropy.com/padding-oracle-attacks/.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_encryptor.rb, line 159
+def decrypt_and_verify(data, purpose: nil, **)
+  _decrypt(verifier.verify(data), purpose)
+end
+
+
+ +
+ +
+

+ + encrypt_and_sign(value, expires_at: nil, expires_in: nil, purpose: nil) + +

+ + +
+

Encrypt and sign a message. We need to sign the message in order to avoid padding attacks. Reference: www.limited-entropy.com/padding-oracle-attacks/.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_encryptor.rb, line 153
+def encrypt_and_sign(value, expires_at: nil, expires_in: nil, purpose: nil)
+  verifier.generate(_encrypt(value, expires_at: expires_at, expires_in: expires_in, purpose: purpose))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/MessageEncryptor/InvalidMessage.html b/src/7.0/classes/ActiveSupport/MessageEncryptor/InvalidMessage.html new file mode 100644 index 0000000000..c7d5d210ca --- /dev/null +++ b/src/7.0/classes/ActiveSupport/MessageEncryptor/InvalidMessage.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::MessageEncryptor::InvalidMessage +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/MessageVerifier.html b/src/7.0/classes/ActiveSupport/MessageVerifier.html new file mode 100644 index 0000000000..a380b73495 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/MessageVerifier.html @@ -0,0 +1,435 @@ +--- +title: ActiveSupport::MessageVerifier +layout: default +--- +
+ +
+
+ +
+ +

MessageVerifier makes it easy to generate and verify messages which are signed to prevent tampering.

+ +

This is useful for cases like remember-me tokens and auto-unsubscribe links where the session store isn’t suitable or available.

+ +

Remember Me:

+ +
cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])
+
+ +

In the authentication filter:

+ +
id, time = @verifier.verify(cookies[:remember_me])
+if Time.now < time
+  self.current_user = User.find(id)
+end
+
+ +

By default it uses Marshal to serialize the message. If you want to use another serialization method, you can set the serializer in the options hash upon initialization:

+ +
@verifier = ActiveSupport::MessageVerifier.new('s3Krit', serializer: YAML)
+
+ +

MessageVerifier creates HMAC signatures using SHA1 hash algorithm by default. If you want to use a different hash algorithm, you can change it by providing :digest key as an option while initializing the verifier:

+ +
@verifier = ActiveSupport::MessageVerifier.new('s3Krit', digest: 'SHA256')
+
+ +

Confining messages to a specific purpose

+ +

By default any message can be used throughout your app. But they can also be confined to a specific :purpose.

+ +
token = @verifier.generate("this is the chair", purpose: :login)
+
+ +

Then that same purpose must be passed when verifying to get the data back out:

+ +
@verifier.verified(token, purpose: :login)    # => "this is the chair"
+@verifier.verified(token, purpose: :shipping) # => nil
+@verifier.verified(token)                     # => nil
+
+@verifier.verify(token, purpose: :login)      # => "this is the chair"
+@verifier.verify(token, purpose: :shipping)   # => ActiveSupport::MessageVerifier::InvalidSignature
+@verifier.verify(token)                       # => ActiveSupport::MessageVerifier::InvalidSignature
+
+ +

Likewise, if a message has no purpose it won’t be returned when verifying with a specific purpose.

+ +
token = @verifier.generate("the conversation is lively")
+@verifier.verified(token, purpose: :scare_tactics) # => nil
+@verifier.verified(token)                          # => "the conversation is lively"
+
+@verifier.verify(token, purpose: :scare_tactics)   # => ActiveSupport::MessageVerifier::InvalidSignature
+@verifier.verify(token)                            # => "the conversation is lively"
+
+ +

Making messages expire

+ +

By default messages last forever and verifying one year from now will still return the original value. But messages can be set to expire at a given time with :expires_in or :expires_at.

+ +
@verifier.generate("parcel", expires_in: 1.month)
+@verifier.generate("doowad", expires_at: Time.now.end_of_year)
+
+ +

Then the messages can be verified and returned up to the expire time. Thereafter, the verified method returns nil while verify raises ActiveSupport::MessageVerifier::InvalidSignature.

+ +

Rotating keys

+ +

MessageVerifier also supports rotating out old configurations by falling back to a stack of verifiers. Call rotate to build and add a verifier so either verified or verify will also try verifying with the fallback.

+ +

By default any rotated verifiers use the values of the primary verifier unless specified otherwise.

+ +

You’d give your verifier the new defaults:

+ +
verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512", serializer: JSON)
+
+ +

Then gradually rotate the old values out by adding them as fallbacks. Any message generated with the old values will then work until the rotation is removed.

+ +
verifier.rotate old_secret          # Fallback to an old secret instead of @secret.
+verifier.rotate digest: "SHA256"    # Fallback to an old digest instead of SHA512.
+verifier.rotate serializer: Marshal # Fallback to an old serializer instead of JSON.
+
+ +

Though the above would most likely be combined into one rotation:

+ +
verifier.rotate old_secret, digest: "SHA256", serializer: Marshal
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(secret, digest: nil, serializer: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_verifier.rb, line 110
+def initialize(secret, digest: nil, serializer: nil)
+  raise ArgumentError, "Secret should not be nil." unless secret
+  @secret = secret
+  @digest = digest&.to_s || "SHA1"
+  @serializer = serializer || Marshal
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + generate(value, expires_at: nil, expires_in: nil, purpose: nil) + +

+ + +
+

Generates a signed message for the provided value.

+ +

The message is signed with the MessageVerifier‘s secret. Returns Base64-encoded message joined with the generated signature.

+ +
verifier = ActiveSupport::MessageVerifier.new 's3Krit'
+verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_verifier.rb, line 188
+def generate(value, expires_at: nil, expires_in: nil, purpose: nil)
+  data = encode(Messages::Metadata.wrap(@serializer.dump(value), expires_at: expires_at, expires_in: expires_in, purpose: purpose))
+  "#{data}#{SEPARATOR}#{generate_digest(data)}"
+end
+
+
+ +
+ +
+

+ + valid_message?(signed_message) + +

+ + +
+

Checks if a signed message could have been generated by signing an object with the MessageVerifier‘s secret.

+ +
verifier = ActiveSupport::MessageVerifier.new 's3Krit'
+signed_message = verifier.generate 'a private message'
+verifier.valid_message?(signed_message) # => true
+
+tampered_message = signed_message.chop # editing the message invalidates the signature
+verifier.valid_message?(tampered_message) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_verifier.rb, line 126
+def valid_message?(signed_message)
+  data, digest = get_data_and_digest_from(signed_message)
+  digest_matches_data?(digest, data)
+end
+
+
+ +
+ +
+

+ + verified(signed_message, purpose: nil, **) + +

+ + +
+

Decodes the signed message using the MessageVerifier‘s secret.

+ +
verifier = ActiveSupport::MessageVerifier.new 's3Krit'
+
+signed_message = verifier.generate 'a private message'
+verifier.verified(signed_message) # => 'a private message'
+
+ +

Returns nil if the message was not signed with the same secret.

+ +
other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
+other_verifier.verified(signed_message) # => nil
+
+ +

Returns nil if the message is not Base64-encoded.

+ +
invalid_message = "f--46a0120593880c733a53b6dad75b42ddc1c8996d"
+verifier.verified(invalid_message) # => nil
+
+ +

Raises any error raised while decoding the signed message.

+ +
incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff"
+verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_verifier.rb, line 152
+def verified(signed_message, purpose: nil, **)
+  data, digest = get_data_and_digest_from(signed_message)
+  if digest_matches_data?(digest, data)
+    begin
+      message = Messages::Metadata.verify(decode(data), purpose)
+      @serializer.load(message) if message
+    rescue ArgumentError => argument_error
+      return if argument_error.message.include?("invalid base64")
+      raise
+    end
+  end
+end
+
+
+ +
+ +
+

+ + verify(*args, **options) + +

+ + +
+

Decodes the signed message using the MessageVerifier‘s secret.

+ +
verifier = ActiveSupport::MessageVerifier.new 's3Krit'
+signed_message = verifier.generate 'a private message'
+
+verifier.verify(signed_message) # => 'a private message'
+
+ +

Raises InvalidSignature if the message was not signed with the same secret or was not Base64-encoded.

+ +
other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
+other_verifier.verify(signed_message) # => ActiveSupport::MessageVerifier::InvalidSignature
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/message_verifier.rb, line 177
+def verify(*args, **options)
+  verified(*args, **options) || raise(InvalidSignature)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/MessageVerifier/InvalidSignature.html b/src/7.0/classes/ActiveSupport/MessageVerifier/InvalidSignature.html new file mode 100644 index 0000000000..9bb5e2865a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/MessageVerifier/InvalidSignature.html @@ -0,0 +1,60 @@ +--- +title: ActiveSupport::MessageVerifier::InvalidSignature +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Messages.html b/src/7.0/classes/ActiveSupport/Messages.html new file mode 100644 index 0000000000..c8299dca9d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Messages.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::Messages +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Messages/Rotator.html b/src/7.0/classes/ActiveSupport/Messages/Rotator.html new file mode 100644 index 0000000000..37f7b045d5 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Messages/Rotator.html @@ -0,0 +1,69 @@ +--- +title: ActiveSupport::Messages::Rotator +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Messages/Rotator/Encryptor.html b/src/7.0/classes/ActiveSupport/Messages/Rotator/Encryptor.html new file mode 100644 index 0000000000..19ee55fb4b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Messages/Rotator/Encryptor.html @@ -0,0 +1,117 @@ +--- +title: ActiveSupport::Messages::Rotator::Encryptor +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + decrypt_and_verify(*args, on_rotation: @on_rotation, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/messages/rotator.rb, line 21
+def decrypt_and_verify(*args, on_rotation: @on_rotation, **options)
+  super
+rescue MessageEncryptor::InvalidMessage, MessageVerifier::InvalidSignature
+  run_rotations(on_rotation) { |encryptor| encryptor.decrypt_and_verify(*args, **options) } || raise
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Messages/Rotator/Verifier.html b/src/7.0/classes/ActiveSupport/Messages/Rotator/Verifier.html new file mode 100644 index 0000000000..9139e09286 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Messages/Rotator/Verifier.html @@ -0,0 +1,115 @@ +--- +title: ActiveSupport::Messages::Rotator::Verifier +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + verified(*args, on_rotation: @on_rotation, **options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/messages/rotator.rb, line 36
+def verified(*args, on_rotation: @on_rotation, **options)
+  super || run_rotations(on_rotation) { |verifier| verifier.verified(*args, **options) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Multibyte.html b/src/7.0/classes/ActiveSupport/Multibyte.html new file mode 100644 index 0000000000..64950d4748 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Multibyte.html @@ -0,0 +1,167 @@ +--- +title: ActiveSupport::Multibyte +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + proxy_class() + +

+ + +
+

Returns the current proxy class.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte.rb, line 19
+def self.proxy_class
+  @proxy_class ||= ActiveSupport::Multibyte::Chars
+end
+
+
+ +
+ +
+

+ + proxy_class=(klass) + +

+ + +
+

The proxy class returned when calling mb_chars. You can use this accessor to configure your own proxy class so you can support other encodings. See the ActiveSupport::Multibyte::Chars implementation for an example how to do this.

+ +
ActiveSupport::Multibyte.proxy_class = CharsForUTF32
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte.rb, line 14
+def self.proxy_class=(klass)
+  @proxy_class = klass
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Multibyte/Chars.html b/src/7.0/classes/ActiveSupport/Multibyte/Chars.html new file mode 100644 index 0000000000..a7e3c7f9a4 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Multibyte/Chars.html @@ -0,0 +1,688 @@ +--- +title: ActiveSupport::Multibyte::Chars +layout: default +--- +
+ +
+
+ +
+ +

Chars enables you to work transparently with UTF-8 encoding in the Ruby String class without having extensive knowledge about the encoding. A Chars object accepts a string upon initialization and proxies String methods in an encoding safe manner. All the normal String methods are also implemented on the proxy.

+ +

String methods are proxied through the Chars object, and can be accessed through the mb_chars method. Methods which would normally return a String object now return a Chars object so methods can be chained.

+ +
'The Perfect String  '.mb_chars.downcase.strip
+# => #<ActiveSupport::Multibyte::Chars:0x007fdc434ccc10 @wrapped_string="the perfect string">
+
+ +

Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made. If certain methods do explicitly check the class, call to_s before you pass chars objects to them.

+ +
bad.explicit_checking_method 'T'.mb_chars.downcase.to_s
+
+ +

The default Chars implementation assumes that the encoding of the string is UTF-8, if you want to handle different encodings you can write your own multibyte string handler and configure it through ActiveSupport::Multibyte.proxy_class.

+ +
class CharsForUTF32
+  def size
+    @wrapped_string.size / 4
+  end
+
+  def self.accepts?(string)
+    string.length % 4 == 0
+  end
+end
+
+ActiveSupport::Multibyte.proxy_class = CharsForUTF32
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Comparable + +
  • + +
+ + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + to_s
+ [R] + to_str
+ [R] + wrapped_string
+ + + + +

Class Public methods

+ +
+

+ + new(string) + +

+ + +
+

Creates a new Chars instance by wrapping string.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 54
+def initialize(string)
+  @wrapped_string = string
+  @wrapped_string.force_encoding(Encoding::UTF_8) unless @wrapped_string.frozen?
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + compose() + +

+ + +
+

Performs composition on all the characters.

+ +
'é'.length                       # => 1
+'é'.mb_chars.compose.to_s.length # => 1
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 138
+def compose
+  chars(Unicode.compose(@wrapped_string.codepoints.to_a).pack("U*"))
+end
+
+
+ +
+ +
+

+ + decompose() + +

+ + +
+

Performs canonical decomposition on all the characters.

+ +
'é'.length                         # => 1
+'é'.mb_chars.decompose.to_s.length # => 2
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 130
+def decompose
+  chars(Unicode.decompose(:canonical, @wrapped_string.codepoints.to_a).pack("U*"))
+end
+
+
+ +
+ +
+

+ + grapheme_length() + +

+ + +
+

Returns the number of grapheme clusters in the string.

+ +
'क्षि'.mb_chars.length   # => 4
+'क्षि'.mb_chars.grapheme_length # => 2
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 146
+def grapheme_length
+  @wrapped_string.grapheme_clusters.length
+end
+
+
+ +
+ +
+

+ + limit(limit) + +

+ + +
+

Limits the byte size of the string to a number of bytes without breaking characters. Usable when the storage for a string is limited for some reason.

+ +
'こんにちは'.mb_chars.limit(7).to_s # => "こん"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 113
+def limit(limit)
+  chars(@wrapped_string.truncate_bytes(limit, omission: nil))
+end
+
+
+ +
+ +
+

+ + method_missing(method, *args, &block) + +

+ + +
+

Forward all undefined methods to the wrapped string.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 60
+def method_missing(method, *args, &block)
+  result = @wrapped_string.__send__(method, *args, &block)
+  if method.end_with?("!")
+    self if result
+  else
+    result.kind_of?(String) ? chars(result) : result
+  end
+end
+
+
+ +
+ +
+

+ + respond_to_missing?(method, include_private) + +

+ + +
+

Returns true if obj responds to the given method. Private methods are included in the search only if the optional second parameter evaluates to true.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 72
+def respond_to_missing?(method, include_private)
+  @wrapped_string.respond_to?(method, include_private)
+end
+
+
+ +
+ +
+

+ + reverse() + +

+ + +
+

Reverses all characters in the string.

+ +
'Café'.mb_chars.reverse.to_s # => 'éfaC'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 104
+def reverse
+  chars(@wrapped_string.grapheme_clusters.reverse.join)
+end
+
+
+ +
+ +
+

+ + slice!(*args) + +

+ + +
+

Works like String#slice!, but returns an instance of Chars, or nil if the string was not modified. The string will not be modified if the range given is out of bounds

+ +
string = 'Welcome'
+string.mb_chars.slice!(3)    # => #<ActiveSupport::Multibyte::Chars:0x000000038109b8 @wrapped_string="c">
+string # => 'Welome'
+string.mb_chars.slice!(0..3) # => #<ActiveSupport::Multibyte::Chars:0x00000002eb80a0 @wrapped_string="Welo">
+string # => 'me'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 94
+def slice!(*args)
+  string_sliced = @wrapped_string.slice!(*args)
+  if string_sliced
+    chars(string_sliced)
+  end
+end
+
+
+ +
+ +
+

+ + split(*args) + +

+ + +
+

Works just like String#split, with the exception that the items in the resulting list are Chars instances instead of String. This makes chaining methods easier.

+ +
'Café périferôl'.mb_chars.split(/é/).map { |part| part.upcase.to_s } # => ["CAF", " P", "RIFERÔL"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 81
+def split(*args)
+  @wrapped_string.split(*args).map { |i| self.class.new(i) }
+end
+
+
+ +
+ +
+

+ + tidy_bytes(force = false) + +

+ + +
+

Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.

+ +

Passing true will forcibly tidy all bytes, assuming that the string’s encoding is entirely CP1252 or ISO-8859-1.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 155
+def tidy_bytes(force = false)
+  chars(Unicode.tidy_bytes(@wrapped_string, force))
+end
+
+
+ +
+ +
+

+ + titlecase() + +

+ + +
+ +
+ + + + + +
+ Alias for: titleize +
+ + + +
+ +
+

+ + titleize() + +

+ + +
+

Capitalizes the first letter of every word, when possible.

+ +
"ÉL QUE SE ENTERÓ".mb_chars.titleize.to_s    # => "Él Que Se Enteró"
+"日本語".mb_chars.titleize.to_s               # => "日本語"
+
+
+ + + +
+ Also aliased as: titlecase +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/chars.rb, line 121
+def titleize
+  chars(downcase.to_s.gsub(/\b('?\S)/u) { $1.upcase })
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Multibyte/Unicode.html b/src/7.0/classes/ActiveSupport/Multibyte/Unicode.html new file mode 100644 index 0000000000..1f54c31a07 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Multibyte/Unicode.html @@ -0,0 +1,205 @@ +--- +title: ActiveSupport::Multibyte::Unicode +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
UNICODE_VERSION=RbConfig::CONFIG["UNICODE_VERSION"]
 

The Unicode version that is supported by the implementation

+ + + + + + + +

Instance Public methods

+ +
+

+ + compose(codepoints) + +

+ + +
+

Compose decomposed characters to the composed form.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/unicode.rb, line 21
+def compose(codepoints)
+  codepoints.pack("U*").unicode_normalize(:nfc).codepoints
+end
+
+
+ +
+ +
+

+ + decompose(type, codepoints) + +

+ + +
+

Decompose composed characters to the decomposed form.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/unicode.rb, line 12
+def decompose(type, codepoints)
+  if type == :compatibility
+    codepoints.pack("U*").unicode_normalize(:nfkd).codepoints
+  else
+    codepoints.pack("U*").unicode_normalize(:nfd).codepoints
+  end
+end
+
+
+ +
+ +
+

+ + tidy_bytes(string, force = false) + +

+ + +
+

Replaces all ISO-8859-1 or CP1252 characters by their UTF-8 equivalent resulting in a valid UTF-8 string.

+ +

Passing true will forcibly tidy all bytes, assuming that the string’s encoding is entirely CP1252 or ISO-8859-1.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/multibyte/unicode.rb, line 32
+def tidy_bytes(string, force = false)
+  return string if string.empty? || string.ascii_only?
+  return recode_windows1252_chars(string) if force
+  string.scrub { |bad| recode_windows1252_chars(bad) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications.html b/src/7.0/classes/ActiveSupport/Notifications.html new file mode 100644 index 0000000000..3f591ef191 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications.html @@ -0,0 +1,584 @@ +--- +title: ActiveSupport::Notifications +layout: default +--- +
+ +
+
+ +
+ +

Notifications

+ +

ActiveSupport::Notifications provides an instrumentation API for Ruby.

+ +

Instrumenters

+ +

To instrument an event you just need to do:

+ +
ActiveSupport::Notifications.instrument('render', extra: :information) do
+  render plain: 'Foo'
+end
+
+ +

That first executes the block and then notifies all subscribers once done.

+ +

In the example above render is the name of the event, and the rest is called the payload. The payload is a mechanism that allows instrumenters to pass extra information to subscribers. Payloads consist of a hash whose contents are arbitrary and generally depend on the event.

+ +

Subscribers

+ +

You can consume those events and the information they provide by registering a subscriber.

+ +
ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
+  name    # => String, name of the event (such as 'render' from above)
+  start   # => Time, when the instrumented block started execution
+  finish  # => Time, when the instrumented block ended execution
+  id      # => String, unique ID for the instrumenter that fired the event
+  payload # => Hash, the payload
+end
+
+ +

Here, the start and finish values represent wall-clock time. If you are concerned about accuracy, you can register a monotonic subscriber.

+ +
ActiveSupport::Notifications.monotonic_subscribe('render') do |name, start, finish, id, payload|
+  name    # => String, name of the event (such as 'render' from above)
+  start   # => Monotonic time, when the instrumented block started execution
+  finish  # => Monotonic time, when the instrumented block ended execution
+  id      # => String, unique ID for the instrumenter that fired the event
+  payload # => Hash, the payload
+end
+
+ +

The start and finish values above represent monotonic time.

+ +

For instance, let’s store all “render” events in an array:

+ +
events = []
+
+ActiveSupport::Notifications.subscribe('render') do |*args|
+  events << ActiveSupport::Notifications::Event.new(*args)
+end
+
+ +

That code returns right away, you are just subscribing to “render” events. The block is saved and will be called whenever someone instruments “render”:

+ +
ActiveSupport::Notifications.instrument('render', extra: :information) do
+  render plain: 'Foo'
+end
+
+event = events.first
+event.name      # => "render"
+event.duration  # => 10 (in milliseconds)
+event.payload   # => { extra: :information }
+
+ +

The block in the subscribe call gets the name of the event, start timestamp, end timestamp, a string with a unique identifier for that event’s instrumenter (something like “535801666f04d0298cd6”), and a hash with the payload, in that order.

+ +

If an exception happens during that particular instrumentation the payload will have a key :exception with an array of two elements as value: a string with the name of the exception class, and the exception message. The :exception_object key of the payload will have the exception itself as the value:

+ +
event.payload[:exception]         # => ["ArgumentError", "Invalid value"]
+event.payload[:exception_object]  # => #<ArgumentError: Invalid value>
+
+ +

As the earlier example depicts, the class ActiveSupport::Notifications::Event is able to take the arguments as they come and provide an object-oriented interface to that data.

+ +

It is also possible to pass an object which responds to call method as the second parameter to the subscribe method instead of a block:

+ +
module ActionController
+  class PageRequest
+    def call(name, started, finished, unique_id, payload)
+      Rails.logger.debug ['notification:', name, started, finished, unique_id, payload].join(' ')
+    end
+  end
+end
+
+ActiveSupport::Notifications.subscribe('process_action.action_controller', ActionController::PageRequest.new)
+
+ +

resulting in the following output within the logs including a hash with the payload:

+ +
notification: process_action.action_controller 2012-04-13 01:08:35 +0300 2012-04-13 01:08:35 +0300 af358ed7fab884532ec7 {
+   controller: "Devise::SessionsController",
+   action: "new",
+   params: {"action"=>"new", "controller"=>"devise/sessions"},
+   format: :html,
+   method: "GET",
+   path: "/login/sign_in",
+   status: 200,
+   view_runtime: 279.3080806732178,
+   db_runtime: 40.053
+ }
+
+ +

You can also subscribe to all events whose name matches a certain regexp:

+ +
ActiveSupport::Notifications.subscribe(/render/) do |*args|
+  ...
+end
+
+ +

and even pass no argument to subscribe, in which case you are subscribing to all events.

+ +

Temporary Subscriptions

+ +

Sometimes you do not want to subscribe to an event for the entire life of the application. There are two ways to unsubscribe.

+ +

WARNING: The instrumentation framework is designed for long-running subscribers, use this feature sparingly because it wipes some internal caches and that has a negative impact on performance.

+ +

Subscribe While a Block Runs

+ +

You can subscribe to some event temporarily while some block runs. For example, in

+ +
callback = lambda {|*args| ... }
+ActiveSupport::Notifications.subscribed(callback, "sql.active_record") do
+  ...
+end
+
+ +

the callback will be called for all “sql.active_record” events instrumented during the execution of the block. The callback is unsubscribed automatically after that.

+ +

To record started and finished values with monotonic time, specify the optional :monotonic option to the subscribed method. The :monotonic option is set to false by default.

+ +
callback = lambda {|name, started, finished, unique_id, payload| ... }
+ActiveSupport::Notifications.subscribed(callback, "sql.active_record", monotonic: true) do
+  ...
+end
+
+ +

Manual Unsubscription

+ +

The subscribe method returns a subscriber object:

+ +
subscriber = ActiveSupport::Notifications.subscribe("render") do |*args|
+  ...
+end
+
+ +

To prevent that block from being called anymore, just unsubscribe passing that reference:

+ +
ActiveSupport::Notifications.unsubscribe(subscriber)
+
+ +

You can also unsubscribe by passing the name of the subscriber object. Note that this will unsubscribe all subscriptions with the given name:

+ +
ActiveSupport::Notifications.unsubscribe("render")
+
+ +

Subscribers using a regexp or other pattern-matching object will remain subscribed to all events that match their original pattern, unless those events match a string passed to unsubscribe:

+ +
subscriber = ActiveSupport::Notifications.subscribe(/render/) { }
+ActiveSupport::Notifications.unsubscribe('render_template.action_view')
+subscriber.matches?('render_template.action_view') # => false
+subscriber.matches?('render_partial.action_view') # => true
+
+ +

Default Queue

+ +

Notifications ships with a queue implementation that consumes and publishes events to all log subscribers. You can use any queue implementation you want.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + notifier
+ + + + +

Class Public methods

+ +
+

+ + instrument(name, payload = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 204
+def instrument(name, payload = {})
+  if notifier.listening?(name)
+    instrumenter.instrument(name, payload) { yield payload if block_given? }
+  else
+    yield payload if block_given?
+  end
+end
+
+
+ +
+ +
+

+ + instrumenter() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 268
+def instrumenter
+  registry[notifier] ||= Instrumenter.new(notifier)
+end
+
+
+ +
+ +
+

+ + monotonic_subscribe(pattern = nil, callback = nil, &block) + +

+ + +
+

Performs the same functionality as subscribe, but the start and finish block arguments are in monotonic time instead of wall-clock time. Monotonic time will not jump forward or backward (due to NTP or Daylights Savings). Use monotonic_subscribe when accuracy of time duration is important. For example, computing elapsed time between two events.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 253
+def monotonic_subscribe(pattern = nil, callback = nil, &block)
+  notifier.subscribe(pattern, callback, monotonic: true, &block)
+end
+
+
+ +
+ +
+

+ + publish(name, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 196
+def publish(name, *args)
+  notifier.publish(name, *args)
+end
+
+
+ +
+ +
+

+ + subscribe(pattern = nil, callback = nil, &block) + +

+ + +
+

Subscribe to a given event name with the passed block.

+ +

You can subscribe to events by passing a String to match exact event names, or by passing a Regexp to match all events that match a pattern.

+ +
ActiveSupport::Notifications.subscribe(/render/) do |*args|
+  @event = ActiveSupport::Notifications::Event.new(*args)
+end
+
+ +

The block will receive five parameters with information about the event:

+ +
ActiveSupport::Notifications.subscribe('render') do |name, start, finish, id, payload|
+  name    # => String, name of the event (such as 'render' from above)
+  start   # => Time, when the instrumented block started execution
+  finish  # => Time, when the instrumented block ended execution
+  id      # => String, unique ID for the instrumenter that fired the event
+  payload # => Hash, the payload
+end
+
+ +

If the block passed to the method only takes one parameter, it will yield an event object to the block:

+ +
ActiveSupport::Notifications.subscribe(/render/) do |event|
+  @event = event
+end
+
+ +

Raises an error if invalid event name type is passed:

+ +
ActiveSupport::Notifications.subscribe(:render) {|*args| ...}
+#=> ArgumentError (pattern must be specified as a String, Regexp or empty)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 243
+def subscribe(pattern = nil, callback = nil, &block)
+  notifier.subscribe(pattern, callback, monotonic: false, &block)
+end
+
+
+ +
+ +
+

+ + subscribed(callback, pattern = nil, monotonic: false, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 257
+def subscribed(callback, pattern = nil, monotonic: false, &block)
+  subscriber = notifier.subscribe(pattern, callback, monotonic: monotonic)
+  yield
+ensure
+  unsubscribe(subscriber)
+end
+
+
+ +
+ +
+

+ + unsubscribe(subscriber_or_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications.rb, line 264
+def unsubscribe(subscriber_or_name)
+  notifier.unsubscribe(subscriber_or_name)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Event.html b/src/7.0/classes/ActiveSupport/Notifications/Event.html new file mode 100644 index 0000000000..0b44f9bd4b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Event.html @@ -0,0 +1,548 @@ +--- +title: ActiveSupport::Notifications::Event +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + children
+ [R] + end
+ [R] + name
+ [RW] + payload
+ [R] + time
+ [R] + transaction_id
+ + + + +

Class Public methods

+ +
+

+ + new(name, start, ending, transaction_id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 62
+def initialize(name, start, ending, transaction_id, payload)
+  @name           = name
+  @payload        = payload.dup
+  @time           = start ? start.to_f * 1_000.0 : start
+  @transaction_id = transaction_id
+  @end            = ending ? ending.to_f * 1_000.0 : ending
+  @children       = []
+  @cpu_time_start = 0.0
+  @cpu_time_finish = 0.0
+  @allocation_count_start = 0
+  @allocation_count_finish = 0
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 136
+def <<(event)
+  @children << event
+end
+
+
+ +
+ +
+

+ + allocations() + +

+ + +
+

Returns the number of allocations made since the call to start! and the call to finish!

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 116
+def allocations
+  @allocation_count_finish - @allocation_count_start
+end
+
+
+ +
+ +
+

+ + cpu_time() + +

+ + +
+

Returns the CPU time (in milliseconds) passed since the call to start! and the call to finish!

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 104
+def cpu_time
+  @cpu_time_finish - @cpu_time_start
+end
+
+
+ +
+ +
+

+ + duration() + +

+ + +
+

Returns the difference in milliseconds between when the execution of the event started and when it ended.

+ +
ActiveSupport::Notifications.subscribe('wait') do |*args|
+  @event = ActiveSupport::Notifications::Event.new(*args)
+end
+
+ActiveSupport::Notifications.instrument('wait') do
+  sleep 1
+end
+
+@event.duration # => 1000.138
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 132
+def duration
+  self.end - time
+end
+
+
+ +
+ +
+

+ + finish!() + +

+ + +
+

Record information at the time this event finishes

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 96
+def finish!
+  @cpu_time_finish = now_cpu
+  @end = now
+  @allocation_count_finish = now_allocations
+end
+
+
+ +
+ +
+

+ + idle_time() + +

+ + +
+

Returns the idle time time (in milliseconds) passed since the call to start! and the call to finish!

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 110
+def idle_time
+  duration - cpu_time
+end
+
+
+ +
+ +
+

+ + parent_of?(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 140
+def parent_of?(event)
+  @children.include? event
+end
+
+
+ +
+ +
+

+ + record() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 75
+def record
+  start!
+  begin
+    yield payload if block_given?
+  rescue Exception => e
+    payload[:exception] = [e.class.name, e.message]
+    payload[:exception_object] = e
+    raise e
+  ensure
+    finish!
+  end
+end
+
+
+ +
+ +
+

+ + start!() + +

+ + +
+

Record information at the time this event starts

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 89
+def start!
+  @time = now
+  @cpu_time_start = now_cpu
+  @allocation_count_start = now_allocations
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Fanout.html b/src/7.0/classes/ActiveSupport/Notifications/Fanout.html new file mode 100644 index 0000000000..c0fabec6f1 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Fanout.html @@ -0,0 +1,586 @@ +--- +title: ActiveSupport::Notifications::Fanout +layout: default +--- +
+ +
+
+ +
+ +

This is a default queue implementation that ships with Notifications. It just pushes events to all registered log subscribers.

+ +

This class is thread safe. All methods are reentrant.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Mutex_m + +
  • + +
+ + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 27
+def initialize
+  @string_subscribers = Hash.new { |h, k| h[k] = [] }
+  @other_subscribers = []
+  @listeners_for = Concurrent::Map.new
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finish(name, id, payload, listeners = listeners_for(name)) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 75
+def finish(name, id, payload, listeners = listeners_for(name))
+  iterate_guarding_exceptions(listeners) { |s| s.finish(name, id, payload) }
+end
+
+
+ +
+ +
+

+ + iterate_guarding_exceptions(listeners) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 87
+def iterate_guarding_exceptions(listeners)
+  exceptions = nil
+
+  listeners.each do |s|
+    yield s
+  rescue Exception => e
+    exceptions ||= []
+    exceptions << e
+  end
+
+  if exceptions
+    if exceptions.size == 1
+      raise exceptions.first
+    else
+      raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
+    end
+  end
+
+  listeners
+end
+
+
+ +
+ +
+

+ + listeners_for(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 108
+def listeners_for(name)
+  # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics)
+  @listeners_for[name] || synchronize do
+    # use synchronisation when accessing @subscribers
+    @listeners_for[name] ||=
+      @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) }
+  end
+end
+
+
+ +
+ +
+

+ + listening?(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 117
+def listening?(name)
+  listeners_for(name).any?
+end
+
+
+ +
+ +
+

+ + publish(name, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 79
+def publish(name, *args)
+  iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, *args) }
+end
+
+
+ +
+ +
+

+ + publish_event(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 83
+def publish_event(event)
+  iterate_guarding_exceptions(listeners_for(event.name)) { |s| s.publish_event(event) }
+end
+
+
+ +
+ +
+

+ + start(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 71
+def start(name, id, payload)
+  iterate_guarding_exceptions(listeners_for(name)) { |s| s.start(name, id, payload) }
+end
+
+
+ +
+ +
+

+ + subscribe(pattern = nil, callable = nil, monotonic: false, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 34
+def subscribe(pattern = nil, callable = nil, monotonic: false, &block)
+  subscriber = Subscribers.new(pattern, callable || block, monotonic)
+  synchronize do
+    case pattern
+    when String
+      @string_subscribers[pattern] << subscriber
+      @listeners_for.delete(pattern)
+    when NilClass, Regexp
+      @other_subscribers << subscriber
+      @listeners_for.clear
+    else
+      raise ArgumentError,  "pattern must be specified as a String, Regexp or empty"
+    end
+  end
+  subscriber
+end
+
+
+ +
+ +
+

+ + unsubscribe(subscriber_or_name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 51
+def unsubscribe(subscriber_or_name)
+  synchronize do
+    case subscriber_or_name
+    when String
+      @string_subscribers[subscriber_or_name].clear
+      @listeners_for.delete(subscriber_or_name)
+      @other_subscribers.each { |sub| sub.unsubscribe!(subscriber_or_name) }
+    else
+      pattern = subscriber_or_name.try(:pattern)
+      if String === pattern
+        @string_subscribers[pattern].delete(subscriber_or_name)
+        @listeners_for.delete(pattern)
+      else
+        @other_subscribers.delete(subscriber_or_name)
+        @listeners_for.clear
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + wait() + +

+ + +
+

This is a sync queue, so there is no waiting.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 122
+def wait
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers.html b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers.html new file mode 100644 index 0000000000..9564df720a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers.html @@ -0,0 +1,69 @@ +--- +title: ActiveSupport::Notifications::Fanout::Subscribers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/EventObject.html b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/EventObject.html new file mode 100644 index 0000000000..4a5ce79135 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/EventObject.html @@ -0,0 +1,192 @@ +--- +title: ActiveSupport::Notifications::Fanout::Subscribers::EventObject +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + finish(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 265
+def finish(name, id, payload)
+  stack = IsolatedExecutionState[:_event_stack]
+  event = stack.pop
+  event.payload = payload
+  event.finish!
+  @delegate.call event
+end
+
+
+ +
+ +
+

+ + publish_event(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 273
+def publish_event(event)
+  @delegate.call event
+end
+
+
+ +
+ +
+

+ + start(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 258
+def start(name, id, payload)
+  stack = IsolatedExecutionState[:_event_stack] ||= []
+  event = build_event name, id, payload
+  event.start!
+  stack.push event
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher.html b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher.html new file mode 100644 index 0000000000..5727477f8e --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::Notifications::Fanout::Subscribers::Matcher +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher/AllMessages.html b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher/AllMessages.html new file mode 100644 index 0000000000..ad7a167178 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Fanout/Subscribers/Matcher/AllMessages.html @@ -0,0 +1,146 @@ +--- +title: ActiveSupport::Notifications::Fanout::Subscribers::Matcher::AllMessages +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + ===(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 172
+def ===(name)
+  true
+end
+
+
+ +
+ +
+

+ + unsubscribe!(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 176
+def unsubscribe!(*)
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/InstrumentationSubscriberError.html b/src/7.0/classes/ActiveSupport/Notifications/InstrumentationSubscriberError.html new file mode 100644 index 0000000000..54053f76b5 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/InstrumentationSubscriberError.html @@ -0,0 +1,123 @@ +--- +title: ActiveSupport::Notifications::InstrumentationSubscriberError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + exceptions
+ + + + +

Class Public methods

+ +
+

+ + new(exceptions) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/fanout.rb, line 13
+def initialize(exceptions)
+  @exceptions = exceptions
+  exception_class_names = exceptions.map { |e| e.class.name }
+  super "Exception(s) occurred within instrumentation subscribers: #{exception_class_names.join(', ')}"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Notifications/Instrumenter.html b/src/7.0/classes/ActiveSupport/Notifications/Instrumenter.html new file mode 100644 index 0000000000..59104e56e7 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Notifications/Instrumenter.html @@ -0,0 +1,297 @@ +--- +title: ActiveSupport::Notifications::Instrumenter +layout: default +--- +
+ +
+
+ +
+ +

Instrumenters are stored in a thread local.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + id
+ + + + +

Class Public methods

+ +
+

+ + new(notifier) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 11
+def initialize(notifier)
+  @id       = unique_id
+  @notifier = notifier
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finish(name, payload) + +

+ + +
+

Send a finish notification with name and payload.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 44
+def finish(name, payload)
+  @notifier.finish name, @id, payload
+end
+
+
+ +
+ +
+

+ + finish_with_state(listeners_state, name, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 48
+def finish_with_state(listeners_state, name, payload)
+  @notifier.finish name, @id, payload, listeners_state
+end
+
+
+ +
+ +
+

+ + instrument(name, payload = {}) + +

+ + +
+

Given a block, instrument it by measuring the time taken to execute and publish it. Without a block, simply send a message via the notifier. Notice that events get sent even if an error occurs in the passed-in block.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 20
+def instrument(name, payload = {})
+  # some of the listeners might have state
+  listeners_state = start name, payload
+  begin
+    yield payload if block_given?
+  rescue Exception => e
+    payload[:exception] = [e.class.name, e.message]
+    payload[:exception_object] = e
+    raise e
+  ensure
+    finish_with_state listeners_state, name, payload
+  end
+end
+
+
+ +
+ +
+

+ + start(name, payload) + +

+ + +
+

Send a start notification with name and payload.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/notifications/instrumenter.rb, line 39
+def start(name, payload)
+  @notifier.start name, @id, payload
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/NumberHelper.html b/src/7.0/classes/ActiveSupport/NumberHelper.html new file mode 100644 index 0000000000..0115ab162a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/NumberHelper.html @@ -0,0 +1,664 @@ +--- +title: ActiveSupport::NumberHelper +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + number_to_currency(number, options = {}) + +

+ + +
+

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).

    +
  • +

    :round_mode - Determine how rounding is performed (defaults to :default. See BigDecimal::mode)

    +
  • +

    :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.

    +
  • +

    :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 €"
+number_to_currency('123a456')                    # => "$123a456"
+
+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: '&pound;', separator: ',', delimiter: '')
+# => "&pound;1234567890,50"
+number_to_currency(1234567890.50, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
+# => "1234567890,50 &pound;"
+number_to_currency(1234567890.50, strip_insignificant_zeros: true)
+# => "$1,234,567,890.5"
+number_to_currency(1234567890.50, precision: 0, round_mode: :up)
+# => "$1,234,567,891"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 114
+def number_to_currency(number, options = {})
+  NumberToCurrencyConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_delimited(number, options = {}) + +

+ + +
+

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.

    +
+ +

Examples

+ +
number_to_delimited(12345678)                    # => "12,345,678"
+number_to_delimited('123456')                    # => "123,456"
+number_to_delimited(12345678.05)                 # => "12,345,678.05"
+number_to_delimited(12345678, delimiter: '.')    # => "12.345.678"
+number_to_delimited(12345678, delimiter: ',')    # => "12,345,678"
+number_to_delimited(12345678.05, separator: ' ') # => "12,345,678 05"
+number_to_delimited(12345678.05, locale: :fr)    # => "12 345 678,05"
+number_to_delimited('112a')                      # => "112a"
+number_to_delimited(98765432.98, delimiter: ' ', separator: ',')
+                                                 # => "98 765 432,98"
+number_to_delimited("123456.78",
+  delimiter_pattern: /(\d+?)(?=(\d\d)+(\d)(?!\d))/)
+                                                 # => "1,23,456.78"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 189
+def number_to_delimited(number, options = {})
+  NumberToDelimitedConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_human(number, options = {}) + +

+ + +
+

Pretty prints (formats and approximates) a number in a way it is more readable by humans (e.g.: 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 (e.g.: 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).

    +
  • +

    :round_mode - Determine how rounding is performed (defaults to :default. See BigDecimal::mode)

    +
  • +

    :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

      +
    +
+ +

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(489939, precision: 2
+                      , round_mode: :down)   # => "480 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"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 392
+def number_to_human(number, options = {})
+  NumberToHumanConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_human_size(number, options = {}) + +

+ + +
+

Formats the bytes in number into a more understandable representation (e.g., giving it 1500 yields 1.46 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).

    +
  • +

    :round_mode - Determine how rounding is performed (defaults to :default. See BigDecimal::mode)

    +
  • +

    :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)

    +
+ +

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(483989, precision: 2, round_mode: :up)  # => "480 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"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 283
+def number_to_human_size(number, options = {})
+  NumberToHumanSizeConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_percentage(number, options = {}) + +

+ + +
+

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). Keeps the number’s precision if nil.

    +
  • +

    :round_mode - Determine how rounding is performed (defaults to :default. See BigDecimal::mode)

    +
  • +

    :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%”).

    +
+ +

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)                                # => "1000,000%"
+number_to_percentage(1000, precision: nil)                             # => "1000%"
+number_to_percentage('98a')                                            # => "98a%"
+number_to_percentage(100, format: '%n  %')                             # => "100.000  %"
+number_to_percentage(302.24398923423, precision: 5, round_mode: :down) # => "302.24398%"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 154
+def number_to_percentage(number, options = {})
+  NumberToPercentageConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_phone(number, options = {}) + +

+ + +
+

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.

    +
+ +

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(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"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 53
+def number_to_phone(number, options = {})
+  NumberToPhoneConverter.convert(number, options)
+end
+
+
+ +
+ +
+

+ + number_to_rounded(number, options = {}) + +

+ + +
+

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). Keeps the number’s precision if nil.

    +
  • +

    :round_mode - Determine how rounding is performed (defaults to :default. See BigDecimal::mode)

    +
  • +

    :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).

    +
+ +

Examples

+ +
number_to_rounded(111.2345)                                  # => "111.235"
+number_to_rounded(111.2345, precision: 2)                    # => "111.23"
+number_to_rounded(13, precision: 5)                          # => "13.00000"
+number_to_rounded(389.32314, precision: 0)                   # => "389"
+number_to_rounded(111.2345, significant: true)               # => "111"
+number_to_rounded(111.2345, precision: 1, significant: true) # => "100"
+number_to_rounded(13, precision: 5, significant: true)       # => "13.000"
+number_to_rounded(13, precision: nil)                        # => "13"
+number_to_rounded(389.32314, precision: 0, round_mode: :up)  # => "390"
+number_to_rounded(111.234, locale: :fr)                      # => "111,234"
+
+number_to_rounded(13, precision: 5, significant: true, strip_insignificant_zeros: true)
+# => "13"
+
+number_to_rounded(389.32314, precision: 4, significant: true) # => "389.3"
+number_to_rounded(1111.2345, precision: 2, separator: ',', delimiter: '.')
+# => "1.111,23"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/number_helper.rb, line 236
+def number_to_rounded(number, options = {})
+  NumberToRoundedConverter.convert(number, options)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/NumericWithFormat.html b/src/7.0/classes/ActiveSupport/NumericWithFormat.html new file mode 100644 index 0000000000..e89950ae61 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/NumericWithFormat.html @@ -0,0 +1,257 @@ +--- +title: ActiveSupport::NumericWithFormat +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + to_formatted_s(format = nil, options = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = nil, options = nil) + +

+ + +
+

Provides options for converting numbers into formatted strings. Options are provided for phone numbers, currency, percentage, precision, positional notation, file size, and pretty printing.

+ +

This method is aliased to to_formatted_s.

+ +

Options

+ +

For details on which formats use which options, see ActiveSupport::NumberHelper

+ +

Examples

+ +
Phone Numbers:
+5551234.to_fs(:phone)                                     # => "555-1234"
+1235551234.to_fs(:phone)                                  # => "123-555-1234"
+1235551234.to_fs(:phone, area_code: true)                 # => "(123) 555-1234"
+1235551234.to_fs(:phone, delimiter: ' ')                  # => "123 555 1234"
+1235551234.to_fs(:phone, area_code: true, extension: 555) # => "(123) 555-1234 x 555"
+1235551234.to_fs(:phone, country_code: 1)                 # => "+1-123-555-1234"
+1235551234.to_fs(:phone, country_code: 1, extension: 1343, delimiter: '.')
+# => "+1.123.555.1234 x 1343"
+
+Currency:
+1234567890.50.to_fs(:currency)                     # => "$1,234,567,890.50"
+1234567890.506.to_fs(:currency)                    # => "$1,234,567,890.51"
+1234567890.506.to_fs(:currency, precision: 3)      # => "$1,234,567,890.506"
+1234567890.506.to_fs(:currency, round_mode: :down) # => "$1,234,567,890.50"
+1234567890.506.to_fs(:currency, locale: :fr)       # => "1 234 567 890,51 €"
+-1234567890.50.to_fs(:currency, negative_format: '(%u%n)')
+# => "($1,234,567,890.50)"
+1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '')
+# => "&pound;1234567890,50"
+1234567890.50.to_fs(:currency, unit: '&pound;', separator: ',', delimiter: '', format: '%n %u')
+# => "1234567890,50 &pound;"
+
+Percentage:
+100.to_fs(:percentage)                                  # => "100.000%"
+100.to_fs(:percentage, precision: 0)                    # => "100%"
+1000.to_fs(:percentage, delimiter: '.', separator: ',') # => "1.000,000%"
+302.24398923423.to_fs(:percentage, precision: 5)        # => "302.24399%"
+302.24398923423.to_fs(:percentage, round_mode: :down)   # => "302.243%"
+1000.to_fs(:percentage, locale: :fr)                    # => "1 000,000%"
+100.to_fs(:percentage, format: '%n  %')                 # => "100.000  %"
+
+Delimited:
+12345678.to_fs(:delimited)                     # => "12,345,678"
+12345678.05.to_fs(:delimited)                  # => "12,345,678.05"
+12345678.to_fs(:delimited, delimiter: '.')     # => "12.345.678"
+12345678.to_fs(:delimited, delimiter: ',')     # => "12,345,678"
+12345678.05.to_fs(:delimited, separator: ' ')  # => "12,345,678 05"
+12345678.05.to_fs(:delimited, locale: :fr)     # => "12 345 678,05"
+98765432.98.to_fs(:delimited, delimiter: ' ', separator: ',')
+# => "98 765 432,98"
+
+Rounded:
+111.2345.to_fs(:rounded)                                      # => "111.235"
+111.2345.to_fs(:rounded, precision: 2)                        # => "111.23"
+111.2345.to_fs(:rounded, precision: 2, round_mode: :up)       # => "111.24"
+13.to_fs(:rounded, precision: 5)                              # => "13.00000"
+389.32314.to_fs(:rounded, precision: 0)                       # => "389"
+111.2345.to_fs(:rounded, significant: true)                   # => "111"
+111.2345.to_fs(:rounded, precision: 1, significant: true)     # => "100"
+13.to_fs(:rounded, precision: 5, significant: true)           # => "13.000"
+111.234.to_fs(:rounded, locale: :fr)                          # => "111,234"
+13.to_fs(:rounded, precision: 5, significant: true, strip_insignificant_zeros: true)
+# => "13"
+389.32314.to_fs(:rounded, precision: 4, significant: true)    # => "389.3"
+1111.2345.to_fs(:rounded, precision: 2, separator: ',', delimiter: '.')
+# => "1.111,23"
+
+Human-friendly size in Bytes:
+123.to_fs(:human_size)                                    # => "123 Bytes"
+1234.to_fs(:human_size)                                   # => "1.21 KB"
+12345.to_fs(:human_size)                                  # => "12.1 KB"
+1234567.to_fs(:human_size)                                # => "1.18 MB"
+1234567890.to_fs(:human_size)                             # => "1.15 GB"
+1234567890123.to_fs(:human_size)                          # => "1.12 TB"
+1234567890123456.to_fs(:human_size)                       # => "1.1 PB"
+1234567890123456789.to_fs(:human_size)                    # => "1.07 EB"
+1234567.to_fs(:human_size, precision: 2)                  # => "1.2 MB"
+1234567.to_fs(:human_size, precision: 2, round_mode: :up) # => "1.3 MB"
+483989.to_fs(:human_size, precision: 2)                   # => "470 KB"
+1234567.to_fs(:human_size, precision: 2, separator: ',')  # => "1,2 MB"
+1234567890123.to_fs(:human_size, precision: 5)            # => "1.1228 TB"
+524288000.to_fs(:human_size, precision: 5)                # => "500 MB"
+
+Human-friendly format:
+123.to_fs(:human)                                       # => "123"
+1234.to_fs(:human)                                      # => "1.23 Thousand"
+12345.to_fs(:human)                                     # => "12.3 Thousand"
+1234567.to_fs(:human)                                   # => "1.23 Million"
+1234567890.to_fs(:human)                                # => "1.23 Billion"
+1234567890123.to_fs(:human)                             # => "1.23 Trillion"
+1234567890123456.to_fs(:human)                          # => "1.23 Quadrillion"
+1234567890123456789.to_fs(:human)                       # => "1230 Quadrillion"
+489939.to_fs(:human, precision: 2)                      # => "490 Thousand"
+489939.to_fs(:human, precision: 2, round_mode: :down)   # => "480 Thousand"
+489939.to_fs(:human, precision: 4)                      # => "489.9 Thousand"
+1234567.to_fs(:human, precision: 4,
+                 significant: false)                             # => "1.2346 Million"
+1234567.to_fs(:human, precision: 1,
+                 separator: ',',
+                 significant: false)                             # => "1,2 Million"
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/conversions.rb, line 111
+def to_fs(format = nil, options = nil)
+  return to_s if format.nil?
+
+  case format
+  when Integer, String
+    to_s(format)
+  when :phone
+    ActiveSupport::NumberHelper.number_to_phone(self, options || {})
+  when :currency
+    ActiveSupport::NumberHelper.number_to_currency(self, options || {})
+  when :percentage
+    ActiveSupport::NumberHelper.number_to_percentage(self, options || {})
+  when :delimited
+    ActiveSupport::NumberHelper.number_to_delimited(self, options || {})
+  when :rounded
+    ActiveSupport::NumberHelper.number_to_rounded(self, options || {})
+  when :human
+    ActiveSupport::NumberHelper.number_to_human(self, options || {})
+  when :human_size
+    ActiveSupport::NumberHelper.number_to_human_size(self, options || {})
+  when Symbol
+    to_s
+  else
+    to_s(format)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/OrderedOptions.html b/src/7.0/classes/ActiveSupport/OrderedOptions.html new file mode 100644 index 0000000000..bca46c30b1 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/OrderedOptions.html @@ -0,0 +1,376 @@ +--- +title: ActiveSupport::OrderedOptions +layout: default +--- +
+ +
+
+ +
+ +

OrderedOptions inherits from Hash and provides dynamic accessor methods.

+ +

With a Hash, key-value pairs are typically managed like this:

+ +
h = {}
+h[:boy] = 'John'
+h[:girl] = 'Mary'
+h[:boy]  # => 'John'
+h[:girl] # => 'Mary'
+h[:dog]  # => nil
+
+ +

Using OrderedOptions, the above code can be written as:

+ +
h = ActiveSupport::OrderedOptions.new
+h.boy = 'John'
+h.girl = 'Mary'
+h.boy  # => 'John'
+h.girl # => 'Mary'
+h.dog  # => nil
+
+ +

To raise an exception when the value is blank, append a bang to the key name, like:

+ +
h.dog! # => raises KeyError: :dog is blank
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + [](key) + +

+ + +
+ +
+ + + +
+ Also aliased as: _get +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 39
+def [](key)
+  super(key.to_sym)
+end
+
+
+ +
+ +
+

+ + []=(key, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 35
+def []=(key, value)
+  super(key.to_sym, value)
+end
+
+
+ +
+ +
+

+ + _get(key) + +

+ + +
+ +
+ + + + + +
+ Alias for: [] +
+ + + +
+ +
+

+ + extractable_options?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 62
+def extractable_options?
+  true
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 66
+def inspect
+  "#<#{self.class.name} #{super}>"
+end
+
+
+ +
+ +
+

+ + method_missing(name, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 43
+def method_missing(name, *args)
+  name_string = +name.to_s
+  if name_string.chomp!("=")
+    self[name_string] = args.first
+  else
+    bangs = name_string.chomp!("!")
+
+    if bangs
+      self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
+    else
+      self[name_string]
+    end
+  end
+end
+
+
+ +
+ +
+

+ + respond_to_missing?(name, include_private) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/ordered_options.rb, line 58
+def respond_to_missing?(name, include_private)
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ParameterFilter.html b/src/7.0/classes/ActiveSupport/ParameterFilter.html new file mode 100644 index 0000000000..ca83caaf4c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ParameterFilter.html @@ -0,0 +1,225 @@ +--- +title: ActiveSupport::ParameterFilter +layout: default +--- +
+ +
+
+ +
+ +

ParameterFilter replaces values in a Hash-like object if their keys match one of the specified filters.

+ +

Matching based on nested keys is possible by using dot notation, e.g. "credit_card.number".

+ +

If a proc is given as a filter, each key and value of the Hash-like and of any nested Hashes will be passed to it. The value or key can then be mutated as desired using methods such as String#replace.

+ +
# Replaces values with "[FILTERED]" for keys that match /password/i.
+ActiveSupport::ParameterFilter.new([:password])
+
+# Replaces values with "[FILTERED]" for keys that match /foo|bar/i.
+ActiveSupport::ParameterFilter.new([:foo, "bar"])
+
+# Replaces values for the exact key "pin" and for keys that begin with
+# "pin_". Does not match keys that otherwise include "pin" as a
+# substring, such as "shipping_id".
+ActiveSupport::ParameterFilter.new([/\Apin\z/, /\Apin_/])
+
+# Replaces the value for :code in `{ credit_card: { code: "xxxx" } }`.
+# Does not change `{ file: { code: "xxxx" } }`.
+ActiveSupport::ParameterFilter.new(["credit_card.code"])
+
+# Reverses values for keys that match /secret/i.
+ActiveSupport::ParameterFilter.new([-> (k, v) do
+  v.reverse! if /secret/i.match?(k)
+end])
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(filters = [], mask: FILTERED) + +

+ + +
+

Create instance with given filters. Supported type of filters are String, Regexp, and Proc. Other types of filters are treated as String using to_s. For Proc filters, key, value, and optional original hash is passed to block arguments.

+ +

Options

+
  • +

    :mask - A replaced object when filtered. Defaults to "[FILTERED]".

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/parameter_filter.rb, line 46
+def initialize(filters = [], mask: FILTERED)
+  @filters = filters
+  @mask = mask
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + filter(params) + +

+ + +
+

Mask value of params if key matches one of filters.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/parameter_filter.rb, line 52
+def filter(params)
+  compiled_filter.call(params)
+end
+
+
+ +
+ +
+

+ + filter_param(key, value) + +

+ + +
+

Returns filtered value for given key. For Proc filters, third block argument is not populated.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/parameter_filter.rb, line 57
+def filter_param(key, value)
+  @filters.empty? ? value : compiled_filter.value_for_key(key, value)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/PerThreadRegistry.html b/src/7.0/classes/ActiveSupport/PerThreadRegistry.html new file mode 100644 index 0000000000..c6a3dbceb0 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/PerThreadRegistry.html @@ -0,0 +1,187 @@ +--- +title: ActiveSupport::PerThreadRegistry +layout: default +--- +
+ +
+
+ +
+ +

NOTE: This approach has been deprecated for end-user code in favor of thread_mattr_accessor and friends. Please use that approach instead.

+ +

This module is used to encapsulate access to thread local variables.

+ +

Instead of polluting the thread locals namespace:

+ +
Thread.current[:connection_handler]
+
+ +

you define a class that extends this module:

+ +
module ActiveRecord
+  class RuntimeRegistry
+    extend ActiveSupport::PerThreadRegistry
+
+    attr_accessor :connection_handler
+  end
+end
+
+ +

and invoke the declared instance accessors as class methods. So

+ +
ActiveRecord::RuntimeRegistry.connection_handler = connection_handler
+
+ +

sets a connection handler local to the current thread, and

+ +
ActiveRecord::RuntimeRegistry.connection_handler
+
+ +

returns a connection handler local to the current thread.

+ +

This feature is accomplished by instantiating the class and storing the instance as a thread local keyed by the class name. In the example above a key “ActiveRecord::RuntimeRegistry” is stored in Thread.current. The class methods proxy to said thread local instance.

+ +

If the class has an initializer, it must accept no arguments.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + extended(object) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/per_thread_registry.rb, line 42
+    def self.extended(object)
+      ActiveSupport::Deprecation.warn(<<~MSG)
+        ActiveSupport::PerThreadRegistry is deprecated and will be removed in Rails 7.1.
+        Use `Module#thread_mattr_accessor` instead.
+      MSG
+      object.instance_variable_set :@per_thread_registry_key, object.name.freeze
+    end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + instance() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/per_thread_registry.rb, line 50
+def instance
+  Thread.current[@per_thread_registry_key] ||= new
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/ProxyObject.html b/src/7.0/classes/ActiveSupport/ProxyObject.html new file mode 100644 index 0000000000..8e721122b6 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/ProxyObject.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::ProxyObject +layout: default +--- +
+ +
+
+ +
+ +

A class with no predefined methods that behaves similarly to Builder’s BlankSlate. Used for proxy classes.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + raise(*args) + +

+ + +
+

Let ActiveSupport::ProxyObject at least raise exceptions.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/proxy_object.rb, line 11
+def raise(*args)
+  ::Object.send(:raise, *args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/RangeWithFormat.html b/src/7.0/classes/ActiveSupport/RangeWithFormat.html new file mode 100644 index 0000000000..41f9a1952f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/RangeWithFormat.html @@ -0,0 +1,181 @@ +--- +title: ActiveSupport::RangeWithFormat +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RANGE_FORMATS={ +db: -> (start, stop) do +case start +when String then "BETWEEN '#{start}' AND '#{stop}'" +else +"BETWEEN '#{start.to_fs(:db)}' AND '#{stop.to_fs(:db)}'" +end +end +}
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Convert range to a formatted string. See RANGE_FORMATS for predefined formats.

+ +

This method is aliased to to_formatted_s.

+ +
range = (1..100)           # => 1..100
+
+range.to_s                 # => "1..100"
+range.to_fs(:db)            # => "BETWEEN '1' AND '100'"
+
+ +

Adding your own range formats to to_s

+ +

You can add your own formats to the Range::RANGE_FORMATS hash. Use the format name as the hash key and a Proc instance.

+ +
# config/initializers/range_formats.rb
+Range::RANGE_FORMATS[:short] = ->(start, stop) { "Between #{start.to_fs(:db)} and #{stop.to_fs(:db)}" }
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/range/conversions.rb, line 30
+def to_fs(format = :default)
+  if formatter = RANGE_FORMATS[format]
+    formatter.call(first, last)
+  else
+    to_s
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Reloader.html b/src/7.0/classes/ActiveSupport/Reloader.html new file mode 100644 index 0000000000..b573c3c0c7 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Reloader.html @@ -0,0 +1,399 @@ +--- +title: ActiveSupport::Reloader +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + after_class_unload(*args, &block) + +

+ + +
+

Registers a callback that will run immediately after the classes are unloaded.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 43
+def self.after_class_unload(*args, &block)
+  set_callback(:class_unload, :after, *args, &block)
+end
+
+
+ +
+ +
+

+ + before_class_unload(*args, &block) + +

+ + +
+

Registers a callback that will run immediately before the classes are unloaded.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 38
+def self.before_class_unload(*args, &block)
+  set_callback(:class_unload, *args, &block)
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 91
+def initialize
+  super
+  @locked = false
+end
+
+
+ +
+ +
+

+ + reload!() + +

+ + +
+

Initiate a manual reload

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 50
+def self.reload!
+  executor.wrap do
+    new.tap do |instance|
+      instance.run!
+    ensure
+      instance.complete!
+    end
+  end
+  prepare!
+end
+
+
+ +
+ +
+

+ + to_prepare(*args, &block) + +

+ + +
+

Registers a callback that will run once at application startup and every time the code is reloaded.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 33
+def self.to_prepare(*args, &block)
+  set_callback(:prepare, *args, &block)
+end
+
+
+ +
+ +
+

+ + wrap() + +

+ + +
+

Run the supplied block as a work unit, reloading code as needed

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 70
+def self.wrap
+  executor.wrap do
+    super
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + release_unload_lock!() + +

+ + +
+

Release the unload lock if it has been previously obtained

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 106
+def release_unload_lock!
+  if @locked
+    @locked = false
+    ActiveSupport::Dependencies.interlock.done_unloading
+  end
+end
+
+
+ +
+ +
+

+ + require_unload_lock!() + +

+ + +
+

Acquire the ActiveSupport::Dependencies::Interlock unload lock, ensuring it will be released automatically

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/reloader.rb, line 98
+def require_unload_lock!
+  unless @locked
+    ActiveSupport::Dependencies.interlock.start_unloading
+    @locked = true
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Rescuable.html b/src/7.0/classes/ActiveSupport/Rescuable.html new file mode 100644 index 0000000000..4b24dc217b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Rescuable.html @@ -0,0 +1,120 @@ +--- +title: ActiveSupport::Rescuable +layout: default +--- +
+ +
+
+ +
+ +

Rescuable module adds support for easier exception handling.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + rescue_with_handler(exception) + +

+ + +
+

Delegates to the class method, but uses the instance as the subject for rescue_from handlers (method calls, instance_exec blocks).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/rescuable.rb, line 164
+def rescue_with_handler(exception)
+  self.class.rescue_with_handler exception, object: self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Rescuable/ClassMethods.html b/src/7.0/classes/ActiveSupport/Rescuable/ClassMethods.html new file mode 100644 index 0000000000..1dc7193d0d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Rescuable/ClassMethods.html @@ -0,0 +1,208 @@ +--- +title: ActiveSupport::Rescuable::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + rescue_from(*klasses, with: nil, &block) + +

+ + +
+

Registers exception classes with a handler to be called by rescue_with_handler.

+ +

rescue_from receives a series of exception classes or class names, and an exception handler specified by a trailing :with option containing the name of a method or a Proc object. Alternatively, a block can be given as the handler.

+ +

Handlers that take one argument will be called with the exception, so that the exception can be inspected when dealing with it.

+ +

Handlers are inherited. They are searched from right to left, from bottom to top, and up the hierarchy. The handler of the first class for which exception.is_a?(klass) holds true is the one invoked, if any.

+ +
class ApplicationController < ActionController::Base
+  rescue_from User::NotAuthorized, with: :deny_access
+  rescue_from ActiveRecord::RecordInvalid, with: :show_record_errors
+
+  rescue_from "MyApp::BaseError" do |exception|
+    redirect_to root_url, alert: exception.message
+  end
+
+  private
+    def deny_access
+      head :forbidden
+    end
+
+    def show_record_errors(exception)
+      redirect_back_or_to root_url, alert: exception.record.errors.full_messages.to_sentence
+    end
+end
+
+ +

Exceptions raised inside exception handlers are not propagated up.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/rescuable.rb, line 51
+def rescue_from(*klasses, with: nil, &block)
+  unless with
+    if block_given?
+      with = block
+    else
+      raise ArgumentError, "Need a handler. Pass the with: keyword argument or provide a block."
+    end
+  end
+
+  klasses.each do |klass|
+    key = if klass.is_a?(Module) && klass.respond_to?(:===)
+      klass.name
+    elsif klass.is_a?(String)
+      klass
+    else
+      raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
+    end
+
+    # Put the new handler at the end because the list is read in reverse.
+    self.rescue_handlers += [[key, with]]
+  end
+end
+
+
+ +
+ +
+

+ + rescue_with_handler(exception, object: self, visited_exceptions: []) + +

+ + +
+

Matches an exception to a handler based on the exception class.

+ +

If no handler matches the exception, check for a handler matching the (optional) exception.cause. If no handler matches the exception or its cause, this returns nil, so you can deal with unhandled exceptions. Be sure to re-raise unhandled exceptions if this is what you expect.

+ +
begin
+  # ...
+rescue => exception
+  rescue_with_handler(exception) || raise
+end
+
+ +

Returns the exception if it was handled and nil if it was not.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/rescuable.rb, line 88
+def rescue_with_handler(exception, object: self, visited_exceptions: [])
+  visited_exceptions << exception
+
+  if handler = handler_for_rescue(exception, object: object)
+    handler.call exception
+    exception
+  elsif exception
+    if visited_exceptions.include?(exception.cause)
+      nil
+    else
+      rescue_with_handler(exception.cause, object: object, visited_exceptions: visited_exceptions)
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/SafeBuffer.html b/src/7.0/classes/ActiveSupport/SafeBuffer.html new file mode 100644 index 0000000000..6318250004 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/SafeBuffer.html @@ -0,0 +1,910 @@ +--- +title: ActiveSupport::SafeBuffer +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
UNSAFE_STRING_METHODS=%w( +capitalize chomp chop delete delete_prefix delete_suffix +downcase lstrip next reverse rstrip scrub slice squeeze strip +succ swapcase tr tr_s unicode_normalize upcase +)
 
UNSAFE_STRING_METHODS_WITH_BACKREF=%w(gsub sub)
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(str = "") + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 200
+def initialize(str = "")
+  @html_safe = true
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + %(args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 257
+def %(args)
+  case args
+  when Hash
+    escaped_args = args.transform_values { |arg| explicit_html_escape_interpolated_argument(arg) }
+  else
+    escaped_args = Array(args).map { |arg| explicit_html_escape_interpolated_argument(arg) }
+  end
+
+  self.class.new(super(escaped_args))
+end
+
+
+ +
+ +
+

+ + *(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 250
+def *(*)
+  new_string = super
+  new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
+  new_safe_buffer.instance_variable_set(:@html_safe, @html_safe)
+  new_safe_buffer
+end
+
+
+ +
+ +
+

+ + +(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 246
+def +(other)
+  dup.concat(other)
+end
+
+
+ +
+ +
+

+ + <<(value) + +

+ + +
+ +
+ + + + + +
+ Alias for: concat +
+ + + +
+ +
+

+ + [](*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 181
+def [](*args)
+  if html_safe?
+    new_string = super
+
+    return unless new_string
+
+    new_safe_buffer = new_string.is_a?(SafeBuffer) ? new_string : SafeBuffer.new(new_string)
+    new_safe_buffer.instance_variable_set :@html_safe, true
+    new_safe_buffer
+  else
+    to_str[*args]
+  end
+end
+
+
+ +
+ +
+

+ + []=(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 238
+def []=(*args)
+  if args.length == 3
+    super(args[0], args[1], implicit_html_escape_interpolated_argument(args[2]))
+  else
+    super(args[0], implicit_html_escape_interpolated_argument(args[1]))
+  end
+end
+
+
+ +
+ +
+

+ + bytesplice(*args, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 222
+def bytesplice(*args, value)
+  super(*args, implicit_html_escape_interpolated_argument(value))
+end
+
+
+ +
+ +
+

+ + clone_empty() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 210
+def clone_empty
+  self[0, 0]
+end
+
+
+ +
+ +
+

+ + concat(value) + +

+ + +
+ +
+ + + +
+ Also aliased as: original_concat, << +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 214
+def concat(value)
+  unless value.nil?
+    super(implicit_html_escape_interpolated_argument(value))
+  end
+  self
+end
+
+
+ +
+ +
+

+ + encode_with(coder) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 280
+def encode_with(coder)
+  coder.represent_object nil, to_str
+end
+
+
+ +
+ +
+

+ + html_safe?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 268
+def html_safe?
+  defined?(@html_safe) && @html_safe
+end
+
+
+ +
+ +
+

+ + initialize_copy(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 205
+def initialize_copy(other)
+  super
+  @html_safe = other.html_safe?
+end
+
+
+ +
+ +
+

+ + insert(index, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 226
+def insert(index, value)
+  super(index, implicit_html_escape_interpolated_argument(value))
+end
+
+
+ +
+ +
+

+ + original_concat(value) + +

+ + +
+ +
+ + + + + +
+ Alias for: concat +
+ + + +
+ +
+

+ + prepend(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 230
+def prepend(value)
+  super(implicit_html_escape_interpolated_argument(value))
+end
+
+
+ +
+ +
+

+ + replace(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 234
+def replace(value)
+  super(implicit_html_escape_interpolated_argument(value))
+end
+
+
+ +
+ +
+

+ + safe_concat(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 195
+def safe_concat(value)
+  raise SafeConcatError unless html_safe?
+  original_concat(value)
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 276
+def to_param
+  to_str
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 272
+def to_s
+  self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/SafeBuffer/SafeConcatError.html b/src/7.0/classes/ActiveSupport/SafeBuffer/SafeConcatError.html new file mode 100644 index 0000000000..e5b4e87cfb --- /dev/null +++ b/src/7.0/classes/ActiveSupport/SafeBuffer/SafeConcatError.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::SafeBuffer::SafeConcatError +layout: default +--- +
+ +
+
+ +
+ +

Raised when ActiveSupport::SafeBuffer#safe_concat is called on unsafe buffers.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 176
+def initialize
+  super "Could not concatenate to the buffer because it is not html safe."
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/SecureCompareRotator.html b/src/7.0/classes/ActiveSupport/SecureCompareRotator.html new file mode 100644 index 0000000000..f620ddd063 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/SecureCompareRotator.html @@ -0,0 +1,212 @@ +--- +title: ActiveSupport::SecureCompareRotator +layout: default +--- +
+ +
+
+ +
+ +

The ActiveSupport::SecureCompareRotator is a wrapper around ActiveSupport::SecurityUtils.secure_compare and allows you to rotate a previously defined value to a new one.

+ +

It can be used as follow:

+ +
rotator = ActiveSupport::SecureCompareRotator.new('new_production_value')
+rotator.rotate('previous_production_value')
+rotator.secure_compare!('previous_production_value')
+
+ +

One real use case example would be to rotate a basic auth credentials:

+ +
class MyController < ApplicationController
+  def authenticate_request
+    rotator = ActiveSupport::SecureCompareRotator.new('new_password')
+    rotator.rotate('old_password')
+
+    authenticate_or_request_with_http_basic do |username, password|
+      rotator.secure_compare!(password)
+    rescue ActiveSupport::SecureCompareRotator::InvalidMatch
+      false
+    end
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
InvalidMatch=Class.new(StandardError)
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(value, **_options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/secure_compare_rotator.rb, line 36
+def initialize(value, **_options)
+  @value = value
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + secure_compare!(other_value, on_rotation: @on_rotation) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/secure_compare_rotator.rb, line 40
+def secure_compare!(other_value, on_rotation: @on_rotation)
+  secure_compare(@value, other_value) ||
+    run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
+    raise(InvalidMatch)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/SecurityUtils.html b/src/7.0/classes/ActiveSupport/SecurityUtils.html new file mode 100644 index 0000000000..73db5abb68 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/SecurityUtils.html @@ -0,0 +1,142 @@ +--- +title: ActiveSupport::SecurityUtils +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + fixed_length_secure_compare(a, b) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/security_utils.rb, line 11
+def fixed_length_secure_compare(a, b)
+  OpenSSL.fixed_length_secure_compare(a, b)
+end
+
+
+ +
+ +
+

+ + secure_compare(a, b) + +

+ + +
+

Secure string comparison for strings of variable length.

+ +

While a timing attack would not be able to discern the content of a secret compared via secure_compare, it is possible to determine the secret length. This should be considered when using secure_compare to compare weak, short secrets to user input.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/security_utils.rb, line 33
+def secure_compare(a, b)
+  a.bytesize == b.bytesize && fixed_length_secure_compare(a, b)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/StringInquirer.html b/src/7.0/classes/ActiveSupport/StringInquirer.html new file mode 100644 index 0000000000..b4356497ea --- /dev/null +++ b/src/7.0/classes/ActiveSupport/StringInquirer.html @@ -0,0 +1,81 @@ +--- +title: ActiveSupport::StringInquirer +layout: default +--- +
+ +
+
+ +
+ +

Wrapping a string in this class gives you a prettier way to test for equality. The value returned by Rails.env is wrapped in a StringInquirer object, so instead of calling this:

+ +
Rails.env == 'production'
+
+ +

you can call this:

+ +
Rails.env.production?
+
+ +

Instantiating a new StringInquirer

+ +
vehicle = ActiveSupport::StringInquirer.new('car')
+vehicle.car?   # => true
+vehicle.bike?  # => false
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Subscriber.html b/src/7.0/classes/ActiveSupport/Subscriber.html new file mode 100644 index 0000000000..8116b468e8 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Subscriber.html @@ -0,0 +1,506 @@ +--- +title: ActiveSupport::Subscriber +layout: default +--- +
+ +
+
+ +
+ +

ActiveSupport::Subscriber is an object set to consume ActiveSupport::Notifications. The subscriber dispatches notifications to a registered object based on its given namespace.

+ +

An example would be an Active Record subscriber responsible for collecting statistics about queries:

+ +
module ActiveRecord
+  class StatsSubscriber < ActiveSupport::Subscriber
+    attach_to :active_record
+
+    def sql(event)
+      Statsd.timing("sql.#{event.payload[:name]}", event.duration)
+    end
+  end
+end
+
+ +

After configured, whenever a “sql.active_record” notification is published, it will properly dispatch the event (ActiveSupport::Notifications::Event) to the sql method.

+ +

We can detach a subscriber as well:

+ +
ActiveRecord::StatsSubscriber.detach_from(:active_record)
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + attach_to(namespace, subscriber = new, notifier = ActiveSupport::Notifications, inherit_all: false) + +

+ + +
+

Attach the subscriber to a namespace.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 33
+def attach_to(namespace, subscriber = new, notifier = ActiveSupport::Notifications, inherit_all: false)
+  @namespace  = namespace
+  @subscriber = subscriber
+  @notifier   = notifier
+  @inherit_all = inherit_all
+
+  subscribers << subscriber
+
+  # Add event subscribers for all existing methods on the class.
+  fetch_public_methods(subscriber, inherit_all).each do |event|
+    add_event_subscriber(event)
+  end
+end
+
+
+ +
+ +
+

+ + detach_from(namespace, notifier = ActiveSupport::Notifications) + +

+ + +
+

Detach the subscriber from a namespace.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 48
+def detach_from(namespace, notifier = ActiveSupport::Notifications)
+  @namespace  = namespace
+  @subscriber = find_attached_subscriber
+  @notifier   = notifier
+
+  return unless subscriber
+
+  subscribers.delete(subscriber)
+
+  # Remove event subscribers of all existing methods on the class.
+  fetch_public_methods(subscriber, true).each do |event|
+    remove_event_subscriber(event)
+  end
+
+  # Reset notifier so that event subscribers will not add for new methods added to the class.
+  @notifier = nil
+end
+
+
+ +
+ +
+

+ + method_added(event) + +

+ + +
+

Adds event subscribers for all new methods added to the class.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 67
+def method_added(event)
+  # Only public methods are added as subscribers, and only if a notifier
+  # has been set up. This means that subscribers will only be set up for
+  # classes that call #attach_to.
+  if public_method_defined?(event) && notifier
+    add_event_subscriber(event)
+  end
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 128
+def initialize
+  @queue_key = [self.class.name, object_id].join "-"
+  @patterns  = {}
+  super
+end
+
+
+ +
+ +
+

+ + subscribers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 76
+def subscribers
+  @@subscribers ||= []
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + add_event_subscriber(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 83
+def add_event_subscriber(event) # :doc:
+  return if invalid_event?(event)
+
+  pattern = prepare_pattern(event)
+
+  # Don't add multiple subscribers (e.g. if methods are redefined).
+  return if pattern_subscribed?(pattern)
+
+  subscriber.patterns[pattern] = notifier.subscribe(pattern, subscriber)
+end
+
+
+ +
+ +
+

+ + remove_event_subscriber(event) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 94
+def remove_event_subscriber(event) # :doc:
+  return if invalid_event?(event)
+
+  pattern = prepare_pattern(event)
+
+  return unless pattern_subscribed?(pattern)
+
+  notifier.unsubscribe(subscriber.patterns[pattern])
+  subscriber.patterns.delete(pattern)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + finish(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 143
+def finish(name, id, payload)
+  event = event_stack.pop
+  event.finish!
+  event.payload.merge!(payload)
+
+  method = name.split(".").first
+  send(method, event)
+end
+
+
+ +
+ +
+

+ + start(name, id, payload) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/subscriber.rb, line 134
+def start(name, id, payload)
+  event = ActiveSupport::Notifications::Event.new(name, nil, nil, id, payload)
+  event.start!
+  parent = event_stack.last
+  parent << event if parent
+
+  event_stack.push event
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/TaggedLogging.html b/src/7.0/classes/ActiveSupport/TaggedLogging.html new file mode 100644 index 0000000000..2eeddf9064 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/TaggedLogging.html @@ -0,0 +1,224 @@ +--- +title: ActiveSupport::TaggedLogging +layout: default +--- +
+ +
+
+ +
+ +

Wraps any standard Logger object to provide tagging capabilities.

+ +

May be called with a block:

+ +
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
+logger.tagged('BCX') { logger.info 'Stuff' }                            # Logs "[BCX] Stuff"
+logger.tagged('BCX', "Jason") { logger.info 'Stuff' }                   # Logs "[BCX] [Jason] Stuff"
+logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
+
+ +

If called without a block, a new logger will be returned with applied tags:

+ +
logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
+logger.tagged("BCX").info "Stuff"                 # Logs "[BCX] Stuff"
+logger.tagged("BCX", "Jason").info "Stuff"        # Logs "[BCX] [Jason] Stuff"
+logger.tagged("BCX").tagged("Jason").info "Stuff" # Logs "[BCX] [Jason] Stuff"
+
+ +

This is used by the default Rails.logger as configured by Railties to make it easy to stamp log lines with subdomains, request ids, and anything else to aid debugging of multi-user production applications.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(logger) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/tagged_logging.rb, line 81
+def self.new(logger)
+  logger = logger.clone
+
+  if logger.formatter
+    logger.formatter = logger.formatter.dup
+  else
+    # Ensure we set a default formatter so we aren't extending nil!
+    logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
+  end
+
+  logger.formatter.extend Formatter
+  logger.extend(self)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + flush() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/tagged_logging.rb, line 108
+def flush
+  clear_tags!
+  super if defined?(super)
+end
+
+
+ +
+ +
+

+ + tagged(*tags) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/tagged_logging.rb, line 97
+def tagged(*tags)
+  if block_given?
+    formatter.tagged(*tags) { yield self }
+  else
+    logger = ActiveSupport::TaggedLogging.new(self)
+    logger.formatter.extend LocalTagStorage
+    logger.push_tags(*formatter.current_tags, *tags)
+    logger
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/TestCase.html b/src/7.0/classes/ActiveSupport/TestCase.html new file mode 100644 index 0000000000..2966a37aea --- /dev/null +++ b/src/7.0/classes/ActiveSupport/TestCase.html @@ -0,0 +1,386 @@ +--- +title: ActiveSupport::TestCase +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
Assertion=Minitest::Assertion
 
+ + + + + + +

Class Public methods

+ +
+

+ + parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold) + +

+ + +
+

Parallelizes the test suite.

+ +

Takes a workers argument that controls how many times the process is forked. For each process a new database will be created suffixed with the worker number.

+ +
test-database-0
+test-database-1
+
+ +

If ENV["PARALLEL_WORKERS"] is set the workers argument will be ignored and the environment variable will be used instead. This is useful for CI environments, or other environments where you may need more workers than you do for local testing.

+ +

If the number of workers is set to 1 or fewer, the tests will not be parallelized.

+ +

If workers is set to :number_of_processors, the number of workers will be set to the actual core count on the machine you are on.

+ +

The default parallelization method is to fork processes. If you’d like to use threads instead you can pass with: :threads to the parallelize method. Note the threaded parallelization does not create multiple database and will not work with system tests at this time.

+ +
parallelize(workers: :number_of_processors, with: :threads)
+
+ +

The threaded parallelization uses minitest’s parallel executor directly. The processes parallelization uses a Ruby DRb server.

+ +

Because parallelization presents an overhead, it is only enabled when the number of tests to run is above the threshold param. The default value is 50, and it’s configurable via config.active_support.test_parallelization_threshold.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/test_case.rb, line 79
+def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
+  workers = Concurrent.physical_processor_count if workers == :number_of_processors
+  workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
+
+  return if workers <= 1
+
+  Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
+end
+
+
+ +
+ +
+

+ + parallelize_setup(&block) + +

+ + +
+

Set up hook for parallel testing. This can be used if you have multiple databases or any behavior that needs to be run after the process is forked but before the tests run.

+ +

Note: this feature is not available with the threaded parallelization.

+ +

In your test_helper.rb add the following:

+ +
class ActiveSupport::TestCase
+  parallelize_setup do
+    # create databases
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/test_case.rb, line 101
+def parallelize_setup(&block)
+  ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
+end
+
+
+ +
+ +
+

+ + parallelize_teardown(&block) + +

+ + +
+

Clean up hook for parallel testing. This can be used to drop databases if your app uses multiple write/read databases or other clean up before the tests finish. This runs before the forked process is closed.

+ +

Note: this feature is not available with the threaded parallelization.

+ +

In your test_helper.rb add the following:

+ +
class ActiveSupport::TestCase
+  parallelize_teardown do
+    # drop databases
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/test_case.rb, line 118
+def parallelize_teardown(&block)
+  ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
+end
+
+
+ +
+ +
+

+ + test_order() + +

+ + +
+

Returns the order in which test cases are run.

+ +
ActiveSupport::TestCase.test_order # => :random
+
+ +

Possible values are :random, :parallel, :alpha, :sorted. Defaults to :random.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/test_case.rb, line 42
+def test_order
+  ActiveSupport.test_order ||= :random
+end
+
+
+ +
+ +
+

+ + test_order=(new_order) + +

+ + +
+

Sets the order in which test cases are run.

+ +
ActiveSupport::TestCase.test_order = :random # => :random
+
+ +

Valid values are:

+
  • +

    :random (to run tests in random order)

    +
  • +

    :parallel (to run tests in parallel)

    +
  • +

    :sorted (to run tests alphabetically by method name)

    +
  • +

    :alpha (equivalent to :sorted)

    +
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/test_case.rb, line 32
+def test_order=(new_order)
+  ActiveSupport.test_order = new_order
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing.html b/src/7.0/classes/ActiveSupport/Testing.html new file mode 100644 index 0000000000..ff9451c4e0 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing.html @@ -0,0 +1,116 @@ +--- +title: ActiveSupport::Testing +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Assertions.html b/src/7.0/classes/ActiveSupport/Testing/Assertions.html new file mode 100644 index 0000000000..b523d0b576 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Assertions.html @@ -0,0 +1,514 @@ +--- +title: ActiveSupport::Testing::Assertions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block) + +

+ + +
+

Assertion that the result of evaluating an expression is changed before and after invoking the passed in block.

+ +
assert_changes 'Status.all_good?' do
+  post :create, params: { status: { ok: false } }
+end
+
+ +

You can pass the block as a string to be evaluated in the context of the block. A lambda can be passed for the block as well.

+ +
assert_changes -> { Status.all_good? } do
+  post :create, params: { status: { ok: false } }
+end
+
+ +

The assertion is useful to test side effects. The passed block can be anything that can be converted to string with to_s.

+ +
assert_changes :@object do
+  @object = 42
+end
+
+ +

The keyword arguments :from and :to can be given to specify the expected initial value and the expected value after the block was executed.

+ +
assert_changes :@object, from: nil, to: :foo do
+  @object = :foo
+end
+
+ +

An error message can be specified.

+ +
assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
+  post :create, params: { status: { incident: true } }
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 175
+def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
+  exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
+
+  before = exp.call
+  retval = _assert_nothing_raised_or_warn("assert_changes", &block)
+
+  unless from == UNTRACKED
+    error = "Expected change from #{from.inspect}"
+    error = "#{message}.\n#{error}" if message
+    assert from === before, error
+  end
+
+  after = exp.call
+
+  error = "#{expression.inspect} didn't change"
+  error = "#{error}. It was already #{to}" if before == to
+  error = "#{message}.\n#{error}" if message
+  refute_equal before, after, error
+
+  unless to == UNTRACKED
+    error = "Expected change to #{to}\n"
+    error = "#{message}.\n#{error}" if message
+    assert to === after, error
+  end
+
+  retval
+end
+
+
+ +
+ +
+

+ + assert_difference(expression, *args, &block) + +

+ + +
+

Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.

+ +
assert_difference 'Article.count' do
+  post :create, params: { article: {...} }
+end
+
+ +

An arbitrary expression is passed in and evaluated.

+ +
assert_difference 'Article.last.comments(:reload).size' do
+  post :create, params: { comment: {...} }
+end
+
+ +

An arbitrary positive or negative difference can be specified. The default is 1.

+ +
assert_difference 'Article.count', -1 do
+  post :delete, params: { id: ... }
+end
+
+ +

An array of expressions can also be passed in and evaluated.

+ +
assert_difference [ 'Article.count', 'Post.count' ], 2 do
+  post :create, params: { article: {...} }
+end
+
+ +

A hash of expressions/numeric differences can also be passed in and evaluated.

+ +
assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
+  post :create, params: { article: {...} }
+end
+
+ +

A lambda or a list of lambdas can be passed in and evaluated:

+ +
assert_difference ->{ Article.count }, 2 do
+  post :create, params: { article: {...} }
+end
+
+assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
+  post :create, params: { article: {...} }
+end
+
+ +

An error message can be specified.

+ +
assert_difference 'Article.count', -1, 'An Article should be destroyed' do
+  post :delete, params: { id: ... }
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 86
+def assert_difference(expression, *args, &block)
+  expressions =
+    if expression.is_a?(Hash)
+      message = args[0]
+      expression
+    else
+      difference = args[0] || 1
+      message = args[1]
+      Array(expression).index_with(difference)
+    end
+
+  exps = expressions.keys.map { |e|
+    e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
+  }
+  before = exps.map(&:call)
+
+  retval = _assert_nothing_raised_or_warn("assert_difference", &block)
+
+  expressions.zip(exps, before) do |(code, diff), exp, before_value|
+    error  = "#{code.inspect} didn't change by #{diff}"
+    error  = "#{message}.\n#{error}" if message
+    assert_equal(before_value + diff, exp.call, error)
+  end
+
+  retval
+end
+
+
+ +
+ +
+

+ + assert_no_changes(expression, message = nil, from: UNTRACKED, &block) + +

+ + +
+

Assertion that the result of evaluating an expression is not changed before and after invoking the passed in block.

+ +
assert_no_changes 'Status.all_good?' do
+  post :create, params: { status: { ok: true } }
+end
+
+ +

Provide the optional keyword argument :from to specify the expected initial value.

+ +
assert_no_changes -> { Status.all_good? }, from: true do
+  post :create, params: { status: { ok: true } }
+end
+
+ +

An error message can be specified.

+ +
assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
+  post :create, params: { status: { ok: false } }
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 222
+def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
+  exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
+
+  before = exp.call
+  retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
+
+  unless from == UNTRACKED
+    error = "Expected initial value of #{from.inspect}"
+    error = "#{message}.\n#{error}" if message
+    assert from === before, error
+  end
+
+  after = exp.call
+
+  error = "#{expression.inspect} changed"
+  error = "#{message}.\n#{error}" if message
+
+  if before.nil?
+    assert_nil after, error
+  else
+    assert_equal before, after, error
+  end
+
+  retval
+end
+
+
+ +
+ +
+

+ + assert_no_difference(expression, message = nil, &block) + +

+ + +
+

Assertion that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.

+ +
assert_no_difference 'Article.count' do
+  post :create, params: { article: invalid_attributes }
+end
+
+ +

A lambda can be passed in and evaluated.

+ +
assert_no_difference -> { Article.count } do
+  post :create, params: { article: invalid_attributes }
+end
+
+ +

An error message can be specified.

+ +
assert_no_difference 'Article.count', 'An Article should not be created' do
+  post :create, params: { article: invalid_attributes }
+end
+
+ +

An array of expressions can also be passed in and evaluated.

+ +
assert_no_difference [ 'Article.count', -> { Post.count } ] do
+  post :create, params: { article: invalid_attributes }
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 137
+def assert_no_difference(expression, message = nil, &block)
+  assert_difference expression, 0, message, &block
+end
+
+
+ +
+ +
+

+ + assert_not(object, message = nil) + +

+ + +
+

Asserts that an expression is not truthy. Passes if object is nil or false. “Truthy” means “considered true in a conditional” like if foo.

+ +
assert_not nil    # => true
+assert_not false  # => true
+assert_not 'foo'  # => Expected "foo" to be nil or false
+
+ +

An error message can be specified.

+ +
assert_not foo, 'foo should be false'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 21
+def assert_not(object, message = nil)
+  message ||= "Expected #{mu_pp(object)} to be nil or false"
+  assert !object, message
+end
+
+
+ +
+ +
+

+ + assert_nothing_raised() + +

+ + +
+

Assertion that the block should not raise an exception.

+ +

Passes if evaluated code in the yielded block raises no exception.

+ +
assert_nothing_raised do
+  perform_service(param: 'no_exception')
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/assertions.rb, line 33
+def assert_nothing_raised
+  yield
+rescue => error
+  raise Minitest::UnexpectedError.new(error)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/ConstantLookup.html b/src/7.0/classes/ActiveSupport/Testing/ConstantLookup.html new file mode 100644 index 0000000000..cb3192d11e --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/ConstantLookup.html @@ -0,0 +1,85 @@ +--- +title: ActiveSupport::Testing::ConstantLookup +layout: default +--- +
+ +
+
+ +
+ +

Resolves a constant from a minitest spec name.

+ +

Given the following spec-style test:

+ +
describe WidgetsController, :index do
+  describe "authenticated user" do
+    describe "returns widgets" do
+      it "has a controller that exists" do
+        assert_kind_of WidgetsController, @controller
+      end
+    end
+  end
+end
+
+ +

The test will have the following name:

+ +
"WidgetsController::index::authenticated user::returns widgets"
+
+ +

The constant WidgetsController can be resolved from the name. The following code will resolve the constant:

+ +
controller = determine_constant_from_test_name(name) do |constant|
+  Class === constant && constant < ::ActionController::Metal
+end
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Declarative.html b/src/7.0/classes/ActiveSupport/Testing/Declarative.html new file mode 100644 index 0000000000..265632ac22 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Declarative.html @@ -0,0 +1,115 @@ +--- +title: ActiveSupport::Testing::Declarative +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + test(name, &block) + +

+ + +
+

Helper to define a test method using a String. Under the hood, it replaces spaces with underscores and defines the test method.

+ +
test "verify something" do
+  ...
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/declarative.rb, line 13
+def test(name, &block)
+  test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
+  defined = method_defined? test_name
+  raise "#{test_name} is already defined in #{self}" if defined
+  if block_given?
+    define_method(test_name, &block)
+  else
+    define_method(test_name) do
+      flunk "No implementation provided for #{name}"
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Deprecation.html b/src/7.0/classes/ActiveSupport/Testing/Deprecation.html new file mode 100644 index 0000000000..170aeb25a2 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Deprecation.html @@ -0,0 +1,251 @@ +--- +title: ActiveSupport::Testing::Deprecation +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_deprecated(match = nil, deprecator = nil, &block) + +

+ + +
+

Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block.

+ +
assert_deprecated(/foo/, CustomDeprecator) do
+  CustomDeprecator.warn "foo should no longer be used"
+end
+
+ +

The match object may be a Regexp, or String appearing in the message.

+ +
assert_deprecated('foo', CustomDeprecator) do
+  CustomDeprecator.warn "foo should no longer be used"
+end
+
+ +

If the match is omitted (or explicitly nil), any deprecation warning will match.

+ +
assert_deprecated(nil, CustomDeprecator) do
+  CustomDeprecator.warn "foo should no longer be used"
+end
+
+ +

If no deprecator is given, defaults to ActiveSupport::Deprecation.

+ +
assert_deprecated do
+  ActiveSupport::Deprecation.warn "foo should no longer be used"
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/deprecation.rb, line 31
+def assert_deprecated(match = nil, deprecator = nil, &block)
+  result, warnings = collect_deprecations(deprecator, &block)
+  assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
+  if match
+    match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
+    assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
+  end
+  result
+end
+
+
+ +
+ +
+

+ + assert_not_deprecated(deprecator = nil, &block) + +

+ + +
+

Asserts that no deprecation warnings are emitted by the given deprecator during the execution of the yielded block.

+ +
assert_not_deprecated(CustomDeprecator) do
+  CustomDeprecator.warn "message" # fails assertion
+end
+
+ +

If no deprecator is given, defaults to ActiveSupport::Deprecation.

+ +
assert_not_deprecated do
+  ActiveSupport::Deprecation.warn "message" # fails assertion
+end
+
+assert_not_deprecated do
+  CustomDeprecator.warn "message" # passes assertion
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/deprecation.rb, line 56
+def assert_not_deprecated(deprecator = nil, &block)
+  result, deprecations = collect_deprecations(deprecator, &block)
+  assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n  #{deprecations * "\n  "}"
+  result
+end
+
+
+ +
+ +
+

+ + collect_deprecations(deprecator = nil) + +

+ + +
+

Returns an array of all the deprecation warnings emitted by the given deprecator during the execution of the yielded block.

+ +
collect_deprecations(CustomDeprecator) do
+  CustomDeprecator.warn "message"
+end # => ["message"]
+
+ +

If no deprecator is given, defaults to ActiveSupport::Deprecation.

+ +
collect_deprecations do
+  CustomDeprecator.warn "custom message"
+  ActiveSupport::Deprecation.warn "message"
+end # => ["message"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/deprecation.rb, line 75
+def collect_deprecations(deprecator = nil)
+  deprecator ||= ActiveSupport::Deprecation
+  old_behavior = deprecator.behavior
+  deprecations = []
+  deprecator.behavior = Proc.new do |message, callstack|
+    deprecations << message
+  end
+  result = yield
+  [result, deprecations]
+ensure
+  deprecator.behavior = old_behavior
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/FileFixtures.html b/src/7.0/classes/ActiveSupport/Testing/FileFixtures.html new file mode 100644 index 0000000000..c258766739 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/FileFixtures.html @@ -0,0 +1,122 @@ +--- +title: ActiveSupport::Testing::FileFixtures +layout: default +--- +
+ +
+
+ +
+ +

Adds simple access to sample files called file fixtures. File fixtures are normal files stored in ActiveSupport::TestCase.file_fixture_path.

+ +

File fixtures are represented as Pathname objects. This makes it easy to extract specific information:

+ +
file_fixture("example.txt").read # get the file's content
+file_fixture("example.mp3").size # get the file size
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + file_fixture(fixture_name) + +

+ + +
+

Returns a Pathname to the fixture file named fixture_name.

+ +

Raises ArgumentError if fixture_name can’t be found.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/file_fixtures.rb, line 26
+def file_fixture(fixture_name)
+  path = Pathname.new(File.join(file_fixture_path, fixture_name))
+
+  if path.exist?
+    path
+  else
+    msg = "the directory '%s' does not contain a file named '%s'"
+    raise ArgumentError, msg % [file_fixture_path, fixture_name]
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Isolation.html b/src/7.0/classes/ActiveSupport/Testing/Isolation.html new file mode 100644 index 0000000000..5d450f4f1c --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Isolation.html @@ -0,0 +1,162 @@ +--- +title: ActiveSupport::Testing::Isolation +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + forking_env?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/isolation.rb, line 14
+def self.forking_env?
+  !ENV["NO_FORK"] && Process.respond_to?(:fork)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + run() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/isolation.rb, line 18
+def run
+  serialized = run_in_isolation do
+    super
+  end
+
+  Marshal.load(serialized)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Isolation/Forking.html b/src/7.0/classes/ActiveSupport/Testing/Isolation/Forking.html new file mode 100644 index 0000000000..defbdc2cef --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Isolation/Forking.html @@ -0,0 +1,133 @@ +--- +title: ActiveSupport::Testing::Isolation::Forking +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + run_in_isolation(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/isolation.rb, line 27
+def run_in_isolation(&blk)
+  IO.pipe do |read, write|
+    read.binmode
+    write.binmode
+
+    pid = fork do
+      read.close
+      yield
+      begin
+        if error?
+          failures.map! { |e|
+            begin
+              Marshal.dump e
+              e
+            rescue TypeError
+              ex = Exception.new e.message
+              ex.set_backtrace e.backtrace
+              Minitest::UnexpectedError.new ex
+            end
+          }
+        end
+        test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
+        result = Marshal.dump(test_result)
+      end
+
+      write.puts [result].pack("m")
+      exit!
+    end
+
+    write.close
+    result = read.read
+    Process.wait2(pid)
+    result.unpack1("m")
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Isolation/Subprocess.html b/src/7.0/classes/ActiveSupport/Testing/Isolation/Subprocess.html new file mode 100644 index 0000000000..c065923a2f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Isolation/Subprocess.html @@ -0,0 +1,153 @@ +--- +title: ActiveSupport::Testing::Isolation::Subprocess +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ORIG_ARGV=ARGV.dup unless defined?(ORIG_ARGV)
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + run_in_isolation(&blk) + +

+ + +
+

Complicated H4X to get this working in windows / jruby with no forking.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/isolation.rb, line 69
+def run_in_isolation(&blk)
+  require "tempfile"
+
+  if ENV["ISOLATION_TEST"]
+    yield
+    test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
+    File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
+      file.puts [Marshal.dump(test_result)].pack("m")
+    end
+    exit!
+  else
+    Tempfile.open("isolation") do |tmpfile|
+      env = {
+        "ISOLATION_TEST" => self.class.name,
+        "ISOLATION_OUTPUT" => tmpfile.path
+      }
+
+      test_opts = "-n#{self.class.name}##{name}"
+
+      load_path_args = []
+      $-I.each do |p|
+        load_path_args << "-I"
+        load_path_args << File.expand_path(p)
+      end
+
+      child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
+
+      begin
+        Process.wait(child.pid)
+      rescue Errno::ECHILD # The child process may exit before we wait
+        nil
+      end
+
+      return tmpfile.read.unpack1("m")
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Parallelization.html b/src/7.0/classes/ActiveSupport/Testing/Parallelization.html new file mode 100644 index 0000000000..621065467d --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Parallelization.html @@ -0,0 +1,79 @@ +--- +title: ActiveSupport::Testing::Parallelization +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Parallelization/Server.html b/src/7.0/classes/ActiveSupport/Testing/Parallelization/Server.html new file mode 100644 index 0000000000..21d3ee501f --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Parallelization/Server.html @@ -0,0 +1,466 @@ +--- +title: ActiveSupport::Testing::Parallelization::Server +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + DRb::DRbUndumped + +
  • + +
+ + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 12
+def initialize
+  @queue = Queue.new
+  @active_workers = Concurrent::Map.new
+  @in_flight = Concurrent::Map.new
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(o) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 28
+def <<(o)
+  o[2] = DRbObject.new(o[2]) if o
+  @queue << o
+end
+
+
+ +
+ +
+

+ + active_workers?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 48
+def active_workers?
+  @active_workers.size > 0
+end
+
+
+ +
+ +
+

+ + interrupt() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 52
+def interrupt
+  @queue.clear
+end
+
+
+ +
+ +
+

+ + pop() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 33
+def pop
+  if test = @queue.pop
+    @in_flight[[test[0].to_s, test[1]]] = test
+    test
+  end
+end
+
+
+ +
+ +
+

+ + record(reporter, result) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 18
+def record(reporter, result)
+  raise DRb::DRbConnError if result.is_a?(DRb::DRbUnknown)
+
+  @in_flight.delete([result.klass, result.name])
+
+  reporter.synchronize do
+    reporter.record(result)
+  end
+end
+
+
+ +
+ +
+

+ + shutdown() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 56
+def shutdown
+  # Wait for initial queue to drain
+  while @queue.length != 0
+    sleep 0.1
+  end
+
+  @queue.close
+
+  # Wait until all workers have finished
+  while active_workers?
+    sleep 0.1
+  end
+
+  @in_flight.values.each do |(klass, name, reporter)|
+    result = Minitest::Result.from(klass.new(name))
+    error = RuntimeError.new("result not reported")
+    error.set_backtrace([""])
+    result.failures << Minitest::UnexpectedError.new(error)
+    reporter.synchronize do
+      reporter.record(result)
+    end
+  end
+end
+
+
+ +
+ +
+

+ + start_worker(worker_id) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 40
+def start_worker(worker_id)
+  @active_workers[worker_id] = true
+end
+
+
+ +
+ +
+

+ + stop_worker(worker_id) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/server.rb, line 44
+def stop_worker(worker_id)
+  @active_workers.delete(worker_id)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/Parallelization/Worker.html b/src/7.0/classes/ActiveSupport/Testing/Parallelization/Worker.html new file mode 100644 index 0000000000..96002c8501 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/Parallelization/Worker.html @@ -0,0 +1,401 @@ +--- +title: ActiveSupport::Testing::Parallelization::Worker +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(number, url) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 7
+def initialize(number, url)
+  @id = SecureRandom.uuid
+  @number = number
+  @url = url
+  @setup_exception = nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + after_fork() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 80
+def after_fork
+  Parallelization.after_fork_hooks.each do |cb|
+    cb.call(@number)
+  end
+end
+
+
+ +
+ +
+

+ + perform_job(job) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 42
+def perform_job(job)
+  klass    = job[0]
+  method   = job[1]
+  reporter = job[2]
+
+  set_process_title("#{klass}##{method}")
+
+  result = klass.with_info_handler reporter do
+    Minitest.run_one_method(klass, method)
+  end
+
+  safe_record(reporter, result)
+end
+
+
+ +
+ +
+

+ + run_cleanup() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 86
+def run_cleanup
+  Parallelization.run_cleanup_hooks.each do |cb|
+    cb.call(@number)
+  end
+end
+
+
+ +
+ +
+

+ + safe_record(reporter, result) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 56
+def safe_record(reporter, result)
+  add_setup_exception(result) if @setup_exception
+
+  begin
+    @queue.record(reporter, result)
+  rescue DRb::DRbConnError
+    result.failures.map! do |failure|
+      if failure.respond_to?(:error)
+        # minitest >5.14.0
+        error = DRb::DRbRemoteError.new(failure.error)
+      else
+        error = DRb::DRbRemoteError.new(failure.exception)
+      end
+      Minitest::UnexpectedError.new(error)
+    end
+    @queue.record(reporter, result)
+  rescue Interrupt
+    @queue.interrupt
+    raise
+  end
+
+  set_process_title("(idle)")
+end
+
+
+ +
+ +
+

+ + start() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 14
+def start
+  fork do
+    set_process_title("(starting)")
+
+    DRb.stop_service
+
+    @queue = DRbObject.new_with_uri(@url)
+    @queue.start_worker(@id)
+
+    begin
+      after_fork
+    rescue => @setup_exception; end
+
+    work_from_queue
+  ensure
+    set_process_title("(stopping)")
+
+    run_cleanup
+    @queue.stop_worker(@id)
+  end
+end
+
+
+ +
+ +
+

+ + work_from_queue() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/parallelization/worker.rb, line 36
+def work_from_queue
+  while job = @queue.pop
+    perform_job(job)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown.html b/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown.html new file mode 100644 index 0000000000..7fe6e2222b --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown.html @@ -0,0 +1,147 @@ +--- +title: ActiveSupport::Testing::SetupAndTeardown +layout: default +--- +
+ +
+
+ +
+ +

Adds support for setup and teardown callbacks. These callbacks serve as a replacement to overwriting the #setup and #teardown methods of your TestCase.

+ +
class ExampleTest < ActiveSupport::TestCase
+  setup do
+    # ...
+  end
+
+  teardown do
+    # ...
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + prepended(klass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/setup_and_teardown.rb, line 21
+def self.prepended(klass)
+  klass.include ActiveSupport::Callbacks
+  klass.define_callbacks :setup, :teardown
+  klass.extend ClassMethods
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown/ClassMethods.html b/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown/ClassMethods.html new file mode 100644 index 0000000000..95e2469f33 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/SetupAndTeardown/ClassMethods.html @@ -0,0 +1,140 @@ +--- +title: ActiveSupport::Testing::SetupAndTeardown::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + setup(*args, &block) + +

+ + +
+

Add a callback, which runs before TestCase#setup.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/setup_and_teardown.rb, line 29
+def setup(*args, &block)
+  set_callback(:setup, :before, *args, &block)
+end
+
+
+ +
+ +
+

+ + teardown(*args, &block) + +

+ + +
+

Add a callback, which runs after TestCase#teardown.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/setup_and_teardown.rb, line 34
+def teardown(*args, &block)
+  set_callback(:teardown, :after, *args, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/Testing/TimeHelpers.html b/src/7.0/classes/ActiveSupport/Testing/TimeHelpers.html new file mode 100644 index 0000000000..95e62322fa --- /dev/null +++ b/src/7.0/classes/ActiveSupport/Testing/TimeHelpers.html @@ -0,0 +1,429 @@ +--- +title: ActiveSupport::Testing::TimeHelpers +layout: default +--- +
+ +
+
+ +
+ +

Contains helpers that help you test passage of time.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + after_teardown() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/time_helpers.rb, line 70
+def after_teardown
+  travel_back
+  super
+end
+
+
+ +
+ +
+

+ + freeze_time(&block) + +

+ + +
+

Calls travel_to with Time.now.

+ +
Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+freeze_time
+sleep(1)
+Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+
+ +

This method also accepts a block, which will return the current time back to its original state at the end of the block:

+ +
Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+freeze_time do
+  sleep(1)
+  User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
+end
+Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/time_helpers.rb, line 234
+def freeze_time(&block)
+  travel_to Time.now, &block
+end
+
+
+ +
+ +
+

+ + travel(duration, &block) + +

+ + +
+

Changes current time to the time in the future or in the past by a given time difference by stubbing Time.now, Date.today, and DateTime.now. The stubs are automatically removed at the end of the test.

+ +
Time.current     # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+travel 1.day
+Time.current     # => Sun, 10 Nov 2013 15:34:49 EST -05:00
+Date.current     # => Sun, 10 Nov 2013
+DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500
+
+ +

This method also accepts a block, which will return the current time back to its original state at the end of the block:

+ +
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+travel 1.day do
+  User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
+end
+Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/time_helpers.rb, line 93
+def travel(duration, &block)
+  travel_to Time.now + duration, &block
+end
+
+
+ +
+ +
+

+ + travel_back() + +

+ + +
+

Returns the current time back to its original state, by removing the stubs added by travel, travel_to, and freeze_time.

+ +
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+
+travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
+Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
+
+travel_back
+Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+
+ +

This method also accepts a block, which brings the stubs back at the end of the block:

+ +
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+
+travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
+Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
+
+travel_back do
+  Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+end
+
+Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
+
+
+ + + +
+ Also aliased as: unfreeze_time +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/time_helpers.rb, line 208
+def travel_back
+  stubbed_time = Time.current if block_given? && simple_stubs.stubbed?
+
+  simple_stubs.unstub_all!
+  yield if block_given?
+ensure
+  travel_to stubbed_time if stubbed_time
+end
+
+
+ +
+ +
+

+ + travel_to(date_or_time) + +

+ + +
+

Changes current time to the given time by stubbing Time.now, Date.today, and DateTime.now to return the time or date passed into this method. The stubs are automatically removed at the end of the test.

+ +
Time.current     # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
+Time.current     # => Wed, 24 Nov 2004 01:04:44 EST -05:00
+Date.current     # => Wed, 24 Nov 2004
+DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
+
+ +

Dates are taken as their timestamp at the beginning of the day in the application time zone. Time.current returns said timestamp, and Time.now its equivalent in the system time zone. Similarly, Date.current returns a date equal to the argument, and Date.today the date according to Time.now, which may be different. (Note that you rarely want to deal with Time.now, or Date.today, in order to honor the application time zone please always use Time.current and Date.current.)

+ +

Note that the usec for the time passed will be set to 0 to prevent rounding errors with external services, like MySQL (which will round instead of floor, leading to off-by-one-second errors).

+ +

This method also accepts a block, which will return the current time back to its original state at the end of the block:

+ +
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+travel_to Time.zone.local(2004, 11, 24, 1, 4, 44) do
+  Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
+end
+Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/testing/time_helpers.rb, line 128
+      def travel_to(date_or_time)
+        if block_given? && in_block
+          travel_to_nested_block_call = <<~MSG
+
+      Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
+
+      Instead of:
+
+         travel_to 2.days.from_now do
+           # 2 days from today
+           travel_to 3.days.from_now do
+             # 5 days from today
+           end
+         end
+
+      preferred way to achieve above is:
+
+         travel 2.days do
+           # 2 days from today
+         end
+
+         travel 5.days do
+           # 5 days from today
+         end
+
+          MSG
+          raise travel_to_nested_block_call
+        end
+
+        if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
+          now = date_or_time.midnight.to_time
+        elsif date_or_time.is_a?(String)
+          now = Time.zone.parse(date_or_time)
+        else
+          now = date_or_time.to_time.change(usec: 0)
+        end
+
+        stubbed_time = Time.now if simple_stubs.stubbing(Time, :now)
+        simple_stubs.stub_object(Time, :now) { at(now.to_i) }
+        simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
+        simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
+
+        if block_given?
+          begin
+            self.in_block = true
+            yield
+          ensure
+            if stubbed_time
+              travel_to stubbed_time
+            else
+              travel_back
+            end
+            self.in_block = false
+          end
+        end
+      end
+
+
+ +
+ +
+

+ + unfreeze_time() + +

+ + +
+ +
+ + + + + +
+ Alias for: travel_back +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/TimeWithZone.html b/src/7.0/classes/ActiveSupport/TimeWithZone.html new file mode 100644 index 0000000000..674ba875ca --- /dev/null +++ b/src/7.0/classes/ActiveSupport/TimeWithZone.html @@ -0,0 +1,2849 @@ +--- +title: ActiveSupport::TimeWithZone +layout: default +--- +
+ +
+
+ +
+ +

A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are limited to UTC and the system’s ENV['TZ'] zone.

+ +

You shouldn’t ever need to create a TimeWithZone instance directly via new. Instead use methods local, parse, at, and now on TimeZone instances, and in_time_zone on Time and DateTime instances.

+ +
Time.zone = 'Eastern Time (US & Canada)'        # => 'Eastern Time (US & Canada)'
+Time.zone.local(2007, 2, 10, 15, 30, 45)        # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
+Time.zone.parse('2007-02-10 15:30:45')          # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
+Time.zone.at(1171139445)                        # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
+Time.zone.now                                   # => Sun, 18 May 2008 13:07:55.754107581 EDT -04:00
+Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone  # => Sat, 10 Feb 2007 15:30:45.000000000 EST -05:00
+
+ +

See Time and TimeZone for further documentation of these methods.

+ +

TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangeable.

+ +
t = Time.zone.now                     # => Sun, 18 May 2008 13:27:25.031505668 EDT -04:00
+t.hour                                # => 13
+t.dst?                                # => true
+t.utc_offset                          # => -14400
+t.zone                                # => "EDT"
+t.to_fs(:rfc822)                      # => "Sun, 18 May 2008 13:27:25 -0400"
+t + 1.day                             # => Mon, 19 May 2008 13:27:25.031505668 EDT -04:00
+t.beginning_of_year                   # => Tue, 01 Jan 2008 00:00:00.000000000 EST -05:00
+t > Time.utc(1999)                    # => true
+t.is_a?(Time)                         # => true
+t.is_a?(ActiveSupport::TimeWithZone)  # => true
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
PRECISIONS=Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" }
 
SECONDS_PER_DAY=86400
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + time_zone
+ + + + +

Class Public methods

+ +
+

+ + name() + +

+ + +
+

Report class name as ‘Time’ to thwart type checking.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 44
+    def self.name
+      ActiveSupport::Deprecation.warn(<<~EOM)
+        ActiveSupport::TimeWithZone.name has been deprecated and
+        from Rails 7.1 will use the default Ruby implementation.
+        You can set `config.active_support.remove_deprecated_time_with_zone_name = true`
+        to enable the new behavior now.
+      EOM
+
+      "Time"
+    end
+
+
+ +
+ +
+

+ + new(utc_time, time_zone, local_time = nil, period = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 61
+def initialize(utc_time, time_zone, local_time = nil, period = nil)
+  @utc = utc_time ? transfer_time_values_to_utc_constructor(utc_time) : nil
+  @time_zone, @time = time_zone, local_time
+  @period = @utc ? period : get_period_and_ensure_valid_local_time(period)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + +(other) + +

+ + +
+

Adds an interval of time to the current object’s time and returns that value as a new TimeWithZone object.

+ +
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
+now + 1000          # => Sun, 02 Nov 2014 01:43:08.725182881 EDT -04:00
+
+ +

If we’re adding a Duration of variable length (i.e., years, months, days), move forward from time, otherwise move forward from utc, for accuracy when moving across DST boundaries.

+ +

For instance, a time + 24.hours will advance exactly 24 hours, while a time + 1.day will advance 23-25 hours, depending on the day.

+ +
now + 24.hours      # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
+now + 1.day         # => Mon, 03 Nov 2014 01:26:28.725182881 EST -05:00
+
+
+ + + +
+ Also aliased as: since, in +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 309
+def +(other)
+  if duration_of_variable_length?(other)
+    method_missing(:+, other)
+  else
+    result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other)
+    result.in_time_zone(time_zone)
+  end
+end
+
+
+ +
+ +
+

+ + -(other) + +

+ + +
+

Subtracts an interval of time and returns a new TimeWithZone object unless the other value acts_like? time. In which case, it will subtract the other time and return the difference in seconds as a Float.

+ +
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
+now - 1000          # => Mon, 03 Nov 2014 00:09:48.725182881 EST -05:00
+
+ +

If subtracting a Duration of variable length (i.e., years, months, days), move backward from time, otherwise move backward from utc, for accuracy when moving across DST boundaries.

+ +

For instance, a time - 24.hours will go subtract exactly 24 hours, while a time - 1.day will subtract 23-25 hours, depending on the day.

+ +
now - 24.hours      # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
+now - 1.day         # => Sun, 02 Nov 2014 00:26:28.725182881 EDT -04:00
+
+ +

If both the TimeWithZone object and the other value act like Time, a Float will be returned.

+ +
Time.zone.now - 1.day.ago # => 86399.999967
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 343
+def -(other)
+  if other.acts_like?(:time)
+    to_time - other.to_time
+  elsif duration_of_variable_length?(other)
+    method_missing(:-, other)
+  else
+    result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other)
+    result.in_time_zone(time_zone)
+  end
+end
+
+
+ +
+ +
+

+ + <=>(other) + +

+ + +
+

Use the time in UTC for comparisons.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 242
+def <=>(other)
+  utc <=> other
+end
+
+
+ +
+ +
+

+ + acts_like_time?() + +

+ + +
+

So that self acts_like?(:time).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 504
+def acts_like_time?
+  true
+end
+
+
+ +
+ +
+

+ + advance(options) + +

+ + +
+

Uses Date to provide precise Time calculations for years, months, and days according to the proleptic Gregorian calendar. The result is returned as a new TimeWithZone object.

+ +

The options parameter takes a hash with any of these keys: :years, :months, :weeks, :days, :hours, :minutes, :seconds.

+ +

If advancing by a value of variable length (i.e., years, weeks, months, days), move forward from time, otherwise move forward from utc, for accuracy when moving across DST boundaries.

+ +
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+now = Time.zone.now # => Sun, 02 Nov 2014 01:26:28.558049687 EDT -04:00
+now.advance(seconds: 1) # => Sun, 02 Nov 2014 01:26:29.558049687 EDT -04:00
+now.advance(minutes: 1) # => Sun, 02 Nov 2014 01:27:28.558049687 EDT -04:00
+now.advance(hours: 1)   # => Sun, 02 Nov 2014 01:26:28.558049687 EST -05:00
+now.advance(days: 1)    # => Mon, 03 Nov 2014 01:26:28.558049687 EST -05:00
+now.advance(weeks: 1)   # => Sun, 09 Nov 2014 01:26:28.558049687 EST -05:00
+now.advance(months: 1)  # => Tue, 02 Dec 2014 01:26:28.558049687 EST -05:00
+now.advance(years: 1)   # => Mon, 02 Nov 2015 01:26:28.558049687 EST -05:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 432
+def advance(options)
+  # If we're advancing a value of variable length (i.e., years, weeks, months, days), advance from #time,
+  # otherwise advance from #utc, for accuracy when moving across DST boundaries
+  if options.values_at(:years, :weeks, :months, :days).any?
+    method_missing(:advance, options)
+  else
+    utc.advance(options).in_time_zone(time_zone)
+  end
+end
+
+
+ +
+ +
+

+ + ago(other) + +

+ + +
+

Subtracts an interval of time from the current object’s time and returns the result as a new TimeWithZone object.

+ +
Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+now = Time.zone.now # => Mon, 03 Nov 2014 00:26:28.725182881 EST -05:00
+now.ago(1000)       # => Mon, 03 Nov 2014 00:09:48.725182881 EST -05:00
+
+ +

If we’re subtracting a Duration of variable length (i.e., years, months, days), move backward from time, otherwise move backward from utc, for accuracy when moving across DST boundaries.

+ +

For instance, time.ago(24.hours) will move back exactly 24 hours, while time.ago(1.day) will move back 23-25 hours, depending on the day.

+ +
now.ago(24.hours)   # => Sun, 02 Nov 2014 01:26:28.725182881 EDT -04:00
+now.ago(1.day)      # => Sun, 02 Nov 2014 00:26:28.725182881 EDT -04:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 371
+def ago(other)
+  since(-other)
+end
+
+
+ +
+ +
+

+ + as_json(options = nil) + +

+ + +
+

Coerces time to a string for JSON encoding. The default format is ISO 8601. You can get %Y/%m/%d %H:%M:%S +offset style by setting ActiveSupport::JSON::Encoding.use_standard_json_time_format to false.

+ +
# With ActiveSupport::JSON::Encoding.use_standard_json_time_format = true
+Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
+# => "2005-02-01T05:15:10.000-10:00"
+
+# With ActiveSupport::JSON::Encoding.use_standard_json_time_format = false
+Time.utc(2005,2,1,15,15,10).in_time_zone("Hawaii").to_json
+# => "2005/02/01 05:15:10 -1000"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 176
+def as_json(options = nil)
+  if ActiveSupport::JSON::Encoding.use_standard_json_time_format
+    xmlschema(ActiveSupport::JSON::Encoding.time_precision)
+  else
+    %(#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)})
+  end
+end
+
+
+ +
+ +
+

+ + between?(min, max) + +

+ + +
+

Returns true if the current object’s time is within the specified min and max time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 250
+def between?(min, max)
+  utc.between?(min, max)
+end
+
+
+ +
+ +
+

+ + blank?() + +

+ + +
+

An instance of ActiveSupport::TimeWithZone is never blank

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 515
+def blank?
+  false
+end
+
+
+ +
+ +
+

+ + change(options) + +

+ + +
+

Returns a new ActiveSupport::TimeWithZone where one or more of the elements have been changed according to the options parameter. The time options (:hour, :min, :sec, :usec, :nsec) reset cascadingly, so if only the hour is passed, then minute, sec, usec, and nsec is set to 0. If the hour and minute is passed, then sec, usec, and nsec is set to 0. The options parameter takes a hash with any of these keys: :year, :month, :day, :hour, :min, :sec, :usec, :nsec, :offset, :zone. Pass either :usec or :nsec, not both. Similarly, pass either :zone or :offset, not both.

+ +
t = Time.zone.now          # => Fri, 14 Apr 2017 11:45:15.116992711 EST -05:00
+t.change(year: 2020)       # => Tue, 14 Apr 2020 11:45:15.116992711 EST -05:00
+t.change(hour: 12)         # => Fri, 14 Apr 2017 12:00:00.116992711 EST -05:00
+t.change(min: 30)          # => Fri, 14 Apr 2017 11:30:00.116992711 EST -05:00
+t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
+t.change(zone: "Hawaii")   # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 392
+def change(options)
+  if options[:zone] && options[:offset]
+    raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
+  end
+
+  new_time = time.change(options)
+
+  if options[:zone]
+    new_zone = ::Time.find_zone(options[:zone])
+  elsif options[:offset]
+    new_zone = ::Time.find_zone(new_time.utc_offset)
+  end
+
+  new_zone ||= time_zone
+  periods = new_zone.periods_for_local(new_time)
+
+  self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
+end
+
+
+ +
+ +
+

+ + comparable_time() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + dst?() + +

+ + +
+

Returns true if the current time is within Daylight Savings Time for the specified time zone.

+ +
Time.zone = 'Eastern Time (US & Canada)'    # => 'Eastern Time (US & Canada)'
+Time.zone.parse("2012-5-30").dst?           # => true
+Time.zone.parse("2012-11-30").dst?          # => false
+
+
+ + + +
+ Also aliased as: isdst +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 104
+def dst?
+  period.dst?
+end
+
+
+ +
+ +
+

+ + eql?(other) + +

+ + +
+

Returns true if other is equal to current object.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 285
+def eql?(other)
+  other.eql?(utc)
+end
+
+
+ +
+ +
+

+ + formatted_offset(colon = true, alternate_utc_string = nil) + +

+ + +
+

Returns a formatted string of the offset from UTC, or an alternative string if the time zone is already UTC.

+ +
Time.zone = 'Eastern Time (US & Canada)'   # => "Eastern Time (US & Canada)"
+Time.zone.now.formatted_offset(true)       # => "-05:00"
+Time.zone.now.formatted_offset(false)      # => "-0500"
+Time.zone = 'UTC'                          # => "UTC"
+Time.zone.now.formatted_offset(true, "0")  # => "0"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 135
+def formatted_offset(colon = true, alternate_utc_string = nil)
+  utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
+end
+
+
+ +
+ +
+

+ + freeze() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 519
+def freeze
+  # preload instance variables before freezing
+  period; utc; time; to_datetime; to_time
+  super
+end
+
+
+ +
+ +
+

+ + future?() + +

+ + +
+

Returns true if the current object’s time is in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 280
+def future?
+  utc.future?
+end
+
+
+ +
+ +
+

+ + getgm() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + getlocal(utc_offset = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: localtime +
+ + + +
+ +
+

+ + getutc() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + gmt?() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc? +
+ + + +
+ +
+

+ + gmt_offset() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc_offset +
+ + + +
+ +
+

+ + gmtime() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + gmtoff() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc_offset +
+ + + +
+ +
+

+ + hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 289
+def hash
+  utc.hash
+end
+
+
+ +
+ +
+

+ + httpdate() + +

+ + +
+

Returns a string of the object’s date and time in the format used by HTTP requests.

+ +
Time.zone.now.httpdate  # => "Tue, 01 Jan 2013 04:39:43 GMT"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 196
+def httpdate
+  utc.httpdate
+end
+
+
+ +
+ +
+

+ + in(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: + +
+ + + +
+ +
+

+ + in_time_zone(new_zone = ::Time.zone) + +

+ + +
+

Returns the simultaneous time in Time.zone, or the specified zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 87
+def in_time_zone(new_zone = ::Time.zone)
+  return self if time_zone == new_zone
+  utc.in_time_zone(new_zone)
+end
+
+
+ +
+ +
+

+ + inspect() + +

+ + +
+

Returns a string of the object’s date, time, zone, and offset from UTC.

+ +
Time.zone.now.inspect # => "Thu, 04 Dec 2014 11:00:25.624541392 EST -05:00"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 150
+def inspect
+  "#{time.strftime('%a, %d %b %Y %H:%M:%S.%9N')} #{zone} #{formatted_offset}"
+end
+
+
+ +
+ +
+

+ + is_a?(klass) + +

+ + +
+

Say we’re a Time to thwart type checking.

+
+ + + +
+ Also aliased as: kind_of? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 509
+def is_a?(klass)
+  klass == ::Time || super
+end
+
+
+ +
+ +
+

+ + isdst() + +

+ + +
+ +
+ + + + + +
+ Alias for: dst? +
+ + + +
+ +
+

+ + iso8601(fraction_digits = 0) + +

+ + +
+ +
+ + + + + +
+ Alias for: xmlschema +
+ + + +
+ +
+

+ + kind_of?(klass) + +

+ + +
+ +
+ + + + + +
+ Alias for: is_a? +
+ + + +
+ +
+

+ + localtime(utc_offset = nil) + +

+ + +
+

Returns a Time instance of the simultaneous time in the system timezone.

+
+ + + +
+ Also aliased as: getlocal +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 93
+def localtime(utc_offset = nil)
+  utc.getlocal(utc_offset)
+end
+
+
+ +
+ +
+

+ + marshal_dump() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 525
+def marshal_dump
+  [utc, time_zone.name, time]
+end
+
+
+ +
+ +
+

+ + marshal_load(variables) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 529
+def marshal_load(variables)
+  initialize(variables[0].utc, ::Time.find_zone(variables[1]), variables[2].utc)
+end
+
+
+ +
+ +
+

+ + method_missing(...) + +

+ + +
+

Send the missing method to time instance, and wrap result in a new TimeWithZone with the existing time_zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 550
+def method_missing(...)
+  wrap_with_time_zone time.__send__(...)
+rescue NoMethodError => e
+  raise e, e.message.sub(time.inspect, inspect).sub("Time", "ActiveSupport::TimeWithZone"), e.backtrace
+end
+
+
+ +
+ +
+

+ + next_day?() + +

+ + +
+ +
+ + + + + +
+ Alias for: tomorrow? +
+ + + +
+ +
+

+ + past?() + +

+ + +
+

Returns true if the current object’s time is in the past.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 255
+def past?
+  utc.past?
+end
+
+
+ +
+ +
+

+ + period() + +

+ + +
+

Returns the underlying TZInfo::TimezonePeriod.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 82
+def period
+  @period ||= time_zone.period_for_utc(@utc)
+end
+
+
+ +
+ +
+

+ + prev_day?() + +

+ + +
+ +
+ + + + + +
+ Alias for: yesterday? +
+ + + +
+ +
+

+ + respond_to?(sym, include_priv = false) + +

+ + +
+

respond_to_missing? is not called in some cases, such as when type conversion is performed with Kernel#String

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 535
+def respond_to?(sym, include_priv = false)
+  # ensure that we're not going to throw and rescue from NoMethodError in method_missing which is slow
+  return false if sym.to_sym == :to_str
+  super
+end
+
+
+ +
+ +
+

+ + respond_to_missing?(sym, include_priv) + +

+ + +
+

Ensure proxy class responds to all methods that underlying time instance responds to.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 543
+def respond_to_missing?(sym, include_priv)
+  return false if sym.to_sym == :acts_like_date?
+  time.respond_to?(sym, include_priv)
+end
+
+
+ +
+ +
+

+ + rfc2822() + +

+ + +
+

Returns a string of the object’s date and time in the RFC 2822 standard format.

+ +
Time.zone.now.rfc2822  # => "Tue, 01 Jan 2013 04:51:39 +0000"
+
+
+ + + +
+ Also aliased as: rfc822 +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 204
+def rfc2822
+  to_fs(:rfc822)
+end
+
+
+ +
+ +
+

+ + rfc3339(fraction_digits = 0) + +

+ + +
+ +
+ + + + + +
+ Alias for: xmlschema +
+ + + +
+ +
+

+ + rfc822() + +

+ + +
+ +
+ + + + + +
+ Alias for: rfc2822 +
+ + + +
+ +
+

+ + since(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: + +
+ + + +
+ +
+

+ + strftime(format) + +

+ + +
+

Replaces %Z directive with +zone before passing to Time#strftime, so that zone information is correct.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 236
+def strftime(format)
+  format = format.gsub(/((?:\A|[^%])(?:%%)*)%Z/, "\\1#{zone}")
+  getlocal(utc_offset).strftime(format)
+end
+
+
+ +
+ +
+

+ + time() + +

+ + +
+

Returns a Time instance that represents the time in time_zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 68
+def time
+  @time ||= incorporate_utc_offset(@utc, utc_offset)
+end
+
+
+ +
+ +
+

+ + to_a() + +

+ + +
+

Returns Array of parts of Time in sequence of [seconds, minutes, hours, day, month, year, weekday, yearday, dst?, zone].

+ +
now = Time.zone.now     # => Tue, 18 Aug 2015 02:29:27.485278555 UTC +00:00
+now.to_a                # => [27, 29, 2, 18, 8, 2015, 2, 230, false, "UTC"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 455
+def to_a
+  [time.sec, time.min, time.hour, time.day, time.mon, time.year, time.wday, time.yday, dst?, zone]
+end
+
+
+ +
+ +
+

+ + to_datetime() + +

+ + +
+

Returns an instance of DateTime with the timezone’s UTC offset

+ +
Time.zone.now.to_datetime                         # => Tue, 18 Aug 2015 02:32:20 +0000
+Time.current.in_time_zone('Hawaii').to_datetime   # => Mon, 17 Aug 2015 16:32:20 -1000
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 488
+def to_datetime
+  @to_datetime ||= utc.to_datetime.new_offset(Rational(utc_offset, 86_400))
+end
+
+
+ +
+ +
+

+ + to_f() + +

+ + +
+

Returns the object’s date and time as a floating-point number of seconds since the Epoch (January 1, 1970 00:00 UTC).

+ +
Time.zone.now.to_f # => 1417709320.285418
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 463
+def to_f
+  utc.to_f
+end
+
+
+ +
+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Returns a string of the object’s date and time.

+ +

This method is aliased to to_formatted_s.

+ +

Accepts an optional format:

+
  • +

    :default - default value, mimics Ruby Time#to_s format.

    +
  • +

    :db - format outputs time in UTC :db time. See Time#to_fs(:db).

    +
  • +

    Any key in Time::DATE_FORMATS can be used. See active_support/core_ext/time/conversions.rb.

    +
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 222
+def to_fs(format = :default)
+  if format == :db
+    utc.to_fs(format)
+  elsif formatter = ::Time::DATE_FORMATS[format]
+    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
+  else
+    # Change to to_s when deprecation is gone.
+    "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}"
+  end
+end
+
+
+ +
+ +
+

+ + to_i() + +

+ + +
+

Returns the object’s date and time as an integer number of seconds since the Epoch (January 1, 1970 00:00 UTC).

+ +
Time.zone.now.to_i # => 1417709320
+
+
+ + + +
+ Also aliased as: tv_sec +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 471
+def to_i
+  utc.to_i
+end
+
+
+ +
+ +
+

+ + to_r() + +

+ + +
+

Returns the object’s date and time as a rational number of seconds since the Epoch (January 1, 1970 00:00 UTC).

+ +
Time.zone.now.to_r # => (708854548642709/500000)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 480
+def to_r
+  utc.to_r
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+

Returns a string of the object’s date and time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 210
+def to_s
+  "#{time.strftime("%Y-%m-%d %H:%M:%S")} #{formatted_offset(false, 'UTC')}" # mimicking Ruby Time#to_s format
+end
+
+
+ +
+ +
+

+ + to_time() + +

+ + +
+

Returns an instance of Time, either with the same UTC offset as self or in the local system timezone depending on the setting of ActiveSupport.to_time_preserves_timezone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 495
+def to_time
+  if preserve_timezone
+    @to_time_with_instance_offset ||= getlocal(utc_offset)
+  else
+    @to_time_with_system_offset ||= getlocal
+  end
+end
+
+
+ +
+ +
+

+ + today?() + +

+ + +
+

Returns true if the current object’s time falls within the current day.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 261
+def today?
+  time.today?
+end
+
+
+ +
+ +
+

+ + tomorrow?() + +

+ + +
+

Returns true if the current object’s time falls within the next day (tomorrow).

+
+ + + +
+ Also aliased as: next_day? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 267
+def tomorrow?
+  time.tomorrow?
+end
+
+
+ +
+ +
+

+ + tv_sec() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_i +
+ + + +
+ +
+

+ + utc() + +

+ + +
+

Returns a Time instance of the simultaneous time in the UTC timezone.

+
+ + + +
+ Also aliased as: comparable_time, getgm, getutc, gmtime +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 73
+def utc
+  @utc ||= incorporate_utc_offset(@time, -utc_offset)
+end
+
+
+ +
+ +
+

+ + utc?() + +

+ + +
+

Returns true if the current time zone is set to UTC.

+ +
Time.zone = 'UTC'                           # => 'UTC'
+Time.zone.now.utc?                          # => true
+Time.zone = 'Eastern Time (US & Canada)'    # => 'Eastern Time (US & Canada)'
+Time.zone.now.utc?                          # => false
+
+
+ + + +
+ Also aliased as: gmt? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 115
+def utc?
+  zone == "UTC" || zone == "UCT"
+end
+
+
+ +
+ +
+

+ + utc_offset() + +

+ + +
+

Returns the offset from current time to UTC time in seconds.

+
+ + + +
+ Also aliased as: gmt_offset, gmtoff +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 121
+def utc_offset
+  period.observed_utc_offset
+end
+
+
+ +
+ +
+

+ + xmlschema(fraction_digits = 0) + +

+ + +
+

Returns a string of the object’s date and time in the ISO 8601 standard format.

+ +
Time.zone.now.xmlschema  # => "2014-12-04T11:02:37-05:00"
+
+
+ + + +
+ Also aliased as: iso8601, rfc3339 +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 158
+def xmlschema(fraction_digits = 0)
+  "#{time.strftime(PRECISIONS[fraction_digits.to_i])}#{formatted_offset(true, 'Z')}"
+end
+
+
+ +
+ +
+

+ + yesterday?() + +

+ + +
+

Returns true if the current object’s time falls within the previous day (yesterday).

+
+ + + +
+ Also aliased as: prev_day? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 274
+def yesterday?
+  time.yesterday?
+end
+
+
+ +
+ +
+

+ + zone() + +

+ + +
+

Returns the time zone abbreviation.

+ +
Time.zone = 'Eastern Time (US & Canada)'   # => "Eastern Time (US & Canada)"
+Time.zone.now.zone # => "EST"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/time_with_zone.rb, line 143
+def zone
+  period.abbreviation
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/TimeZone.html b/src/7.0/classes/ActiveSupport/TimeZone.html new file mode 100644 index 0000000000..fb9796e889 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/TimeZone.html @@ -0,0 +1,1591 @@ +--- +title: ActiveSupport::TimeZone +layout: default +--- +
+ +
+
+ +
+ +

The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following:

+
  • +

    Limit the set of zones provided by TZInfo to a meaningful subset of 134 zones.

    +
  • +

    Retrieve and display zones with a friendlier name (e.g., “Eastern Time (US & Canada)” instead of “America/New_York”).

    +
  • +

    Lazily load TZInfo::Timezone instances only when they’re needed.

    +
  • +

    Create ActiveSupport::TimeWithZone instances via TimeZone’s local, parse, at, and now methods.

    +
+ +

If you set config.time_zone in the Rails Application, you can access this TimeZone object via Time.zone:

+ +
# application.rb:
+class Application < Rails::Application
+  config.time_zone = 'Eastern Time (US & Canada)'
+end
+
+Time.zone      # => #<ActiveSupport::TimeZone:0x514834...>
+Time.zone.name # => "Eastern Time (US & Canada)"
+Time.zone.now  # => Sun, 18 May 2008 14:30:44 EDT -04:00
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + Comparable + +
  • + +
+ + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
MAPPING={ +"International Date Line West" => "Etc/GMT+12", +"Midway Island" => "Pacific/Midway", +"American Samoa" => "Pacific/Pago_Pago", +"Hawaii" => "Pacific/Honolulu", +"Alaska" => "America/Juneau", +"Pacific Time (US & Canada)" => "America/Los_Angeles", +"Tijuana" => "America/Tijuana", +"Mountain Time (US & Canada)" => "America/Denver", +"Arizona" => "America/Phoenix", +"Chihuahua" => "America/Chihuahua", +"Mazatlan" => "America/Mazatlan", +"Central Time (US & Canada)" => "America/Chicago", +"Saskatchewan" => "America/Regina", +"Guadalajara" => "America/Mexico_City", +"Mexico City" => "America/Mexico_City", +"Monterrey" => "America/Monterrey", +"Central America" => "America/Guatemala", +"Eastern Time (US & Canada)" => "America/New_York", +"Indiana (East)" => "America/Indiana/Indianapolis", +"Bogota" => "America/Bogota", +"Lima" => "America/Lima", +"Quito" => "America/Lima", +"Atlantic Time (Canada)" => "America/Halifax", +"Caracas" => "America/Caracas", +"La Paz" => "America/La_Paz", +"Santiago" => "America/Santiago", +"Newfoundland" => "America/St_Johns", +"Brasilia" => "America/Sao_Paulo", +"Buenos Aires" => "America/Argentina/Buenos_Aires", +"Montevideo" => "America/Montevideo", +"Georgetown" => "America/Guyana", +"Puerto Rico" => "America/Puerto_Rico", +"Greenland" => "America/Godthab", +"Mid-Atlantic" => "Atlantic/South_Georgia", +"Azores" => "Atlantic/Azores", +"Cape Verde Is." => "Atlantic/Cape_Verde", +"Dublin" => "Europe/Dublin", +"Edinburgh" => "Europe/London", +"Lisbon" => "Europe/Lisbon", +"London" => "Europe/London", +"Casablanca" => "Africa/Casablanca", +"Monrovia" => "Africa/Monrovia", +"UTC" => "Etc/UTC", +"Belgrade" => "Europe/Belgrade", +"Bratislava" => "Europe/Bratislava", +"Budapest" => "Europe/Budapest", +"Ljubljana" => "Europe/Ljubljana", +"Prague" => "Europe/Prague", +"Sarajevo" => "Europe/Sarajevo", +"Skopje" => "Europe/Skopje", +"Warsaw" => "Europe/Warsaw", +"Zagreb" => "Europe/Zagreb", +"Brussels" => "Europe/Brussels", +"Copenhagen" => "Europe/Copenhagen", +"Madrid" => "Europe/Madrid", +"Paris" => "Europe/Paris", +"Amsterdam" => "Europe/Amsterdam", +"Berlin" => "Europe/Berlin", +"Bern" => "Europe/Zurich", +"Zurich" => "Europe/Zurich", +"Rome" => "Europe/Rome", +"Stockholm" => "Europe/Stockholm", +"Vienna" => "Europe/Vienna", +"West Central Africa" => "Africa/Algiers", +"Bucharest" => "Europe/Bucharest", +"Cairo" => "Africa/Cairo", +"Helsinki" => "Europe/Helsinki", +"Kyiv" => "Europe/Kiev", +"Riga" => "Europe/Riga", +"Sofia" => "Europe/Sofia", +"Tallinn" => "Europe/Tallinn", +"Vilnius" => "Europe/Vilnius", +"Athens" => "Europe/Athens", +"Istanbul" => "Europe/Istanbul", +"Minsk" => "Europe/Minsk", +"Jerusalem" => "Asia/Jerusalem", +"Harare" => "Africa/Harare", +"Pretoria" => "Africa/Johannesburg", +"Kaliningrad" => "Europe/Kaliningrad", +"Moscow" => "Europe/Moscow", +"St. Petersburg" => "Europe/Moscow", +"Volgograd" => "Europe/Volgograd", +"Samara" => "Europe/Samara", +"Kuwait" => "Asia/Kuwait", +"Riyadh" => "Asia/Riyadh", +"Nairobi" => "Africa/Nairobi", +"Baghdad" => "Asia/Baghdad", +"Tehran" => "Asia/Tehran", +"Abu Dhabi" => "Asia/Muscat", +"Muscat" => "Asia/Muscat", +"Baku" => "Asia/Baku", +"Tbilisi" => "Asia/Tbilisi", +"Yerevan" => "Asia/Yerevan", +"Kabul" => "Asia/Kabul", +"Ekaterinburg" => "Asia/Yekaterinburg", +"Islamabad" => "Asia/Karachi", +"Karachi" => "Asia/Karachi", +"Tashkent" => "Asia/Tashkent", +"Chennai" => "Asia/Kolkata", +"Kolkata" => "Asia/Kolkata", +"Mumbai" => "Asia/Kolkata", +"New Delhi" => "Asia/Kolkata", +"Kathmandu" => "Asia/Kathmandu", +"Astana" => "Asia/Dhaka", +"Dhaka" => "Asia/Dhaka", +"Sri Jayawardenepura" => "Asia/Colombo", +"Almaty" => "Asia/Almaty", +"Novosibirsk" => "Asia/Novosibirsk", +"Rangoon" => "Asia/Rangoon", +"Bangkok" => "Asia/Bangkok", +"Hanoi" => "Asia/Bangkok", +"Jakarta" => "Asia/Jakarta", +"Krasnoyarsk" => "Asia/Krasnoyarsk", +"Beijing" => "Asia/Shanghai", +"Chongqing" => "Asia/Chongqing", +"Hong Kong" => "Asia/Hong_Kong", +"Urumqi" => "Asia/Urumqi", +"Kuala Lumpur" => "Asia/Kuala_Lumpur", +"Singapore" => "Asia/Singapore", +"Taipei" => "Asia/Taipei", +"Perth" => "Australia/Perth", +"Irkutsk" => "Asia/Irkutsk", +"Ulaanbaatar" => "Asia/Ulaanbaatar", +"Seoul" => "Asia/Seoul", +"Osaka" => "Asia/Tokyo", +"Sapporo" => "Asia/Tokyo", +"Tokyo" => "Asia/Tokyo", +"Yakutsk" => "Asia/Yakutsk", +"Darwin" => "Australia/Darwin", +"Adelaide" => "Australia/Adelaide", +"Canberra" => "Australia/Melbourne", +"Melbourne" => "Australia/Melbourne", +"Sydney" => "Australia/Sydney", +"Brisbane" => "Australia/Brisbane", +"Hobart" => "Australia/Hobart", +"Vladivostok" => "Asia/Vladivostok", +"Guam" => "Pacific/Guam", +"Port Moresby" => "Pacific/Port_Moresby", +"Magadan" => "Asia/Magadan", +"Srednekolymsk" => "Asia/Srednekolymsk", +"Solomon Is." => "Pacific/Guadalcanal", +"New Caledonia" => "Pacific/Noumea", +"Fiji" => "Pacific/Fiji", +"Kamchatka" => "Asia/Kamchatka", +"Marshall Is." => "Pacific/Majuro", +"Auckland" => "Pacific/Auckland", +"Wellington" => "Pacific/Auckland", +"Nuku'alofa" => "Pacific/Tongatapu", +"Tokelau Is." => "Pacific/Fakaofo", +"Chatham Is." => "Pacific/Chatham", +"Samoa" => "Pacific/Apia" +}
 

Keys are Rails TimeZone names, values are TZInfo identifiers.

+ + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + name
+ [R] + tzinfo
+ + + + +

Class Public methods

+ +
+

+ + [](arg) + +

+ + +
+

Locate a specific time zone object. If the argument is a string, it is interpreted to mean the name of the timezone to locate. If it is a numeric value it is either the hour offset, or the second offset, of the timezone to find. (The first one with that offset will be returned.) Returns nil if no such time zone is known to the system.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 230
+def [](arg)
+  case arg
+  when self
+    arg
+  when String
+    begin
+      @lazy_zones_map[arg] ||= create(arg)
+    rescue TZInfo::InvalidTimezoneIdentifier
+      nil
+    end
+  when TZInfo::Timezone
+    @lazy_zones_map[arg.name] ||= create(arg.name, nil, arg)
+  when Numeric, ActiveSupport::Duration
+    arg *= 3600 if arg.abs <= 13
+    all.find { |z| z.utc_offset == arg.to_i }
+  else
+    raise ArgumentError, "invalid argument to TimeZone[]: #{arg.inspect}"
+  end
+end
+
+
+ +
+ +
+

+ + all() + +

+ + +
+

Returns an array of all TimeZone objects. There are multiple TimeZone objects per time zone, in many cases, to make it easier for users to find their own time zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 221
+def all
+  @zones ||= zones_map.values.sort
+end
+
+
+ +
+ +
+

+ + country_zones(country_code) + +

+ + +
+

A convenience method for returning a collection of TimeZone objects for time zones in the country specified by its ISO 3166-1 Alpha2 code.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 258
+def country_zones(country_code)
+  code = country_code.to_s.upcase
+  @country_zones[code] ||= load_country_zones(code)
+end
+
+
+ +
+ +
+

+ + create(name) + +

+ + +
+ +
+ + + + + +
+ Alias for: new +
+ + + +
+ +
+

+ + find_tzinfo(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 205
+def find_tzinfo(name)
+  TZInfo::Timezone.get(MAPPING[name] || name)
+end
+
+
+ +
+ +
+

+ + new(name, utc_offset = nil, tzinfo = nil) + +

+ + +
+

Create a new TimeZone object with the given name and offset. The offset is the number of seconds that this time zone is offset from UTC (GMT). Seconds were chosen as the offset unit because that is the unit that Ruby uses to represent time zone offsets (see Time#utc_offset).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 301
+def initialize(name, utc_offset = nil, tzinfo = nil)
+  @name = name
+  @utc_offset = utc_offset
+  @tzinfo = tzinfo || TimeZone.find_tzinfo(name)
+end
+
+
+ +
+ +
+

+ + new(name) + +

+ + +
+

Returns a TimeZone instance with the given name, or nil if no such TimeZone instance exists. (This exists to support the use of this class with the composed_of macro.)

+
+ + + +
+ Also aliased as: create +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 214
+def new(name)
+  self[name]
+end
+
+
+ +
+ +
+

+ + seconds_to_utc_offset(seconds, colon = true) + +

+ + +
+

Assumes self represents an offset from UTC in seconds (as returned from Time#utc_offset) and turns this into an +HH:MM formatted string.

+ +
ActiveSupport::TimeZone.seconds_to_utc_offset(-21_600) # => "-06:00"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 197
+def seconds_to_utc_offset(seconds, colon = true)
+  format = colon ? UTC_OFFSET_WITH_COLON : UTC_OFFSET_WITHOUT_COLON
+  sign = (seconds < 0 ? "-" : "+")
+  hours = seconds.abs / 3600
+  minutes = (seconds.abs % 3600) / 60
+  format % [sign, hours, minutes]
+end
+
+
+ +
+ +
+

+ + us_zones() + +

+ + +
+

A convenience method for returning a collection of TimeZone objects for time zones in the USA.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 252
+def us_zones
+  country_zones(:us)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(zone) + +

+ + +
+

Compare this time zone to the parameter. The two are compared first on their offsets, and then by name.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 324
+def <=>(zone)
+  return unless zone.respond_to? :utc_offset
+  result = (utc_offset <=> zone.utc_offset)
+  result = (name <=> zone.name) if result == 0
+  result
+end
+
+
+ +
+ +
+

+ + =~(re) + +

+ + +
+

Compare name and TZInfo identifier to a supplied regexp, returning true if a match is found.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 333
+def =~(re)
+  re === name || re === MAPPING[name]
+end
+
+
+ +
+ +
+

+ + at(*args) + +

+ + +
+

Method for creating new ActiveSupport::TimeWithZone instance in time zone of self from number of seconds since the Unix epoch.

+ +
Time.zone = 'Hawaii'        # => "Hawaii"
+Time.utc(2000).to_f         # => 946684800.0
+Time.zone.at(946684800.0)   # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+
+ +

A second argument can be supplied to specify sub-second precision.

+ +
Time.zone = 'Hawaii'                # => "Hawaii"
+Time.at(946684800, 123456.789).nsec # => 123456789
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 370
+def at(*args)
+  Time.at(*args).utc.in_time_zone(self)
+end
+
+
+ +
+ +
+

+ + formatted_offset(colon = true, alternate_utc_string = nil) + +

+ + +
+

Returns a formatted string of the offset from UTC, or an alternative string if the time zone is already UTC.

+ +
zone = ActiveSupport::TimeZone['Central Time (US & Canada)']
+zone.formatted_offset        # => "-06:00"
+zone.formatted_offset(false) # => "-0600"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 318
+def formatted_offset(colon = true, alternate_utc_string = nil)
+  utc_offset == 0 && alternate_utc_string || self.class.seconds_to_utc_offset(utc_offset, colon)
+end
+
+
+ +
+ +
+

+ + iso8601(str) + +

+ + +
+

Method for creating new ActiveSupport::TimeWithZone instance in time zone of self from an ISO 8601 string.

+ +
Time.zone = 'Hawaii'                     # => "Hawaii"
+Time.zone.iso8601('1999-12-31T14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+
+ +

If the time components are missing then they will be set to zero.

+ +
Time.zone = 'Hawaii'            # => "Hawaii"
+Time.zone.iso8601('1999-12-31') # => Fri, 31 Dec 1999 00:00:00 HST -10:00
+
+ +

If the string is invalid then an ArgumentError will be raised unlike parse which usually returns nil when given an invalid date string.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 387
+def iso8601(str)
+  # Historically `Date._iso8601(nil)` returns `{}`, but in the `date` gem versions `3.2.1`, `3.1.2`, `3.0.2`,
+  # and `2.0.1`, `Date._iso8601(nil)` raises `TypeError` https://github.com/ruby/date/issues/39
+  # Future `date` releases are expected to revert back to the original behavior.
+  raise ArgumentError, "invalid date" if str.nil?
+
+  parts = Date._iso8601(str)
+
+  year = parts.fetch(:year)
+
+  if parts.key?(:yday)
+    ordinal_date = Date.ordinal(year, parts.fetch(:yday))
+    month = ordinal_date.month
+    day = ordinal_date.day
+  else
+    month = parts.fetch(:mon)
+    day = parts.fetch(:mday)
+  end
+
+  time = Time.new(
+    year,
+    month,
+    day,
+    parts.fetch(:hour, 0),
+    parts.fetch(:min, 0),
+    parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
+    parts.fetch(:offset, 0)
+  )
+
+  if parts[:offset]
+    TimeWithZone.new(time.utc, self)
+  else
+    TimeWithZone.new(nil, self, time)
+  end
+
+rescue Date::Error, KeyError
+  raise ArgumentError, "invalid date"
+end
+
+
+ +
+ +
+

+ + local(*args) + +

+ + +
+

Method for creating new ActiveSupport::TimeWithZone instance in time zone of self from given values.

+ +
Time.zone = 'Hawaii'                    # => "Hawaii"
+Time.zone.local(2007, 2, 1, 15, 30, 45) # => Thu, 01 Feb 2007 15:30:45 HST -10:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 354
+def local(*args)
+  time = Time.utc(*args)
+  ActiveSupport::TimeWithZone.new(nil, self, time)
+end
+
+
+ +
+ +
+

+ + local_to_utc(time, dst = true) + +

+ + +
+

Adjust the given time to the simultaneous time in UTC. Returns a Time.utc() instance.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 542
+def local_to_utc(time, dst = true)
+  tzinfo.local_to_utc(time, dst)
+end
+
+
+ +
+ +
+

+ + match?(re) + +

+ + +
+

Compare name and TZInfo identifier to a supplied regexp, returning true if a match is found.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 339
+def match?(re)
+  (re == name) || (re == MAPPING[name]) ||
+    ((Regexp === re) && (re.match?(name) || re.match?(MAPPING[name])))
+end
+
+
+ +
+ +
+

+ + now() + +

+ + +
+

Returns an ActiveSupport::TimeWithZone instance representing the current time in the time zone represented by self.

+ +
Time.zone = 'Hawaii'  # => "Hawaii"
+Time.zone.now         # => Wed, 23 Jan 2008 20:24:27 HST -10:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 507
+def now
+  time_now.utc.in_time_zone(self)
+end
+
+
+ +
+ +
+

+ + parse(str, now = now()) + +

+ + +
+

Method for creating new ActiveSupport::TimeWithZone instance in time zone of self from parsed string.

+ +
Time.zone = 'Hawaii'                   # => "Hawaii"
+Time.zone.parse('1999-12-31 14:00:00') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+
+ +

If upper components are missing from the string, they are supplied from TimeZone#now:

+ +
Time.zone.now               # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+Time.zone.parse('22:30:00') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
+
+ +

However, if the date component is not provided, but any other upper components are supplied, then the day of the month defaults to 1:

+ +
Time.zone.parse('Mar 2000') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
+
+ +

If the string is invalid then an ArgumentError could be raised.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 444
+def parse(str, now = now())
+  parts_to_time(Date._parse(str, false), now)
+end
+
+
+ +
+ +
+

+ + period_for_local(time, dst = true) + +

+ + +
+

Available so that TimeZone instances respond like TZInfo::Timezone instances.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 554
+def period_for_local(time, dst = true)
+  tzinfo.period_for_local(time, dst) { |periods| periods.last }
+end
+
+
+ +
+ +
+

+ + period_for_utc(time) + +

+ + +
+

Available so that TimeZone instances respond like TZInfo::Timezone instances.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 548
+def period_for_utc(time)
+  tzinfo.period_for_utc(time)
+end
+
+
+ +
+ +
+

+ + rfc3339(str) + +

+ + +
+

Method for creating new ActiveSupport::TimeWithZone instance in time zone of self from an RFC 3339 string.

+ +
Time.zone = 'Hawaii'                     # => "Hawaii"
+Time.zone.rfc3339('2000-01-01T00:00:00Z') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+
+ +

If the time or zone components are missing then an ArgumentError will be raised. This is much stricter than either parse or iso8601 which allow for missing components.

+ +
Time.zone = 'Hawaii'            # => "Hawaii"
+Time.zone.rfc3339('1999-12-31') # => ArgumentError: invalid date
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 460
+def rfc3339(str)
+  parts = Date._rfc3339(str)
+
+  raise ArgumentError, "invalid date" if parts.empty?
+
+  time = Time.new(
+    parts.fetch(:year),
+    parts.fetch(:mon),
+    parts.fetch(:mday),
+    parts.fetch(:hour),
+    parts.fetch(:min),
+    parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
+    parts.fetch(:offset)
+  )
+
+  TimeWithZone.new(time.utc, self)
+end
+
+
+ +
+ +
+

+ + strptime(str, format, now = now()) + +

+ + +
+

Parses str according to format and returns an ActiveSupport::TimeWithZone.

+ +

Assumes that str is a time in the time zone self, unless format includes an explicit time zone. (This is the same behavior as parse.) In either case, the returned TimeWithZone has the timezone of self.

+ +
Time.zone = 'Hawaii'                   # => "Hawaii"
+Time.zone.strptime('1999-12-31 14:00:00', '%Y-%m-%d %H:%M:%S') # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+
+ +

If upper components are missing from the string, they are supplied from TimeZone#now:

+ +
Time.zone.now                              # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+Time.zone.strptime('22:30:00', '%H:%M:%S') # => Fri, 31 Dec 1999 22:30:00 HST -10:00
+
+ +

However, if the date component is not provided, but any other upper components are supplied, then the day of the month defaults to 1:

+ +
Time.zone.strptime('Mar 2000', '%b %Y') # => Wed, 01 Mar 2000 00:00:00 HST -10:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 498
+def strptime(str, format, now = now())
+  parts_to_time(DateTime._strptime(str, format), now)
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+

Returns a textual representation of this time zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 345
+def to_s
+  "(GMT#{formatted_offset}) #{name}"
+end
+
+
+ +
+ +
+

+ + today() + +

+ + +
+

Returns the current date in this time zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 512
+def today
+  tzinfo.now.to_date
+end
+
+
+ +
+ +
+

+ + tomorrow() + +

+ + +
+

Returns the next date in this time zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 517
+def tomorrow
+  today + 1
+end
+
+
+ +
+ +
+

+ + utc_offset() + +

+ + +
+

Returns the offset of this time zone from UTC in seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 308
+def utc_offset
+  @utc_offset || tzinfo&.current_period&.base_utc_offset
+end
+
+
+ +
+ +
+

+ + utc_to_local(time) + +

+ + +
+

Adjust the given time to the simultaneous time in the time zone represented by self. Returns a local time with the appropriate offset – if you want an ActiveSupport::TimeWithZone instance, use Time#in_time_zone() instead.

+ +

As of tzinfo 2, utc_to_local returns a Time with a non-zero utc_offset. See the utc_to_local_returns_utc_offset_times config for more info.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 533
+def utc_to_local(time)
+  tzinfo.utc_to_local(time).yield_self do |t|
+    ActiveSupport.utc_to_local_returns_utc_offset_times ?
+      t : Time.utc(t.year, t.month, t.day, t.hour, t.min, t.sec, t.sec_fraction * 1_000_000)
+  end
+end
+
+
+ +
+ +
+

+ + yesterday() + +

+ + +
+

Returns the previous date in this time zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/values/time_zone.rb, line 522
+def yesterday
+  today - 1
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/VERSION.html b/src/7.0/classes/ActiveSupport/VERSION.html new file mode 100644 index 0000000000..175bf83dbb --- /dev/null +++ b/src/7.0/classes/ActiveSupport/VERSION.html @@ -0,0 +1,120 @@ +--- +title: ActiveSupport::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XMLConverter.html b/src/7.0/classes/ActiveSupport/XMLConverter.html new file mode 100644 index 0000000000..9e7e59b919 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XMLConverter.html @@ -0,0 +1,73 @@ +--- +title: ActiveSupport::XMLConverter +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XMLConverter/DisallowedType.html b/src/7.0/classes/ActiveSupport/XMLConverter/DisallowedType.html new file mode 100644 index 0000000000..08087941a2 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XMLConverter/DisallowedType.html @@ -0,0 +1,113 @@ +--- +title: ActiveSupport::XMLConverter::DisallowedType +layout: default +--- +
+ +
+
+ +
+ +

Raised if the XML contains attributes with type=“yaml” or type=“symbol”. Read Hash#from_xml for more details.

+ +
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/conversions.rb, line 144
+def initialize(type)
+  super "Disallowed type attribute: #{type.inspect}"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XmlMini.html b/src/7.0/classes/ActiveSupport/XmlMini.html new file mode 100644 index 0000000000..19a59709d8 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XmlMini.html @@ -0,0 +1,417 @@ +--- +title: ActiveSupport::XmlMini +layout: default +--- +
+ +
+
+ +
+ +

XmlMini

+ +

To use the much faster libxml parser:

+ +
gem 'libxml-ruby', '=0.9.7'
+XmlMini.backend = 'LibXML'
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_ENCODINGS={ +"binary" => "base64" +} unless defined?(DEFAULT_ENCODINGS)
 
FORMATTING={ +"symbol" => Proc.new { |symbol| symbol.to_s }, +"date" => Proc.new { |date| date.to_fs(:db) }, +"dateTime" => Proc.new { |time| time.xmlschema }, +"binary" => Proc.new { |binary| ::Base64.encode64(binary) }, +"yaml" => Proc.new { |yaml| yaml.to_yaml } +} unless defined?(FORMATTING)
 
PARSING={ +"symbol" => Proc.new { |symbol| symbol.to_s.to_sym }, +"date" => Proc.new { |date| ::Date.parse(date) }, +"datetime" => Proc.new { |time| Time.xmlschema(time).utc rescue ::DateTime.parse(time).utc }, +"integer" => Proc.new { |integer| integer.to_i }, +"float" => Proc.new { |float| float.to_f }, +"decimal" => Proc.new do |number| +if String === number +number.to_d +else +BigDecimal(number) +end +end, +"boolean" => Proc.new { |boolean| %w(1 true).include?(boolean.to_s.strip) }, +"string" => Proc.new { |string| string.to_s }, +"yaml" => Proc.new { |yaml| YAML.load(yaml) rescue yaml }, +"base64Binary" => Proc.new { |bin| ::Base64.decode64(bin) }, +"binary" => Proc.new { |bin, entity| _parse_binary(bin, entity) }, +"file" => Proc.new { |file, entity| _parse_file(file, entity) } +}
 
TYPE_NAMES={ +"Symbol" => "symbol", +"Integer" => "integer", +"BigDecimal" => "decimal", +"Float" => "float", +"TrueClass" => "boolean", +"FalseClass" => "boolean", +"Date" => "date", +"DateTime" => "dateTime", +"Time" => "dateTime", +"Array" => "array", +"Hash" => "hash" +}
 
+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + depth
+ + + + + +

Instance Public methods

+ +
+

+ + backend() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini.rb, line 97
+def backend
+  current_thread_backend || @backend
+end
+
+
+ +
+ +
+

+ + backend=(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini.rb, line 101
+def backend=(name)
+  backend = name && cast_backend_name_to_module(name)
+  self.current_thread_backend = backend if current_thread_backend
+  @backend = backend
+end
+
+
+ +
+ +
+

+ + rename_key(key, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini.rb, line 148
+def rename_key(key, options = {})
+  camelize  = options[:camelize]
+  dasherize = !options.has_key?(:dasherize) || options[:dasherize]
+  if camelize
+    key = true == camelize ? key.camelize : key.camelize(camelize)
+  end
+  key = _dasherize(key) if dasherize
+  key
+end
+
+
+ +
+ +
+

+ + to_tag(key, value, options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini.rb, line 115
+def to_tag(key, value, options)
+  type_name = options.delete(:type)
+  merged_options = options.merge(root: key, skip_instruct: true)
+
+  if value.is_a?(::Method) || value.is_a?(::Proc)
+    if value.arity == 1
+      value.call(merged_options)
+    else
+      value.call(merged_options, key.to_s.singularize)
+    end
+  elsif value.respond_to?(:to_xml)
+    value.to_xml(merged_options)
+  else
+    type_name ||= TYPE_NAMES[value.class.name]
+    type_name ||= value.class.name if value && !value.respond_to?(:to_str)
+    type_name   = type_name.to_s   if type_name
+    type_name   = "dateTime" if type_name == "datetime"
+
+    key = rename_key(key.to_s, options)
+
+    attributes = options[:skip_types] || type_name.nil? ? {} : { type: type_name }
+    attributes[:nil] = true if value.nil?
+
+    encoding = options[:encoding] || DEFAULT_ENCODINGS[type_name]
+    attributes[:encoding] = encoding if encoding
+
+    formatted_value = FORMATTING[type_name] && !value.nil? ?
+      FORMATTING[type_name].call(value) : value
+
+    options[:builder].tag!(key, formatted_value, attributes)
+  end
+end
+
+
+ +
+ +
+

+ + with_backend(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini.rb, line 107
+def with_backend(name)
+  old_backend = current_thread_backend
+  self.current_thread_backend = name && cast_backend_name_to_module(name)
+  yield
+ensure
+  self.current_thread_backend = old_backend
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX.html b/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX.html new file mode 100644 index 0000000000..761a02a9b6 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX.html @@ -0,0 +1,67 @@ +--- +title: ActiveSupport::XmlMini_LibXMLSAX +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX/HashBuilder.html b/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX/HashBuilder.html new file mode 100644 index 0000000000..c0444a1c44 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XmlMini_LibXMLSAX/HashBuilder.html @@ -0,0 +1,410 @@ +--- +title: ActiveSupport::XmlMini_LibXMLSAX::HashBuilder +layout: default +--- +
+ +
+
+ +
+ +

Class that will build the hash while the XML document is being parsed using SAX events.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + LibXML::XML::SaxParser::Callbacks + +
  • + +
+ + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_KEY="__content__"
 
HASH_SIZE_KEY="__hash_size__"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + hash
+ + + + + +

Instance Public methods

+ +
+

+ + current_hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 21
+def current_hash
+  @hash_stack.last
+end
+
+
+ +
+ +
+

+ + on_cdata_block(string) + +

+ + +
+ +
+ + + + + +
+ Alias for: on_characters +
+ + + +
+ +
+

+ + on_characters(string) + +

+ + +
+ +
+ + + +
+ Also aliased as: on_cdata_block +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 55
+def on_characters(string)
+  current_hash[CONTENT_KEY] << string
+end
+
+
+ +
+ +
+

+ + on_end_document() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 30
+def on_end_document
+  @hash = @hash_stack.pop
+  @hash.delete(CONTENT_KEY)
+end
+
+
+ +
+ +
+

+ + on_end_element(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 48
+def on_end_element(name)
+  if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ""
+    current_hash.delete(CONTENT_KEY)
+  end
+  @hash_stack.pop
+end
+
+
+ +
+ +
+

+ + on_start_document() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 25
+def on_start_document
+  @hash = { CONTENT_KEY => +"" }
+  @hash_stack = [@hash]
+end
+
+
+ +
+ +
+

+ + on_start_element(name, attrs = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/libxmlsax.rb, line 35
+def on_start_element(name, attrs = {})
+  new_hash = { CONTENT_KEY => +"" }.merge!(attrs)
+  new_hash[HASH_SIZE_KEY] = new_hash.size + 1
+
+  case current_hash[name]
+  when Array then current_hash[name] << new_hash
+  when Hash  then current_hash[name] = [current_hash[name], new_hash]
+  when nil   then current_hash[name] = new_hash
+  end
+
+  @hash_stack.push(new_hash)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX.html b/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX.html new file mode 100644 index 0000000000..3b87e13f38 --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX.html @@ -0,0 +1,67 @@ +--- +title: ActiveSupport::XmlMini_NokogiriSAX +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX/HashBuilder.html b/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX/HashBuilder.html new file mode 100644 index 0000000000..dd9489857a --- /dev/null +++ b/src/7.0/classes/ActiveSupport/XmlMini_NokogiriSAX/HashBuilder.html @@ -0,0 +1,436 @@ +--- +title: ActiveSupport::XmlMini_NokogiriSAX::HashBuilder +layout: default +--- +
+ +
+
+ +
+ +

Class that will build the hash while the XML document is being parsed using SAX events.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
CONTENT_KEY="__content__"
 
HASH_SIZE_KEY="__hash_size__"
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + hash
+ + + + + +

Instance Public methods

+ +
+

+ + cdata_block(string) + +

+ + +
+ +
+ + + + + +
+ Alias for: characters +
+ + + +
+ +
+

+ + characters(string) + +

+ + +
+ +
+ + + +
+ Also aliased as: cdata_block +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 61
+def characters(string)
+  current_hash[CONTENT_KEY] << string
+end
+
+
+ +
+ +
+

+ + current_hash() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 24
+def current_hash
+  @hash_stack.last
+end
+
+
+ +
+ +
+

+ + end_document() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 33
+def end_document
+  raise "Parse stack not empty!" if @hash_stack.size > 1
+end
+
+
+ +
+ +
+

+ + end_element(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 54
+def end_element(name)
+  if current_hash.length > current_hash.delete(HASH_SIZE_KEY) && current_hash[CONTENT_KEY].blank? || current_hash[CONTENT_KEY] == ""
+    current_hash.delete(CONTENT_KEY)
+  end
+  @hash_stack.pop
+end
+
+
+ +
+ +
+

+ + error(error_message) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 37
+def error(error_message)
+  raise error_message
+end
+
+
+ +
+ +
+

+ + start_document() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 28
+def start_document
+  @hash = {}
+  @hash_stack = [@hash]
+end
+
+
+ +
+ +
+

+ + start_element(name, attrs = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/xml_mini/nokogirisax.rb, line 41
+def start_element(name, attrs = [])
+  new_hash = { CONTENT_KEY => +"" }.merge!(Hash[attrs])
+  new_hash[HASH_SIZE_KEY] = new_hash.size + 1
+
+  case current_hash[name]
+  when Array then current_hash[name] << new_hash
+  when Hash  then current_hash[name] = [current_hash[name], new_hash]
+  when nil   then current_hash[name] = new_hash
+  end
+
+  @hash_stack.push(new_hash)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Arel.html b/src/7.0/classes/Arel.html new file mode 100644 index 0000000000..534dafef98 --- /dev/null +++ b/src/7.0/classes/Arel.html @@ -0,0 +1,143 @@ +--- +title: Arel +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+
    + +
  • + sql +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
VERSION="10.0.0"
 
+ + + + + + +

Class Public methods

+ +
+

+ + sql(raw_sql) + +

+ + +
+

Wrap a known-safe SQL string for passing to query methods, e.g.

+ +
Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz') asc")).pluck(:id)
+
+ +

Great caution should be taken to avoid SQL injection vulnerabilities. This method should not be used with unsafe values such as request parameters or model attributes.

+
+ + + + + + + + +
+ + +
+
# File activerecord/lib/arel.rb, line 38
+def self.sql(raw_sql)
+  Arel::Nodes::SqlLiteral.new raw_sql
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Arel/Nodes.html b/src/7.0/classes/Arel/Nodes.html new file mode 100644 index 0000000000..696d0707d1 --- /dev/null +++ b/src/7.0/classes/Arel/Nodes.html @@ -0,0 +1,58 @@ +--- +title: Arel::Nodes +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Array.html b/src/7.0/classes/Array.html new file mode 100644 index 0000000000..74cfc38dd3 --- /dev/null +++ b/src/7.0/classes/Array.html @@ -0,0 +1,1518 @@ +--- +title: Array +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + wrap(object) + +

+ + +
+

Wraps its argument in an array unless it is already an array (or array-like).

+ +

Specifically:

+
  • +

    If the argument is nil an empty array is returned.

    +
  • +

    Otherwise, if the argument responds to to_ary it is invoked, and its result returned.

    +
  • +

    Otherwise, returns an array with the argument as its single element.

    + +
    Array.wrap(nil)       # => []
    +Array.wrap([1, 2, 3]) # => [1, 2, 3]
    +Array.wrap(0)         # => [0]
    +
    +
+ +

This method is similar in purpose to Kernel#Array, but there are some differences:

+
  • +

    If the argument responds to to_ary the method is invoked. Kernel#Array moves on to try to_a if the returned value is nil, but Array.wrap returns an array with the argument as its single element right away.

    +
  • +

    If the returned value from to_ary is neither nil nor an Array object, Kernel#Array raises an exception, while Array.wrap does not, it just returns the value.

    +
  • +

    It does not call to_a on the argument, if the argument does not respond to to_ary it returns an array with the argument as its single element.

    +
+ +

The last point is easily explained with some enumerables:

+ +
Array(foo: :bar)      # => [[:foo, :bar]]
+Array.wrap(foo: :bar) # => [{:foo=>:bar}]
+
+ +

There’s also a related idiom that uses the splat operator:

+ +
[*object]
+
+ +

which returns [] for nil, but calls to Array(object) otherwise.

+ +

The differences with Kernel#Array explained above apply to the rest of objects.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/wrap.rb, line 39
+def self.wrap(object)
+  if object.nil?
+    []
+  elsif object.respond_to?(:to_ary)
+    object.to_ary || [object]
+  else
+    [object]
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + deep_dup() + +

+ + +
+

Returns a deep copy of array.

+ +
array = [1, [2, 3]]
+dup   = array.deep_dup
+dup[1][2] = 4
+
+array[1][2] # => nil
+dup[1][2]   # => 4
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 29
+def deep_dup
+  map(&:deep_dup)
+end
+
+
+ +
+ +
+

+ + excluding(*elements) + +

+ + +
+

Returns a copy of the Array excluding the specified elements.

+ +
["David", "Rafael", "Aaron", "Todd"].excluding("Aaron", "Todd") # => ["David", "Rafael"]
+[ [ 0, 1 ], [ 1, 0 ] ].excluding([ [ 1, 0 ] ]) # => [ [ 0, 1 ] ]
+
+ +

Note: This is an optimization of Enumerable#excluding that uses Array#- instead of Array#reject for performance reasons.

+
+ + + +
+ Also aliased as: without +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 47
+def excluding(*elements)
+  self - elements.flatten(1)
+end
+
+
+ +
+ +
+

+ + extract!() + +

+ + +
+

Removes and returns the elements for which the block returns a true value. If no block is given, an Enumerator is returned instead.

+ +
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9]
+numbers # => [0, 2, 4, 6, 8]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/extract.rb, line 10
+def extract!
+  return to_enum(:extract!) { size } unless block_given?
+
+  extracted_elements = []
+
+  reject! do |element|
+    extracted_elements << element if yield(element)
+  end
+
+  extracted_elements
+end
+
+
+ +
+ +
+

+ + extract_options!() + +

+ + +
+

Extracts options from a set of arguments. Removes and returns the last element in the array if it’s a hash, otherwise returns a blank hash.

+ +
def options(*args)
+  args.extract_options!
+end
+
+options(1, 2)        # => {}
+options(1, 2, a: :b) # => {:a=>:b}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/extract_options.rb, line 24
+def extract_options!
+  if last.is_a?(Hash) && last.extractable_options?
+    pop
+  else
+    {}
+  end
+end
+
+
+ +
+ +
+

+ + fifth() + +

+ + +
+

Equal to self[4].

+ +
%w( a b c d e ).fifth # => "e"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 76
+def fifth
+  self[4]
+end
+
+
+ +
+ +
+

+ + forty_two() + +

+ + +
+

Equal to self[41]. Also known as accessing “the reddit”.

+ +
(1..42).to_a.forty_two # => 42
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 83
+def forty_two
+  self[41]
+end
+
+
+ +
+ +
+

+ + fourth() + +

+ + +
+

Equal to self[3].

+ +
%w( a b c d e ).fourth # => "d"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 69
+def fourth
+  self[3]
+end
+
+
+ +
+ +
+

+ + from(position) + +

+ + +
+

Returns the tail of the array from position.

+ +
%w( a b c d ).from(0)  # => ["a", "b", "c", "d"]
+%w( a b c d ).from(2)  # => ["c", "d"]
+%w( a b c d ).from(10) # => []
+%w().from(0)           # => []
+%w( a b c d ).from(-2) # => ["c", "d"]
+%w( a b c ).from(-10)  # => []
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 12
+def from(position)
+  self[position, length] || []
+end
+
+
+ +
+ +
+

+ + in_groups(number, fill_with = nil, &block) + +

+ + +
+

Splits or iterates over the array in number of groups, padding any remaining slots with fill_with unless it is false.

+ +
%w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
+["1", "2", "3", "4"]
+["5", "6", "7", nil]
+["8", "9", "10", nil]
+
+%w(1 2 3 4 5 6 7 8 9 10).in_groups(3, '&nbsp;') {|group| p group}
+["1", "2", "3", "4"]
+["5", "6", "7", "&nbsp;"]
+["8", "9", "10", "&nbsp;"]
+
+%w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
+["1", "2", "3"]
+["4", "5"]
+["6", "7"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 62
+def in_groups(number, fill_with = nil, &block)
+  # size.div number gives minor group size;
+  # size % number gives how many objects need extra accommodation;
+  # each group hold either division or division + 1 items.
+  division = size.div number
+  modulo = size % number
+
+  # create a new array avoiding dup
+  groups = []
+  start = 0
+
+  number.times do |index|
+    length = division + (modulo > 0 && modulo > index ? 1 : 0)
+    groups << last_group = slice(start, length)
+    last_group << fill_with if fill_with != false &&
+      modulo > 0 && length == division
+    start += length
+  end
+
+  if block_given?
+    groups.each(&block)
+  else
+    groups
+  end
+end
+
+
+ +
+ +
+

+ + in_groups_of(number, fill_with = nil, &block) + +

+ + +
+

Splits or iterates over the array in groups of size number, padding any remaining slots with fill_with unless it is false.

+ +
%w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
+["1", "2", "3"]
+["4", "5", "6"]
+["7", "8", "9"]
+["10", nil, nil]
+
+%w(1 2 3 4 5).in_groups_of(2, '&nbsp;') {|group| p group}
+["1", "2"]
+["3", "4"]
+["5", "&nbsp;"]
+
+%w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
+["1", "2"]
+["3", "4"]
+["5"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 22
+def in_groups_of(number, fill_with = nil, &block)
+  if number.to_i <= 0
+    raise ArgumentError,
+      "Group size must be a positive integer, was #{number.inspect}"
+  end
+
+  if fill_with == false
+    collection = self
+  else
+    # size % number gives how many extra we have;
+    # subtracting from number gives how many to add;
+    # modulo number ensures we don't add group of just fill.
+    padding = (number - size % number) % number
+    collection = dup.concat(Array.new(padding, fill_with))
+  end
+
+  if block_given?
+    collection.each_slice(number, &block)
+  else
+    collection.each_slice(number).to_a
+  end
+end
+
+
+ +
+ +
+

+ + including(*elements) + +

+ + +
+

Returns a new array that includes the passed elements.

+ +
[ 1, 2, 3 ].including(4, 5) # => [ 1, 2, 3, 4, 5 ]
+[ [ 0, 1 ] ].including([ [ 1, 0 ] ]) # => [ [ 0, 1 ], [ 1, 0 ] ]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 36
+def including(*elements)
+  self + elements.flatten(1)
+end
+
+
+ +
+ +
+

+ + inquiry() + +

+ + +
+

Wraps the array in an ActiveSupport::ArrayInquirer object, which gives a friendlier way to check its string-like contents.

+ +
pets = [:cat, :dog].inquiry
+
+pets.cat?     # => true
+pets.ferret?  # => false
+
+pets.any?(:cat, :ferret)  # => true
+pets.any?(:ferret, :alligator)  # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/inquiry.rb, line 16
+def inquiry
+  ActiveSupport::ArrayInquirer.new(self)
+end
+
+
+ +
+ +
+

+ + second() + +

+ + +
+

Equal to self[1].

+ +
%w( a b c d e ).second # => "b"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 55
+def second
+  self[1]
+end
+
+
+ +
+ +
+

+ + second_to_last() + +

+ + +
+

Equal to self[-2].

+ +
%w( a b c d e ).second_to_last # => "d"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 97
+def second_to_last
+  self[-2]
+end
+
+
+ +
+ +
+

+ + split(value = nil, &block) + +

+ + +
+

Divides the array into one or more subarrays based on a delimiting value or the result of an optional block.

+ +
[1, 2, 3, 4, 5].split(3)              # => [[1, 2], [4, 5]]
+(1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 93
+def split(value = nil, &block)
+  arr = dup
+  result = []
+  if block_given?
+    while (idx = arr.index(&block))
+      result << arr.shift(idx)
+      arr.shift
+    end
+  else
+    while (idx = arr.index(value))
+      result << arr.shift(idx)
+      arr.shift
+    end
+  end
+  result << arr
+end
+
+
+ +
+ +
+

+ + third() + +

+ + +
+

Equal to self[2].

+ +
%w( a b c d e ).third # => "c"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 62
+def third
+  self[2]
+end
+
+
+ +
+ +
+

+ + third_to_last() + +

+ + +
+

Equal to self[-3].

+ +
%w( a b c d e ).third_to_last # => "c"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 90
+def third_to_last
+  self[-3]
+end
+
+
+ +
+ +
+

+ + to(position) + +

+ + +
+

Returns the beginning of the array up to position.

+ +
%w( a b c d ).to(0)  # => ["a"]
+%w( a b c d ).to(2)  # => ["a", "b", "c"]
+%w( a b c d ).to(10) # => ["a", "b", "c", "d"]
+%w().to(0)           # => []
+%w( a b c d ).to(-2) # => ["a", "b", "c"]
+%w( a b c ).to(-10)  # => []
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/access.rb, line 24
+def to(position)
+  if position >= 0
+    take position + 1
+  else
+    self[0..position]
+  end
+end
+
+
+ +
+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Extends Array#to_s to convert a collection of elements into a comma separated id list if :db argument is given as the format.

+ +

This method is aliased to to_formatted_s.

+ +
Blog.all.to_fs(:db)  # => "1,2,3"
+Blog.none.to_fs(:db) # => "null"
+[1,2].to_fs          # => "[1, 2]"
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 94
+def to_fs(format = :default)
+  case format
+  when :db
+    if empty?
+      "null"
+    else
+      collect(&:id).join(",")
+    end
+  else
+    to_default_s
+  end
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Calls to_param on all its elements and joins the result with slashes. This is used by url_for in Action Pack.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 42
+def to_param
+  collect(&:to_param).join "/"
+end
+
+
+ +
+ +
+

+ + to_query(key) + +

+ + +
+

Converts an array into a string suitable for use as a URL query string, using the given key as the param name.

+ +
['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 50
+def to_query(key)
+  prefix = "#{key}[]"
+
+  if empty?
+    nil.to_query(prefix)
+  else
+    collect { |value| value.to_query(prefix) }.join "&"
+  end
+end
+
+
+ +
+ +
+

+ + to_sentence(options = {}) + +

+ + +
+

Converts the array to a comma-separated sentence where the last element is joined by the connector word.

+ +

You can pass the following options to change the default behavior. If you pass an option key that doesn’t exist in the list below, it will raise an ArgumentError.

+ +

Options

+
  • +

    :words_connector - The sign or word used to join all but the last element in arrays with three or more elements (default: “, ”).

    +
  • +

    :last_word_connector - The sign or word used to join the last element in arrays with three or more elements (default: “, and ”).

    +
  • +

    :two_words_connector - The sign or word used to join the elements in arrays with two elements (default: “ and ”).

    +
  • +

    :locale - If i18n is available, you can set a locale and use the connector options defined on the ‘support.array’ namespace in the corresponding dictionary file.

    +
+ +

Examples

+ +
[].to_sentence                      # => ""
+['one'].to_sentence                 # => "one"
+['one', 'two'].to_sentence          # => "one and two"
+['one', 'two', 'three'].to_sentence # => "one, two, and three"
+
+['one', 'two'].to_sentence(passing: 'invalid option')
+# => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale
+
+['one', 'two'].to_sentence(two_words_connector: '-')
+# => "one-two"
+
+['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ')
+# => "one or two or at least three"
+
+ +

Using :locale option:

+ +
# Given this locale dictionary:
+#
+#   es:
+#     support:
+#       array:
+#         words_connector: " o "
+#         two_words_connector: " y "
+#         last_word_connector: " o al menos "
+
+['uno', 'dos'].to_sentence(locale: :es)
+# => "uno y dos"
+
+['uno', 'dos', 'tres'].to_sentence(locale: :es)
+# => "uno o dos o al menos tres"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 60
+def to_sentence(options = {})
+  options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
+
+  default_connectors = {
+    words_connector: ", ",
+    two_words_connector: " and ",
+    last_word_connector: ", and "
+  }
+  if options[:locale] != false && defined?(I18n)
+    i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
+    default_connectors.merge!(i18n_connectors)
+  end
+  options = default_connectors.merge!(options)
+
+  case length
+  when 0
+    +""
+  when 1
+    +"#{self[0]}"
+  when 2
+    +"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
+  else
+    +"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
+  end
+end
+
+
+ +
+ +
+

+ + to_xml(options = {}) + +

+ + +
+

Returns a string that represents the array in XML by invoking to_xml on each element. Active Record collections delegate their representation in XML to this method.

+ +

All elements are expected to respond to to_xml, if any of them does not then an exception is raised.

+ +

The root node reflects the class name of the first element in plural if all elements belong to the same type and that’s not Hash:

+ +
customer.projects.to_xml
+
+<?xml version="1.0" encoding="UTF-8"?>
+<projects type="array">
+  <project>
+    <amount type="decimal">20000.0</amount>
+    <customer-id type="integer">1567</customer-id>
+    <deal-date type="date">2008-04-09</deal-date>
+    ...
+  </project>
+  <project>
+    <amount type="decimal">57230.0</amount>
+    <customer-id type="integer">1567</customer-id>
+    <deal-date type="date">2008-04-15</deal-date>
+    ...
+  </project>
+</projects>
+
+ +

Otherwise the root element is “objects”:

+ +
[{ foo: 1, bar: 2}, { baz: 3}].to_xml
+
+<?xml version="1.0" encoding="UTF-8"?>
+<objects type="array">
+  <object>
+    <bar type="integer">2</bar>
+    <foo type="integer">1</foo>
+  </object>
+  <object>
+    <baz type="integer">3</baz>
+  </object>
+</objects>
+
+ +

If the collection is empty the root element is “nil-classes” by default:

+ +
[].to_xml
+
+<?xml version="1.0" encoding="UTF-8"?>
+<nil-classes type="array"/>
+
+ +

To ensure a meaningful root element use the :root option:

+ +
customer_with_no_projects.projects.to_xml(root: 'projects')
+
+<?xml version="1.0" encoding="UTF-8"?>
+<projects type="array"/>
+
+ +

By default name of the node for the children of root is root.singularize. You can change it with the :children option.

+ +

The options hash is passed downwards:

+ +
Message.all.to_xml(skip_types: true)
+
+<?xml version="1.0" encoding="UTF-8"?>
+<messages>
+  <message>
+    <created-at>2008-03-07T09:58:18+01:00</created-at>
+    <id>1</id>
+    <name>1</name>
+    <updated-at>2008-03-07T09:58:18+01:00</updated-at>
+    <user-id>1</user-id>
+  </message>
+</messages>
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 184
+def to_xml(options = {})
+  require "active_support/builder" unless defined?(Builder::XmlMarkup)
+
+  options = options.dup
+  options[:indent]  ||= 2
+  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
+  options[:root]    ||= \
+    if first.class != Hash && all?(first.class)
+      underscored = ActiveSupport::Inflector.underscore(first.class.name)
+      ActiveSupport::Inflector.pluralize(underscored).tr("/", "_")
+    else
+      "objects"
+    end
+
+  builder = options[:builder]
+  builder.instruct! unless options.delete(:skip_instruct)
+
+  root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
+  children = options.delete(:children) || root.singularize
+  attributes = options[:skip_types] ? {} : { type: "array" }
+
+  if empty?
+    builder.tag!(root, attributes)
+  else
+    builder.tag!(root, attributes) do
+      each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
+      yield builder if block_given?
+    end
+  end
+end
+
+
+ +
+ +
+

+ + without(*elements) + +

+ + +
+ +
+ + + + + +
+ Alias for: excluding +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Benchmark.html b/src/7.0/classes/Benchmark.html new file mode 100644 index 0000000000..694b96c9e7 --- /dev/null +++ b/src/7.0/classes/Benchmark.html @@ -0,0 +1,108 @@ +--- +title: Benchmark +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + ms +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + ms(&block) + +

+ + +
+

Benchmark realtime in milliseconds.

+ +
Benchmark.realtime { User.all }
+# => 8.0e-05
+
+Benchmark.ms { User.all }
+# => 0.074
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/benchmark.rb, line 13
+def ms(&block)
+  1000 * realtime(&block)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/BigDecimal.html b/src/7.0/classes/BigDecimal.html new file mode 100644 index 0000000000..798eb09f92 --- /dev/null +++ b/src/7.0/classes/BigDecimal.html @@ -0,0 +1,60 @@ +--- +title: BigDecimal +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Class.html b/src/7.0/classes/Class.html new file mode 100644 index 0000000000..67c7d8af47 --- /dev/null +++ b/src/7.0/classes/Class.html @@ -0,0 +1,332 @@ +--- +title: Class +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + class_attribute(*attrs, instance_accessor: true, instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil) + +

+ + +
+

Declare a class-level attribute whose value is inheritable by subclasses. Subclasses can change their own value and it will not impact parent class.

+ +

Options

+
  • +

    :instance_reader - Sets the instance reader method (defaults to true).

    +
  • +

    :instance_writer - Sets the instance writer method (defaults to true).

    +
  • +

    :instance_accessor - Sets both instance methods (defaults to true).

    +
  • +

    :instance_predicate - Sets a predicate method (defaults to true).

    +
  • +

    :default - Sets a default value for the attribute (defaults to nil).

    +
+ +

Examples

+ +
class Base
+  class_attribute :setting
+end
+
+class Subclass < Base
+end
+
+Base.setting = true
+Subclass.setting            # => true
+Subclass.setting = false
+Subclass.setting            # => false
+Base.setting                # => true
+
+ +

In the above case as long as Subclass does not assign a value to setting by performing Subclass.setting = something, Subclass.setting would read value assigned to parent class. Once Subclass assigns a value then the value assigned by Subclass would be returned.

+ +

This matches normal Ruby method inheritance: think of writing an attribute on a subclass as overriding the reader method. However, you need to be aware when using class_attribute with mutable structures as Array or Hash. In such cases, you don’t want to do changes in place. Instead use setters:

+ +
Base.setting = []
+Base.setting                # => []
+Subclass.setting            # => []
+
+# Appending in child changes both parent and child because it is the same object:
+Subclass.setting << :foo
+Base.setting               # => [:foo]
+Subclass.setting           # => [:foo]
+
+# Use setters to not propagate changes:
+Base.setting = []
+Subclass.setting += [:foo]
+Base.setting               # => []
+Subclass.setting           # => [:foo]
+
+ +

For convenience, an instance predicate method is defined as well. To skip it, pass instance_predicate: false.

+ +
Subclass.setting?       # => false
+
+ +

Instances may overwrite the class value in the same way:

+ +
Base.setting = true
+object = Base.new
+object.setting          # => true
+object.setting = false
+object.setting          # => false
+Base.setting            # => true
+
+ +

To opt out of the instance reader method, pass instance_reader: false.

+ +
object.setting          # => NoMethodError
+object.setting?         # => NoMethodError
+
+ +

To opt out of the instance writer method, pass instance_writer: false.

+ +
object.setting = false  # => NoMethodError
+
+ +

To opt out of both instance methods, pass instance_accessor: false.

+ +

To set a default value for the attribute, pass default:, like so:

+ +
class_attribute :settings, default: {}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/class/attribute.rb, line 85
+  def class_attribute(*attrs, instance_accessor: true,
+    instance_reader: instance_accessor, instance_writer: instance_accessor, instance_predicate: true, default: nil)
+
+    class_methods, methods = [], []
+    attrs.each do |name|
+      unless name.is_a?(Symbol) || name.is_a?(String)
+        raise TypeError, "#{name.inspect} is not a symbol nor a string"
+      end
+
+      class_methods << <<~RUBY # In case the method exists and is not public
+        silence_redefinition_of_method def #{name}
+        end
+      RUBY
+
+      methods << <<~RUBY if instance_reader
+        silence_redefinition_of_method def #{name}
+          defined?(@#{name}) ? @#{name} : self.class.#{name}
+        end
+      RUBY
+
+      class_methods << <<~RUBY
+        silence_redefinition_of_method def #{name}=(value)
+          redefine_method(:#{name}) { value } if singleton_class?
+          redefine_singleton_method(:#{name}) { value }
+          value
+        end
+      RUBY
+
+      methods << <<~RUBY if instance_writer
+        silence_redefinition_of_method(:#{name}=)
+        attr_writer :#{name}
+      RUBY
+
+      if instance_predicate
+        class_methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
+        if instance_reader
+          methods << "silence_redefinition_of_method def #{name}?; !!self.#{name}; end"
+        end
+      end
+    end
+
+    location = caller_locations(1, 1).first
+    class_eval(["class << self", *class_methods, "end", *methods].join(";").tr("\n", ";"), location.path, location.lineno)
+
+    attrs.each { |name| public_send("#{name}=", default) }
+  end
+
+
+ +
+ +
+

+ + descendants() + +

+ + +
+

Returns an array with all classes that are < than its receiver.

+ +
class C; end
+C.descendants # => []
+
+class B < C; end
+C.descendants # => [B]
+
+class A < B; end
+C.descendants # => [B, A]
+
+class D < C; end
+C.descendants # => [B, A, D]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/class/subclasses.rb, line 20
+def descendants
+  subclasses.concat(subclasses.flat_map(&:descendants))
+end
+
+
+ +
+ +
+

+ + subclasses() + +

+ + +
+

Returns an array with the direct children of self.

+ +
class Foo; end
+class Bar < Foo; end
+class Baz < Bar; end
+
+Foo.subclasses # => [Bar]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/class/subclasses.rb, line 38
+def subclasses
+  descendants.select { |descendant| descendant.superclass == self }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Date.html b/src/7.0/classes/Date.html new file mode 100644 index 0000000000..38a4e309c6 --- /dev/null +++ b/src/7.0/classes/Date.html @@ -0,0 +1,1427 @@ +--- +title: Date +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DATE_FORMATS={ +short: "%d %b", +long: "%B %d, %Y", +db: "%Y-%m-%d", +inspect: "%Y-%m-%d", +number: "%Y%m%d", +long_ordinal: lambda { |date| +day_format = ActiveSupport::Inflector.ordinalize(date.day) +date.strftime("%B #{day_format}, %Y") # => "April 25th, 2007" +}, +rfc822: "%d %b %Y", +iso8601: lambda { |date| date.iso8601 } +}
 
+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + beginning_of_week_default
+ + + + +

Class Public methods

+ +
+

+ + beginning_of_week() + +

+ + +
+

Returns the week start (e.g. :monday) for the current request, if this has been set (via Date.beginning_of_week=). If Date.beginning_of_week has not been set for the current request, returns the week start specified in config.beginning_of_week. If no config.beginning_of_week was specified, returns :monday.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 19
+def beginning_of_week
+  ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] || beginning_of_week_default || :monday
+end
+
+
+ +
+ +
+

+ + beginning_of_week=(week_start) + +

+ + +
+

Sets Date.beginning_of_week to a week start (e.g. :monday) for current request/thread.

+ +

This method accepts any of the following day symbols: :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 27
+def beginning_of_week=(week_start)
+  ::ActiveSupport::IsolatedExecutionState[:beginning_of_week] = find_beginning_of_week!(week_start)
+end
+
+
+ +
+ +
+

+ + current() + +

+ + +
+

Returns Time.zone.today when Time.zone or config.time_zone are set, otherwise just returns Date.today.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 48
+def current
+  ::Time.zone ? ::Time.zone.today : ::Date.today
+end
+
+
+ +
+ +
+

+ + find_beginning_of_week!(week_start) + +

+ + +
+

Returns week start day symbol (e.g. :monday), or raises an ArgumentError for invalid day symbol.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 32
+def find_beginning_of_week!(week_start)
+  raise ArgumentError, "Invalid beginning of week: #{week_start}" unless ::Date::DAYS_INTO_WEEK.key?(week_start)
+  week_start
+end
+
+
+ +
+ +
+

+ + tomorrow() + +

+ + +
+

Returns a new Date representing the date 1 day after today (i.e. tomorrow’s date).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 43
+def tomorrow
+  ::Date.current.tomorrow
+end
+
+
+ +
+ +
+

+ + yesterday() + +

+ + +
+

Returns a new Date representing the date 1 day ago (i.e. yesterday’s date).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 38
+def yesterday
+  ::Date.current.yesterday
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(other) + +

+ + +
+ +
+ + + +
+ Also aliased as: compare_without_coercion +
+ + + +
+ Alias for: compare_with_coercion +
+ + + +
+ +
+

+ + acts_like_date?() + +

+ + +
+

Duck-types as a Date-like class. See Object#acts_like?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/acts_like.rb, line 7
+def acts_like_date?
+  true
+end
+
+
+ +
+ +
+

+ + advance(options) + +

+ + +
+

Provides precise Date calculations for years, months, and days. The options parameter takes a hash with any of these keys: :years, :months, :weeks, :days.

+ +

The increments are applied in order of time units from largest to smallest. In other words, the date is incremented first by :years, then by :months, then by :weeks, then by :days. This order can affect the result around the end of a month. For example, incrementing first by months then by days:

+ +
Date.new(2004, 9, 30).advance(months: 1, days: 1)
+# => Sun, 31 Oct 2004
+
+ +

Whereas incrementing first by days then by months yields a different result:

+ +
Date.new(2004, 9, 30).advance(days: 1).advance(months: 1)
+# => Mon, 01 Nov 2004
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 127
+def advance(options)
+  d = self
+
+  d = d >> options[:years] * 12 if options[:years]
+  d = d >> options[:months] if options[:months]
+  d = d + options[:weeks] * 7 if options[:weeks]
+  d = d + options[:days] if options[:days]
+
+  d
+end
+
+
+ +
+ +
+

+ + ago(seconds) + +

+ + +
+

Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00) and then subtracts the specified number of seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 55
+def ago(seconds)
+  in_time_zone.since(-seconds)
+end
+
+
+ +
+ +
+

+ + at_beginning_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_end_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_day +
+ + + +
+ +
+

+ + at_midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_middle_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + beginning_of_day() + +

+ + +
+

Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00)

+
+ + + +
+ Also aliased as: midnight, at_midnight, at_beginning_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 67
+def beginning_of_day
+  in_time_zone
+end
+
+
+ +
+ +
+

+ + change(options) + +

+ + +
+

Returns a new Date where one or more of the elements have been changed according to the options parameter. The options parameter is a hash with a combination of these keys: :year, :month, :day.

+ +
Date.new(2007, 5, 12).change(day: 1)               # => Date.new(2007, 5, 1)
+Date.new(2007, 5, 12).change(year: 2005, month: 1) # => Date.new(2005, 1, 12)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 143
+def change(options)
+  ::Date.new(
+    options.fetch(:year, year),
+    options.fetch(:month, month),
+    options.fetch(:day, day)
+  )
+end
+
+
+ +
+ +
+

+ + compare_with_coercion(other) + +

+ + +
+

Allow Date to be compared with Time by converting to DateTime and relying on the <=> from there.

+
+ + + +
+ Also aliased as: <=> +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 152
+def compare_with_coercion(other)
+  if other.is_a?(Time)
+    to_datetime <=> other
+  else
+    compare_without_coercion(other)
+  end
+end
+
+
+ +
+ +
+

+ + compare_without_coercion(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: <=> +
+ + + +
+ +
+

+ + default_inspect() + +

+ + +
+ +
+ + + + + +
+ Alias for: inspect +
+ + + +
+ +
+

+ + end_of_day() + +

+ + +
+

Converts Date to a Time (or DateTime if necessary) with the time portion set to the end of the day (23:59:59)

+
+ + + +
+ Also aliased as: at_end_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 85
+def end_of_day
+  in_time_zone.end_of_day
+end
+
+
+ +
+ +
+

+ + in(seconds) + +

+ + +
+ +
+ + + + + +
+ Alias for: since +
+ + + +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + +
+ Also aliased as: default_inspect +
+ + + +
+ Alias for: readable_inspect +
+ + + +
+ +
+

+ + midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + middle_of_day() + +

+ + +
+

Converts Date to a Time (or DateTime if necessary) with the time portion set to the middle of the day (12:00)

+
+ + + +
+ Also aliased as: midday, noon, at_midday, at_noon, at_middle_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 75
+def middle_of_day
+  in_time_zone.middle_of_day
+end
+
+
+ +
+ +
+

+ + midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + readable_inspect() + +

+ + +
+

Overrides the default inspect method with a human readable one, e.g., “Mon, 21 Feb 2005”

+
+ + + +
+ Also aliased as: inspect +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/conversions.rb, line 62
+def readable_inspect
+  strftime("%a, %d %b %Y")
+end
+
+
+ +
+ +
+

+ + since(seconds) + +

+ + +
+

Converts Date to a Time (or DateTime if necessary) with the time portion set to the beginning of the day (0:00) and then adds the specified number of seconds

+
+ + + +
+ Also aliased as: in +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/calculations.rb, line 61
+def since(seconds)
+  in_time_zone.since(seconds)
+end
+
+
+ +
+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Convert to a formatted string. See DATE_FORMATS for predefined formats.

+ +

This method is aliased to to_formatted_s.

+ +
date = Date.new(2007, 11, 10)       # => Sat, 10 Nov 2007
+
+date.to_fs(:db)                     # => "2007-11-10"
+date.to_formatted_s(:db)            # => "2007-11-10"
+
+date.to_fs(:short)         # => "10 Nov"
+date.to_fs(:number)        # => "20071110"
+date.to_fs(:long)          # => "November 10, 2007"
+date.to_fs(:long_ordinal)  # => "November 10th, 2007"
+date.to_fs(:rfc822)        # => "10 Nov 2007"
+date.to_fs(:iso8601)       # => "2007-11-10"
+
+ +

Adding your own date formats to to_fs

+ +

You can add your own formats to the Date::DATE_FORMATS hash. Use the format name as the hash key and either a strftime string or Proc instance that takes a date argument as the value.

+ +
# config/initializers/date_formats.rb
+Date::DATE_FORMATS[:month_and_year] = '%B %Y'
+Date::DATE_FORMATS[:short_ordinal] = ->(date) { date.strftime("%B #{date.day.ordinalize}") }
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/conversions.rb, line 47
+def to_fs(format = :default)
+  if formatter = DATE_FORMATS[format]
+    if formatter.respond_to?(:call)
+      formatter.call(self).to_s
+    else
+      strftime(formatter)
+    end
+  else
+    to_default_s
+  end
+end
+
+
+ +
+ +
+

+ + to_time(form = :local) + +

+ + +
+

Converts a Date instance to a Time, where the time is set to the beginning of the day. The timezone can be either :local or :utc (default :local).

+ +
date = Date.new(2007, 11, 10)  # => Sat, 10 Nov 2007
+
+date.to_time                   # => 2007-11-10 00:00:00 0800
+date.to_time(:local)           # => 2007-11-10 00:00:00 0800
+
+date.to_time(:utc)             # => 2007-11-10 00:00:00 UTC
+
+ +

NOTE: The :local timezone is Ruby’s process timezone, i.e. ENV['TZ']. If the application’s timezone is needed, then use in_time_zone instead.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/conversions.rb, line 82
+def to_time(form = :local)
+  raise ArgumentError, "Expected :local or :utc, got #{form.inspect}." unless [:local, :utc].include?(form)
+  ::Time.public_send(form, year, month, day)
+end
+
+
+ +
+ +
+

+ + xmlschema() + +

+ + +
+

Returns a string which represents the time in used time zone as DateTime defined by XML Schema:

+ +
date = Date.new(2015, 05, 23)  # => Sat, 23 May 2015
+date.xmlschema                 # => "2015-05-23T00:00:00+04:00"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date/conversions.rb, line 94
+def xmlschema
+  in_time_zone.xmlschema
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/DateAndTime.html b/src/7.0/classes/DateAndTime.html new file mode 100644 index 0000000000..7be624eec1 --- /dev/null +++ b/src/7.0/classes/DateAndTime.html @@ -0,0 +1,75 @@ +--- +title: DateAndTime +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/DateAndTime/Calculations.html b/src/7.0/classes/DateAndTime/Calculations.html new file mode 100644 index 0000000000..77e5c9e963 --- /dev/null +++ b/src/7.0/classes/DateAndTime/Calculations.html @@ -0,0 +1,2356 @@ +--- +title: DateAndTime::Calculations +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
DAYS_INTO_WEEK={ +sunday: 0, +monday: 1, +tuesday: 2, +wednesday: 3, +thursday: 4, +friday: 5, +saturday: 6 +}
 
WEEKEND_DAYS=[ 6, 0 ]
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + after?(date_or_time) + +

+ + +
+

Returns true if the date/time falls after date_or_time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 72
+def after?(date_or_time)
+  self > date_or_time
+end
+
+
+ +
+ +
+

+ + all_day() + +

+ + +
+

Returns a Range representing the whole day of the current date/time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 300
+def all_day
+  beginning_of_day..end_of_day
+end
+
+
+ +
+ +
+

+ + all_month() + +

+ + +
+

Returns a Range representing the whole month of the current date/time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 311
+def all_month
+  beginning_of_month..end_of_month
+end
+
+
+ +
+ +
+

+ + all_quarter() + +

+ + +
+

Returns a Range representing the whole quarter of the current date/time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 316
+def all_quarter
+  beginning_of_quarter..end_of_quarter
+end
+
+
+ +
+ +
+

+ + all_week(start_day = Date.beginning_of_week) + +

+ + +
+

Returns a Range representing the whole week of the current date/time. Week starts on start_day, default is Date.beginning_of_week or config.beginning_of_week when set.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 306
+def all_week(start_day = Date.beginning_of_week)
+  beginning_of_week(start_day)..end_of_week(start_day)
+end
+
+
+ +
+ +
+

+ + all_year() + +

+ + +
+

Returns a Range representing the whole year of the current date/time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 321
+def all_year
+  beginning_of_year..end_of_year
+end
+
+
+ +
+ +
+

+ + at_beginning_of_month() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_month +
+ + + +
+ +
+

+ + at_beginning_of_quarter() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_quarter +
+ + + +
+ +
+

+ + at_beginning_of_week(start_day = Date.beginning_of_week) + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_week +
+ + + +
+ +
+

+ + at_beginning_of_year() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_year +
+ + + +
+ +
+

+ + at_end_of_month() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_month +
+ + + +
+ +
+

+ + at_end_of_quarter() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_quarter +
+ + + +
+ +
+

+ + at_end_of_week(start_day = Date.beginning_of_week) + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_week +
+ + + +
+ +
+

+ + at_end_of_year() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_year +
+ + + +
+ +
+

+ + before?(date_or_time) + +

+ + +
+

Returns true if the date/time falls before date_or_time.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 67
+def before?(date_or_time)
+  self < date_or_time
+end
+
+
+ +
+ +
+

+ + beginning_of_month() + +

+ + +
+

Returns a new date/time at the start of the month.

+ +
today = Date.today # => Thu, 18 Jun 2015
+today.beginning_of_month # => Mon, 01 Jun 2015
+
+ +

DateTime objects will have a time set to 0:00.

+ +
now = DateTime.current # => Thu, 18 Jun 2015 15:23:13 +0000
+now.beginning_of_month # => Mon, 01 Jun 2015 00:00:00 +0000
+
+
+ + + +
+ Also aliased as: at_beginning_of_month +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 125
+def beginning_of_month
+  first_hour(change(day: 1))
+end
+
+
+ +
+ +
+

+ + beginning_of_quarter() + +

+ + +
+

Returns a new date/time at the start of the quarter.

+ +
today = Date.today # => Fri, 10 Jul 2015
+today.beginning_of_quarter # => Wed, 01 Jul 2015
+
+ +

DateTime objects will have a time set to 0:00.

+ +
now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
+now.beginning_of_quarter # => Wed, 01 Jul 2015 00:00:00 +0000
+
+
+ + + +
+ Also aliased as: at_beginning_of_quarter +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 139
+def beginning_of_quarter
+  first_quarter_month = month - (2 + month) % 3
+  beginning_of_month.change(month: first_quarter_month)
+end
+
+
+ +
+ +
+

+ + beginning_of_week(start_day = Date.beginning_of_week) + +

+ + +
+

Returns a new date/time representing the start of this week on the given day. Week is assumed to start on start_day, default is Date.beginning_of_week or config.beginning_of_week when set. DateTime objects have their time set to 0:00.

+
+ + + +
+ Also aliased as: at_beginning_of_week +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 257
+def beginning_of_week(start_day = Date.beginning_of_week)
+  result = days_ago(days_to_week_start(start_day))
+  acts_like?(:time) ? result.midnight : result
+end
+
+
+ +
+ +
+

+ + beginning_of_year() + +

+ + +
+

Returns a new date/time at the beginning of the year.

+ +
today = Date.today # => Fri, 10 Jul 2015
+today.beginning_of_year # => Thu, 01 Jan 2015
+
+ +

DateTime objects will have a time set to 0:00.

+ +
now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
+now.beginning_of_year # => Thu, 01 Jan 2015 00:00:00 +0000
+
+
+ + + +
+ Also aliased as: at_beginning_of_year +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 169
+def beginning_of_year
+  change(month: 1).beginning_of_month
+end
+
+
+ +
+ +
+

+ + days_ago(days) + +

+ + +
+

Returns a new date/time the specified number of days ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 77
+def days_ago(days)
+  advance(days: -days)
+end
+
+
+ +
+ +
+

+ + days_since(days) + +

+ + +
+

Returns a new date/time the specified number of days in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 82
+def days_since(days)
+  advance(days: days)
+end
+
+
+ +
+ +
+

+ + days_to_week_start(start_day = Date.beginning_of_week) + +

+ + +
+

Returns the number of days to the start of the week on the given day. Week is assumed to start on start_day, default is Date.beginning_of_week or config.beginning_of_week when set.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 248
+def days_to_week_start(start_day = Date.beginning_of_week)
+  start_day_number = DAYS_INTO_WEEK.fetch(start_day)
+  (wday - start_day_number) % 7
+end
+
+
+ +
+ +
+

+ + end_of_month() + +

+ + +
+

Returns a new date/time representing the end of the month. DateTime objects will have a time set to 23:59:59.

+
+ + + +
+ Also aliased as: at_end_of_month +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 286
+def end_of_month
+  last_day = ::Time.days_in_month(month, year)
+  last_hour(days_since(last_day - day))
+end
+
+
+ +
+ +
+

+ + end_of_quarter() + +

+ + +
+

Returns a new date/time at the end of the quarter.

+ +
today = Date.today # => Fri, 10 Jul 2015
+today.end_of_quarter # => Wed, 30 Sep 2015
+
+ +

DateTime objects will have a time set to 23:59:59.

+ +
now = DateTime.current # => Fri, 10 Jul 2015 18:41:29 +0000
+now.end_of_quarter # => Wed, 30 Sep 2015 23:59:59 +0000
+
+
+ + + +
+ Also aliased as: at_end_of_quarter +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 154
+def end_of_quarter
+  last_quarter_month = month + (12 - month) % 3
+  beginning_of_month.change(month: last_quarter_month).end_of_month
+end
+
+
+ +
+ +
+

+ + end_of_week(start_day = Date.beginning_of_week) + +

+ + +
+

Returns a new date/time representing the end of this week on the given day. Week is assumed to start on start_day, default is Date.beginning_of_week or config.beginning_of_week when set. DateTime objects have their time set to 23:59:59.

+
+ + + +
+ Also aliased as: at_end_of_week +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 273
+def end_of_week(start_day = Date.beginning_of_week)
+  last_hour(days_since(6 - days_to_week_start(start_day)))
+end
+
+
+ +
+ +
+

+ + end_of_year() + +

+ + +
+

Returns a new date/time representing the end of the year. DateTime objects will have a time set to 23:59:59.

+
+ + + +
+ Also aliased as: at_end_of_year +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 294
+def end_of_year
+  change(month: 12).end_of_month
+end
+
+
+ +
+ +
+

+ + future?() + +

+ + +
+

Returns true if the date/time is in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 52
+def future?
+  self > self.class.current
+end
+
+
+ +
+ +
+

+ + last_month() + +

+ + +
+

Short-hand for months_ago(1).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 230
+def last_month
+  months_ago(1)
+end
+
+
+ +
+ +
+

+ + last_quarter() + +

+ + +
+ +
+ + + + + +
+ Alias for: prev_quarter +
+ + + +
+ +
+

+ + last_week(start_day = Date.beginning_of_week, same_time: false) + +

+ + +
+ +
+ + + + + +
+ Alias for: prev_week +
+ + + +
+ +
+

+ + last_weekday() + +

+ + +
+ +
+ + + + + +
+ Alias for: prev_weekday +
+ + + +
+ +
+

+ + last_year() + +

+ + +
+

Short-hand for years_ago(1).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 241
+def last_year
+  years_ago(1)
+end
+
+
+ +
+ +
+

+ + monday() + +

+ + +
+

Returns Monday of this week assuming that week starts on Monday. DateTime objects have their time set to 0:00.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 265
+def monday
+  beginning_of_week(:monday)
+end
+
+
+ +
+ +
+

+ + months_ago(months) + +

+ + +
+

Returns a new date/time the specified number of months ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 97
+def months_ago(months)
+  advance(months: -months)
+end
+
+
+ +
+ +
+

+ + months_since(months) + +

+ + +
+

Returns a new date/time the specified number of months in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 102
+def months_since(months)
+  advance(months: months)
+end
+
+
+ +
+ +
+

+ + next_day?() + +

+ + +
+ +
+ + + + + +
+ Alias for: tomorrow? +
+ + + +
+ +
+

+ + next_occurring(day_of_week) + +

+ + +
+

Returns a new date/time representing the next occurrence of the specified day of week.

+ +
today = Date.today               # => Thu, 14 Dec 2017
+today.next_occurring(:monday)    # => Mon, 18 Dec 2017
+today.next_occurring(:thursday)  # => Thu, 21 Dec 2017
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 330
+def next_occurring(day_of_week)
+  from_now = DAYS_INTO_WEEK.fetch(day_of_week) - wday
+  from_now += 7 unless from_now > 0
+  advance(days: from_now)
+end
+
+
+ +
+ +
+

+ + next_quarter() + +

+ + +
+

Short-hand for months_since(3).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 205
+def next_quarter
+  months_since(3)
+end
+
+
+ +
+ +
+

+ + next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false) + +

+ + +
+

Returns a new date/time representing the given day in the next week.

+ +
today = Date.today # => Thu, 07 May 2015
+today.next_week    # => Mon, 11 May 2015
+
+ +

The given_day_in_next_week defaults to the beginning of the week which is determined by Date.beginning_of_week or config.beginning_of_week when set.

+ +
today = Date.today       # => Thu, 07 May 2015
+today.next_week(:friday) # => Fri, 15 May 2015
+
+ +

DateTime objects have their time set to 0:00 unless same_time is true.

+ +
now = DateTime.current # => Thu, 07 May 2015 13:31:16 +0000
+now.next_week      # => Mon, 11 May 2015 00:00:00 +0000
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 190
+def next_week(given_day_in_next_week = Date.beginning_of_week, same_time: false)
+  result = first_hour(weeks_since(1).beginning_of_week.days_since(days_span(given_day_in_next_week)))
+  same_time ? copy_time_to(result) : result
+end
+
+
+ +
+ +
+

+ + next_weekday() + +

+ + +
+

Returns a new date/time representing the next weekday.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 196
+def next_weekday
+  if next_day.on_weekend?
+    next_week(:monday, same_time: true)
+  else
+    next_day
+  end
+end
+
+
+ +
+ +
+

+ + on_weekday?() + +

+ + +
+

Returns true if the date/time does not fall on a Saturday or Sunday.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 62
+def on_weekday?
+  !WEEKEND_DAYS.include?(wday)
+end
+
+
+ +
+ +
+

+ + on_weekend?() + +

+ + +
+

Returns true if the date/time falls on a Saturday or Sunday.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 57
+def on_weekend?
+  WEEKEND_DAYS.include?(wday)
+end
+
+
+ +
+ +
+

+ + past?() + +

+ + +
+

Returns true if the date/time is in the past.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 47
+def past?
+  self < self.class.current
+end
+
+
+ +
+ +
+

+ + prev_day?() + +

+ + +
+ +
+ + + + + +
+ Alias for: yesterday? +
+ + + +
+ +
+

+ + prev_occurring(day_of_week) + +

+ + +
+

Returns a new date/time representing the previous occurrence of the specified day of week.

+ +
today = Date.today               # => Thu, 14 Dec 2017
+today.prev_occurring(:monday)    # => Mon, 11 Dec 2017
+today.prev_occurring(:thursday)  # => Thu, 07 Dec 2017
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 341
+def prev_occurring(day_of_week)
+  ago = wday - DAYS_INTO_WEEK.fetch(day_of_week)
+  ago += 7 unless ago > 0
+  advance(days: -ago)
+end
+
+
+ +
+ +
+

+ + prev_quarter() + +

+ + +
+

Short-hand for months_ago(3).

+
+ + + +
+ Also aliased as: last_quarter +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 235
+def prev_quarter
+  months_ago(3)
+end
+
+
+ +
+ +
+

+ + prev_week(start_day = Date.beginning_of_week, same_time: false) + +

+ + +
+

Returns a new date/time representing the given day in the previous week. Week is assumed to start on start_day, default is Date.beginning_of_week or config.beginning_of_week when set. DateTime objects have their time set to 0:00 unless same_time is true.

+
+ + + +
+ Also aliased as: last_week +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 213
+def prev_week(start_day = Date.beginning_of_week, same_time: false)
+  result = first_hour(weeks_ago(1).beginning_of_week.days_since(days_span(start_day)))
+  same_time ? copy_time_to(result) : result
+end
+
+
+ +
+ +
+

+ + prev_weekday() + +

+ + +
+

Returns a new date/time representing the previous weekday.

+
+ + + +
+ Also aliased as: last_weekday +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 220
+def prev_weekday
+  if prev_day.on_weekend?
+    copy_time_to(beginning_of_week(:friday))
+  else
+    prev_day
+  end
+end
+
+
+ +
+ +
+

+ + sunday() + +

+ + +
+

Returns Sunday of this week assuming that week starts on Monday. DateTime objects have their time set to 23:59:59.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 280
+def sunday
+  end_of_week(:monday)
+end
+
+
+ +
+ +
+

+ + today?() + +

+ + +
+

Returns true if the date/time is today.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 30
+def today?
+  to_date == ::Date.current
+end
+
+
+ +
+ +
+

+ + tomorrow() + +

+ + +
+

Returns a new date/time representing tomorrow.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 25
+def tomorrow
+  advance(days: 1)
+end
+
+
+ +
+ +
+

+ + tomorrow?() + +

+ + +
+

Returns true if the date/time is tomorrow.

+
+ + + +
+ Also aliased as: next_day? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 35
+def tomorrow?
+  to_date == ::Date.current.tomorrow
+end
+
+
+ +
+ +
+

+ + weeks_ago(weeks) + +

+ + +
+

Returns a new date/time the specified number of weeks ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 87
+def weeks_ago(weeks)
+  advance(weeks: -weeks)
+end
+
+
+ +
+ +
+

+ + weeks_since(weeks) + +

+ + +
+

Returns a new date/time the specified number of weeks in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 92
+def weeks_since(weeks)
+  advance(weeks: weeks)
+end
+
+
+ +
+ +
+

+ + years_ago(years) + +

+ + +
+

Returns a new date/time the specified number of years ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 107
+def years_ago(years)
+  advance(years: -years)
+end
+
+
+ +
+ +
+

+ + years_since(years) + +

+ + +
+

Returns a new date/time the specified number of years in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 112
+def years_since(years)
+  advance(years: years)
+end
+
+
+ +
+ +
+

+ + yesterday() + +

+ + +
+

Returns a new date/time representing yesterday.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 20
+def yesterday
+  advance(days: -1)
+end
+
+
+ +
+ +
+

+ + yesterday?() + +

+ + +
+

Returns true if the date/time is yesterday.

+
+ + + +
+ Also aliased as: prev_day? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/calculations.rb, line 41
+def yesterday?
+  to_date == ::Date.current.yesterday
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/DateAndTime/Compatibility.html b/src/7.0/classes/DateAndTime/Compatibility.html new file mode 100644 index 0000000000..6affb549e4 --- /dev/null +++ b/src/7.0/classes/DateAndTime/Compatibility.html @@ -0,0 +1,54 @@ +--- +title: DateAndTime::Compatibility +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/DateAndTime/Zones.html b/src/7.0/classes/DateAndTime/Zones.html new file mode 100644 index 0000000000..fd3bf8e76c --- /dev/null +++ b/src/7.0/classes/DateAndTime/Zones.html @@ -0,0 +1,121 @@ +--- +title: DateAndTime::Zones +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + in_time_zone(zone = ::Time.zone) + +

+ + +
+

Returns the simultaneous time in Time.zone if a zone is given or if Time.zone_default is set. Otherwise, it returns the current time.

+ +
Time.zone = 'Hawaii'        # => 'Hawaii'
+Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00
+Date.new(2000).in_time_zone # => Sat, 01 Jan 2000 00:00:00 HST -10:00
+
+ +

This method is similar to Time#localtime, except that it uses Time.zone as the local zone instead of the operating system’s time zone.

+ +

You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument, and the conversion will be based on that zone instead of Time.zone.

+ +
Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00
+Date.new(2000).in_time_zone('Alaska') # => Sat, 01 Jan 2000 00:00:00 AKST -09:00
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_and_time/zones.rb, line 20
+def in_time_zone(zone = ::Time.zone)
+  time_zone = ::Time.find_zone! zone
+  time = acts_like?(:time) ? self : nil
+
+  if time_zone
+    time_with_zone(time, time_zone)
+  else
+    time || to_time
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/DateTime.html b/src/7.0/classes/DateTime.html new file mode 100644 index 0000000000..0312c6b8c8 --- /dev/null +++ b/src/7.0/classes/DateTime.html @@ -0,0 +1,2069 @@ +--- +title: DateTime +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0) + +

+ + +
+

Returns DateTime with local offset for given year if format is local else offset is zero.

+ +
DateTime.civil_from_format :local, 2012
+# => Sun, 01 Jan 2012 00:00:00 +0300
+DateTime.civil_from_format :local, 2012, 12, 17
+# => Mon, 17 Dec 2012 00:00:00 +0000
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 69
+def self.civil_from_format(utc_or_local, year, month = 1, day = 1, hour = 0, min = 0, sec = 0)
+  if utc_or_local.to_sym == :local
+    offset = ::Time.local(year, month, day).utc_offset.to_r / 86400
+  else
+    offset = 0
+  end
+  civil(year, month, day, hour, min, sec, offset)
+end
+
+
+ +
+ +
+

+ + current() + +

+ + +
+

Returns Time.zone.now.to_datetime when Time.zone or config.time_zone are set, otherwise returns Time.now.to_datetime.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 10
+def current
+  ::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <=>(other) + +

+ + +
+

Layers additional behavior on DateTime#<=> so that Time and ActiveSupport::TimeWithZone instances can be compared with a DateTime.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 208
+def <=>(other)
+  if other.respond_to? :to_datetime
+    super other.to_datetime rescue nil
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + acts_like_date?() + +

+ + +
+

Duck-types as a Date-like class. See Object#acts_like?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/acts_like.rb, line 8
+def acts_like_date?
+  true
+end
+
+
+ +
+ +
+

+ + acts_like_time?() + +

+ + +
+

Duck-types as a Time-like class. See Object#acts_like?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/acts_like.rb, line 13
+def acts_like_time?
+  true
+end
+
+
+ +
+ +
+

+ + advance(options) + +

+ + +
+

Uses Date to provide precise Time calculations for years, months, and days. The options parameter takes a hash with any of these keys: :years, :months, :weeks, :days, :hours, :minutes, :seconds.

+ +

Just like Date#advance, increments are applied in order of time units from largest to smallest. This order can affect the result around the end of a month.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 82
+def advance(options)
+  unless options[:weeks].nil?
+    options[:weeks], partial_weeks = options[:weeks].divmod(1)
+    options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
+  end
+
+  unless options[:days].nil?
+    options[:days], partial_days = options[:days].divmod(1)
+    options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
+  end
+
+  d = to_date.advance(options)
+  datetime_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
+  seconds_to_advance = \
+    options.fetch(:seconds, 0) +
+    options.fetch(:minutes, 0) * 60 +
+    options.fetch(:hours, 0) * 3600
+
+  if seconds_to_advance.zero?
+    datetime_advanced_by_date
+  else
+    datetime_advanced_by_date.since(seconds_to_advance)
+  end
+end
+
+
+ +
+ +
+

+ + ago(seconds) + +

+ + +
+

Returns a new DateTime representing the time a number of seconds ago. Do not use this method in combination with x.months, use months_ago instead!

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 109
+def ago(seconds)
+  since(-seconds)
+end
+
+
+ +
+ +
+

+ + at_beginning_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_beginning_of_hour() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_hour +
+ + + +
+ +
+

+ + at_beginning_of_minute() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_minute +
+ + + +
+ +
+

+ + at_end_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_day +
+ + + +
+ +
+

+ + at_end_of_hour() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_hour +
+ + + +
+ +
+

+ + at_end_of_minute() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_minute +
+ + + +
+ +
+

+ + at_midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_middle_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + beginning_of_day() + +

+ + +
+

Returns a new DateTime representing the start of the day (0:00).

+
+ + + +
+ Also aliased as: midnight, at_midnight, at_beginning_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 122
+def beginning_of_day
+  change(hour: 0)
+end
+
+
+ +
+ +
+

+ + beginning_of_hour() + +

+ + +
+

Returns a new DateTime representing the start of the hour (hh:00:00).

+
+ + + +
+ Also aliased as: at_beginning_of_hour +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 146
+def beginning_of_hour
+  change(min: 0)
+end
+
+
+ +
+ +
+

+ + beginning_of_minute() + +

+ + +
+

Returns a new DateTime representing the start of the minute (hh:mm:00).

+
+ + + +
+ Also aliased as: at_beginning_of_minute +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 158
+def beginning_of_minute
+  change(sec: 0)
+end
+
+
+ +
+ +
+

+ + change(options) + +

+ + +
+

Returns a new DateTime where one or more of the elements have been changed according to the options parameter. The time options (:hour, :min, :sec) reset cascadingly, so if only the hour is passed, then minute and sec is set to 0. If the hour and minute is passed, then sec is set to 0. The options parameter takes a hash with any of these keys: :year, :month, :day, :hour, :min, :sec, :offset, :start.

+ +
DateTime.new(2012, 8, 29, 22, 35, 0).change(day: 1)              # => DateTime.new(2012, 8, 1, 22, 35, 0)
+DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1)  # => DateTime.new(1981, 8, 1, 22, 35, 0)
+DateTime.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => DateTime.new(1981, 8, 29, 0, 0, 0)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 51
+def change(options)
+  if new_nsec = options[:nsec]
+    raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
+    new_fraction = Rational(new_nsec, 1000000000)
+  else
+    new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
+    new_fraction = Rational(new_usec, 1000000)
+  end
+
+  raise ArgumentError, "argument out of range" if new_fraction >= 1
+
+  ::DateTime.civil(
+    options.fetch(:year, year),
+    options.fetch(:month, month),
+    options.fetch(:day, day),
+    options.fetch(:hour, hour),
+    options.fetch(:min, options[:hour] ? 0 : min),
+    options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec) + new_fraction,
+    options.fetch(:offset, offset),
+    options.fetch(:start, start)
+  )
+end
+
+
+ +
+ +
+

+ + default_inspect() + +

+ + +
+ +
+ + + + + +
+ Alias for: inspect +
+ + + +
+ +
+

+ + end_of_day() + +

+ + +
+

Returns a new DateTime representing the end of the day (23:59:59).

+
+ + + +
+ Also aliased as: at_end_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 140
+def end_of_day
+  change(hour: 23, min: 59, sec: 59, usec: Rational(999999999, 1000))
+end
+
+
+ +
+ +
+

+ + end_of_hour() + +

+ + +
+

Returns a new DateTime representing the end of the hour (hh:59:59).

+
+ + + +
+ Also aliased as: at_end_of_hour +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 152
+def end_of_hour
+  change(min: 59, sec: 59, usec: Rational(999999999, 1000))
+end
+
+
+ +
+ +
+

+ + end_of_minute() + +

+ + +
+

Returns a new DateTime representing the end of the minute (hh:mm:59).

+
+ + + +
+ Also aliased as: at_end_of_minute +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 164
+def end_of_minute
+  change(sec: 59, usec: Rational(999999999, 1000))
+end
+
+
+ +
+ +
+

+ + formatted_offset(colon = true, alternate_utc_string = nil) + +

+ + +
+

Returns a formatted string of the offset from UTC, or an alternative string if the time zone is already UTC.

+ +
datetime = DateTime.civil(2000, 1, 1, 0, 0, 0, Rational(-6, 24))
+datetime.formatted_offset         # => "-06:00"
+datetime.formatted_offset(false)  # => "-0600"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 51
+def formatted_offset(colon = true, alternate_utc_string = nil)
+  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
+end
+
+
+ +
+ +
+

+ + getgm() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + getlocal(utc_offset = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: localtime +
+ + + +
+ +
+

+ + getutc() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + gmtime() + +

+ + +
+ +
+ + + + + +
+ Alias for: utc +
+ + + +
+ +
+

+ + in(seconds) + +

+ + +
+ +
+ + + + + +
+ Alias for: since +
+ + + +
+ +
+

+ + inspect() + +

+ + +
+ +
+ + + +
+ Also aliased as: default_inspect +
+ + + +
+ Alias for: readable_inspect +
+ + + +
+ +
+

+ + localtime(utc_offset = nil) + +

+ + +
+

Returns a Time instance of the simultaneous time in the system timezone.

+
+ + + +
+ Also aliased as: getlocal +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 170
+def localtime(utc_offset = nil)
+  utc = new_offset(0)
+
+  Time.utc(
+    utc.year, utc.month, utc.day,
+    utc.hour, utc.min, utc.sec + utc.sec_fraction
+  ).getlocal(utc_offset)
+end
+
+
+ +
+ +
+

+ + midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + middle_of_day() + +

+ + +
+

Returns a new DateTime representing the middle of the day (12:00)

+
+ + + +
+ Also aliased as: midday, noon, at_midday, at_noon, at_middle_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 130
+def middle_of_day
+  change(hour: 12)
+end
+
+
+ +
+ +
+

+ + midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + nsec() + +

+ + +
+

Returns the fraction of a second as nanoseconds

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 94
+def nsec
+  (sec_fraction * 1_000_000_000).to_i
+end
+
+
+ +
+ +
+

+ + readable_inspect() + +

+ + +
+

Overrides the default inspect method with a human readable one, e.g., “Mon, 21 Feb 2005 14:30:00 +0000”.

+
+ + + +
+ Also aliased as: inspect +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 56
+def readable_inspect
+  to_fs(:rfc822)
+end
+
+
+ +
+ +
+

+ + seconds_since_midnight() + +

+ + +
+

Returns the number of seconds since 00:00:00.

+ +
DateTime.new(2012, 8, 29,  0,  0,  0).seconds_since_midnight # => 0
+DateTime.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296
+DateTime.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 20
+def seconds_since_midnight
+  sec + (min * 60) + (hour * 3600)
+end
+
+
+ +
+ +
+

+ + seconds_until_end_of_day() + +

+ + +
+

Returns the number of seconds until 23:59:59.

+ +
DateTime.new(2012, 8, 29,  0,  0,  0).seconds_until_end_of_day # => 86399
+DateTime.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
+DateTime.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 29
+def seconds_until_end_of_day
+  end_of_day.to_i - to_i
+end
+
+
+ +
+ +
+

+ + since(seconds) + +

+ + +
+

Returns a new DateTime representing the time a number of seconds since the instance time. Do not use this method in combination with x.months, use months_since instead!

+
+ + + +
+ Also aliased as: in +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 116
+def since(seconds)
+  self + Rational(seconds, 86400)
+end
+
+
+ +
+ +
+

+ + subsec() + +

+ + +
+

Returns the fraction of a second as a Rational

+ +
DateTime.new(2012, 8, 29, 0, 0, 0.5).subsec # => (1/2)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 36
+def subsec
+  sec_fraction
+end
+
+
+ +
+ +
+

+ + to_f() + +

+ + +
+

Converts self to a floating-point number of seconds, including fractional microseconds, since the Unix epoch.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 79
+def to_f
+  seconds_since_unix_epoch.to_f + sec_fraction
+end
+
+
+ +
+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Convert to a formatted string. See Time::DATE_FORMATS for predefined formats.

+ +

This method is aliased to to_formatted_s.

+ +

Examples

+ +
datetime = DateTime.civil(2007, 12, 4, 0, 0, 0, 0)   # => Tue, 04 Dec 2007 00:00:00 +0000
+
+datetime.to_fs(:db)            # => "2007-12-04 00:00:00"
+datetime.to_formatted_s(:db)   # => "2007-12-04 00:00:00"
+datetime.to_fs(:number)        # => "20071204000000"
+datetime.to_fs(:short)         # => "04 Dec 00:00"
+datetime.to_fs(:long)          # => "December 04, 2007 00:00"
+datetime.to_fs(:long_ordinal)  # => "December 4th, 2007 00:00"
+datetime.to_fs(:rfc822)        # => "Tue, 04 Dec 2007 00:00:00 +0000"
+datetime.to_fs(:iso8601)       # => "2007-12-04T00:00:00+00:00"
+
+ +

Adding your own datetime formats to to_fs

+ +

DateTime formats are shared with Time. You can add your own to the Time::DATE_FORMATS hash. Use the format name as the hash key and either a strftime string or Proc instance that takes a time or datetime argument as the value.

+ +
# config/initializers/time_formats.rb
+Time::DATE_FORMATS[:month_and_year] = '%B %Y'
+Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 35
+def to_fs(format = :default)
+  if formatter = ::Time::DATE_FORMATS[format]
+    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
+  else
+    to_default_s
+  end
+end
+
+
+ +
+ +
+

+ + to_i() + +

+ + +
+

Converts self to an integer number of seconds since the Unix epoch.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 84
+def to_i
+  seconds_since_unix_epoch.to_i
+end
+
+
+ +
+ +
+

+ + to_time() + +

+ + +
+

Either return an instance of Time with the same UTC offset as self or an instance of Time representing the same time in the local system timezone depending on the setting of on the setting of ActiveSupport.to_time_preserves_timezone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/compatibility.rb, line 15
+def to_time
+  preserve_timezone ? getlocal(utc_offset) : getlocal
+end
+
+
+ +
+ +
+

+ + usec() + +

+ + +
+

Returns the fraction of a second as microseconds

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/conversions.rb, line 89
+def usec
+  (sec_fraction * 1_000_000).to_i
+end
+
+
+ +
+ +
+

+ + utc() + +

+ + +
+

Returns a Time instance of the simultaneous time in the UTC timezone.

+ +
DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24))     # => Mon, 21 Feb 2005 10:11:12 -0600
+DateTime.civil(2005, 2, 21, 10, 11, 12, Rational(-6, 24)).utc # => Mon, 21 Feb 2005 16:11:12 UTC
+
+
+ + + +
+ Also aliased as: getgm, getutc, gmtime +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 184
+def utc
+  utc = new_offset(0)
+
+  Time.utc(
+    utc.year, utc.month, utc.day,
+    utc.hour, utc.min, utc.sec + utc.sec_fraction
+  )
+end
+
+
+ +
+ +
+

+ + utc?() + +

+ + +
+

Returns true if offset == 0.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 197
+def utc?
+  offset == 0
+end
+
+
+ +
+ +
+

+ + utc_offset() + +

+ + +
+

Returns the offset value in seconds.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/date_time/calculations.rb, line 202
+def utc_offset
+  (offset * 86400).to_i
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Delegator.html b/src/7.0/classes/Delegator.html new file mode 100644 index 0000000000..b902bd2470 --- /dev/null +++ b/src/7.0/classes/Delegator.html @@ -0,0 +1,144 @@ +--- +title: Delegator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + try(*args, &block) + + +

+ + +
+

See Object#try

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 121
+  
+
+
+ +
+ +
+

+ + try!(*args, &block) + + +

+ + +
+

See Object#try!

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 129
+
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Digest.html b/src/7.0/classes/Digest.html new file mode 100644 index 0000000000..e9e5792a49 --- /dev/null +++ b/src/7.0/classes/Digest.html @@ -0,0 +1,67 @@ +--- +title: Digest +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Digest/UUID.html b/src/7.0/classes/Digest/UUID.html new file mode 100644 index 0000000000..6af378cc24 --- /dev/null +++ b/src/7.0/classes/Digest/UUID.html @@ -0,0 +1,240 @@ +--- +title: Digest::UUID +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + uuid_from_hash(hash_class, namespace, name) + +

+ + +
+

Generates a v5 non-random UUID (Universally Unique IDentifier).

+ +

Using OpenSSL::Digest::MD5 generates version 3 UUIDs; OpenSSL::Digest::SHA1 generates version 5 UUIDs. uuid_from_hash always generates the same UUID for a given name and namespace combination.

+ +

See RFC 4122 for details of UUID at: www.ietf.org/rfc/rfc4122.txt

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/digest/uuid.rb, line 21
+def self.uuid_from_hash(hash_class, namespace, name)
+  if hash_class == Digest::MD5 || hash_class == OpenSSL::Digest::MD5
+    version = 3
+  elsif hash_class == Digest::SHA1 || hash_class == OpenSSL::Digest::SHA1
+    version = 5
+  else
+    raise ArgumentError, "Expected OpenSSL::Digest::SHA1 or OpenSSL::Digest::MD5, got #{hash_class.name}."
+  end
+
+  uuid_namespace = pack_uuid_namespace(namespace)
+
+  hash = hash_class.new
+  hash.update(uuid_namespace)
+  hash.update(name)
+
+  ary = hash.digest.unpack("NnnnnN")
+  ary[2] = (ary[2] & 0x0FFF) | (version << 12)
+  ary[3] = (ary[3] & 0x3FFF) | 0x8000
+
+  "%08x-%04x-%04x-%04x-%04x%08x" % ary
+end
+
+
+ +
+ +
+

+ + uuid_v3(uuid_namespace, name) + +

+ + +
+

Convenience method for uuid_from_hash using OpenSSL::Digest::MD5.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/digest/uuid.rb, line 44
+def self.uuid_v3(uuid_namespace, name)
+  uuid_from_hash(OpenSSL::Digest::MD5, uuid_namespace, name)
+end
+
+
+ +
+ +
+

+ + uuid_v4() + +

+ + +
+

Convenience method for SecureRandom.uuid.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/digest/uuid.rb, line 54
+def self.uuid_v4
+  SecureRandom.uuid
+end
+
+
+ +
+ +
+

+ + uuid_v5(uuid_namespace, name) + +

+ + +
+

Convenience method for uuid_from_hash using OpenSSL::Digest::SHA1.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/digest/uuid.rb, line 49
+def self.uuid_v5(uuid_namespace, name)
+  uuid_from_hash(OpenSSL::Digest::SHA1, uuid_namespace, name)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/ERB.html b/src/7.0/classes/ERB.html new file mode 100644 index 0000000000..a4b4a1b400 --- /dev/null +++ b/src/7.0/classes/ERB.html @@ -0,0 +1,75 @@ +--- +title: ERB +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/ERB/Util.html b/src/7.0/classes/ERB/Util.html new file mode 100644 index 0000000000..dc782aedbf --- /dev/null +++ b/src/7.0/classes/ERB/Util.html @@ -0,0 +1,414 @@ +--- +title: ERB::Util +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
HTML_ESCAPE={ "&" => "&amp;", ">" => "&gt;", "<" => "&lt;", '"' => "&quot;", "'" => "&#39;" }
 
HTML_ESCAPE_ONCE_REGEXP=/["><']|&(?!([a-zA-Z]+|(#\d+)|(#[xX][\dA-Fa-f]+));)/
 
JSON_ESCAPE={ "&" => '\u0026', ">" => '\u003e', "<" => '\u003c', "\u2028" => '\u2028', "\u2029" => '\u2029' }
 
JSON_ESCAPE_REGEXP=/[\u2028\u2029&><]/u
 
TAG_NAME_FOLLOWING_REGEXP=/[^#{TAG_NAME_START_REGEXP_SET}\-.0-9\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}]/
 
TAG_NAME_REPLACEMENT_CHAR="_"
 
TAG_NAME_START_REGEXP=/[^#{TAG_NAME_START_REGEXP_SET}]/
 
TAG_NAME_START_REGEXP_SET="@:A-Z_a-z\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}\u{37F}-\u{1FFF}" \ +"\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}" \ +"\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}"
 

Following XML requirements: www.w3.org/TR/REC-xml/#NT-Name

+ + + + + + +

Class Public methods

+ +
+

+ + h(s) + +

+ + +
+ +
+ + + + + +
+ Alias for: html_escape +
+ + + +
+ +
+

+ + html_escape(s) + +

+ + +
+

A utility method for escaping HTML tag characters. This method is also aliased as h.

+ +
puts html_escape('is a > 0 & a < 10?')
+# => is a &gt; 0 &amp; a &lt; 10?
+
+
+ + + +
+ Also aliased as: h +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 27
+def html_escape(s)
+  unwrapped_html_escape(s).html_safe
+end
+
+
+ +
+ +
+

+ + html_escape_once(s) + +

+ + +
+

A utility method for escaping HTML without affecting existing escaped entities.

+ +
html_escape_once('1 < 2 &amp; 3')
+# => "1 &lt; 2 &amp; 3"
+
+html_escape_once('&lt;&lt; Accept & Checkout')
+# => "&lt;&lt; Accept &amp; Checkout"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 58
+def html_escape_once(s)
+  result = ActiveSupport::Multibyte::Unicode.tidy_bytes(s.to_s).gsub(HTML_ESCAPE_ONCE_REGEXP, HTML_ESCAPE)
+  s.html_safe? ? result.html_safe : result
+end
+
+
+ +
+ +
+

+ + json_escape(s) + +

+ + +
+

A utility method for escaping HTML entities in JSON strings. Specifically, the &, > and < characters are replaced with their equivalent unicode escaped form - u0026, u003e, and u003c. The Unicode sequences u2028 and u2029 are also escaped as they are treated as newline characters in some JavaScript engines. These sequences have identical meaning as the original characters inside the context of a JSON string, so assuming the input is a valid and well-formed JSON value, the output will have equivalent meaning when parsed:

+ +
json = JSON.generate({ name: "</script><script>alert('PWNED!!!')</script>"})
+# => "{\"name\":\"</script><script>alert('PWNED!!!')</script>\"}"
+
+json_escape(json)
+# => "{\"name\":\"\\u003C/script\\u003E\\u003Cscript\\u003Ealert('PWNED!!!')\\u003C/script\\u003E\"}"
+
+JSON.parse(json) == JSON.parse(json_escape(json))
+# => true
+
+ +

The intended use case for this method is to escape JSON strings before including them inside a script tag to avoid XSS vulnerability:

+ +
<script>
+  var currentUser = <%= raw json_escape(current_user.to_json) %>;
+</script>
+
+ +

It is necessary to raw the result of json_escape, so that quotation marks don’t get converted to &quot; entities. json_escape doesn’t automatically flag the result as HTML safe, since the raw value is unsafe to use inside HTML attributes.

+ +

If your JSON is being used downstream for insertion into the DOM, be aware of whether or not it is being inserted via html(). Most jQuery plugins do this. If that is the case, be sure to html_escape or sanitize any user-generated content returned by your JSON.

+ +

If you need to output JSON elsewhere in your HTML, you can just do something like this, as any unsafe characters (including quotation marks) will be automatically escaped for you:

+ +
<div data-user-info="<%= current_user.to_json %>">...</div>
+
+ +

WARNING: this helper only works with valid JSON. Using this on non-JSON values will open up serious XSS vulnerabilities. For example, if you replace the current_user.to_json in the example above with user input instead, the browser will happily eval() that string as JavaScript.

+ +

The escaping performed in this method is identical to those performed in the Active Support JSON encoder when ActiveSupport.escape_html_entities_in_json is set to true. Because this transformation is idempotent, this helper can be applied even if ActiveSupport.escape_html_entities_in_json is already true.

+ +

Therefore, when you are unsure if ActiveSupport.escape_html_entities_in_json is enabled, or if you are unsure where your JSON string originated from, it is recommended that you always apply this helper (other libraries, such as the JSON gem, do not provide this kind of protection by default; also some gems might override to_json to bypass Active Support’s encoder).

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 120
+def json_escape(s)
+  result = s.to_s.gsub(JSON_ESCAPE_REGEXP, JSON_ESCAPE)
+  s.html_safe? ? result.html_safe : result
+end
+
+
+ +
+ +
+

+ + xml_name_escape(name) + +

+ + +
+

A utility method for escaping XML names of tags and names of attributes.

+ +
xml_name_escape('1 < 2 & 3')
+# => "1___2___3"
+
+ +

It follows the requirements of the specification: www.w3.org/TR/REC-xml/#NT-Name

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 133
+def xml_name_escape(name)
+  name = name.to_s
+  return "" if name.blank?
+
+  starting_char = name[0].gsub(TAG_NAME_START_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
+
+  return starting_char if name.size == 1
+
+  following_chars = name[1..-1].gsub(TAG_NAME_FOLLOWING_REGEXP, TAG_NAME_REPLACEMENT_CHAR)
+
+  starting_char + following_chars
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Enumerable.html b/src/7.0/classes/Enumerable.html new file mode 100644 index 0000000000..63cc06304c --- /dev/null +++ b/src/7.0/classes/Enumerable.html @@ -0,0 +1,820 @@ +--- +title: Enumerable +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + compact_blank() + +

+ + +
+

Returns a new Array without the blank items. Uses Object#blank? for determining if an item is blank.

+ +
[1, "", nil, 2, " ", [], {}, false, true].compact_blank
+# =>  [1, 2, true]
+
+Set.new([nil, "", 1, false]).compact_blank
+# => [1]
+
+ +

When called on a Hash, returns a new Hash without the blank values.

+ +
{ a: "", b: 1, c: nil, d: [], e: false, f: true }.compact_blank
+# => { b: 1, f: true }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 240
+def compact_blank
+  reject(&:blank?)
+end
+
+
+ +
+ +
+

+ + exclude?(object) + +

+ + +
+

The negative of the Enumerable#include?. Returns true if the collection does not include the object.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 174
+def exclude?(object)
+  !include?(object)
+end
+
+
+ +
+ +
+

+ + excluding(*elements) + +

+ + +
+

Returns a copy of the enumerable excluding the specified elements.

+ +
["David", "Rafael", "Aaron", "Todd"].excluding "Aaron", "Todd"
+# => ["David", "Rafael"]
+
+["David", "Rafael", "Aaron", "Todd"].excluding %w[ Aaron Todd ]
+# => ["David", "Rafael"]
+
+{foo: 1, bar: 2, baz: 3}.excluding :bar
+# => {foo: 1, baz: 3}
+
+
+ + + +
+ Also aliased as: without +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 188
+def excluding(*elements)
+  elements.flatten!(1)
+  reject { |element| elements.include?(element) }
+end
+
+
+ +
+ +
+

+ + in_order_of(key, series) + +

+ + +
+

Returns a new Array where the order has been set to that provided in the series, based on the key of the objects in the original enumerable.

+ +
[ Person.find(5), Person.find(3), Person.find(1) ].in_order_of(:id, [ 1, 5, 3 ])
+# => [ Person.find(1), Person.find(5), Person.find(3) ]
+
+ +

If the series include keys that have no corresponding element in the Enumerable, these are ignored. If the Enumerable has additional elements that aren’t named in the series, these are not included in the result.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 252
+def in_order_of(key, series)
+  group_by(&key).values_at(*series).flatten(1).compact
+end
+
+
+ +
+ +
+

+ + including(*elements) + +

+ + +
+

Returns a new array that includes the passed elements.

+ +
[ 1, 2, 3 ].including(4, 5)
+# => [ 1, 2, 3, 4, 5 ]
+
+["David", "Rafael"].including %w[ Aaron Todd ]
+# => ["David", "Rafael", "Aaron", "Todd"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 168
+def including(*elements)
+  to_a.including(*elements)
+end
+
+
+ +
+ +
+

+ + index_by() + +

+ + +
+

Convert an enumerable to a hash, using the block result as the key and the element as the value.

+ +
people.index_by(&:login)
+# => { "nextangle" => <Person ...>, "chade-" => <Person ...>, ...}
+
+people.index_by { |person| "#{person.first_name} #{person.last_name}" }
+# => { "Chade- Fowlersburg-e" => <Person ...>, "David Heinemeier Hansson" => <Person ...>, ...}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 108
+def index_by
+  if block_given?
+    result = {}
+    each { |elem| result[yield(elem)] = elem }
+    result
+  else
+    to_enum(:index_by) { size if respond_to?(:size) }
+  end
+end
+
+
+ +
+ +
+

+ + index_with(default = (no_default = true)) + +

+ + +
+

Convert an enumerable to a hash, using the element as the key and the block result as the value.

+ +
post = Post.new(title: "hey there", body: "what's up?")
+
+%i( title body ).index_with { |attr_name| post.public_send(attr_name) }
+# => { title: "hey there", body: "what's up?" }
+
+ +

If an argument is passed instead of a block, it will be used as the value for all elements:

+ +
%i( created_at updated_at ).index_with(Time.now)
+# => { created_at: 2020-03-09 22:31:47, updated_at: 2020-03-09 22:31:47 }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 131
+def index_with(default = (no_default = true))
+  if block_given?
+    result = {}
+    each { |elem| result[elem] = yield(elem) }
+    result
+  elsif no_default
+    to_enum(:index_with) { size if respond_to?(:size) }
+  else
+    result = {}
+    each { |elem| result[elem] = default }
+    result
+  end
+end
+
+
+ +
+ +
+

+ + many?() + +

+ + +
+

Returns true if the enumerable has more than 1 element. Functionally equivalent to enum.to_a.size > 1. Can be called with a block too, much like any?, so people.many? { |p| p.age > 26 } returns true if more than one person is over 26.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 149
+def many?
+  cnt = 0
+  if block_given?
+    any? do |*args|
+      cnt += 1 if yield(*args)
+      cnt > 1
+    end
+  else
+    any? { (cnt += 1) > 1 }
+  end
+end
+
+
+ +
+ +
+

+ + maximum(key) + +

+ + +
+

Calculates the maximum from the extracted elements.

+ +
payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
+payments.maximum(:price) # => 15
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 52
+def maximum(key)
+  map(&key).max
+end
+
+
+ +
+ +
+

+ + minimum(key) + +

+ + +
+

Calculates the minimum from the extracted elements.

+ +
payments = [Payment.new(5), Payment.new(15), Payment.new(10)]
+payments.minimum(:price) # => 5
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 44
+def minimum(key)
+  map(&key).min
+end
+
+
+ +
+ +
+

+ + pick(*keys) + +

+ + +
+

Extract the given key from the first element in the enumerable.

+ +
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pick(:name)
+# => "David"
+
+[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pick(:id, :name)
+# => [1, "David"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 217
+def pick(*keys)
+  return if none?
+
+  if keys.many?
+    keys.map { |key| first[key] }
+  else
+    first[keys.first]
+  end
+end
+
+
+ +
+ +
+

+ + pluck(*keys) + +

+ + +
+

Extract the given key from each element in the enumerable.

+ +
[{ name: "David" }, { name: "Rafael" }, { name: "Aaron" }].pluck(:name)
+# => ["David", "Rafael", "Aaron"]
+
+[{ id: 1, name: "David" }, { id: 2, name: "Rafael" }].pluck(:id, :name)
+# => [[1, "David"], [2, "Rafael"]]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 201
+def pluck(*keys)
+  if keys.many?
+    map { |element| keys.map { |key| element[key] } }
+  else
+    key = keys.first
+    map { |element| element[key] }
+  end
+end
+
+
+ +
+ +
+

+ + sole() + +

+ + +
+

Returns the sole item in the enumerable. If there are no items, or more than one item, raises Enumerable::SoleItemExpectedError.

+ +
["x"].sole          # => "x"
+Set.new.sole        # => Enumerable::SoleItemExpectedError: no item found
+{ a: 1, b: 2 }.sole # => Enumerable::SoleItemExpectedError: multiple items found
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 262
+def sole
+  case count
+  when 1   then return first # rubocop:disable Style/RedundantReturn
+  when 0   then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "no item found"
+  when 2.. then raise ActiveSupport::EnumerableCoreExt::SoleItemExpectedError, "multiple items found"
+  end
+end
+
+
+ +
+ +
+

+ + sum(identity = nil, &block) + +

+ + +
+

Calculates a sum from the elements.

+ +
payments.sum { |p| p.price * p.tax_rate }
+payments.sum(&:price)
+
+ +

The latter is a shortcut for:

+ +
payments.inject(0) { |sum, p| sum + p.price }
+
+ +

It can also calculate the sum without the use of a block.

+ +
[5, 15, 10].sum # => 30
+['foo', 'bar'].sum('') # => "foobar"
+[[1, 2], [3, 1, 5]].sum([]) # => [1, 2, 3, 1, 5]
+
+ +

The default sum of an empty list is zero. You can override this default:

+ +
[].sum(Payment.new(0)) { |i| i.amount } # => Payment.new(0)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 74
+  def sum(identity = nil, &block)
+    if identity
+      _original_sum_with_required_identity(identity, &block)
+    elsif block_given?
+      map(&block).sum
+    else
+      first = true
+
+      reduce(nil) do |sum, value|
+        if first
+          first = false
+
+          unless value.is_a?(Numeric) || value.respond_to?(:coerce)
+            ActiveSupport::Deprecation.warn(<<-MSG.squish)
+              Rails 7.0 has deprecated Enumerable.sum in favor of Ruby's native implementation available since 2.4.
+              Sum of non-numeric elements requires an initial argument.
+            MSG
+          end
+          value
+        else
+          sum + value
+        end
+      end || 0
+    end
+  end
+
+
+ +
+ +
+

+ + without(*elements) + +

+ + +
+ +
+ + + + + +
+ Alias for: excluding +
+ + + +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Enumerable/SoleItemExpectedError.html b/src/7.0/classes/Enumerable/SoleItemExpectedError.html new file mode 100644 index 0000000000..f0c642673e --- /dev/null +++ b/src/7.0/classes/Enumerable/SoleItemExpectedError.html @@ -0,0 +1,66 @@ +--- +title: Enumerable::SoleItemExpectedError +layout: default +--- +
+ +
+
+ +
+ +

Error generated by sole when called on an enumerable that doesn’t have exactly one item.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Exception.html b/src/7.0/classes/Exception.html new file mode 100644 index 0000000000..442ed75499 --- /dev/null +++ b/src/7.0/classes/Exception.html @@ -0,0 +1,107 @@ +--- +title: Exception +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + as_json(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/json.rb, line 241
+def as_json(options = nil)
+  to_s
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/FalseClass.html b/src/7.0/classes/FalseClass.html new file mode 100644 index 0000000000..ee8f1a860b --- /dev/null +++ b/src/7.0/classes/FalseClass.html @@ -0,0 +1,155 @@ +--- +title: FalseClass +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + blank?() + +

+ + +
+

false is blank:

+ +
false.blank? # => true
+
+ +

@return [true]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 67
+def blank?
+  true
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Returns self.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 34
+def to_param
+  self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/File.html b/src/7.0/classes/File.html new file mode 100644 index 0000000000..722f1d2b26 --- /dev/null +++ b/src/7.0/classes/File.html @@ -0,0 +1,155 @@ +--- +title: File +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + atomic_write(file_name, temp_dir = dirname(file_name)) + +

+ + +
+

Write to a file atomically. Useful for situations where you don’t want other processes or threads to see half-written files.

+ +
File.atomic_write('important.file') do |file|
+  file.write('hello')
+end
+
+ +

This method needs to create a temporary file. By default it will create it in the same directory as the destination file. If you don’t like this behavior you can provide a different directory but it must be on the same physical filesystem as the file you’re trying to write.

+ +
File.atomic_write('/data/something.important', '/data/tmp') do |file|
+  file.write('hello')
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/file/atomic.rb, line 21
+def self.atomic_write(file_name, temp_dir = dirname(file_name))
+  require "tempfile" unless defined?(Tempfile)
+
+  Tempfile.open(".#{basename(file_name)}", temp_dir) do |temp_file|
+    temp_file.binmode
+    return_val = yield temp_file
+    temp_file.close
+
+    old_stat = if exist?(file_name)
+      # Get original file permissions
+      stat(file_name)
+    else
+      # If not possible, probe which are the default permissions in the
+      # destination directory.
+      probe_stat_in(dirname(file_name))
+    end
+
+    if old_stat
+      # Set correct permissions on new file
+      begin
+        chown(old_stat.uid, old_stat.gid, temp_file.path)
+        # This operation will affect filesystem ACL's
+        chmod(old_stat.mode, temp_file.path)
+      rescue Errno::EPERM, Errno::EACCES
+        # Changing file ownership failed, moving on.
+      end
+    end
+
+    # Overwrite original file with temp file
+    rename(temp_file.path, file_name)
+    return_val
+  end
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Float.html b/src/7.0/classes/Float.html new file mode 100644 index 0000000000..648e88b010 --- /dev/null +++ b/src/7.0/classes/Float.html @@ -0,0 +1,60 @@ +--- +title: Float +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Hash.html b/src/7.0/classes/Hash.html new file mode 100644 index 0000000000..f6ea40c152 --- /dev/null +++ b/src/7.0/classes/Hash.html @@ -0,0 +1,1711 @@ +--- +title: Hash +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + from_trusted_xml(xml) + +

+ + +
+

Builds a Hash from XML just like Hash.from_xml, but also allows Symbol and YAML.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/conversions.rb, line 133
+def from_trusted_xml(xml)
+  from_xml xml, []
+end
+
+
+ +
+ +
+

+ + from_xml(xml, disallowed_types = nil) + +

+ + +
+

Returns a Hash containing a collection of pairs when the key is the node name and the value is its content

+ +
xml = <<-XML
+  <?xml version="1.0" encoding="UTF-8"?>
+    <hash>
+      <foo type="integer">1</foo>
+      <bar type="integer">2</bar>
+    </hash>
+XML
+
+hash = Hash.from_xml(xml)
+# => {"hash"=>{"foo"=>1, "bar"=>2}}
+
+ +

DisallowedType is raised if the XML contains attributes with type="yaml" or type="symbol". Use Hash.from_trusted_xml to parse this XML.

+ +

Custom disallowed_types can also be passed in the form of an array.

+ +
xml = <<-XML
+  <?xml version="1.0" encoding="UTF-8"?>
+    <hash>
+      <foo type="integer">1</foo>
+      <bar type="string">"David"</bar>
+    </hash>
+XML
+
+hash = Hash.from_xml(xml, ['integer'])
+# => ActiveSupport::XMLConverter::DisallowedType: Disallowed type attribute: "integer"
+
+ +

Note that passing custom disallowed types will override the default types, which are Symbol and YAML.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/conversions.rb, line 128
+def from_xml(xml, disallowed_types = nil)
+  ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + assert_valid_keys(*valid_keys) + +

+ + +
+

Validates all keys in a hash match *valid_keys, raising ArgumentError on a mismatch.

+ +

Note that keys are treated differently than HashWithIndifferentAccess, meaning that string and symbol keys will not match.

+ +
{ name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
+{ name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
+{ name: 'Rob', age: '28' }.assert_valid_keys(:name, :age)   # => passes, raises nothing
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 48
+def assert_valid_keys(*valid_keys)
+  valid_keys.flatten!
+  each_key do |k|
+    unless valid_keys.include?(k)
+      raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
+    end
+  end
+end
+
+
+ +
+ +
+

+ + compact_blank!() + +

+ + +
+

Removes all blank values from the Hash in place and returns self. Uses Object#blank? for determining if a value is blank.

+ +
h = { a: "", b: 1, c: nil, d: [], e: false, f: true }
+h.compact_blank!
+# => { b: 1, f: true }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/enumerable.rb, line 283
+def compact_blank!
+  # use delete_if rather than reject! because it always returns self even if nothing changed
+  delete_if { |_k, v| v.blank? }
+end
+
+
+ +
+ +
+

+ + deep_dup() + +

+ + +
+

Returns a deep copy of hash.

+ +
hash = { a: { b: 'b' } }
+dup  = hash.deep_dup
+dup[:a][:c] = 'c'
+
+hash[:a][:c] # => nil
+dup[:a][:c]  # => "c"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 43
+def deep_dup
+  hash = dup
+  each_pair do |key, value|
+    if ::String === key || ::Symbol === key
+      hash[key] = value.deep_dup
+    else
+      hash.delete(key)
+      hash[key.deep_dup] = value.deep_dup
+    end
+  end
+  hash
+end
+
+
+ +
+ +
+

+ + deep_merge(other_hash, &block) + +

+ + +
+

Returns a new hash with self and other_hash merged recursively.

+ +
h1 = { a: true, b: { c: [1, 2, 3] } }
+h2 = { a: false, b: { x: [3, 4, 5] } }
+
+h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
+
+ +

Like with Hash#merge in the standard library, a block can be provided to merge values:

+ +
h1 = { a: 100, b: 200, c: { c1: 100 } }
+h2 = { b: 250, c: { c1: 200 } }
+h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
+# => { a: 100, b: 450, c: { c1: 300 } }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/deep_merge.rb, line 18
+def deep_merge(other_hash, &block)
+  dup.deep_merge!(other_hash, &block)
+end
+
+
+ +
+ +
+

+ + deep_merge!(other_hash, &block) + +

+ + +
+

Same as deep_merge, but modifies self.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/deep_merge.rb, line 23
+def deep_merge!(other_hash, &block)
+  merge!(other_hash) do |key, this_val, other_val|
+    if this_val.is_a?(Hash) && other_val.is_a?(Hash)
+      this_val.deep_merge(other_val, &block)
+    elsif block_given?
+      block.call(key, this_val, other_val)
+    else
+      other_val
+    end
+  end
+end
+
+
+ +
+ +
+

+ + deep_stringify_keys() + +

+ + +
+

Returns a new hash with all keys converted to strings. This includes the keys from the root hash and from all nested hashes and arrays.

+ +
hash = { person: { name: 'Rob', age: '28' } }
+
+hash.deep_stringify_keys
+# => {"person"=>{"name"=>"Rob", "age"=>"28"}}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 84
+def deep_stringify_keys
+  deep_transform_keys(&:to_s)
+end
+
+
+ +
+ +
+

+ + deep_stringify_keys!() + +

+ + +
+

Destructively converts all keys to strings. This includes the keys from the root hash and from all nested hashes and arrays.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 91
+def deep_stringify_keys!
+  deep_transform_keys!(&:to_s)
+end
+
+
+ +
+ +
+

+ + deep_symbolize_keys() + +

+ + +
+

Returns a new hash with all keys converted to symbols, as long as they respond to to_sym. This includes the keys from the root hash and from all nested hashes and arrays.

+ +
hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
+
+hash.deep_symbolize_keys
+# => {:person=>{:name=>"Rob", :age=>"28"}}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 103
+def deep_symbolize_keys
+  deep_transform_keys { |key| key.to_sym rescue key }
+end
+
+
+ +
+ +
+

+ + deep_symbolize_keys!() + +

+ + +
+

Destructively converts all keys to symbols, as long as they respond to to_sym. This includes the keys from the root hash and from all nested hashes and arrays.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 110
+def deep_symbolize_keys!
+  deep_transform_keys! { |key| key.to_sym rescue key }
+end
+
+
+ +
+ +
+

+ + deep_transform_keys(&block) + +

+ + +
+

Returns a new hash with all keys converted by the block operation. This includes the keys from the root hash and from all nested hashes and arrays.

+ +
hash = { person: { name: 'Rob', age: '28' } }
+
+hash.deep_transform_keys{ |key| key.to_s.upcase }
+# => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 65
+def deep_transform_keys(&block)
+  _deep_transform_keys_in_object(self, &block)
+end
+
+
+ +
+ +
+

+ + deep_transform_keys!(&block) + +

+ + +
+

Destructively converts all keys by using the block operation. This includes the keys from the root hash and from all nested hashes and arrays.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 72
+def deep_transform_keys!(&block)
+  _deep_transform_keys_in_object!(self, &block)
+end
+
+
+ +
+ +
+

+ + deep_transform_values(&block) + +

+ + +
+

Returns a new hash with all values converted by the block operation. This includes the values from the root hash and from all nested hashes and arrays.

+ +
hash = { person: { name: 'Rob', age: '28' } }
+
+hash.deep_transform_values{ |value| value.to_s.upcase }
+# => {person: {name: "ROB", age: "28"}}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb, line 12
+def deep_transform_values(&block)
+  _deep_transform_values_in_object(self, &block)
+end
+
+
+ +
+ +
+

+ + deep_transform_values!(&block) + +

+ + +
+

Destructively converts all values by using the block operation. This includes the values from the root hash and from all nested hashes and arrays.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/deep_transform_values.rb, line 19
+def deep_transform_values!(&block)
+  _deep_transform_values_in_object!(self, &block)
+end
+
+
+ +
+ +
+

+ + except(*keys) + +

+ + +
+

Returns a hash that includes everything except given keys.

+ +
hash = { a: true, b: false, c: nil }
+hash.except(:c)     # => { a: true, b: false }
+hash.except(:a, :b) # => { c: nil }
+hash                # => { a: true, b: false, c: nil }
+
+ +

This is useful for limiting a set of parameters to everything but a few known toggles:

+ +
@person.update(params[:person].except(:admin))
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/except.rb, line 12
+def except(*keys)
+  slice(*self.keys - keys)
+end
+
+
+ +
+ +
+

+ + except!(*keys) + +

+ + +
+

Removes the given keys from hash and returns it.

+ +
hash = { a: true, b: false, c: nil }
+hash.except!(:c) # => { a: true, b: false }
+hash             # => { a: true, b: false }
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/except.rb, line 20
+def except!(*keys)
+  keys.each { |key| delete(key) }
+  self
+end
+
+
+ +
+ +
+

+ + extract!(*keys) + +

+ + +
+

Removes and returns the key/value pairs matching the given keys.

+ +
hash = { a: 1, b: 2, c: 3, d: 4 }
+hash.extract!(:a, :b) # => {:a=>1, :b=>2}
+hash                  # => {:c=>3, :d=>4}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/slice.rb, line 24
+def extract!(*keys)
+  keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
+end
+
+
+ +
+ +
+

+ + extractable_options?() + +

+ + +
+

By default, only instances of Hash itself are extractable. Subclasses of Hash may implement this method and return true to declare themselves as extractable. If a Hash is extractable, Array#extract_options! pops it from the Array when it is the last element of the Array.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/array/extract_options.rb, line 9
+def extractable_options?
+  instance_of?(Hash)
+end
+
+
+ +
+ +
+

+ + nested_under_indifferent_access() + +

+ + +
+

Called when object is nested under an object that receives with_indifferent_access. This method will be called on the current object by the enclosing object and is aliased to with_indifferent_access by default. Subclasses of Hash may override this method to return self if converting to an ActiveSupport::HashWithIndifferentAccess would not be desirable.

+ +
b = { b: 1 }
+{ a: b }.with_indifferent_access['a'] # calls b.nested_under_indifferent_access
+# => {"b"=>1}
+
+
+ + + + + +
+ Alias for: with_indifferent_access +
+ + + +
+ +
+

+ + reverse_merge(other_hash) + +

+ + +
+

Merges the caller into other_hash. For example,

+ +
options = options.reverse_merge(size: 25, velocity: 10)
+
+ +

is equivalent to

+ +
options = { size: 25, velocity: 10 }.merge(options)
+
+ +

This is particularly useful for initializing an options hash with default values.

+
+ + + +
+ Also aliased as: with_defaults +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/reverse_merge.rb, line 14
+def reverse_merge(other_hash)
+  other_hash.merge(self)
+end
+
+
+ +
+ +
+

+ + reverse_merge!(other_hash) + +

+ + +
+

Destructive reverse_merge.

+
+ + + +
+ Also aliased as: reverse_update, with_defaults! +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/reverse_merge.rb, line 20
+def reverse_merge!(other_hash)
+  replace(reverse_merge(other_hash))
+end
+
+
+ +
+ +
+

+ + reverse_update(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge! +
+ + + +
+ +
+

+ + slice!(*keys) + +

+ + +
+

Replaces the hash with only the given keys. Returns a hash containing the removed key/value pairs.

+ +
hash = { a: 1, b: 2, c: 3, d: 4 }
+hash.slice!(:a, :b)  # => {:c=>3, :d=>4}
+hash                 # => {:a=>1, :b=>2}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/slice.rb, line 10
+def slice!(*keys)
+  omit = slice(*self.keys - keys)
+  hash = slice(*keys)
+  hash.default      = default
+  hash.default_proc = default_proc if default_proc
+  replace(hash)
+  omit
+end
+
+
+ +
+ +
+

+ + stringify_keys() + +

+ + +
+

Returns a new hash with all keys converted to strings.

+ +
hash = { name: 'Rob', age: '28' }
+
+hash.stringify_keys
+# => {"name"=>"Rob", "age"=>"28"}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 10
+def stringify_keys
+  transform_keys(&:to_s)
+end
+
+
+ +
+ +
+

+ + stringify_keys!() + +

+ + +
+

Destructively converts all keys to strings. Same as stringify_keys, but modifies self.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 16
+def stringify_keys!
+  transform_keys!(&:to_s)
+end
+
+
+ +
+ +
+

+ + symbolize_keys() + +

+ + +
+

Returns a new hash with all keys converted to symbols, as long as they respond to to_sym.

+ +
hash = { 'name' => 'Rob', 'age' => '28' }
+
+hash.symbolize_keys
+# => {:name=>"Rob", :age=>"28"}
+
+
+ + + +
+ Also aliased as: to_options +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 27
+def symbolize_keys
+  transform_keys { |key| key.to_sym rescue key }
+end
+
+
+ +
+ +
+

+ + symbolize_keys!() + +

+ + +
+

Destructively converts all keys to symbols, as long as they respond to to_sym. Same as symbolize_keys, but modifies self.

+
+ + + +
+ Also aliased as: to_options! +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/keys.rb, line 34
+def symbolize_keys!
+  transform_keys! { |key| key.to_sym rescue key }
+end
+
+
+ +
+ +
+

+ + to_options() + +

+ + +
+ +
+ + + + + +
+ Alias for: symbolize_keys +
+ + + +
+ +
+

+ + to_options!() + +

+ + +
+ +
+ + + + + +
+ Alias for: symbolize_keys! +
+ + + +
+ +
+

+ + to_param(namespace = nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_query +
+ + + +
+ +
+

+ + to_query(namespace = nil) + +

+ + +
+

Returns a string representation of the receiver suitable for use as a URL query string:

+ +
{name: 'David', nationality: 'Danish'}.to_query
+# => "name=David&nationality=Danish"
+
+ +

An optional namespace can be passed to enclose key names:

+ +
{name: 'David', nationality: 'Danish'}.to_query('user')
+# => "user%5Bname%5D=David&user%5Bnationality%5D=Danish"
+
+ +

The string pairs “key=value” that conform the query string are sorted lexicographically in ascending order.

+
+ + + +
+ Also aliased as: to_param +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 75
+def to_query(namespace = nil)
+  query = filter_map do |key, value|
+    unless (value.is_a?(Hash) || value.is_a?(Array)) && value.empty?
+      value.to_query(namespace ? "#{namespace}[#{key}]" : key)
+    end
+  end
+
+  query.sort! unless namespace.to_s.include?("[]")
+  query.join("&")
+end
+
+
+ +
+ +
+

+ + to_xml(options = {}) + +

+ + +
+

Returns a string containing an XML representation of its receiver:

+ +
{ foo: 1, bar: 2 }.to_xml
+# =>
+# <?xml version="1.0" encoding="UTF-8"?>
+# <hash>
+#   <foo type="integer">1</foo>
+#   <bar type="integer">2</bar>
+# </hash>
+
+ +

To do so, the method loops over the pairs and builds nodes that depend on the values. Given a pair key, value:

+
  • +

    If value is a hash there’s a recursive call with key as :root.

    +
  • +

    If value is an array there’s a recursive call with key as :root, and key singularized as :children.

    +
  • +

    If value is a callable object it must expect one or two arguments. Depending on the arity, the callable is invoked with the options hash as first argument with key as :root, and key singularized as second argument. The callable can add nodes by using options[:builder].

    + +
    {foo: lambda { |options, key| options[:builder].b(key) }}.to_xml
    +# => "<b>foo</b>"
    +
    +
  • +

    If value responds to to_xml the method is invoked with key as :root.

    + +
    class Foo
    +  def to_xml(options)
    +    options[:builder].bar 'fooing!'
    +  end
    +end
    +
    +{ foo: Foo.new }.to_xml(skip_instruct: true)
    +# =>
    +# <hash>
    +#   <bar>fooing!</bar>
    +# </hash>
    +
    +
  • +

    Otherwise, a node with key as tag is created with a string representation of value as text node. If value is nil an attribute “nil” set to “true” is added. Unless the option :skip_types exists and is true, an attribute “type” is added as well according to the following mapping:

    + +
    XML_TYPE_NAMES = {
    +  "Symbol"     => "symbol",
    +  "Integer"    => "integer",
    +  "BigDecimal" => "decimal",
    +  "Float"      => "float",
    +  "TrueClass"  => "boolean",
    +  "FalseClass" => "boolean",
    +  "Date"       => "date",
    +  "DateTime"   => "dateTime",
    +  "Time"       => "dateTime"
    +}
    +
    +
+ +

By default the root node is “hash”, but that’s configurable via the :root option.

+ +

The default XML builder is a fresh instance of Builder::XmlMarkup. You can configure your own builder with the :builder option. The method also accepts options like :dasherize and friends, they are forwarded to the builder.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/conversions.rb, line 74
+def to_xml(options = {})
+  require "active_support/builder" unless defined?(Builder::XmlMarkup)
+
+  options = options.dup
+  options[:indent]  ||= 2
+  options[:root]    ||= "hash"
+  options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
+
+  builder = options[:builder]
+  builder.instruct! unless options.delete(:skip_instruct)
+
+  root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
+
+  builder.tag!(root) do
+    each { |key, value| ActiveSupport::XmlMini.to_tag(key, value, options) }
+    yield builder if block_given?
+  end
+end
+
+
+ +
+ +
+

+ + with_defaults(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge +
+ + + +
+ +
+

+ + with_defaults!(other_hash) + +

+ + +
+ +
+ + + + + +
+ Alias for: reverse_merge! +
+ + + +
+ +
+

+ + with_indifferent_access() + +

+ + +
+

Returns an ActiveSupport::HashWithIndifferentAccess out of its receiver:

+ +
{ a: 1 }.with_indifferent_access['a'] # => 1
+
+
+ + + +
+ Also aliased as: nested_under_indifferent_access +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/hash/indifferent_access.rb, line 9
+def with_indifferent_access
+  ActiveSupport::HashWithIndifferentAccess.new(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/IO.html b/src/7.0/classes/IO.html new file mode 100644 index 0000000000..1a430fd7cc --- /dev/null +++ b/src/7.0/classes/IO.html @@ -0,0 +1,62 @@ +--- +title: IO +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Integer.html b/src/7.0/classes/Integer.html new file mode 100644 index 0000000000..b10b0fd873 --- /dev/null +++ b/src/7.0/classes/Integer.html @@ -0,0 +1,358 @@ +--- +title: Integer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + month() + +

+ + +
+ +
+ + + + + +
+ Alias for: months +
+ + + +
+ +
+

+ + months() + +

+ + +
+

Returns a Duration instance matching the number of months provided.

+ +
2.months # => 2 months
+
+
+ + + +
+ Also aliased as: month +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/integer/time.rb, line 10
+def months
+  ActiveSupport::Duration.months(self)
+end
+
+
+ +
+ +
+

+ + multiple_of?(number) + +

+ + +
+

Check whether the integer is evenly divisible by the argument.

+ +
0.multiple_of?(0)  # => true
+6.multiple_of?(5)  # => false
+10.multiple_of?(2) # => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/integer/multiple.rb, line 9
+def multiple_of?(number)
+  number == 0 ? self == 0 : self % number == 0
+end
+
+
+ +
+ +
+

+ + ordinal() + +

+ + +
+

Ordinal returns the suffix used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th.

+ +
1.ordinal     # => "st"
+2.ordinal     # => "nd"
+1002.ordinal  # => "nd"
+1003.ordinal  # => "rd"
+-11.ordinal   # => "th"
+-1001.ordinal # => "st"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/integer/inflections.rb, line 28
+def ordinal
+  ActiveSupport::Inflector.ordinal(self)
+end
+
+
+ +
+ +
+

+ + ordinalize() + +

+ + +
+

Ordinalize turns a number into an ordinal string used to denote the position in an ordered sequence such as 1st, 2nd, 3rd, 4th.

+ +
1.ordinalize     # => "1st"
+2.ordinalize     # => "2nd"
+1002.ordinalize  # => "1002nd"
+1003.ordinalize  # => "1003rd"
+-11.ordinalize   # => "-11th"
+-1001.ordinalize # => "-1001st"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/integer/inflections.rb, line 15
+def ordinalize
+  ActiveSupport::Inflector.ordinalize(self)
+end
+
+
+ +
+ +
+

+ + year() + +

+ + +
+ +
+ + + + + +
+ Alias for: years +
+ + + +
+ +
+

+ + years() + +

+ + +
+

Returns a Duration instance matching the number of years provided.

+ +
2.years # => 2 years
+
+
+ + + +
+ Also aliased as: year +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/integer/time.rb, line 18
+def years
+  ActiveSupport::Duration.years(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Kernel.html b/src/7.0/classes/Kernel.html new file mode 100644 index 0000000000..d3f890422c --- /dev/null +++ b/src/7.0/classes/Kernel.html @@ -0,0 +1,321 @@ +--- +title: Kernel +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + class_eval(*args, &block) + +

+ + +
+

class_eval on an object acts like singleton_class.class_eval.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/singleton_class.rb, line 5
+def class_eval(*args, &block)
+  singleton_class.class_eval(*args, &block)
+end
+
+
+ +
+ +
+

+ + concern(topic, &module_definition) + +

+ + +
+

A shortcut to define a toplevel concern, not within a module.

+ +

See Module::Concerning for more.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/concern.rb, line 11
+def concern(topic, &module_definition)
+  Object.concern topic, &module_definition
+end
+
+
+ +
+ +
+

+ + enable_warnings(&block) + +

+ + +
+

Sets $VERBOSE to true for the duration of the block and back to its original value afterwards.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/reporting.rb, line 20
+def enable_warnings(&block)
+  with_warnings(true, &block)
+end
+
+
+ +
+ +
+

+ + silence_warnings(&block) + +

+ + +
+

Sets $VERBOSE to nil for the duration of the block and back to its original value afterwards.

+ +
silence_warnings do
+  value = noisy_call # no warning voiced
+end
+
+noisy_call # warning voiced
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/reporting.rb, line 14
+def silence_warnings(&block)
+  with_warnings(nil, &block)
+end
+
+
+ +
+ +
+

+ + suppress(*exception_classes) + +

+ + +
+

Blocks and ignores any exception passed as argument if raised within the block.

+ +
suppress(ZeroDivisionError) do
+  1/0
+  puts 'This code is NOT reached'
+end
+
+puts 'This code gets executed and nothing related to ZeroDivisionError was seen'
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/reporting.rb, line 41
+def suppress(*exception_classes)
+  yield
+rescue *exception_classes
+end
+
+
+ +
+ +
+

+ + with_warnings(flag) + +

+ + +
+

Sets $VERBOSE for the duration of the block and back to its original value afterwards.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/kernel/reporting.rb, line 26
+def with_warnings(flag)
+  old_verbose, $VERBOSE = $VERBOSE, flag
+  yield
+ensure
+  $VERBOSE = old_verbose
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/LoadError.html b/src/7.0/classes/LoadError.html new file mode 100644 index 0000000000..0fff158e6d --- /dev/null +++ b/src/7.0/classes/LoadError.html @@ -0,0 +1,107 @@ +--- +title: LoadError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + is_missing?(location) + +

+ + +
+

Returns true if the given path name (except perhaps for the “.rb” extension) is the missing file which caused the exception to be raised.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/load_error.rb, line 6
+def is_missing?(location)
+  location.delete_suffix(".rb") == path.to_s.delete_suffix(".rb")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mail.html b/src/7.0/classes/Mail.html new file mode 100644 index 0000000000..0192e7c977 --- /dev/null +++ b/src/7.0/classes/Mail.html @@ -0,0 +1,130 @@ +--- +title: Mail +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + from_source(source) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/from_source.rb, line 4
+def self.from_source(source)
+  Mail.new Mail::Utilities.binary_unsafe_to_crlf(source.to_s)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Mail/Address.html b/src/7.0/classes/Mail/Address.html new file mode 100644 index 0000000000..c75ead7540 --- /dev/null +++ b/src/7.0/classes/Mail/Address.html @@ -0,0 +1,151 @@ +--- +title: Mail::Address +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + wrap(address) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/address_wrapping.rb, line 5
+def self.wrap(address)
+  address.is_a?(Mail::Address) ? address : Mail::Address.new(address)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(other_address) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/address_equality.rb, line 5
+def ==(other_address)
+  other_address.is_a?(Mail::Address) && to_s == other_address.to_s
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mail/Message.html b/src/7.0/classes/Mail/Message.html new file mode 100644 index 0000000000..3c7cb39082 --- /dev/null +++ b/src/7.0/classes/Mail/Message.html @@ -0,0 +1,343 @@ +--- +title: Mail::Message +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + bcc_addresses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 21
+def bcc_addresses
+  Array(address_list(header[:bcc])&.addresses)
+end
+
+
+ +
+ +
+

+ + cc_addresses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 17
+def cc_addresses
+  Array(address_list(header[:cc])&.addresses)
+end
+
+
+ +
+ +
+

+ + from_address() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 5
+def from_address
+  address_list(header[:from])&.addresses&.first
+end
+
+
+ +
+ +
+

+ + recipients() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/recipients.rb, line 5
+def recipients
+  Array(to) + Array(cc) + Array(bcc) + Array(header[:x_original_to]).map(&:to_s)
+end
+
+
+ +
+ +
+

+ + recipients_addresses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 9
+def recipients_addresses
+  to_addresses + cc_addresses + bcc_addresses + x_original_to_addresses
+end
+
+
+ +
+ +
+

+ + to_addresses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 13
+def to_addresses
+  Array(address_list(header[:to])&.addresses)
+end
+
+
+ +
+ +
+

+ + x_original_to_addresses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/lib/action_mailbox/mail_ext/addresses.rb, line 25
+def x_original_to_addresses
+  Array(header[:x_original_to]).collect { |header| Mail::Address.new header.to_s }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Method.html b/src/7.0/classes/Method.html new file mode 100644 index 0000000000..8f41840ecc --- /dev/null +++ b/src/7.0/classes/Method.html @@ -0,0 +1,111 @@ +--- +title: Method +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + duplicable?() + +

+ + +
+

Methods are not duplicable:

+ +
method(:puts).duplicable? # => false
+method(:puts).dup         # => TypeError: allocator undefined for Method
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 36
+def duplicable?
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mime.html b/src/7.0/classes/Mime.html new file mode 100644 index 0000000000..fe124e089c --- /dev/null +++ b/src/7.0/classes/Mime.html @@ -0,0 +1,221 @@ +--- +title: Mime +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ALL=AllType.instance
 

ALL isn’t a real MIME type, so we don’t register it for lookup with the other concrete types. It’s a wildcard match that we use for respond_to negotiation internals.

EXTENSION_LOOKUP={}
 
LOOKUP={}
 
SET=Mimes.new
 
+ + + + + + +

Class Public methods

+ +
+

+ + [](type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 40
+def [](type)
+  return type if type.is_a?(Type)
+  Type.lookup_by_extension(type)
+end
+
+
+ +
+ +
+

+ + fetch(type, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 45
+def fetch(type, &block)
+  return type if type.is_a?(Type)
+  EXTENSION_LOOKUP.fetch(type.to_s, &block)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Mime/AllType.html b/src/7.0/classes/Mime/AllType.html new file mode 100644 index 0000000000..9613b79582 --- /dev/null +++ b/src/7.0/classes/Mime/AllType.html @@ -0,0 +1,198 @@ +--- +title: Mime::AllType +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 322
+def initialize
+  super "*/*", nil
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + all?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 326
+def all?; true; end
+
+
+ +
+ +
+

+ + html?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 327
+def html?; true; end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mime/Mimes.html b/src/7.0/classes/Mime/Mimes.html new file mode 100644 index 0000000000..d91d3aa04d --- /dev/null +++ b/src/7.0/classes/Mime/Mimes.html @@ -0,0 +1,262 @@ +--- +title: Mime::Mimes +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + symbols
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 11
+def initialize
+  @mimes = []
+  @symbols = []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 20
+def <<(type)
+  @mimes << type
+  @symbols << type.to_sym
+end
+
+
+ +
+ +
+

+ + delete_if() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 25
+def delete_if
+  @mimes.delete_if do |x|
+    if yield x
+      @symbols.delete(x.to_sym)
+      true
+    end
+  end
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 16
+def each(&block)
+  @mimes.each(&block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mime/NullType.html b/src/7.0/classes/Mime/NullType.html new file mode 100644 index 0000000000..8ca9ff327e --- /dev/null +++ b/src/7.0/classes/Mime/NullType.html @@ -0,0 +1,197 @@ +--- +title: Mime::NullType +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + nil?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 338
+def nil?
+  true
+end
+
+
+ +
+ +
+

+ + ref() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 346
+def ref; end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 342
+def to_s
+  ""
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mime/Type.html b/src/7.0/classes/Mime/Type.html new file mode 100644 index 0000000000..3ee6fcbb7d --- /dev/null +++ b/src/7.0/classes/Mime/Type.html @@ -0,0 +1,1098 @@ +--- +title: Mime::Type +layout: default +--- +
+ +
+
+ +
+ +

Encapsulates the notion of a MIME type. Can be used at render time, for example, with:

+ +
class PostsController < ActionController::Base
+  def show
+    @post = Post.find(params[:id])
+
+    respond_to do |format|
+      format.html
+      format.ics { render body: @post.to_ics, mime_type: Mime::Type.lookup("text/calendar")  }
+      format.xml { render xml: @post }
+    end
+  end
+end
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MIME_NAME="[a-zA-Z0-9][a-zA-Z0-9#{Regexp.escape('!#$&-^_.+')}]{0,126}"
 
MIME_PARAMETER="\s*;\s*#{MIME_NAME}(?:=#{MIME_PARAMETER_VALUE})?"
 
MIME_PARAMETER_VALUE="#{Regexp.escape('"')}?#{MIME_NAME}#{Regexp.escape('"')}?"
 
MIME_REGEXP=/\A(?:\*\/\*|#{MIME_NAME}\/(?:\*|#{MIME_NAME})(?>#{MIME_PARAMETER})*\s*)\z/
 
PARAMETER_SEPARATOR_REGEXP=/;\s*\w+="?\w+"?/
 
TRAILING_STAR_REGEXP=/^(text|application)\/\*/
 
+ + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [R] + hash
+ [R] + string
+ [R] + symbol
+ [R] + synonyms
+ + + + +

Class Public methods

+ +
+

+ + lookup(string) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 144
+def lookup(string)
+  LOOKUP[string] || Type.new(string)
+end
+
+
+ +
+ +
+

+ + lookup_by_extension(extension) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 148
+def lookup_by_extension(extension)
+  EXTENSION_LOOKUP[extension.to_s]
+end
+
+
+ +
+ +
+

+ + new(string, symbol = nil, synonyms = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 234
+def initialize(string, symbol = nil, synonyms = [])
+  unless MIME_REGEXP.match?(string)
+    raise InvalidMimeType, "#{string.inspect} is not a valid MIME type"
+  end
+  @symbol, @synonyms = symbol, synonyms
+  @string = string
+  @hash = [@string, @synonyms, @symbol].hash
+end
+
+
+ +
+ +
+

+ + parse(accept_header) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 172
+def parse(accept_header)
+  if !accept_header.include?(",")
+    accept_header = accept_header.split(PARAMETER_SEPARATOR_REGEXP).first
+    return [] unless accept_header
+    parse_trailing_star(accept_header) || [Mime::Type.lookup(accept_header)].compact
+  else
+    list, index = [], 0
+    accept_header.split(",").each do |header|
+      params, q = header.split(PARAMETER_SEPARATOR_REGEXP)
+
+      next unless params
+      params.strip!
+      next if params.empty?
+
+      params = parse_trailing_star(params) || [params]
+
+      params.each do |m|
+        list << AcceptItem.new(index, m.to_s, q)
+        index += 1
+      end
+    end
+    AcceptList.sort! list
+  end
+end
+
+
+ +
+ +
+

+ + parse_data_with_trailing_star(type) + +

+ + +
+

For an input of 'text', returns [Mime[:json], Mime[:xml], Mime[:ics], Mime[:html], Mime[:css], Mime[:csv], Mime[:js], Mime[:yaml], Mime[:text].

+ +

For an input of 'application', returns [Mime[:html], Mime[:js], Mime[:xml], Mime[:yaml], Mime[:atom], Mime[:json], Mime[:rss], Mime[:url_encoded_form].

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 206
+def parse_data_with_trailing_star(type)
+  Mime::SET.select { |m| m.match?(type) }
+end
+
+
+ +
+ +
+

+ + parse_trailing_star(accept_header) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 197
+def parse_trailing_star(accept_header)
+  parse_data_with_trailing_star($1) if accept_header =~ TRAILING_STAR_REGEXP
+end
+
+
+ +
+ +
+

+ + register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 158
+def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
+  new_mime = Type.new(string, symbol, mime_type_synonyms)
+
+  SET << new_mime
+
+  ([string] + mime_type_synonyms).each { |str| LOOKUP[str] = new_mime } unless skip_lookup
+  ([symbol] + extension_synonyms).each { |ext| EXTENSION_LOOKUP[ext.to_s] = new_mime }
+
+  @register_callbacks.each do |callback|
+    callback.call(new_mime)
+  end
+  new_mime
+end
+
+
+ +
+ +
+

+ + register_alias(string, symbol, extension_synonyms = []) + +

+ + +
+

Registers an alias that’s not used on MIME type lookup, but can be referenced directly. Especially useful for rendering different HTML versions depending on the user agent, like an iPhone.

+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 154
+def register_alias(string, symbol, extension_synonyms = [])
+  register(string, symbol, [], extension_synonyms, true)
+end
+
+
+ +
+ +
+

+ + register_callback(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 140
+def register_callback(&block)
+  @register_callbacks << block
+end
+
+
+ +
+ +
+

+ + unregister(symbol) + +

+ + +
+

This method is opposite of register method.

+ +

To unregister a MIME type:

+ +
Mime::Type.unregister(:mobile)
+
+
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 215
+def unregister(symbol)
+  symbol = symbol.downcase
+  if mime = Mime[symbol]
+    SET.delete_if { |v| v.eql?(mime) }
+    LOOKUP.delete_if { |_, v| v.eql?(mime) }
+    EXTENSION_LOOKUP.delete_if { |_, v| v.eql?(mime) }
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + ==(mime_type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 267
+def ==(mime_type)
+  return false unless mime_type
+  (@synonyms + [ self ]).any? do |synonym|
+    synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym
+  end
+end
+
+
+ +
+ +
+

+ + ===(list) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 259
+def ===(list)
+  if list.is_a?(Array)
+    (@synonyms + [ self ]).any? { |synonym| list.include?(synonym) }
+  else
+    super
+  end
+end
+
+
+ +
+ +
+

+ + =~(mime_type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 281
+def =~(mime_type)
+  return false unless mime_type
+  regexp = Regexp.new(Regexp.quote(mime_type.to_s))
+  @synonyms.any? { |synonym| synonym.to_s =~ regexp } || @string =~ regexp
+end
+
+
+ +
+ +
+

+ + all?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 297
+def all?; false; end
+
+
+ +
+ +
+

+ + eql?(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 274
+def eql?(other)
+  super || (self.class == other.class &&
+            @string    == other.string &&
+            @synonyms  == other.synonyms &&
+            @symbol    == other.symbol)
+end
+
+
+ +
+ +
+

+ + html?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 293
+def html?
+  (symbol == :html) || /html/.match?(@string)
+end
+
+
+ +
+ +
+

+ + match?(mime_type) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 287
+def match?(mime_type)
+  return false unless mime_type
+  regexp = Regexp.new(Regexp.quote(mime_type.to_s))
+  @synonyms.any? { |synonym| synonym.to_s.match?(regexp) } || @string.match?(regexp)
+end
+
+
+ +
+ +
+

+ + ref() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 255
+def ref
+  symbol || to_s
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 243
+def to_s
+  @string
+end
+
+
+ +
+ +
+

+ + to_str() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 247
+def to_str
+  to_s
+end
+
+
+ +
+ +
+

+ + to_sym() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionpack/lib/action_dispatch/http/mime_type.rb, line 251
+def to_sym
+  @symbol
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Mime/Type/InvalidMimeType.html b/src/7.0/classes/Mime/Type/InvalidMimeType.html new file mode 100644 index 0000000000..87c078e3b2 --- /dev/null +++ b/src/7.0/classes/Mime/Type/InvalidMimeType.html @@ -0,0 +1,60 @@ +--- +title: Mime::Type::InvalidMimeType +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Minitest.html b/src/7.0/classes/Minitest.html new file mode 100644 index 0000000000..566df7e2a5 --- /dev/null +++ b/src/7.0/classes/Minitest.html @@ -0,0 +1,189 @@ +--- +title: Minitest +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + plugin_rails_init(options) + +

+ + +
+

Owes great inspiration to test runner trailblazers like RSpec, minitest-reporters, maxitest, and others.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/minitest/rails_plugin.rb, line 53
+def self.plugin_rails_init(options)
+  unless options[:full_backtrace] || ENV["BACKTRACE"]
+    # Plugin can run without Rails loaded, check before filtering.
+    if ::Rails.respond_to?(:backtrace_cleaner)
+      Minitest.backtrace_filter = BacktraceFilterWithFallback.new(::Rails.backtrace_cleaner, Minitest.backtrace_filter)
+    end
+  end
+
+  # Suppress summary reports when outputting inline rerun snippets.
+  if reporter.reporters.reject! { |reporter| reporter.kind_of?(SummaryReporter) }
+    reporter << SuppressedSummaryReporter.new(options[:io], options)
+  end
+
+  # Replace progress reporter for colors.
+  if reporter.reporters.reject! { |reporter| reporter.kind_of?(ProgressReporter) }
+    reporter << ::Rails::TestUnitReporter.new(options[:io], options)
+  end
+end
+
+
+ +
+ +
+

+ + plugin_rails_options(opts, options) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/minitest/rails_plugin.rb, line 28
+def self.plugin_rails_options(opts, options)
+  ::Rails::TestUnit::Runner.attach_before_load_options(opts)
+
+  opts.on("-b", "--backtrace", "Show the complete backtrace") do
+    options[:full_backtrace] = true
+  end
+
+  opts.on("-d", "--defer-output", "Output test failures and errors after the test run") do
+    options[:output_inline] = false
+  end
+
+  opts.on("-f", "--fail-fast", "Abort test run on first failure or error") do
+    options[:fail_fast] = true
+  end
+
+  opts.on("-c", "--[no-]color", "Enable color in the output") do |value|
+    options[:color] = value
+  end
+
+  options[:color] = true
+  options[:output_inline] = true
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Minitest/BacktraceFilterWithFallback.html b/src/7.0/classes/Minitest/BacktraceFilterWithFallback.html new file mode 100644 index 0000000000..a3d28e6dd6 --- /dev/null +++ b/src/7.0/classes/Minitest/BacktraceFilterWithFallback.html @@ -0,0 +1,152 @@ +--- +title: Minitest::BacktraceFilterWithFallback +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(preferred, fallback) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/minitest/rails_plugin.rb, line 9
+def initialize(preferred, fallback)
+  @preferred = preferred
+  @fallback = fallback
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + filter(backtrace) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/minitest/rails_plugin.rb, line 14
+def filter(backtrace)
+  filtered = @preferred.filter(backtrace)
+  filtered = @fallback.filter(backtrace) if filtered.empty?
+  filtered
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Minitest/SuppressedSummaryReporter.html b/src/7.0/classes/Minitest/SuppressedSummaryReporter.html new file mode 100644 index 0000000000..024b45e425 --- /dev/null +++ b/src/7.0/classes/Minitest/SuppressedSummaryReporter.html @@ -0,0 +1,107 @@ +--- +title: Minitest::SuppressedSummaryReporter +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + aggregated_results(*) + +

+ + +
+

Disable extra failure output after a run if output is inline.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/minitest/rails_plugin.rb, line 23
+def aggregated_results(*)
+  super unless options[:output_inline]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Module.html b/src/7.0/classes/Module.html new file mode 100644 index 0000000000..3f7677d4a5 --- /dev/null +++ b/src/7.0/classes/Module.html @@ -0,0 +1,1779 @@ +--- +title: Module +layout: default +--- +
+ +
+
+ +
+ +

Attribute Accessors

+ +

Extends the module object with class/module and instance accessors for class/module attributes, just like the native attr* accessors for instance attributes.

+ +

Attribute Accessors per Thread

+ +

Extends the module object with class/module and instance accessors for class/module attributes, just like the native attr* accessors for instance attributes, but does so on a per-thread basis.

+ +

So the values are scoped within the Thread.current space under the class name of the module.

+ +

Note that it can also be scoped per-fiber if Rails.application.config.active_support.isolation_level is set to :fiber.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DELEGATION_RESERVED_KEYWORDS=%w(_ arg args block)
 
DELEGATION_RESERVED_METHOD_NAMES=Set.new( +RUBY_RESERVED_KEYWORDS + DELEGATION_RESERVED_KEYWORDS +).freeze
 
RUBY_RESERVED_KEYWORDS=%w(alias and BEGIN begin break case class def defined? do +else elsif END end ensure false for if in module next nil not or redo rescue retry +return self super then true undef unless until when while yield)
 
+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + attr_internal_naming_format
+ + + + + +

Instance Public methods

+ +
+

+ + alias_attribute(new_name, old_name) + +

+ + +
+

Allows you to make aliases for attributes, which includes getter, setter, and a predicate.

+ +
class Content < ActiveRecord::Base
+  # has a title attribute
+end
+
+class Email < Content
+  alias_attribute :subject, :title
+end
+
+e = Email.find(1)
+e.title    # => "Superstars"
+e.subject  # => "Superstars"
+e.subject? # => true
+e.subject = "Megastars"
+e.title    # => "Megastars"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/aliasing.rb, line 21
+  def alias_attribute(new_name, old_name)
+    # The following reader methods use an explicit `self` receiver in order to
+    # support aliases that start with an uppercase letter. Otherwise, they would
+    # be resolved as constants instead.
+    module_eval <<-STR, __FILE__, __LINE__ + 1
+      def #{new_name}; self.#{old_name}; end          # def subject; self.title; end
+      def #{new_name}?; self.#{old_name}?; end        # def subject?; self.title?; end
+      def #{new_name}=(v); self.#{old_name} = v; end  # def subject=(v); self.title = v; end
+    STR
+  end
+
+
+ +
+ +
+

+ + anonymous?() + +

+ + +
+

A module may or may not have a name.

+ +
module M; end
+M.name # => "M"
+
+m = Module.new
+m.name # => nil
+
+ +

anonymous? method returns true if module does not have a name, false otherwise:

+ +
Module.new.anonymous? # => true
+
+module M; end
+M.anonymous?          # => false
+
+ +

A module gets a name when it is first assigned to a constant. Either via the module or class keyword or by an explicit assignment:

+ +
m = Module.new # creates an anonymous module
+m.anonymous?   # => true
+M = m          # m gets a name here as a side-effect
+m.name         # => "M"
+m.anonymous?   # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/anonymous.rb, line 27
+def anonymous?
+  name.nil?
+end
+
+
+ +
+ +
+

+ + attr_internal(*attrs) + +

+ + +
+ +
+ + + + + +
+ Alias for: attr_internal_accessor +
+ + + +
+ +
+

+ + attr_internal_accessor(*attrs) + +

+ + +
+

Declares an attribute reader and writer backed by an internally-named instance variable.

+
+ + + +
+ Also aliased as: attr_internal +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 16
+def attr_internal_accessor(*attrs)
+  attr_internal_reader(*attrs)
+  attr_internal_writer(*attrs)
+end
+
+
+ +
+ +
+

+ + attr_internal_reader(*attrs) + +

+ + +
+

Declares an attribute reader backed by an internally-named instance variable.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 5
+def attr_internal_reader(*attrs)
+  attrs.each { |attr_name| attr_internal_define(attr_name, :reader) }
+end
+
+
+ +
+ +
+

+ + attr_internal_writer(*attrs) + +

+ + +
+

Declares an attribute writer backed by an internally-named instance variable.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attr_internal.rb, line 10
+def attr_internal_writer(*attrs)
+  attrs.each { |attr_name| attr_internal_define(attr_name, :writer) }
+end
+
+
+ +
+ +
+

+ + cattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk) + +

+ + +
+ +
+ + + + + +
+ Alias for: mattr_accessor +
+ + + +
+ +
+

+ + cattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: mattr_reader +
+ + + +
+ +
+

+ + cattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: mattr_writer +
+ + + +
+ +
+

+ + delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil) + +

+ + +
+

Provides a delegate class method to easily expose contained objects’ public methods as your own.

+ +

Options

+
  • +

    :to - Specifies the target object name as a symbol or string

    +
  • +

    :prefix - Prefixes the new method with the target name or a custom prefix

    +
  • +

    :allow_nil - If set to true, prevents a Module::DelegationError from being raised

    +
  • +

    :private - If set to true, changes method visibility to private

    +
+ +

The macro receives one or more method names (specified as symbols or strings) and the name of the target object via the :to option (also a symbol or string).

+ +

Delegation is particularly useful with Active Record associations:

+ +
class Greeter < ActiveRecord::Base
+  def hello
+    'hello'
+  end
+
+  def goodbye
+    'goodbye'
+  end
+end
+
+class Foo < ActiveRecord::Base
+  belongs_to :greeter
+  delegate :hello, to: :greeter
+end
+
+Foo.new.hello   # => "hello"
+Foo.new.goodbye # => NoMethodError: undefined method `goodbye' for #<Foo:0x1af30c>
+
+ +

Multiple delegates to the same target are allowed:

+ +
class Foo < ActiveRecord::Base
+  belongs_to :greeter
+  delegate :hello, :goodbye, to: :greeter
+end
+
+Foo.new.goodbye # => "goodbye"
+
+ +

Methods can be delegated to instance variables, class variables, or constants by providing them as a symbols:

+ +
class Foo
+  CONSTANT_ARRAY = [0,1,2,3]
+  @@class_array  = [4,5,6,7]
+
+  def initialize
+    @instance_array = [8,9,10,11]
+  end
+  delegate :sum, to: :CONSTANT_ARRAY
+  delegate :min, to: :@@class_array
+  delegate :max, to: :@instance_array
+end
+
+Foo.new.sum # => 6
+Foo.new.min # => 4
+Foo.new.max # => 11
+
+ +

It’s also possible to delegate a method to the class by using :class:

+ +
class Foo
+  def self.hello
+    "world"
+  end
+
+  delegate :hello, to: :class
+end
+
+Foo.new.hello # => "world"
+
+ +

Delegates can optionally be prefixed using the :prefix option. If the value is true, the delegate methods are prefixed with the name of the object being delegated to.

+ +
Person = Struct.new(:name, :address)
+
+class Invoice < Struct.new(:client)
+  delegate :name, :address, to: :client, prefix: true
+end
+
+john_doe = Person.new('John Doe', 'Vimmersvej 13')
+invoice = Invoice.new(john_doe)
+invoice.client_name    # => "John Doe"
+invoice.client_address # => "Vimmersvej 13"
+
+ +

It is also possible to supply a custom prefix.

+ +
class Invoice < Struct.new(:client)
+  delegate :name, :address, to: :client, prefix: :customer
+end
+
+invoice = Invoice.new(john_doe)
+invoice.customer_name    # => 'John Doe'
+invoice.customer_address # => 'Vimmersvej 13'
+
+ +

The delegated methods are public by default. Pass private: true to change that.

+ +
class User < ActiveRecord::Base
+  has_one :profile
+  delegate :first_name, to: :profile
+  delegate :date_of_birth, to: :profile, private: true
+
+  def age
+    Date.today.year - date_of_birth.year
+  end
+end
+
+User.new.first_name # => "Tomas"
+User.new.date_of_birth # => NoMethodError: private method `date_of_birth' called for #<User:0x00000008221340>
+User.new.age # => 2
+
+ +

If the target is nil and does not respond to the delegated method a Module::DelegationError is raised. If you wish to instead return nil, use the :allow_nil option.

+ +
class User < ActiveRecord::Base
+  has_one :profile
+  delegate :age, to: :profile
+end
+
+User.new.age
+# => Module::DelegationError: User#age delegated to profile.age, but profile is nil
+
+ +

But if not having a profile yet is fine and should not be an error condition:

+ +
class User < ActiveRecord::Base
+  has_one :profile
+  delegate :age, to: :profile, allow_nil: true
+end
+
+User.new.age # nil
+
+ +

Note that if the target is not nil then the call is attempted regardless of the :allow_nil option, and thus an exception is still raised if said object does not respond to the method:

+ +
class Foo
+  def initialize(bar)
+    @bar = bar
+  end
+
+  delegate :name, to: :@bar, allow_nil: true
+end
+
+Foo.new("Bar").name # raises NoMethodError: undefined method `name'
+
+ +

The target method must be public, otherwise it will raise NoMethodError.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 171
+def delegate(*methods, to: nil, prefix: nil, allow_nil: nil, private: nil)
+  unless to
+    raise ArgumentError, "Delegation needs a target. Supply a keyword argument 'to' (e.g. delegate :hello, to: :greeter)."
+  end
+
+  if prefix == true && /^[^a-z_]/.match?(to)
+    raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
+  end
+
+  method_prefix = \
+    if prefix
+      "#{prefix == true ? to : prefix}_"
+    else
+      ""
+    end
+
+  location = caller_locations(1, 1).first
+  file, line = location.path, location.lineno
+
+  to = to.to_s
+  to = "self.#{to}" if DELEGATION_RESERVED_METHOD_NAMES.include?(to)
+
+  method_def = []
+  method_names = []
+
+  methods.map do |method|
+    method_name = prefix ? "#{method_prefix}#{method}" : method
+    method_names << method_name.to_sym
+
+    # Attribute writer methods only accept one argument. Makes sure []=
+    # methods still accept two arguments.
+    definition = /[^\]]=\z/.match?(method) ? "arg" : "..."
+
+    # The following generated method calls the target exactly once, storing
+    # the returned value in a dummy variable.
+    #
+    # Reason is twofold: On one hand doing less calls is in general better.
+    # On the other hand it could be that the target has side-effects,
+    # whereas conceptually, from the user point of view, the delegator should
+    # be doing one call.
+    if allow_nil
+      method = method.to_s
+
+      method_def <<
+        "def #{method_name}(#{definition})" <<
+        "  _ = #{to}" <<
+        "  if !_.nil? || nil.respond_to?(:#{method})" <<
+        "    _.#{method}(#{definition})" <<
+        "  end" <<
+        "end"
+    else
+      method = method.to_s
+      method_name = method_name.to_s
+
+      method_def <<
+        "def #{method_name}(#{definition})" <<
+        "  _ = #{to}" <<
+        "  _.#{method}(#{definition})" <<
+        "rescue NoMethodError => e" <<
+        "  if _.nil? && e.name == :#{method}" <<
+        %(   raise DelegationError, "#{self}##{method_name} delegated to #{to}.#{method}, but #{to} is nil: \#{self.inspect}") <<
+        "  else" <<
+        "    raise" <<
+        "  end" <<
+        "end"
+    end
+  end
+  module_eval(method_def.join(";"), file, line)
+  private(*method_names) if private
+  method_names
+end
+
+
+ +
+ +
+

+ + delegate_missing_to(target, allow_nil: nil) + +

+ + +
+

When building decorators, a common pattern may emerge:

+ +
class Partition
+  def initialize(event)
+    @event = event
+  end
+
+  def person
+    detail.person || creator
+  end
+
+  private
+    def respond_to_missing?(name, include_private = false)
+      @event.respond_to?(name, include_private)
+    end
+
+    def method_missing(method, *args, &block)
+      @event.send(method, *args, &block)
+    end
+end
+
+ +

With Module#delegate_missing_to, the above is condensed to:

+ +
class Partition
+  delegate_missing_to :@event
+
+  def initialize(event)
+    @event = event
+  end
+
+  def person
+    detail.person || creator
+  end
+end
+
+ +

The target can be anything callable within the object, e.g. instance variables, methods, constants, etc.

+ +

The delegated method must be public on the target, otherwise it will raise DelegationError. If you wish to instead return nil, use the :allow_nil option.

+ +

The marshal_dump and _dump methods are exempt from delegation due to possible interference when calling Marshal.dump(object), should the delegation target method of object add or remove instance variables.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/delegation.rb, line 289
+  def delegate_missing_to(target, allow_nil: nil)
+    target = target.to_s
+    target = "self.#{target}" if DELEGATION_RESERVED_METHOD_NAMES.include?(target)
+
+    module_eval <<-RUBY, __FILE__, __LINE__ + 1
+      def respond_to_missing?(name, include_private = false)
+        # It may look like an oversight, but we deliberately do not pass
+        # +include_private+, because they do not get delegated.
+
+        return false if name == :marshal_dump || name == :_dump
+        #{target}.respond_to?(name) || super
+      end
+
+      def method_missing(method, *args, &block)
+        if #{target}.respond_to?(method)
+          #{target}.public_send(method, *args, &block)
+        else
+          begin
+            super
+          rescue NoMethodError
+            if #{target}.nil?
+              if #{allow_nil == true}
+                nil
+              else
+                raise DelegationError, "\#{method} delegated to #{target}, but #{target} is nil"
+              end
+            else
+              raise
+            end
+          end
+        end
+      end
+      ruby2_keywords(:method_missing)
+    RUBY
+  end
+
+
+ +
+ +
+

+ + deprecate(*method_names) + +

+ + +
+
deprecate :foo
+deprecate bar: 'message'
+deprecate :foo, :bar, baz: 'warning!', qux: 'gone!'
+
+ +

You can also use custom deprecator instance:

+ +
deprecate :foo, deprecator: MyLib::Deprecator.new
+deprecate :foo, bar: "warning!", deprecator: MyLib::Deprecator.new
+
+ +

Custom deprecators must respond to deprecation_warning(deprecated_method_name, message, caller_backtrace) method where you can implement your custom warning behavior.

+ +
class MyLib::Deprecator
+  def deprecation_warning(deprecated_method_name, message, caller_backtrace = nil)
+    message = "#{deprecated_method_name} is deprecated and will be removed from MyLibrary | #{message}"
+    Kernel.warn message
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/deprecation.rb, line 22
+def deprecate(*method_names)
+  ActiveSupport::Deprecation.deprecate_methods(self, *method_names)
+end
+
+
+ +
+ +
+

+ + mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk) + +

+ + +
+

Defines both class and instance accessors for class attributes. All class and instance methods created will be public, even if this method is called with a private or protected access modifier.

+ +
module HairColors
+  mattr_accessor :hair_colors
+end
+
+class Person
+  include HairColors
+end
+
+HairColors.hair_colors = [:brown, :black, :blonde, :red]
+HairColors.hair_colors # => [:brown, :black, :blonde, :red]
+Person.new.hair_colors # => [:brown, :black, :blonde, :red]
+
+ +

If a subclass changes the value then that would also change the value for parent class. Similarly if parent class changes the value then that would change the value of subclasses too.

+ +
class Citizen < Person
+end
+
+Citizen.new.hair_colors << :blue
+Person.new.hair_colors # => [:brown, :black, :blonde, :red, :blue]
+
+ +

To omit the instance writer method, pass instance_writer: false. To omit the instance reader method, pass instance_reader: false.

+ +
module HairColors
+  mattr_accessor :hair_colors, instance_writer: false, instance_reader: false
+end
+
+class Person
+  include HairColors
+end
+
+Person.new.hair_colors = [:brown]  # => NoMethodError
+Person.new.hair_colors             # => NoMethodError
+
+ +

Or pass instance_accessor: false, to omit both instance methods.

+ +
module HairColors
+  mattr_accessor :hair_colors, instance_accessor: false
+end
+
+class Person
+  include HairColors
+end
+
+Person.new.hair_colors = [:brown]  # => NoMethodError
+Person.new.hair_colors             # => NoMethodError
+
+ +

You can set a default value for the attribute.

+ +
module HairColors
+  mattr_accessor :hair_colors, default: [:brown, :black, :blonde, :red]
+end
+
+class Person
+  include HairColors
+end
+
+Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
+
+
+ + + +
+ Also aliased as: cattr_accessor +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 202
+def mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil, &blk)
+  location = caller_locations(1, 1).first
+  mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default, location: location, &blk)
+  mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor, default: default, location: location)
+end
+
+
+ +
+ +
+

+ + mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil) + +

+ + +
+

Defines a class attribute and creates a class and instance reader methods. The underlying class variable is set to nil, if it is not previously defined. All class and instance methods created will be public, even if this method is called with a private or protected access modifier.

+ +
module HairColors
+  mattr_reader :hair_colors
+end
+
+HairColors.hair_colors # => nil
+HairColors.class_variable_set("@@hair_colors", [:brown, :black])
+HairColors.hair_colors # => [:brown, :black]
+
+ +

The attribute name must be a valid method name in Ruby.

+ +
module Foo
+  mattr_reader :"1_Badname"
+end
+# => NameError: invalid attribute name: 1_Badname
+
+ +

To omit the instance reader method, pass instance_reader: false or instance_accessor: false.

+ +
module HairColors
+  mattr_reader :hair_colors, instance_reader: false
+end
+
+class Person
+  include HairColors
+end
+
+Person.new.hair_colors # => NoMethodError
+
+ +

You can set a default value for the attribute.

+ +
module HairColors
+  mattr_reader :hair_colors, default: [:brown, :black, :blonde, :red]
+end
+
+class Person
+  include HairColors
+end
+
+Person.new.hair_colors # => [:brown, :black, :blonde, :red]
+
+
+ + + +
+ Also aliased as: cattr_reader +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 53
+def mattr_reader(*syms, instance_reader: true, instance_accessor: true, default: nil, location: nil)
+  raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
+  location ||= caller_locations(1, 1).first
+
+  definition = []
+  syms.each do |sym|
+    raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
+
+    definition << "def self.#{sym}; @@#{sym}; end"
+
+    if instance_reader && instance_accessor
+      definition << "def #{sym}; @@#{sym}; end"
+    end
+
+    sym_default_value = (block_given? && default.nil?) ? yield : default
+    class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
+  end
+
+  module_eval(definition.join(";"), location.path, location.lineno)
+end
+
+
+ +
+ +
+

+ + mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil) + +

+ + +
+

Defines a class attribute and creates a class and instance writer methods to allow assignment to the attribute. All class and instance methods created will be public, even if this method is called with a private or protected access modifier.

+ +
module HairColors
+  mattr_writer :hair_colors
+end
+
+class Person
+  include HairColors
+end
+
+HairColors.hair_colors = [:brown, :black]
+Person.class_variable_get("@@hair_colors") # => [:brown, :black]
+Person.new.hair_colors = [:blonde, :red]
+HairColors.class_variable_get("@@hair_colors") # => [:blonde, :red]
+
+ +

To omit the instance writer method, pass instance_writer: false or instance_accessor: false.

+ +
module HairColors
+  mattr_writer :hair_colors, instance_writer: false
+end
+
+class Person
+  include HairColors
+end
+
+Person.new.hair_colors = [:blonde, :red] # => NoMethodError
+
+ +

You can set a default value for the attribute.

+ +
module HairColors
+  mattr_writer :hair_colors, default: [:brown, :black, :blonde, :red]
+end
+
+class Person
+  include HairColors
+end
+
+Person.class_variable_get("@@hair_colors") # => [:brown, :black, :blonde, :red]
+
+
+ + + +
+ Also aliased as: cattr_writer +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attribute_accessors.rb, line 117
+def mattr_writer(*syms, instance_writer: true, instance_accessor: true, default: nil, location: nil)
+  raise TypeError, "module attributes should be defined directly on class, not singleton" if singleton_class?
+  location ||= caller_locations(1, 1).first
+
+  definition = []
+  syms.each do |sym|
+    raise NameError.new("invalid attribute name: #{sym}") unless /\A[_A-Za-z]\w*\z/.match?(sym)
+    definition << "def self.#{sym}=(val); @@#{sym} = val; end"
+
+    if instance_writer && instance_accessor
+      definition << "def #{sym}=(val); @@#{sym} = val; end"
+    end
+
+    sym_default_value = (block_given? && default.nil?) ? yield : default
+    class_variable_set("@@#{sym}", sym_default_value) unless sym_default_value.nil? && class_variable_defined?("@@#{sym}")
+  end
+
+  module_eval(definition.join(";"), location.path, location.lineno)
+end
+
+
+ +
+ +
+

+ + module_parent() + +

+ + +
+

Returns the module which contains this one according to its name.

+ +
module M
+  module N
+  end
+end
+X = M::N
+
+M::N.module_parent # => M
+X.module_parent    # => M
+
+ +

The parent of top-level and anonymous modules is Object.

+ +
M.module_parent          # => Object
+Module.new.module_parent # => Object
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 35
+def module_parent
+  module_parent_name ? ActiveSupport::Inflector.constantize(module_parent_name) : Object
+end
+
+
+ +
+ +
+

+ + module_parent_name() + +

+ + +
+

Returns the name of the module containing this one.

+ +
M::N.module_parent_name # => "M"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 10
+def module_parent_name
+  if defined?(@parent_name)
+    @parent_name
+  else
+    parent_name = name =~ /::[^:]+\z/ ? -$` : nil
+    @parent_name = parent_name unless frozen?
+    parent_name
+  end
+end
+
+
+ +
+ +
+

+ + module_parents() + +

+ + +
+

Returns all the parents of this module according to its name, ordered from nested outwards. The receiver is not contained within the result.

+ +
module M
+  module N
+  end
+end
+X = M::N
+
+M.module_parents    # => [Object]
+M::N.module_parents # => [M, Object]
+X.module_parents    # => [M, Object]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/introspection.rb, line 51
+def module_parents
+  parents = []
+  if module_parent_name
+    parts = module_parent_name.split("::")
+    until parts.empty?
+      parents << ActiveSupport::Inflector.constantize(parts * "::")
+      parts.pop
+    end
+  end
+  parents << Object unless parents.include? Object
+  parents
+end
+
+
+ +
+ +
+

+ + redefine_method(method, &block) + +

+ + +
+

Replaces the existing method definition, if there is one, with the passed block as its body.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 17
+def redefine_method(method, &block)
+  visibility = method_visibility(method)
+  silence_redefinition_of_method(method)
+  define_method(method, &block)
+  send(visibility, method)
+end
+
+
+ +
+ +
+

+ + redefine_singleton_method(method, &block) + +

+ + +
+

Replaces the existing singleton method definition, if there is one, with the passed block as its body.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 26
+def redefine_singleton_method(method, &block)
+  singleton_class.redefine_method(method, &block)
+end
+
+
+ +
+ +
+

+ + remove_possible_method(method) + +

+ + +
+

Removes the named method, if it exists.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/remove_method.rb, line 7
+def remove_possible_method(method)
+  if method_defined?(method) || private_method_defined?(method)
+    undef_method(method)
+  end
+end
+
+
+ +
+ +
+

+ + remove_possible_singleton_method(method) + +

+ + +
+

Removes the named singleton method, if it exists.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/remove_method.rb, line 14
+def remove_possible_singleton_method(method)
+  singleton_class.remove_possible_method(method)
+end
+
+
+ +
+ +
+

+ + silence_redefinition_of_method(method) + +

+ + +
+

Marks the named method as intended to be redefined, if it exists. Suppresses the Ruby method redefinition warning. Prefer redefine_method where possible.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/redefine_method.rb, line 7
+def silence_redefinition_of_method(method)
+  if method_defined?(method) || private_method_defined?(method)
+    # This suppresses the "method redefined" warning; the self-alias
+    # looks odd, but means we don't need to generate a unique name
+    alias_method method, method
+  end
+end
+
+
+ +
+ +
+

+ + thread_cattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) + +

+ + +
+ +
+ + + + + +
+ Alias for: thread_mattr_accessor +
+ + + +
+ +
+

+ + thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil) + +

+ + +
+

Defines both class and instance accessors for class attributes.

+ +
class Account
+  thread_mattr_accessor :user
+end
+
+Account.user = "DHH"
+Account.user     # => "DHH"
+Account.new.user # => "DHH"
+
+ +

Unlike mattr_accessor, values are not shared with subclasses or parent classes. If a subclass changes the value, the parent class’ value is not changed. If the parent class changes the value, the value of subclasses is not changed.

+ +
class Customer < Account
+end
+
+Account.user   # => "DHH"
+Customer.user  # => nil
+Customer.user  = "Rafael"
+Customer.user  # => "Rafael"
+Account.user   # => "DHH"
+
+ +

To omit the instance writer method, pass instance_writer: false. To omit the instance reader method, pass instance_reader: false.

+ +
class Current
+  thread_mattr_accessor :user, instance_writer: false, instance_reader: false
+end
+
+Current.new.user = "DHH"  # => NoMethodError
+Current.new.user          # => NoMethodError
+
+ +

Or pass instance_accessor: false, to omit both instance methods.

+ +
class Current
+  thread_mattr_accessor :user, instance_accessor: false
+end
+
+Current.new.user = "DHH"  # => NoMethodError
+Current.new.user          # => NoMethodError
+
+
+ + + +
+ Also aliased as: thread_cattr_accessor +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb, line 152
+def thread_mattr_accessor(*syms, instance_reader: true, instance_writer: true, instance_accessor: true, default: nil)
+  thread_mattr_reader(*syms, instance_reader: instance_reader, instance_accessor: instance_accessor, default: default)
+  thread_mattr_writer(*syms, instance_writer: instance_writer, instance_accessor: instance_accessor)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Module/Concerning.html b/src/7.0/classes/Module/Concerning.html new file mode 100644 index 0000000000..c8aa9c5091 --- /dev/null +++ b/src/7.0/classes/Module/Concerning.html @@ -0,0 +1,265 @@ +--- +title: Module::Concerning +layout: default +--- +
+ +
+
+ +
+ +

Bite-sized separation of concerns

+ +

We often find ourselves with a medium-sized chunk of behavior that we’d like to extract, but only mix in to a single class.

+ +

Extracting a plain old Ruby object to encapsulate it and collaborate or delegate to the original object is often a good choice, but when there’s no additional state to encapsulate or we’re making DSL-style declarations about the parent class, introducing new collaborators can obfuscate rather than simplify.

+ +

The typical route is to just dump everything in a monolithic class, perhaps with a comment, as a least-bad alternative. Using modules in separate files means tedious sifting to get a big-picture view.

+ +

Dissatisfying ways to separate small concerns

+ +

Using comments:

+ +
class Todo < ApplicationRecord
+  # Other todo implementation
+  # ...
+
+  ## Event tracking
+  has_many :events
+
+  before_create :track_creation
+
+  private
+    def track_creation
+      # ...
+    end
+end
+
+ +

With an inline module:

+ +

Noisy syntax.

+ +
class Todo < ApplicationRecord
+  # Other todo implementation
+  # ...
+
+  module EventTracking
+    extend ActiveSupport::Concern
+
+    included do
+      has_many :events
+      before_create :track_creation
+    end
+
+    private
+      def track_creation
+        # ...
+      end
+  end
+  include EventTracking
+end
+
+ +

Mix-in noise exiled to its own file:

+ +

Once our chunk of behavior starts pushing the scroll-to-understand-it boundary, we give in and move it to a separate file. At this size, the increased overhead can be a reasonable tradeoff even if it reduces our at-a-glance perception of how things work.

+ +
class Todo < ApplicationRecord
+  # Other todo implementation
+  # ...
+
+  include TodoEventTracking
+end
+
+ +

Introducing Module#concerning

+ +

By quieting the mix-in noise, we arrive at a natural, low-ceremony way to separate bite-sized concerns.

+ +
class Todo < ApplicationRecord
+  # Other todo implementation
+  # ...
+
+  concerning :EventTracking do
+    included do
+      has_many :events
+      before_create :track_creation
+    end
+
+    private
+      def track_creation
+        # ...
+      end
+  end
+end
+
+Todo.ancestors
+# => [Todo, Todo::EventTracking, ApplicationRecord, Object]
+
+ +

This small step has some wonderful ripple effects. We can

+
  • +

    grok the behavior of our class in one glance,

    +
  • +

    clean up monolithic junk-drawer classes by separating their concerns, and

    +
  • +

    stop leaning on protected/private for crude “this is internal stuff” modularity.

    +
+ +

Prepending concerning

+ +

concerning supports a prepend: true argument which will prepend the concern instead of using include for it.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + concern(topic, &module_definition) + +

+ + +
+

A low-cruft shortcut to define a concern.

+ +
concern :EventTracking do
+  ...
+end
+
+ +

is equivalent to

+ +
module EventTracking
+  extend ActiveSupport::Concern
+
+  ...
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/concerning.rb, line 132
+def concern(topic, &module_definition)
+  const_set topic, Module.new {
+    extend ::ActiveSupport::Concern
+    module_eval(&module_definition)
+  }
+end
+
+
+ +
+ +
+

+ + concerning(topic, prepend: false, &block) + +

+ + +
+

Define a new concern and mix it in.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/module/concerning.rb, line 114
+def concerning(topic, prepend: false, &block)
+  method = prepend ? :prepend : :include
+  __send__(method, concern(topic, &block))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Module/DelegationError.html b/src/7.0/classes/Module/DelegationError.html new file mode 100644 index 0000000000..3f7712d756 --- /dev/null +++ b/src/7.0/classes/Module/DelegationError.html @@ -0,0 +1,66 @@ +--- +title: Module::DelegationError +layout: default +--- +
+ +
+
+ +
+ +

Error generated by delegate when a method is called on nil and allow_nil option is not used.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/NameError.html b/src/7.0/classes/NameError.html new file mode 100644 index 0000000000..68fb0450ee --- /dev/null +++ b/src/7.0/classes/NameError.html @@ -0,0 +1,186 @@ +--- +title: NameError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + missing_name() + +

+ + +
+

Extract the name of the missing constant from the exception message.

+ +
begin
+  HelloWorld
+rescue NameError => e
+  e.missing_name
+end
+# => "HelloWorld"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/name_error.rb, line 12
+def missing_name
+  # Since ruby v2.3.0 `did_you_mean` gem is loaded by default.
+  # It extends NameError#message with spell corrections which are SLOW.
+  # We should use original_message message instead.
+  message = respond_to?(:original_message) ? original_message : self.message
+  return unless message.start_with?("uninitialized constant ")
+
+  receiver = begin
+    self.receiver
+  rescue ArgumentError
+    nil
+  end
+
+  if receiver == Object
+    name.to_s
+  elsif receiver
+    "#{real_mod_name(receiver)}::#{self.name}"
+  else
+    if match = message.match(/((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/)
+      match[1]
+    end
+  end
+end
+
+
+ +
+ +
+

+ + missing_name?(name) + +

+ + +
+

Was this exception raised because the given name was missing?

+ +
begin
+  HelloWorld
+rescue NameError => e
+  e.missing_name?("HelloWorld")
+end
+# => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/name_error.rb, line 44
+def missing_name?(name)
+  if name.is_a? Symbol
+    self.name == name
+  else
+    missing_name == name.to_s
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/NilClass.html b/src/7.0/classes/NilClass.html new file mode 100644 index 0000000000..8e90532c9e --- /dev/null +++ b/src/7.0/classes/NilClass.html @@ -0,0 +1,251 @@ +--- +title: NilClass +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + blank?() + +

+ + +
+

nil is blank:

+ +
nil.blank? # => true
+
+ +

@return [true]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 56
+def blank?
+  true
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Returns self.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 20
+def to_param
+  self
+end
+
+
+ +
+ +
+

+ + try(*) + +

+ + +
+

Calling try on nil always returns nil. It becomes especially helpful when navigating through associations that may return nil.

+ +
nil.try(:name) # => nil
+
+ +

Without try

+ +
@person && @person.children.any? && @person.children.first.name
+
+ +

With try

+ +
@person.try(:children).try(:first).try(:name)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 148
+def try(*)
+  nil
+end
+
+
+ +
+ +
+

+ + try!(*) + +

+ + +
+

Calling try! on nil always returns nil.

+ +
nil.try!(:name) # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 155
+def try!(*)
+  nil
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Numeric.html b/src/7.0/classes/Numeric.html new file mode 100644 index 0000000000..85424922f7 --- /dev/null +++ b/src/7.0/classes/Numeric.html @@ -0,0 +1,1198 @@ +--- +title: Numeric +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
EXABYTE=PETABYTE * 1024
 
GIGABYTE=MEGABYTE * 1024
 
KILOBYTE=1024
 
MEGABYTE=KILOBYTE * 1024
 
PETABYTE=TERABYTE * 1024
 
TERABYTE=GIGABYTE * 1024
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + byte() + +

+ + +
+ +
+ + + + + +
+ Alias for: bytes +
+ + + +
+ +
+

+ + bytes() + +

+ + +
+

Enables the use of byte calculations and declarations, like 45.bytes + 2.6.megabytes

+ +
2.bytes # => 2
+
+
+ + + +
+ Also aliased as: byte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 14
+def bytes
+  self
+end
+
+
+ +
+ +
+

+ + day() + +

+ + +
+ +
+ + + + + +
+ Alias for: days +
+ + + +
+ +
+

+ + days() + +

+ + +
+

Returns a Duration instance matching the number of days provided.

+ +
2.days # => 2 days
+
+
+ + + +
+ Also aliased as: day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 37
+def days
+  ActiveSupport::Duration.days(self)
+end
+
+
+ +
+ +
+

+ + exabyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: exabytes +
+ + + +
+ +
+

+ + exabytes() + +

+ + +
+

Returns the number of bytes equivalent to the exabytes provided.

+ +
2.exabytes # => 2_305_843_009_213_693_952
+
+
+ + + +
+ Also aliased as: exabyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 62
+def exabytes
+  self * EXABYTE
+end
+
+
+ +
+ +
+

+ + fortnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: fortnights +
+ + + +
+ +
+

+ + fortnights() + +

+ + +
+

Returns a Duration instance matching the number of fortnights provided.

+ +
2.fortnights # => 4 weeks
+
+
+ + + +
+ Also aliased as: fortnight +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 53
+def fortnights
+  ActiveSupport::Duration.weeks(self * 2)
+end
+
+
+ +
+ +
+

+ + gigabyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: gigabytes +
+ + + +
+ +
+

+ + gigabytes() + +

+ + +
+

Returns the number of bytes equivalent to the gigabytes provided.

+ +
2.gigabytes # => 2_147_483_648
+
+
+ + + +
+ Also aliased as: gigabyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 38
+def gigabytes
+  self * GIGABYTE
+end
+
+
+ +
+ +
+

+ + hour() + +

+ + +
+ +
+ + + + + +
+ Alias for: hours +
+ + + +
+ +
+

+ + hours() + +

+ + +
+

Returns a Duration instance matching the number of hours provided.

+ +
2.hours # => 2 hours
+
+
+ + + +
+ Also aliased as: hour +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 29
+def hours
+  ActiveSupport::Duration.hours(self)
+end
+
+
+ +
+ +
+

+ + html_safe?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 156
+def html_safe?
+  true
+end
+
+
+ +
+ +
+

+ + in_milliseconds() + +

+ + +
+

Returns the number of milliseconds equivalent to the seconds provided. Used with the standard time durations.

+ +
2.in_milliseconds # => 2000
+1.hour.in_milliseconds # => 3600000
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 63
+def in_milliseconds
+  self * 1000
+end
+
+
+ +
+ +
+

+ + kilobyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: kilobytes +
+ + + +
+ +
+

+ + kilobytes() + +

+ + +
+

Returns the number of bytes equivalent to the kilobytes provided.

+ +
2.kilobytes # => 2048
+
+
+ + + +
+ Also aliased as: kilobyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 22
+def kilobytes
+  self * KILOBYTE
+end
+
+
+ +
+ +
+

+ + megabyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: megabytes +
+ + + +
+ +
+

+ + megabytes() + +

+ + +
+

Returns the number of bytes equivalent to the megabytes provided.

+ +
2.megabytes # => 2_097_152
+
+
+ + + +
+ Also aliased as: megabyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 30
+def megabytes
+  self * MEGABYTE
+end
+
+
+ +
+ +
+

+ + minute() + +

+ + +
+ +
+ + + + + +
+ Alias for: minutes +
+ + + +
+ +
+

+ + minutes() + +

+ + +
+

Returns a Duration instance matching the number of minutes provided.

+ +
2.minutes # => 2 minutes
+
+
+ + + +
+ Also aliased as: minute +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 21
+def minutes
+  ActiveSupport::Duration.minutes(self)
+end
+
+
+ +
+ +
+

+ + petabyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: petabytes +
+ + + +
+ +
+

+ + petabytes() + +

+ + +
+

Returns the number of bytes equivalent to the petabytes provided.

+ +
2.petabytes # => 2_251_799_813_685_248
+
+
+ + + +
+ Also aliased as: petabyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 54
+def petabytes
+  self * PETABYTE
+end
+
+
+ +
+ +
+

+ + second() + +

+ + +
+ +
+ + + + + +
+ Alias for: seconds +
+ + + +
+ +
+

+ + seconds() + +

+ + +
+

Returns a Duration instance matching the number of seconds provided.

+ +
2.seconds # => 2 seconds
+
+
+ + + +
+ Also aliased as: second +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 13
+def seconds
+  ActiveSupport::Duration.seconds(self)
+end
+
+
+ +
+ +
+

+ + terabyte() + +

+ + +
+ +
+ + + + + +
+ Alias for: terabytes +
+ + + +
+ +
+

+ + terabytes() + +

+ + +
+

Returns the number of bytes equivalent to the terabytes provided.

+ +
2.terabytes # => 2_199_023_255_552
+
+
+ + + +
+ Also aliased as: terabyte +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/bytes.rb, line 46
+def terabytes
+  self * TERABYTE
+end
+
+
+ +
+ +
+

+ + week() + +

+ + +
+ +
+ + + + + +
+ Alias for: weeks +
+ + + +
+ +
+

+ + weeks() + +

+ + +
+

Returns a Duration instance matching the number of weeks provided.

+ +
2.weeks # => 2 weeks
+
+
+ + + +
+ Also aliased as: week +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/numeric/time.rb, line 45
+def weeks
+  ActiveSupport::Duration.weeks(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Object.html b/src/7.0/classes/Object.html new file mode 100644 index 0000000000..8a44ee163c --- /dev/null +++ b/src/7.0/classes/Object.html @@ -0,0 +1,1017 @@ +--- +title: Object +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
APP_PATH=File.expand_path("test/dummy/config/application", ENGINE_ROOT)
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + acts_like?(duck) + +

+ + +
+

Provides a way to check whether some class acts like some other class based on the existence of an appropriately-named marker method.

+ +

A class that provides the same interface as SomeClass may define a marker method named acts_like_some_class? to signal its compatibility to callers of acts_like?(:some_class).

+ +

For example, Active Support extends Date to define an acts_like_date? method, and extends Time to define acts_like_time?. As a result, developers can call x.acts_like?(:time) and x.acts_like?(:date) to test duck-type compatibility, and classes that are able to act like Time can also define an acts_like_time? method to interoperate.

+ +

Note that the marker method is only expected to exist. It isn’t called, so its body or return value are irrelevant.

+ +

Example: A class that provides the same interface as String

+ +

This class may define:

+ +
class Stringish
+  def acts_like_string?
+  end
+end
+
+ +

Then client code can query for duck-type-safeness this way:

+ +
Stringish.new.acts_like?(:string) # => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/acts_like.rb, line 33
+def acts_like?(duck)
+  case duck
+  when :time
+    respond_to? :acts_like_time?
+  when :date
+    respond_to? :acts_like_date?
+  when :string
+    respond_to? :acts_like_string?
+  else
+    respond_to? :"acts_like_#{duck}?"
+  end
+end
+
+
+ +
+ +
+

+ + blank?() + +

+ + +
+

An object is blank if it’s false, empty, or a whitespace string. For example, nil, ”, ‘ ’, [], {}, and false are all blank.

+ +

This simplifies

+ +
!address || address.empty?
+
+ +

to

+ +
address.blank?
+
+ +

@return [true, false]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 18
+def blank?
+  respond_to?(:empty?) ? !!empty? : !self
+end
+
+
+ +
+ +
+

+ + deep_dup() + +

+ + +
+

Returns a deep copy of object if it’s duplicable. If it’s not duplicable, returns self.

+ +
object = Object.new
+dup    = object.deep_dup
+dup.instance_variable_set(:@a, 1)
+
+object.instance_variable_defined?(:@a) # => false
+dup.instance_variable_defined?(:@a)    # => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 15
+def deep_dup
+  duplicable? ? dup : self
+end
+
+
+ +
+ +
+

+ + duplicable?() + +

+ + +
+

Can you safely dup this object?

+ +

False for method objects; true otherwise.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 26
+def duplicable?
+  true
+end
+
+
+ +
+ +
+

+ + html_safe?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 150
+def html_safe?
+  false
+end
+
+
+ +
+ +
+

+ + in?(another_object) + +

+ + +
+

Returns true if this object is included in the argument. Argument must be any object which responds to #include?. Usage:

+ +
characters = ["Konata", "Kagami", "Tsukasa"]
+"Konata".in?(characters) # => true
+
+ +

This will throw an ArgumentError if the argument doesn’t respond to #include?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 12
+def in?(another_object)
+  another_object.include?(self)
+rescue NoMethodError
+  raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
+end
+
+
+ +
+ +
+

+ + instance_values() + +

+ + +
+

Returns a hash with string keys that maps instance variable names without “@” to their corresponding values.

+ +
class C
+  def initialize(x, y)
+    @x, @y = x, y
+  end
+end
+
+C.new(0, 1).instance_values # => {"x" => 0, "y" => 1}
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 14
+def instance_values
+  Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
+end
+
+
+ +
+ +
+

+ + instance_variable_names() + +

+ + +
+

Returns an array of instance variable names as strings including “@”.

+ +
class C
+  def initialize(x, y)
+    @x, @y = x, y
+  end
+end
+
+C.new(0, 1).instance_variable_names # => ["@y", "@x"]
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/instance_variables.rb, line 27
+def instance_variable_names
+  instance_variables.map(&:to_s)
+end
+
+
+ +
+ +
+

+ + presence() + +

+ + +
+

Returns the receiver if it’s present otherwise returns nil. object.presence is equivalent to

+ +
object.present? ? object : nil
+
+ +

For example, something like

+ +
state   = params[:state]   if params[:state].present?
+country = params[:country] if params[:country].present?
+region  = state || country || 'US'
+
+ +

becomes

+ +
region = params[:state].presence || params[:country].presence || 'US'
+
+ +

@return [Object]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 45
+def presence
+  self if present?
+end
+
+
+ +
+ +
+

+ + presence_in(another_object) + +

+ + +
+

Returns the receiver if it’s included in the argument otherwise returns nil. Argument must be any object which responds to #include?. Usage:

+ +
params[:bucket_type].presence_in %w( project calendar )
+
+ +

This will throw an ArgumentError if the argument doesn’t respond to #include?.

+ +

@return [Object]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/inclusion.rb, line 26
+def presence_in(another_object)
+  in?(another_object) ? self : nil
+end
+
+
+ +
+ +
+

+ + present?() + +

+ + +
+

An object is present if it’s not blank.

+ +

@return [true, false]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 25
+def present?
+  !blank?
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Alias of to_s.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 7
+def to_param
+  to_s
+end
+
+
+ +
+ +
+

+ + to_query(key) + +

+ + +
+

Converts an object into a string suitable for use as a URL query string, using the given key as the param name.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 13
+def to_query(key)
+  "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
+end
+
+
+ +
+ +
+

+ + try(*args, &block) + + +

+ + +
+

Invokes the public method whose name goes as first argument just like public_send does, except that if the receiver does not respond to it the call returns nil rather than raising an exception.

+ +

This method is defined to be able to write

+ +
@person.try(:name)
+
+ +

instead of

+ +
@person.name if @person
+
+ +

try calls can be chained:

+ +
@person.try(:spouse).try(:name)
+
+ +

instead of

+ +
@person.spouse.name if @person && @person.spouse
+
+ +

try will also return nil if the receiver does not respond to the method:

+ +
@person.try(:non_existing_method) # => nil
+
+ +

instead of

+ +
@person.non_existing_method if @person.respond_to?(:non_existing_method) # => nil
+
+ +

try returns nil when called on nil regardless of whether it responds to the method:

+ +
nil.try(:to_i) # => nil, rather than 0
+
+ +

Arguments and blocks are forwarded to the method if invoked:

+ +
@posts.try(:each_slice, 2) do |a, b|
+  ...
+end
+
+ +

The number of arguments in the signature must match. If the object responds to the method the call is attempted and ArgumentError is still raised in case of argument mismatch.

+ +

If try is called without arguments it yields the receiver to a given block unless it is nil:

+ +
@person.try do |p|
+  ...
+end
+
+ +

You can also call try with a block without accepting an argument, and the block will be instance_eval’ed instead:

+ +
@person.try { upcase.truncate(50) }
+
+ +

Please also note that try is defined on Object. Therefore, it won’t work with instances of classes that do not have Object among their ancestors, like direct subclasses of BasicObject.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 39
+  
+
+
+ +
+ +
+

+ + try!(*args, &block) + + +

+ + +
+

Same as try, but raises a NoMethodError exception if the receiver is not nil and does not implement the tried method.

+ +
"a".try!(:upcase) # => "A"
+nil.try!(:upcase) # => nil
+123.try!(:upcase) # => NoMethodError: undefined method `upcase' for 123:Integer
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/try.rb, line 104
+
+
+
+ +
+ +
+

+ + with_options(options, &block) + +

+ + +
+

An elegant way to factor duplication out of options passed to a series of method calls. Each method called in the block, with the block variable as the receiver, will have its options merged with the default options hash provided. Each method called on the block variable must take an options hash as its final argument.

+ +

Without with_options, this code contains duplication:

+ +
class Account < ActiveRecord::Base
+  has_many :customers, dependent: :destroy
+  has_many :products,  dependent: :destroy
+  has_many :invoices,  dependent: :destroy
+  has_many :expenses,  dependent: :destroy
+end
+
+ +

Using with_options, we can remove the duplication:

+ +
class Account < ActiveRecord::Base
+  with_options dependent: :destroy do |assoc|
+    assoc.has_many :customers
+    assoc.has_many :products
+    assoc.has_many :invoices
+    assoc.has_many :expenses
+  end
+end
+
+ +

It can also be used with an explicit receiver:

+ +
I18n.with_options locale: user.locale, scope: 'newsletter' do |i18n|
+  subject i18n.t :subject
+  body    i18n.t :body, user_name: user.name
+end
+
+ +

When you don’t pass an explicit receiver, it executes the whole block in merging options context:

+ +
class Account < ActiveRecord::Base
+  with_options dependent: :destroy do
+    has_many :customers
+    has_many :products
+    has_many :invoices
+    has_many :expenses
+  end
+end
+
+ +

with_options can also be nested since the call is forwarded to its receiver.

+ +

NOTE: Each nesting level will merge inherited defaults in addition to their own.

+ +
class Post < ActiveRecord::Base
+  with_options if: :persisted?, length: { minimum: 50 } do
+    validates :content, if: -> { content.present? }
+  end
+end
+
+ +

The code is equivalent to:

+ +
validates :content, length: { minimum: 50 }, if: -> { content.present? }
+
+ +

Hence the inherited default for if key is ignored.

+ +

NOTE: You cannot call class methods implicitly inside of with_options. You can access these methods using the class name instead:

+ +
class Phone < ActiveRecord::Base
+  enum phone_number_type: { home: 0, office: 1, mobile: 2 }
+
+  with_options presence: true do
+    validates :phone_number_type, inclusion: { in: Phone.phone_number_types.keys }
+  end
+end
+
+ +

When the block argument is omitted, the decorated Object instance is returned:

+ +
module MyStyledHelpers
+  def styled
+    with_options style: "color: red;"
+  end
+end
+
+styled.link_to "I'm red", "/"
+# => <a href="/" style="color: red;">I'm red</a>
+
+styled.button_tag "I'm red too!"
+# => <button style="color: red;">I'm red too!</button>
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/with_options.rb, line 92
+def with_options(options, &block)
+  option_merger = ActiveSupport::OptionMerger.new(self, options)
+
+  if block
+    block.arity.zero? ? option_merger.instance_eval(&block) : block.call(option_merger)
+  else
+    option_merger
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Pathname.html b/src/7.0/classes/Pathname.html new file mode 100644 index 0000000000..432cf6cb31 --- /dev/null +++ b/src/7.0/classes/Pathname.html @@ -0,0 +1,124 @@ +--- +title: Pathname +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + existence() + +

+ + +
+

Returns the receiver if the named file exists otherwise returns nil. pathname.existence is equivalent to

+ +
pathname.exist? ? pathname : nil
+
+ +

For example, something like

+ +
content = pathname.read if pathname.exist?
+
+ +

becomes

+ +
content = pathname.existence&.read
+
+ +

@return [Pathname]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/pathname/existence.rb, line 18
+def existence
+  self if exist?
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Process.html b/src/7.0/classes/Process.html new file mode 100644 index 0000000000..537a87dbd2 --- /dev/null +++ b/src/7.0/classes/Process.html @@ -0,0 +1,58 @@ +--- +title: Process +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails.html b/src/7.0/classes/Rails.html new file mode 100644 index 0000000000..63ef732797 --- /dev/null +++ b/src/7.0/classes/Rails.html @@ -0,0 +1,905 @@ +--- +title: Rails +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + app_class
+ [W] + application
+ [RW] + cache
+ [RW] + logger
+ + + + +

Class Public methods

+ +
+

+ + application() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 39
+def application
+  @application ||= (app_class.instance if app_class)
+end
+
+
+ +
+ +
+

+ + autoloaders() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 123
+def autoloaders
+  application.autoloaders
+end
+
+
+ +
+ +
+

+ + backtrace_cleaner() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 50
+def backtrace_cleaner
+  @backtrace_cleaner ||= begin
+    # Relies on Active Support, so we have to lazy load to postpone definition until Active Support has been loaded
+    require "rails/backtrace_cleaner"
+    Rails::BacktraceCleaner.new
+  end
+end
+
+
+ +
+ +
+

+ + configuration() + +

+ + +
+

The Configuration instance used to configure the Rails environment

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 46
+def configuration
+  application.config
+end
+
+
+ +
+ +
+

+ + env() + +

+ + +
+

Returns the current Rails environment.

+ +
Rails.env # => "development"
+Rails.env.development? # => true
+Rails.env.production? # => false
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 72
+def env
+  @_env ||= ActiveSupport::EnvironmentInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
+end
+
+
+ +
+ +
+

+ + env=(environment) + +

+ + +
+

Sets the Rails environment.

+ +
Rails.env = "staging" # => "staging"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 79
+def env=(environment)
+  @_env = ActiveSupport::EnvironmentInquirer.new(environment)
+end
+
+
+ +
+ +
+

+ + error() + +

+ + +
+

Returns the ActiveSupport::ErrorReporter of the current Rails project, otherwise it returns nil if there is no project.

+ +
Rails.error.handle(IOError) do
+  # ...
+end
+Rails.error.report(error)
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 90
+def error
+  application && application.executor.error_reporter
+end
+
+
+ +
+ +
+

+ + gem_version() + +

+ + +
+

Returns the currently loaded version of Rails as a Gem::Version.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/gem_version.rb, line 5
+def self.gem_version
+  Gem::Version.new VERSION::STRING
+end
+
+
+ +
+ +
+

+ + groups(*groups) + +

+ + +
+

Returns all Rails groups for loading based on:

+
  • +

    The Rails environment;

    +
  • +

    The environment variable RAILS_GROUPS;

    +
  • +

    The optional envs given as argument and the hash with group dependencies;

    +
+ +
Rails.groups assets: [:development, :test]
+# => [:default, "development", :assets] for Rails.env == "development"
+# => [:default, "production"]           for Rails.env == "production"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 103
+def groups(*groups)
+  hash = groups.extract_options!
+  env = Rails.env
+  groups.unshift(:default, env)
+  groups.concat ENV["RAILS_GROUPS"].to_s.split(",")
+  groups.concat hash.map { |k, v| k if v.map(&:to_s).include?(env) }
+  groups.compact!
+  groups.uniq!
+  groups
+end
+
+
+ +
+ +
+

+ + public_path() + +

+ + +
+

Returns a Pathname object of the public folder of the current Rails project, otherwise it returns nil if there is no project:

+ +
Rails.public_path
+  # => #<Pathname:/Users/someuser/some/path/project/public>
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 119
+def public_path
+  application && Pathname.new(application.paths["public"].first)
+end
+
+
+ +
+ +
+

+ + root() + +

+ + +
+

Returns a Pathname object of the current Rails project, otherwise it returns nil if there is no project:

+ +
Rails.root
+  # => #<Pathname:/Users/someuser/some/path/project>
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails.rb, line 63
+def root
+  application && application.config.root
+end
+
+
+ +
+ +
+

+ + version() + +

+ + +
+

Returns the currently loaded version of Rails as a string.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/version.rb, line 7
+def self.version
+  VERSION::STRING
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/API.html b/src/7.0/classes/Rails/API.html new file mode 100644 index 0000000000..96c6d105f6 --- /dev/null +++ b/src/7.0/classes/Rails/API.html @@ -0,0 +1,73 @@ +--- +title: Rails::API +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/API/EdgeTask.html b/src/7.0/classes/Rails/API/EdgeTask.html new file mode 100644 index 0000000000..fa59b1890c --- /dev/null +++ b/src/7.0/classes/Rails/API/EdgeTask.html @@ -0,0 +1,107 @@ +--- +title: Rails::API::EdgeTask +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + rails_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 191
+def rails_version
+  "main@#{`git rev-parse HEAD`[0, 7]}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/API/RepoTask.html b/src/7.0/classes/Rails/API/RepoTask.html new file mode 100644 index 0000000000..87d1267dc3 --- /dev/null +++ b/src/7.0/classes/Rails/API/RepoTask.html @@ -0,0 +1,186 @@ +--- +title: Rails::API::RepoTask +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + api_dir() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 185
+def api_dir
+  "doc/rdoc"
+end
+
+
+ +
+ +
+

+ + component_root_dir(component) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 181
+def component_root_dir(component)
+  component
+end
+
+
+ +
+ +
+

+ + configure_sdoc() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 176
+def configure_sdoc
+  super
+  options << "-g" # link to GitHub, SDoc flag
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/API/StableTask.html b/src/7.0/classes/Rails/API/StableTask.html new file mode 100644 index 0000000000..8d3093eecf --- /dev/null +++ b/src/7.0/classes/Rails/API/StableTask.html @@ -0,0 +1,107 @@ +--- +title: Rails::API::StableTask +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + rails_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 197
+def rails_version
+  File.read("RAILS_VERSION").strip
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/API/Task.html b/src/7.0/classes/Rails/API/Task.html new file mode 100644 index 0000000000..90955b2990 --- /dev/null +++ b/src/7.0/classes/Rails/API/Task.html @@ -0,0 +1,461 @@ +--- +title: Rails::API::Task +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
RDOC_FILES={ +"activesupport" => { +include: %w( +README.rdoc +lib/active_support/**/*.rb +) +}, + +"activerecord" => { +include: %w( +README.rdoc +lib/active_record/**/*.rb +lib/arel.rb +) +}, + +"activemodel" => { +include: %w( +README.rdoc +lib/active_model/**/*.rb +) +}, + +"actionpack" => { +include: %w( +README.rdoc +lib/abstract_controller/**/*.rb +lib/action_controller/**/*.rb +lib/action_dispatch/**/*.rb +) +}, + +"actionview" => { +include: %w( +README.rdoc +lib/action_view/**/*.rb +), +exclude: "lib/action_view/vendor/*" +}, + +"actionmailer" => { +include: %w( +README.rdoc +lib/action_mailer/**/*.rb +) +}, + +"activejob" => { +include: %w( +README.md +lib/active_job/**/*.rb +) +}, + +"actioncable" => { +include: %w( +README.md +lib/action_cable/**/*.rb +) +}, + +"activestorage" => { +include: %w( +README.md +app/**/active_storage/**/*.rb +lib/active_storage/**/*.rb +) +}, + +"actionmailbox" => { +include: %w( +README.md +app/**/action_mailbox/**/*.rb +lib/action_mailbox/**/*.rb +) +}, + +"actiontext" => { +include: %w( +README.md +app/**/action_text/**/*.rb +lib/action_text/**/*.rb +) +}, + +"railties" => { +include: %w( +README.rdoc +lib/**/*.rb +), +exclude: %w( +lib/rails/generators/**/templates/**/*.rb +lib/rails/test_unit/* +lib/rails/api/generator.rb +) +} +}
 
+ + + + + + +

Class Public methods

+ +
+

+ + new(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 107
+def initialize(name)
+  super
+
+  # Every time rake runs this task is instantiated as all the rest.
+  # Be lazy computing stuff to have as light impact as possible to
+  # the rest of tasks.
+  before_running_rdoc do
+    configure_sdoc
+    configure_rdoc_files
+    setup_horo_variables
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + api_main() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 170
+def api_main
+  component_root_dir("railties") + "/RDOC_MAIN.rdoc"
+end
+
+
+ +
+ +
+

+ + configure_rdoc_files() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 136
+def configure_rdoc_files
+  rdoc_files.include(api_main)
+
+  RDOC_FILES.each do |component, cfg|
+    cdr = component_root_dir(component)
+
+    Array(cfg[:include]).each do |pattern|
+      rdoc_files.include("#{cdr}/#{pattern}")
+    end
+
+    Array(cfg[:exclude]).each do |pattern|
+      rdoc_files.exclude("#{cdr}/#{pattern}")
+    end
+  end
+
+  # Only generate documentation for files that have been
+  # changed since the API was generated.
+  if Dir.exist?("doc/rdoc") && !ENV["ALL"]
+    last_generation = DateTime.rfc2822(File.open("doc/rdoc/created.rid", &:readline))
+
+    rdoc_files.keep_if do |file|
+      File.mtime(file).to_datetime > last_generation
+    end
+
+    # Nothing to do
+    exit(0) if rdoc_files.empty?
+  end
+end
+
+
+ +
+ +
+

+ + configure_sdoc() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 125
+def configure_sdoc
+  self.title    = "Ruby on Rails API"
+  self.rdoc_dir = api_dir
+
+  options << "-m"  << api_main
+  options << "-e"  << "UTF-8"
+
+  options << "-f"  << "api"
+  options << "-T"  << "rails"
+end
+
+
+ +
+ +
+

+ + desc(description) + +

+ + +
+

Hack, ignore the desc calls performed by the original initializer.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 121
+def desc(description)
+  # no-op
+end
+
+
+ +
+ +
+

+ + setup_horo_variables() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/api/task.rb, line 165
+def setup_horo_variables
+  ENV["HORO_PROJECT_NAME"]    = "Ruby on Rails"
+  ENV["HORO_PROJECT_VERSION"] = rails_version
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/AppBuilder.html b/src/7.0/classes/Rails/AppBuilder.html new file mode 100644 index 0000000000..03859af11f --- /dev/null +++ b/src/7.0/classes/Rails/AppBuilder.html @@ -0,0 +1,1241 @@ +--- +title: Rails::AppBuilder +layout: default +--- +
+ +
+
+ +
+ +

The application builder allows you to override elements of the application generator without being forced to reverse the operations of the default generator.

+ +

This allows you to override entire operations, like the creation of the Gemfile, README, or JavaScript files, without needing to know exactly what those operations do so you can create another template action.

+ +
class CustomAppBuilder < Rails::AppBuilder
+  def test
+    @generator.gem "rspec-rails", group: [:development, :test]
+    run "bundle install"
+    generate "rspec:install"
+  end
+end
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + app() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 82
+def app
+  directory "app"
+
+  empty_directory_with_keep_file "app/assets/images"
+
+  keep_file  "app/controllers/concerns"
+  keep_file  "app/models/concerns"
+end
+
+
+ +
+ +
+

+ + bin() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 91
+def bin
+  directory "bin" do |content|
+    "#{shebang}\n" + content
+  end
+  chmod "bin", 0755 & ~File.umask, verbose: false
+end
+
+
+ +
+ +
+

+ + bin_when_updating() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 98
+def bin_when_updating
+  bin
+end
+
+
+ +
+ +
+

+ + config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 102
+def config
+  empty_directory "config"
+
+  inside "config" do
+    template "routes.rb" unless options[:updating]
+    template "application.rb"
+    template "environment.rb"
+    template "cable.yml" unless options[:updating] || options[:skip_action_cable]
+    template "puma.rb"   unless options[:updating]
+    template "storage.yml" unless options[:updating] || skip_active_storage?
+
+    directory "environments"
+    directory "initializers"
+    directory "locales" unless options[:updating]
+  end
+end
+
+
+ +
+ +
+

+ + config_target_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 252
+def config_target_version
+  defined?(@config_target_version) ? @config_target_version : Rails::VERSION::STRING.to_f
+end
+
+
+ +
+ +
+

+ + config_when_updating() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 119
+def config_when_updating
+  action_cable_config_exist       = File.exist?("config/cable.yml")
+  active_storage_config_exist     = File.exist?("config/storage.yml")
+  rack_cors_config_exist          = File.exist?("config/initializers/cors.rb")
+  assets_config_exist             = File.exist?("config/initializers/assets.rb")
+  asset_manifest_exist            = File.exist?("app/assets/config/manifest.js")
+  asset_app_stylesheet_exist      = File.exist?("app/assets/stylesheets/application.css")
+  csp_config_exist                = File.exist?("config/initializers/content_security_policy.rb")
+  permissions_policy_config_exist = File.exist?("config/initializers/permissions_policy.rb")
+
+  @config_target_version = Rails.application.config.loaded_config_version || "5.0"
+
+  config
+
+  if !options[:skip_action_cable] && !action_cable_config_exist
+    template "config/cable.yml"
+  end
+
+  if !skip_active_storage? && !active_storage_config_exist
+    template "config/storage.yml"
+  end
+
+  if skip_sprockets? && skip_propshaft? && !assets_config_exist
+    remove_file "config/initializers/assets.rb"
+  end
+
+  if skip_sprockets? && !asset_manifest_exist
+    remove_file "app/assets/config/manifest.js"
+  end
+
+  if skip_sprockets? && !asset_app_stylesheet_exist
+    remove_file "app/assets/stylesheets/application.css"
+  end
+
+  unless rack_cors_config_exist
+    remove_file "config/initializers/cors.rb"
+  end
+
+  if options[:api]
+    unless csp_config_exist
+      remove_file "config/initializers/content_security_policy.rb"
+    end
+
+    unless permissions_policy_config_exist
+      remove_file "config/initializers/permissions_policy.rb"
+    end
+  end
+
+  if !skip_sprockets?
+    insert_into_file "config/application.rb", %(require "sprockets/railtie"), after: /require\(["']rails\/all["']\)\n/
+  end
+end
+
+
+ +
+ +
+

+ + configru() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 61
+def configru
+  template "config.ru"
+end
+
+
+ +
+ +
+

+ + credentials() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 181
+def credentials
+  return if options[:pretend] || options[:dummy_app]
+
+  require "rails/generators/rails/credentials/credentials_generator"
+  Rails::Generators::CredentialsGenerator.new([], quiet: options[:quiet]).add_credentials_file_silently
+end
+
+
+ +
+ +
+

+ + database_yml() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 188
+def database_yml
+  template "config/databases/#{options[:database]}.yml", "config/database.yml"
+end
+
+
+ +
+ +
+

+ + db() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 192
+def db
+  directory "db"
+end
+
+
+ +
+ +
+

+ + db_when_updating() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 196
+def db_when_updating
+  path = File.expand_path("db/schema.rb", destination_root)
+
+  if File.exist?(path)
+    gsub_file("db/schema.rb", /ActiveRecord::Schema\.define/, "ActiveRecord::Schema[6.1].define")
+  end
+end
+
+
+ +
+ +
+

+ + gemfile() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 57
+def gemfile
+  template "Gemfile"
+end
+
+
+ +
+ +
+

+ + gitattributes() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 69
+def gitattributes
+  template "gitattributes", ".gitattributes"
+end
+
+
+ +
+ +
+

+ + gitignore() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 65
+def gitignore
+  template "gitignore", ".gitignore"
+end
+
+
+ +
+ +
+

+ + lib() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 204
+def lib
+  empty_directory "lib"
+  empty_directory_with_keep_file "lib/tasks"
+  empty_directory_with_keep_file "lib/assets"
+end
+
+
+ +
+ +
+

+ + log() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 210
+def log
+  empty_directory_with_keep_file "log"
+end
+
+
+ +
+ +
+

+ + master_key() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 172
+def master_key
+  return if options[:pretend] || options[:dummy_app]
+
+  require "rails/generators/rails/master_key/master_key_generator"
+  master_key_generator = Rails::Generators::MasterKeyGenerator.new([], quiet: options[:quiet], force: options[:force])
+  master_key_generator.add_master_key_file_silently
+  master_key_generator.ignore_master_key_file_silently
+end
+
+
+ +
+ +
+

+ + public_directory() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 214
+def public_directory
+  directory "public", "public", recursive: false
+end
+
+
+ +
+ +
+

+ + rakefile() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 45
+def rakefile
+  template "Rakefile"
+end
+
+
+ +
+ +
+

+ + readme() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 49
+def readme
+  copy_file "README.md", "README.md"
+end
+
+
+ +
+ +
+

+ + ruby_version() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 53
+def ruby_version
+  template "ruby-version", ".ruby-version"
+end
+
+
+ +
+ +
+

+ + storage() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 218
+def storage
+  empty_directory_with_keep_file "storage"
+  empty_directory_with_keep_file "tmp/storage"
+end
+
+
+ +
+ +
+

+ + system_test() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 235
+def system_test
+  empty_directory_with_keep_file "test/system"
+
+  template "test/application_system_test_case.rb"
+end
+
+
+ +
+ +
+

+ + test() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 223
+def test
+  empty_directory_with_keep_file "test/fixtures/files"
+  empty_directory_with_keep_file "test/controllers"
+  empty_directory_with_keep_file "test/mailers"
+  empty_directory_with_keep_file "test/models"
+  empty_directory_with_keep_file "test/helpers"
+  empty_directory_with_keep_file "test/integration"
+
+  template "test/channels/application_cable/connection_test.rb"
+  template "test/test_helper.rb"
+end
+
+
+ +
+ +
+

+ + tmp() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 241
+def tmp
+  empty_directory_with_keep_file "tmp"
+  empty_directory_with_keep_file "tmp/pids"
+  empty_directory "tmp/cache"
+  empty_directory "tmp/cache/assets"
+end
+
+
+ +
+ +
+

+ + vendor() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 248
+def vendor
+  empty_directory_with_keep_file "vendor"
+end
+
+
+ +
+ +
+

+ + version_control() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 73
+def version_control
+  if !options[:skip_git] && !options[:pretend]
+    run "git init", capture: options[:quiet], abort_on_failure: false
+    if user_default_branch.strip.empty?
+      `git symbolic-ref HEAD refs/heads/main`
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application.html b/src/7.0/classes/Rails/Application.html new file mode 100644 index 0000000000..2b46c9524e --- /dev/null +++ b/src/7.0/classes/Rails/Application.html @@ -0,0 +1,1361 @@ +--- +title: Rails::Application +layout: default +--- +
+ +
+
+ +
+ +

An Engine with the responsibility of coordinating the whole boot process.

+ +

Initialization

+ +

Rails::Application is responsible for executing all railties and engines initializers. It also executes some bootstrap initializers (check Rails::Application::Bootstrap) and finishing initializers, after all the others are executed (check Rails::Application::Finisher).

+ +

Configuration

+ +

Besides providing the same configuration as Rails::Engine and Rails::Railtie, the application object has several specific configurations, for example cache_classes, consider_all_requests_local, filter_parameters, logger, and so forth.

+ +

Check Rails::Application::Configuration to see them all.

+ +

Routes

+ +

The application object is also responsible for holding the routes and reloading routes whenever the files change in development.

+ +

Middlewares

+ +

The Application is also responsible for building the middleware stack.

+ +

Booting process

+ +

The application is also responsible for setting up and executing the booting process. From the moment you require config/application.rb in your app, the booting process goes like this:

+
  1. +

    require "config/boot.rb" to set up load paths.

    +
  2. +

    require railties and engines.

    +
  3. +

    Define Rails.application as class MyApp::Application < Rails::Application.

    +
  4. +

    Run config.before_configuration callbacks.

    +
  5. +

    Load config/environments/ENV.rb.

    +
  6. +

    Run config.before_initialize callbacks.

    +
  7. +

    Run Railtie#initializer defined by railties, engines, and application. One by one, each engine sets up its load paths and routes, and runs its config/initializers/* files.

    +
  8. +

    Custom Railtie#initializers added by railties, engines, and applications are executed.

    +
  9. +

    Build the middleware stack and run to_prepare callbacks.

    +
  10. +

    Run config.before_eager_load and eager_load! if eager_load is true.

    +
  11. +

    Run config.after_initialize callbacks.

    +
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + assets
+ [R] + autoloaders
+ [W] + config
+ [W] + credentials
+ [R] + executor
+ [R] + reloader
+ [R] + reloaders
+ [RW] + sandbox
+ [RW] + sandbox?
+ [W] + secrets
+ + + + +

Class Public methods

+ +
+

+ + create(initial_variable_values = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 81
+def create(initial_variable_values = {}, &block)
+  new(initial_variable_values, &block).run_load_hooks!
+end
+
+
+ +
+ +
+

+ + find_root(from) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 85
+def find_root(from)
+  find_root_with_flag "config.ru", from, Dir.pwd
+end
+
+
+ +
+ +
+

+ + inherited(base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 70
+def inherited(base)
+  super
+  Rails.app_class = base
+  add_lib_to_load_path!(find_root(base.called_from))
+  ActiveSupport.run_load_hooks(:before_configuration, base)
+end
+
+
+ +
+ +
+

+ + instance() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 77
+def instance
+  super.run_load_hooks!
+end
+
+
+ +
+ +
+

+ + new(initial_variable_values = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 106
+def initialize(initial_variable_values = {}, &block)
+  super()
+  @initialized       = false
+  @reloaders         = []
+  @routes_reloader   = nil
+  @app_env_config    = nil
+  @ordered_railties  = nil
+  @railties          = nil
+  @message_verifiers = {}
+  @ran_load_hooks    = false
+
+  @executor          = Class.new(ActiveSupport::Executor)
+  @reloader          = Class.new(ActiveSupport::Reloader)
+  @reloader.executor = @executor
+
+  @autoloaders = Rails::Autoloaders.new
+
+  # are these actually used?
+  @initial_variable_values = initial_variable_values
+  @block = block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + config_for(name, env: Rails.env) + +

+ + +
+

Convenience for loading config/foo.yml for the current Rails env.

+ +

Examples:

+ +
# config/exception_notification.yml:
+production:
+  url: http://127.0.0.1:8080
+  namespace: my_app_production
+
+development:
+  url: http://localhost:3001
+  namespace: my_app_development
+
+# config/environments/production.rb
+Rails.application.configure do
+  config.middleware.use ExceptionNotifier, config_for(:exception_notification)
+end
+
+# You can also store configurations in a shared section which will be
+# merged with the environment configuration
+
+# config/example.yml
+shared:
+  foo:
+    bar:
+      baz: 1
+
+development:
+  foo:
+    bar:
+      qux: 2
+
+# development environment
+Rails.application.config_for(:example)[:foo][:bar]
+# => { baz: 1, qux: 2 }
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 221
+def config_for(name, env: Rails.env)
+  yaml = name.is_a?(Pathname) ? name : Pathname.new("#{paths["config"].existent.first}/#{name}.yml")
+
+  if yaml.exist?
+    require "erb"
+    all_configs    = ActiveSupport::ConfigurationFile.parse(yaml).deep_symbolize_keys
+    config, shared = all_configs[env.to_sym], all_configs[:shared]
+
+    if shared
+      config = {} if config.nil? && shared.is_a?(Hash)
+      if config.is_a?(Hash) && shared.is_a?(Hash)
+        config = shared.deep_merge(config)
+      elsif config.nil?
+        config = shared
+      end
+    end
+
+    if config.is_a?(Hash)
+      config = ActiveSupport::OrderedOptions.new.update(config)
+    end
+
+    config
+  else
+    raise "Could not load configuration. No such file - #{yaml}"
+  end
+end
+
+
+ +
+ +
+

+ + console(&blk) + +

+ + +
+

Sends any console called in the instance of a new application up to the console method defined in Rails::Railtie.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 303
+def console(&blk)
+  self.class.console(&blk)
+end
+
+
+ +
+ +
+

+ + credentials() + +

+ + +
+

Returns an ActiveSupport::EncryptedConfiguration instance for the credentials file specified by config.credentials.content_path.

+ +

By default, config.credentials.content_path will point to either config/credentials/#{environment}.yml.enc for the current environment (for example, config/credentials/production.yml.enc for the production environment), or config/credentials.yml.enc if that file does not exist.

+ +

The encryption key is taken from either ENV["RAILS_MASTER_KEY"], or from the file specified by config.credentials.key_path. By default, config.credentials.key_path will point to either config/credentials/#{environment}.key for the current environment, or config/master.key if that file does not exist.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 439
+def credentials
+  @credentials ||= encrypted(config.credentials.content_path, key_path: config.credentials.key_path)
+end
+
+
+ +
+ +
+

+ + eager_load!() + +

+ + +
+

Eager loads the application code.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 492
+def eager_load!
+  Rails.autoloaders.each(&:eager_load)
+end
+
+
+ +
+ +
+

+ + encrypted(path, key_path: "config/master.key", env_key: "RAILS_MASTER_KEY") + +

+ + +
+

Returns an ActiveSupport::EncryptedConfiguration instance for an encrypted file. By default, the encryption key is taken from either ENV["RAILS_MASTER_KEY"], or from the config/master.key file.

+ +
my_config = Rails.application.encrypted("config/my_config.enc")
+
+my_config.read
+# => "foo:\n  bar: 123\n"
+
+my_config.foo.bar
+# => 123
+
+ +

Encrypted files can be edited with the bin/rails encrypted:edit command. (See the output of bin/rails encrypted:edit --help for more information.)

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 458
+def encrypted(path, key_path: "config/master.key", env_key: "RAILS_MASTER_KEY")
+  ActiveSupport::EncryptedConfiguration.new(
+    config_path: Rails.root.join(path),
+    key_path: Rails.root.join(key_path),
+    env_key: env_key,
+    raise_if_missing_key: config.require_master_key
+  )
+end
+
+
+ +
+ +
+

+ + env_config() + +

+ + +
+

Stores some of the Rails initial environment parameters which will be used by middlewares and engines to configure themselves.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 250
+def env_config
+  @app_env_config ||= super.merge(
+      "action_dispatch.parameter_filter" => config.filter_parameters,
+      "action_dispatch.redirect_filter" => config.filter_redirect,
+      "action_dispatch.secret_key_base" => secret_key_base,
+      "action_dispatch.show_exceptions" => config.action_dispatch.show_exceptions,
+      "action_dispatch.show_detailed_exceptions" => config.consider_all_requests_local,
+      "action_dispatch.log_rescued_responses" => config.action_dispatch.log_rescued_responses,
+      "action_dispatch.logger" => Rails.logger,
+      "action_dispatch.backtrace_cleaner" => Rails.backtrace_cleaner,
+      "action_dispatch.key_generator" => key_generator,
+      "action_dispatch.http_auth_salt" => config.action_dispatch.http_auth_salt,
+      "action_dispatch.signed_cookie_salt" => config.action_dispatch.signed_cookie_salt,
+      "action_dispatch.encrypted_cookie_salt" => config.action_dispatch.encrypted_cookie_salt,
+      "action_dispatch.encrypted_signed_cookie_salt" => config.action_dispatch.encrypted_signed_cookie_salt,
+      "action_dispatch.authenticated_encrypted_cookie_salt" => config.action_dispatch.authenticated_encrypted_cookie_salt,
+      "action_dispatch.use_authenticated_cookie_encryption" => config.action_dispatch.use_authenticated_cookie_encryption,
+      "action_dispatch.encrypted_cookie_cipher" => config.action_dispatch.encrypted_cookie_cipher,
+      "action_dispatch.signed_cookie_digest" => config.action_dispatch.signed_cookie_digest,
+      "action_dispatch.cookies_serializer" => config.action_dispatch.cookies_serializer,
+      "action_dispatch.cookies_digest" => config.action_dispatch.cookies_digest,
+      "action_dispatch.cookies_rotations" => config.action_dispatch.cookies_rotations,
+      "action_dispatch.cookies_same_site_protection" => coerce_same_site_protection(config.action_dispatch.cookies_same_site_protection),
+      "action_dispatch.use_cookies_with_metadata" => config.action_dispatch.use_cookies_with_metadata,
+      "action_dispatch.content_security_policy" => config.content_security_policy,
+      "action_dispatch.content_security_policy_report_only" => config.content_security_policy_report_only,
+      "action_dispatch.content_security_policy_nonce_generator" => config.content_security_policy_nonce_generator,
+      "action_dispatch.content_security_policy_nonce_directives" => config.content_security_policy_nonce_directives,
+      "action_dispatch.permissions_policy" => config.permissions_policy,
+    )
+end
+
+
+ +
+ +
+

+ + generators(&blk) + +

+ + +
+

Sends any generators called in the instance of a new application up to the generators method defined in Rails::Railtie.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 309
+def generators(&blk)
+  self.class.generators(&blk)
+end
+
+
+ +
+ +
+

+ + initialized?() + +

+ + +
+

Returns true if the application is initialized.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 129
+def initialized?
+  @initialized
+end
+
+
+ +
+ +
+

+ + initializer(name, opts = {}, &block) + +

+ + +
+

Sends the initializers to the initializer method defined in the Rails::Initializable module. Each Rails::Application class has its own set of initializers, as defined by the Initializable module.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 291
+def initializer(name, opts = {}, &block)
+  self.class.initializer(name, opts, &block)
+end
+
+
+ +
+ +
+

+ + isolate_namespace(mod) + +

+ + +
+

Sends the isolate_namespace method up to the class method.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 320
+def isolate_namespace(mod)
+  self.class.isolate_namespace(mod)
+end
+
+
+ +
+ +
+

+ + key_generator() + +

+ + +
+

Returns the application’s KeyGenerator

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 153
+def key_generator
+  # number of iterations selected based on consultation with the google security
+  # team. Details at https://github.com/rails/rails/pull/6952#issuecomment-7661220
+  @caching_key_generator ||= ActiveSupport::CachingKeyGenerator.new(
+    ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000)
+  )
+end
+
+
+ +
+ +
+

+ + message_verifier(verifier_name) + +

+ + +
+

Returns a message verifier object.

+ +

This verifier can be used to generate and verify signed messages in the application.

+ +

It is recommended not to use the same verifier for different things, so you can get different verifiers passing the verifier_name argument.

+ +

Parameters

+
  • +

    verifier_name - the name of the message verifier.

    +
+ +

Examples

+ +
message = Rails.application.message_verifier('sensitive_data').generate('my sensible data')
+Rails.application.message_verifier('sensitive_data').verify(message)
+# => 'my sensible data'
+
+ +

See the ActiveSupport::MessageVerifier documentation for more information.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 179
+def message_verifier(verifier_name)
+  @message_verifiers[verifier_name] ||= begin
+    secret = key_generator.generate_key(verifier_name.to_s)
+    ActiveSupport::MessageVerifier.new(secret)
+  end
+end
+
+
+ +
+ +
+

+ + rake_tasks(&block) + +

+ + +
+

If you try to define a set of Rake tasks on the instance, these will get passed up to the Rake tasks defined on the application’s class.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 284
+def rake_tasks(&block)
+  self.class.rake_tasks(&block)
+end
+
+
+ +
+ +
+

+ + reload_routes!() + +

+ + +
+

Reload application routes regardless if they changed or not.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 148
+def reload_routes!
+  routes_reloader.reload!
+end
+
+
+ +
+ +
+

+ + runner(&blk) + +

+ + +
+

Sends any runner called in the instance of a new application up to the runner method defined in Rails::Railtie.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 297
+def runner(&blk)
+  self.class.runner(&blk)
+end
+
+
+ +
+ +
+

+ + secret_key_base() + +

+ + +
+

The secret_key_base is used as the input secret to the application’s key generator, which in turn is used to create all ActiveSupport::MessageVerifier and ActiveSupport::MessageEncryptor instances, including the ones that sign and encrypt cookies.

+ +

In development and test, this is randomly generated and stored in a temporary file in tmp/development_secret.txt.

+ +

In all other environments, we look for it first in ENV["SECRET_KEY_BASE"], then credentials.secret_key_base, and finally secrets.secret_key_base. For most applications, the correct place to store it is in the encrypted credentials file.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 415
+def secret_key_base
+  if Rails.env.development? || Rails.env.test?
+    secrets.secret_key_base ||= generate_development_secret
+  else
+    validate_secret_key_base(
+      ENV["SECRET_KEY_BASE"] || credentials.secret_key_base || secrets.secret_key_base
+    )
+  end
+end
+
+
+ +
+ +
+

+ + secrets() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 389
+def secrets
+  @secrets ||= begin
+    secrets = ActiveSupport::OrderedOptions.new
+    files = config.paths["config/secrets"].existent
+    files = files.reject { |path| path.end_with?(".enc") } unless config.read_encrypted_secrets
+    secrets.merge! Rails::Secrets.parse(files, env: Rails.env)
+
+    # Fallback to config.secret_key_base if secrets.secret_key_base isn't set
+    secrets.secret_key_base ||= config.secret_key_base
+
+    secrets
+  end
+end
+
+
+ +
+ +
+

+ + server(&blk) + +

+ + +
+

Sends any server called in the instance of a new application up to the server method defined in Rails::Railtie.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 315
+def server(&blk)
+  self.class.server(&blk)
+end
+
+
+ +
+ + +

Instance Protected methods

+ +
+

+ + validate_secret_key_base(secret_key_base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application.rb, line 570
+def validate_secret_key_base(secret_key_base)
+  if secret_key_base.is_a?(String) && secret_key_base.present?
+    secret_key_base
+  elsif secret_key_base
+    raise ArgumentError, "`secret_key_base` for #{Rails.env} environment must be a type of String`"
+  else
+    raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `bin/rails credentials:edit`"
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application/Bootstrap.html b/src/7.0/classes/Rails/Application/Bootstrap.html new file mode 100644 index 0000000000..e605a637dd --- /dev/null +++ b/src/7.0/classes/Rails/Application/Bootstrap.html @@ -0,0 +1,68 @@ +--- +title: Rails::Application::Bootstrap +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application/Configuration.html b/src/7.0/classes/Rails/Application/Configuration.html new file mode 100644 index 0000000000..98ee9721b1 --- /dev/null +++ b/src/7.0/classes/Rails/Application/Configuration.html @@ -0,0 +1,1308 @@ +--- +title: Rails::Application::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + add_autoload_paths_to_load_path
+ [RW] + allow_concurrency
+ [R] + api_only
+ [RW] + asset_host
+ [RW] + autoflush_log
+ [RW] + beginning_of_week
+ [RW] + cache_classes
+ [RW] + cache_store
+ [RW] + consider_all_requests_local
+ [RW] + console
+ [RW] + content_security_policy_nonce_directives
+ [RW] + content_security_policy_nonce_generator
+ [RW] + content_security_policy_report_only
+ [RW] + credentials
+ [W] + debug_exception_response_format
+ [RW] + disable_sandbox
+ [RW] + eager_load
+ [RW] + enable_dependency_loading
+ [R] + encoding
+ [RW] + exceptions_app
+ [RW] + file_watcher
+ [RW] + filter_parameters
+ [RW] + filter_redirect
+ [RW] + force_ssl
+ [RW] + helpers_paths
+ [RW] + host_authorization
+ [RW] + hosts
+ [R] + loaded_config_version
+ [RW] + log_formatter
+ [RW] + log_level
+ [RW] + log_tags
+ [RW] + logger
+ [RW] + public_file_server
+ [RW] + railties_order
+ [RW] + rake_eager_load
+ [RW] + read_encrypted_secrets
+ [RW] + relative_url_root
+ [RW] + reload_classes_only_on_change
+ [RW] + require_master_key
+ [RW] + secret_key_base
+ [RW] + server_timing
+ [RW] + session_options
+ [RW] + ssl_options
+ [RW] + time_zone
+ [RW] + x
+ + + + +

Class Public methods

+ +
+

+ + new(*) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 28
+def initialize(*)
+  super
+  self.encoding                            = Encoding::UTF_8
+  @allow_concurrency                       = nil
+  @consider_all_requests_local             = false
+  @filter_parameters                       = []
+  @filter_redirect                         = []
+  @helpers_paths                           = []
+  if Rails.env.development?
+    @hosts = ActionDispatch::HostAuthorization::ALLOWED_HOSTS_IN_DEVELOPMENT +
+      ENV["RAILS_DEVELOPMENT_HOSTS"].to_s.split(",").map(&:strip)
+  else
+    @hosts = []
+  end
+  @host_authorization                      = {}
+  @public_file_server                      = ActiveSupport::OrderedOptions.new
+  @public_file_server.enabled              = true
+  @public_file_server.index_name           = "index"
+  @force_ssl                               = false
+  @ssl_options                             = {}
+  @session_store                           = nil
+  @time_zone                               = "UTC"
+  @beginning_of_week                       = :monday
+  @log_level                               = :debug
+  @generators                              = app_generators
+  @cache_store                             = [ :file_store, "#{root}/tmp/cache/" ]
+  @railties_order                          = [:all]
+  @relative_url_root                       = ENV["RAILS_RELATIVE_URL_ROOT"]
+  @reload_classes_only_on_change           = true
+  @file_watcher                            = ActiveSupport::FileUpdateChecker
+  @exceptions_app                          = nil
+  @autoflush_log                           = true
+  @log_formatter                           = ActiveSupport::Logger::SimpleFormatter.new
+  @eager_load                              = nil
+  @secret_key_base                         = nil
+  @api_only                                = false
+  @debug_exception_response_format         = nil
+  @x                                       = Custom.new
+  @enable_dependency_loading               = false
+  @read_encrypted_secrets                  = false
+  @content_security_policy                 = nil
+  @content_security_policy_report_only     = false
+  @content_security_policy_nonce_generator = nil
+  @content_security_policy_nonce_directives = nil
+  @require_master_key                      = false
+  @loaded_config_version                   = nil
+  @credentials                             = ActiveSupport::OrderedOptions.new
+  @credentials.content_path                = default_credentials_content_path
+  @credentials.key_path                    = default_credentials_key_path
+  @disable_sandbox                         = false
+  @add_autoload_paths_to_load_path         = true
+  @permissions_policy                      = nil
+  @rake_eager_load                         = false
+  @server_timing                           = false
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + annotations() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 414
+def annotations
+  Rails::SourceAnnotationExtractor::Annotation
+end
+
+
+ +
+ +
+

+ + api_only=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 275
+def api_only=(value)
+  @api_only = value
+  generators.api_only = value
+
+  @debug_exception_response_format ||= :api
+end
+
+
+ +
+ +
+

+ + colorize_logging() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 360
+def colorize_logging
+  ActiveSupport::LogSubscriber.colorize_logging
+end
+
+
+ +
+ +
+

+ + colorize_logging=(val) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 364
+def colorize_logging=(val)
+  ActiveSupport::LogSubscriber.colorize_logging = val
+  generators.colorize_logging = val
+end
+
+
+ +
+ +
+

+ + content_security_policy(&block) + +

+ + + + + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 419
+def content_security_policy(&block)
+  if block_given?
+    @content_security_policy = ActionDispatch::ContentSecurityPolicy.new(&block)
+  else
+    @content_security_policy
+  end
+end
+
+
+ +
+ +
+

+ + database_configuration() + +

+ + +
+

Loads and returns the entire raw configuration of database from values stored in config/database.yml.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 329
+def database_configuration
+  path = paths["config/database"].existent.first
+  yaml = Pathname.new(path) if path
+
+  config = if yaml&.exist?
+    loaded_yaml = ActiveSupport::ConfigurationFile.parse(yaml)
+    if (shared = loaded_yaml.delete("shared"))
+      loaded_yaml.each do |env, config|
+        if config.is_a?(Hash) && config.values.all?(Hash)
+          config.map do |name, sub_config|
+            sub_config.reverse_merge!(shared)
+          end
+        else
+          config.reverse_merge!(shared)
+        end
+      end
+    end
+    Hash.new(shared).merge(loaded_yaml)
+  elsif ENV["DATABASE_URL"]
+    # Value from ENV['DATABASE_URL'] is set to default database connection
+    # by Active Record.
+    {}
+  else
+    raise "Could not load database configuration. No such file - #{paths["config/database"].instance_variable_get(:@paths)}"
+  end
+
+  config
+rescue => e
+  raise e, "Cannot load database configuration:\n#{e.message}", e.backtrace
+end
+
+
+ +
+ +
+

+ + debug_exception_response_format() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 282
+def debug_exception_response_format
+  @debug_exception_response_format || :default
+end
+
+
+ +
+ +
+

+ + default_log_file() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 436
+def default_log_file
+  path = paths["log"].first
+  unless File.exist? File.dirname path
+    FileUtils.mkdir_p File.dirname path
+  end
+
+  f = File.open path, "a"
+  f.binmode
+  f.sync = autoflush_log # if true make sure every write flushes
+  f
+end
+
+
+ +
+ +
+

+ + encoding=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 267
+def encoding=(value)
+  @encoding = value
+  silence_warnings do
+    Encoding.default_external = value
+    Encoding.default_internal = value
+  end
+end
+
+
+ +
+ +
+

+ + load_defaults(target_version) + +

+ + +
+

Loads default configuration values for a target version. This includes defaults for versions prior to the target version. See the configuration guide for the default values associated with a particular version.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 88
+def load_defaults(target_version)
+  case target_version.to_s
+  when "5.0"
+    if respond_to?(:action_controller)
+      action_controller.per_form_csrf_tokens = true
+      action_controller.forgery_protection_origin_check = true
+      action_controller.urlsafe_csrf_tokens = false
+    end
+
+    ActiveSupport.to_time_preserves_timezone = true
+
+    if respond_to?(:active_record)
+      active_record.belongs_to_required_by_default = true
+    end
+
+    self.ssl_options = { hsts: { subdomains: true } }
+  when "5.1"
+    load_defaults "5.0"
+
+    if respond_to?(:assets)
+      assets.unknown_asset_fallback = false
+    end
+
+    if respond_to?(:action_view)
+      action_view.form_with_generates_remote_forms = true
+    end
+  when "5.2"
+    load_defaults "5.1"
+
+    if respond_to?(:active_record)
+      active_record.cache_versioning = true
+    end
+
+    if respond_to?(:action_dispatch)
+      action_dispatch.use_authenticated_cookie_encryption = true
+    end
+
+    if respond_to?(:active_support)
+      active_support.use_authenticated_message_encryption = true
+      active_support.hash_digest_class = OpenSSL::Digest::SHA1
+    end
+
+    if respond_to?(:action_controller)
+      action_controller.default_protect_from_forgery = true
+    end
+
+    if respond_to?(:action_view)
+      action_view.form_with_generates_ids = true
+    end
+  when "6.0"
+    load_defaults "5.2"
+
+    if respond_to?(:action_view)
+      action_view.default_enforce_utf8 = false
+    end
+
+    if respond_to?(:action_dispatch)
+      action_dispatch.use_cookies_with_metadata = true
+    end
+
+    if respond_to?(:action_mailer)
+      action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"
+    end
+
+    if respond_to?(:active_storage)
+      active_storage.queues.analysis = :active_storage_analysis
+      active_storage.queues.purge    = :active_storage_purge
+
+      active_storage.replace_on_assign_to_many = true
+    end
+
+    if respond_to?(:active_record)
+      active_record.collection_cache_versioning = true
+    end
+  when "6.1"
+    load_defaults "6.0"
+
+    if respond_to?(:active_record)
+      active_record.has_many_inversing = true
+      active_record.legacy_connection_handling = false
+    end
+
+    if respond_to?(:active_job)
+      active_job.retry_jitter = 0.15
+    end
+
+    if respond_to?(:action_dispatch)
+      action_dispatch.cookies_same_site_protection = :lax
+      action_dispatch.ssl_default_redirect_status = 308
+    end
+
+    if respond_to?(:action_controller)
+      action_controller.delete(:urlsafe_csrf_tokens)
+    end
+
+    if respond_to?(:action_view)
+      action_view.form_with_generates_remote_forms = false
+      action_view.preload_links_header = true
+    end
+
+    if respond_to?(:active_storage)
+      active_storage.track_variants = true
+
+      active_storage.queues.analysis = nil
+      active_storage.queues.purge = nil
+    end
+
+    if respond_to?(:action_mailbox)
+      action_mailbox.queues.incineration = nil
+      action_mailbox.queues.routing = nil
+    end
+
+    if respond_to?(:action_mailer)
+      action_mailer.deliver_later_queue_name = nil
+    end
+
+    ActiveSupport.utc_to_local_returns_utc_offset_times = true
+  when "7.0"
+    load_defaults "6.1"
+
+    if respond_to?(:action_dispatch)
+      action_dispatch.default_headers = {
+        "X-Frame-Options" => "SAMEORIGIN",
+        "X-XSS-Protection" => "0",
+        "X-Content-Type-Options" => "nosniff",
+        "X-Download-Options" => "noopen",
+        "X-Permitted-Cross-Domain-Policies" => "none",
+        "Referrer-Policy" => "strict-origin-when-cross-origin"
+      }
+      action_dispatch.return_only_request_media_type_on_content_type = false
+      action_dispatch.cookies_serializer = :json
+    end
+
+    if respond_to?(:action_view)
+      action_view.button_to_generates_button_tag = true
+      action_view.apply_stylesheet_media_default = false
+    end
+
+    if respond_to?(:active_support)
+      active_support.hash_digest_class = OpenSSL::Digest::SHA256
+      active_support.key_generator_hash_digest_class = OpenSSL::Digest::SHA256
+      active_support.remove_deprecated_time_with_zone_name = true
+      active_support.cache_format_version = 7.0
+      active_support.use_rfc4122_namespaced_uuids = true
+      active_support.executor_around_test_case = true
+      active_support.disable_to_s_conversion = true
+    end
+
+    if respond_to?(:action_mailer)
+      action_mailer.smtp_timeout = 5
+    end
+
+    if respond_to?(:active_storage)
+      active_storage.video_preview_arguments =
+        "-vf 'select=eq(n\\,0)+eq(key\\,1)+gt(scene\\,0.015),loop=loop=-1:size=2,trim=start_frame=1'" \
+        " -frames:v 1 -f image2"
+
+      active_storage.variant_processor = :vips
+      active_storage.multiple_file_field_include_hidden = true
+    end
+
+    if respond_to?(:active_record)
+      active_record.verify_foreign_keys_for_fixtures = true
+      active_record.partial_inserts = false
+      active_record.automatic_scope_inversing = true
+    end
+
+    if respond_to?(:action_controller)
+      action_controller.raise_on_open_redirects = true
+
+      action_controller.wrap_parameters_by_default = true
+    end
+  else
+    raise "Unknown version #{target_version.to_s.inspect}"
+  end
+
+  @loaded_config_version = target_version
+end
+
+
+ +
+ +
+

+ + paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 288
+def paths
+  @paths ||= begin
+    paths = super
+    paths.add "config/database",    with: "config/database.yml"
+    paths.add "config/secrets",     with: "config", glob: "secrets.yml{,.enc}"
+    paths.add "config/environment", with: "config/environment.rb"
+    paths.add "lib/templates"
+    paths.add "log",                with: "log/#{Rails.env}.log"
+    paths.add "public"
+    paths.add "public/javascripts"
+    paths.add "public/stylesheets"
+    paths.add "tmp"
+    paths
+  end
+end
+
+
+ +
+ +
+

+ + permissions_policy(&block) + +

+ + +
+

Configures the ActionDispatch::PermissionsPolicy.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 428
+def permissions_policy(&block)
+  if block_given?
+    @permissions_policy = ActionDispatch::PermissionsPolicy.new(&block)
+  else
+    @permissions_policy
+  end
+end
+
+
+ +
+ +
+

+ + session_store(new_session_store = nil, **options) + +

+ + +
+

Specifies what class to use to store the session. Possible values are :cookie_store, :mem_cache_store, a custom store, or :disabled. :disabled tells Rails not to deal with sessions.

+ +

Additional options will be set as session_options:

+ +
config.session_store :cookie_store, key: "_your_app_session"
+config.session_options # => {key: "_your_app_session"}
+
+ +

If a custom store is specified as a symbol, it will be resolved to the ActionDispatch::Session namespace:

+ +
# use ActionDispatch::Session::MyCustomStore as the session store
+config.session_store :my_custom_store
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/configuration.rb, line 383
+def session_store(new_session_store = nil, **options)
+  if new_session_store
+    if new_session_store == :active_record_store
+      begin
+        ActionDispatch::Session::ActiveRecordStore
+      rescue NameError
+        raise "`ActiveRecord::SessionStore` is extracted out of Rails into a gem. " \
+          "Please add `activerecord-session_store` to your Gemfile to use it."
+      end
+    end
+
+    @session_store = new_session_store
+    @session_options = options || {}
+  else
+    case @session_store
+    when :disabled
+      nil
+    when :active_record_store
+      ActionDispatch::Session::ActiveRecordStore
+    when Symbol
+      ActionDispatch::Session.const_get(@session_store.to_s.camelize)
+    else
+      @session_store
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application/DefaultMiddlewareStack.html b/src/7.0/classes/Rails/Application/DefaultMiddlewareStack.html new file mode 100644 index 0000000000..0f1d710c2c --- /dev/null +++ b/src/7.0/classes/Rails/Application/DefaultMiddlewareStack.html @@ -0,0 +1,265 @@ +--- +title: Rails::Application::DefaultMiddlewareStack +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + app
+ [R] + config
+ [R] + paths
+ + + + +

Class Public methods

+ +
+

+ + new(app, config, paths) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/default_middleware_stack.rb, line 8
+def initialize(app, config, paths)
+  @app = app
+  @config = config
+  @paths = paths
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + build_stack() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/default_middleware_stack.rb, line 14
+def build_stack
+  ActionDispatch::MiddlewareStack.new do |middleware|
+    middleware.use ::ActionDispatch::HostAuthorization, config.hosts, **config.host_authorization
+
+    if config.force_ssl
+      middleware.use ::ActionDispatch::SSL, **config.ssl_options,
+        ssl_default_redirect_status: config.action_dispatch.ssl_default_redirect_status
+    end
+
+    middleware.use ::Rack::Sendfile, config.action_dispatch.x_sendfile_header
+
+    if config.public_file_server.enabled
+      headers = config.public_file_server.headers || {}
+
+      middleware.use ::ActionDispatch::Static, paths["public"].first, index: config.public_file_server.index_name, headers: headers
+    end
+
+    if rack_cache = load_rack_cache
+      require "action_dispatch/http/rack_cache"
+      middleware.use ::Rack::Cache, rack_cache
+    end
+
+    if config.allow_concurrency == false
+      # User has explicitly opted out of concurrent request
+      # handling: presumably their code is not threadsafe
+
+      middleware.use ::Rack::Lock
+    end
+
+    middleware.use ::ActionDispatch::Executor, app.executor
+
+    middleware.use ::ActionDispatch::ServerTiming if config.server_timing
+    middleware.use ::Rack::Runtime
+    middleware.use ::Rack::MethodOverride unless config.api_only
+    middleware.use ::ActionDispatch::RequestId, header: config.action_dispatch.request_id_header
+    middleware.use ::ActionDispatch::RemoteIp, config.action_dispatch.ip_spoofing_check, config.action_dispatch.trusted_proxies
+
+    middleware.use ::Rails::Rack::Logger, config.log_tags
+    middleware.use ::ActionDispatch::ShowExceptions, show_exceptions_app
+    middleware.use ::ActionDispatch::DebugExceptions, app, config.debug_exception_response_format
+
+    if config.consider_all_requests_local
+      middleware.use ::ActionDispatch::ActionableExceptions
+    end
+
+    unless config.cache_classes
+      middleware.use ::ActionDispatch::Reloader, app.reloader
+    end
+
+    middleware.use ::ActionDispatch::Callbacks
+    middleware.use ::ActionDispatch::Cookies unless config.api_only
+
+    if !config.api_only && config.session_store
+      if config.force_ssl && config.ssl_options.fetch(:secure_cookies, true) && !config.session_options.key?(:secure)
+        config.session_options[:secure] = true
+      end
+      middleware.use config.session_store, config.session_options
+    end
+
+    unless config.api_only
+      middleware.use ::ActionDispatch::Flash
+      middleware.use ::ActionDispatch::ContentSecurityPolicy::Middleware
+      middleware.use ::ActionDispatch::PermissionsPolicy::Middleware
+    end
+
+    middleware.use ::Rack::Head
+    middleware.use ::Rack::ConditionalGet
+    middleware.use ::Rack::ETag, "no-cache"
+
+    middleware.use ::Rack::TempfileReaper unless config.api_only
+
+    if config.respond_to?(:active_record)
+      if selector_options = config.active_record.database_selector
+        resolver = config.active_record.database_resolver
+        context = config.active_record.database_resolver_context
+
+        middleware.use ::ActiveRecord::Middleware::DatabaseSelector, resolver, context, selector_options
+      end
+
+      if shard_resolver = config.active_record.shard_resolver
+        options = config.active_record.shard_selector || {}
+
+        middleware.use ::ActiveRecord::Middleware::ShardSelector, shard_resolver, options
+      end
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application/Finisher.html b/src/7.0/classes/Rails/Application/Finisher.html new file mode 100644 index 0000000000..08501aecd1 --- /dev/null +++ b/src/7.0/classes/Rails/Application/Finisher.html @@ -0,0 +1,68 @@ +--- +title: Rails::Application::Finisher +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Application/RoutesReloader.html b/src/7.0/classes/Rails/Application/RoutesReloader.html new file mode 100644 index 0000000000..122f7024db --- /dev/null +++ b/src/7.0/classes/Rails/Application/RoutesReloader.html @@ -0,0 +1,209 @@ +--- +title: Rails::Application::RoutesReloader +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [RW] + eager_load
+ [R] + external_routes
+ [R] + paths
+ [R] + route_sets
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/routes_reloader.rb, line 15
+def initialize
+  @paths      = []
+  @route_sets = []
+  @external_routes = []
+  @eager_load = false
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + reload!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/application/routes_reloader.rb, line 22
+def reload!
+  clear!
+  load_paths
+  finalize!
+  route_sets.each(&:eager_load!) if eager_load
+ensure
+  revert
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/BacktraceCleaner.html b/src/7.0/classes/Rails/BacktraceCleaner.html new file mode 100644 index 0000000000..ad61023600 --- /dev/null +++ b/src/7.0/classes/Rails/BacktraceCleaner.html @@ -0,0 +1,149 @@ +--- +title: Rails::BacktraceCleaner +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
APP_DIRS_PATTERN=/\A(?:\.\/)?(?:app|config|lib|test|\(\w*\))/
 
RENDER_TEMPLATE_PATTERN=/:in `.*_\w+_{2,3}\d+_\d+'/
 
+ + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/backtrace_cleaner.rb, line 11
+def initialize
+  super
+  @root = "#{Rails.root}/"
+  add_filter do |line|
+    line.start_with?(@root) ? line.from(@root.size) : line
+  end
+  add_filter do |line|
+    if RENDER_TEMPLATE_PATTERN.match?(line)
+      line.sub(RENDER_TEMPLATE_PATTERN, "")
+    else
+      line
+    end
+  end
+  add_silencer { |line| !APP_DIRS_PATTERN.match?(line) }
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command.html b/src/7.0/classes/Rails/Command.html new file mode 100644 index 0000000000..5bbaadba8f --- /dev/null +++ b/src/7.0/classes/Rails/Command.html @@ -0,0 +1,385 @@ +--- +title: Rails::Command +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
HELP_MAPPINGS=%w(-h -? --help)
 
+ + + + + + +

Class Public methods

+ +
+

+ + invoke(full_namespace, args = [], **config) + +

+ + +
+

Receives a namespace, arguments, and the behavior to invoke the command.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command.rb, line 30
+def invoke(full_namespace, args = [], **config)
+  namespace = full_namespace = full_namespace.to_s
+
+  if char = namespace =~ /:(\w+)$/
+    command_name, namespace = $1, namespace.slice(0, char)
+  else
+    command_name = namespace
+  end
+
+  command_name, namespace = "help", "help" if command_name.blank? || HELP_MAPPINGS.include?(command_name)
+  command_name, namespace, args = "application", "application", ["--help"] if rails_new_with_no_path?(args)
+  command_name, namespace = "version", "version" if %w( -v --version ).include?(command_name)
+
+  original_argv = ARGV.dup
+  ARGV.replace(args)
+
+  command = find_by_namespace(namespace, command_name)
+  if command && command.all_commands[command_name]
+    command.perform(command_name, args, config)
+  else
+    args = ["--describe", full_namespace] if HELP_MAPPINGS.include?(args[0])
+    find_by_namespace("rake").perform(full_namespace, args, config)
+  end
+ensure
+  ARGV.replace(original_argv)
+end
+
+
+ +
+ +
+

+ + root() + +

+ + +
+

Returns the root of the Rails engine or app running the command.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command.rb, line 80
+def root
+  if defined?(ENGINE_ROOT)
+    Pathname.new(ENGINE_ROOT)
+  elsif defined?(APP_PATH)
+    Pathname.new(File.expand_path("../..", APP_PATH))
+  end
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + command_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command.rb, line 108
+def command_type # :doc:
+  @command_type ||= "command"
+end
+
+
+ +
+ +
+

+ + file_lookup_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command.rb, line 116
+def file_lookup_paths # :doc:
+  @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_command.rb" ]
+end
+
+
+ +
+ +
+

+ + lookup_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command.rb, line 112
+def lookup_paths # :doc:
+  @lookup_paths ||= %w( rails/commands commands )
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Actions.html b/src/7.0/classes/Rails/Command/Actions.html new file mode 100644 index 0000000000..7824aeabc1 --- /dev/null +++ b/src/7.0/classes/Rails/Command/Actions.html @@ -0,0 +1,306 @@ +--- +title: Rails::Command::Actions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + load_generators() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 38
+def load_generators
+  engine = ::Rails::Engine.find(ENGINE_ROOT)
+  Rails::Generators.namespace = engine.railtie_namespace
+  engine.load_generators
+end
+
+
+ +
+ +
+

+ + load_tasks() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 33
+def load_tasks
+  Rake.application.init("rails")
+  Rake.application.load_rakefile
+end
+
+
+ +
+ +
+

+ + require_application!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 18
+def require_application!
+  require ENGINE_PATH if defined?(ENGINE_PATH)
+
+  if defined?(APP_PATH)
+    require APP_PATH
+  end
+end
+
+
+ +
+ +
+

+ + require_application_and_environment!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 13
+def require_application_and_environment!
+  require_application!
+  require_environment!
+end
+
+
+ +
+ +
+

+ + require_environment!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 26
+def require_environment!
+  if defined?(APP_PATH)
+    Rails.application.require_environment!
+  end
+end
+
+
+ +
+ +
+

+ + set_application_directory!() + +

+ + +
+

Change to the application’s path if there is no config.ru file in current directory. This allows us to run rails server from other directories, but still get the main config.ru and properly set the tmp directory.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/actions.rb, line 9
+def set_application_directory!
+  Dir.chdir(File.expand_path("../..", APP_PATH)) unless File.exist?(File.expand_path("config.ru"))
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Base.html b/src/7.0/classes/Rails/Command/Base.html new file mode 100644 index 0000000000..7b2c55f58d --- /dev/null +++ b/src/7.0/classes/Rails/Command/Base.html @@ -0,0 +1,584 @@ +--- +title: Rails::Command::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + banner(*) + +

+ + +
+

Use Rails’ default banner.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 99
+def banner(*)
+  "#{executable} #{arguments.map(&:usage).join(' ')} [options]".squish
+end
+
+
+ +
+ +
+

+ + base_name() + +

+ + +
+

Sets the base_name taking into account the current class namespace.

+ +
Rails::Command::TestCommand.base_name # => 'rails'
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 106
+def base_name
+  @base_name ||= if base = name.to_s.split("::").first
+    base.underscore
+  end
+end
+
+
+ +
+ +
+

+ + command_name() + +

+ + +
+

Return command name without namespaces.

+ +
Rails::Command::TestCommand.command_name # => 'test'
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 115
+def command_name
+  @command_name ||= if command = name.to_s.split("::").last
+    command.chomp!("Command")
+    command.underscore
+  end
+end
+
+
+ +
+ +
+

+ + default_command_root() + +

+ + +
+

Default file root to place extra files a command might need, placed one folder above the command file.

+ +

For a Rails::Command::TestCommand placed in rails/command/test_command.rb would return rails/test.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 135
+def default_command_root
+  path = File.expand_path(relative_command_path, __dir__)
+  path if File.exist?(path)
+end
+
+
+ +
+ +
+

+ + desc(usage = nil, description = nil, options = {}) + +

+ + +
+

Tries to get the description from a USAGE file one folder above the command root.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 49
+def desc(usage = nil, description = nil, options = {})
+  if usage
+    super
+  else
+    @desc ||= ERB.new(File.read(usage_path), trim_mode: "-").result(binding) if usage_path
+  end
+end
+
+
+ +
+ +
+

+ + engine?() + +

+ + +
+

Returns true when the app is a Rails engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 43
+def engine?
+  defined?(ENGINE_ROOT)
+end
+
+
+ +
+ +
+

+ + executable() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 94
+def executable
+  "rails #{command_name}"
+end
+
+
+ +
+ +
+

+ + hide_command!() + +

+ + +
+

Convenience method to hide this command from the available ones when running rails command.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 70
+def hide_command!
+  Rails::Command.hidden_commands << self
+end
+
+
+ +
+ +
+

+ + namespace(name = nil) + +

+ + +
+

Convenience method to get the namespace from the class name. It’s the same as Thor default except that the Command at the end of the class is removed.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 60
+def namespace(name = nil)
+  if name
+    super
+  else
+    @namespace ||= super.chomp("_command").sub(/:command:/, ":")
+  end
+end
+
+
+ +
+ +
+

+ + printing_commands() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 90
+def printing_commands
+  namespaced_commands
+end
+
+
+ +
+ +
+

+ + usage_path() + +

+ + +
+

Path to lookup a USAGE description in a file.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 123
+def usage_path
+  if default_command_root
+    path = File.join(default_command_root, "USAGE")
+    path if File.exist?(path)
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + help() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/command/base.rb, line 174
+def help
+  if command_name = self.class.command_name
+    self.class.command_help(shell, command_name)
+  else
+    super
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Db.html b/src/7.0/classes/Rails/Command/Db.html new file mode 100644 index 0000000000..0e00212c8f --- /dev/null +++ b/src/7.0/classes/Rails/Command/Db.html @@ -0,0 +1,67 @@ +--- +title: Rails::Command::Db +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Db/System.html b/src/7.0/classes/Rails/Command/Db/System.html new file mode 100644 index 0000000000..90dbe69986 --- /dev/null +++ b/src/7.0/classes/Rails/Command/Db/System.html @@ -0,0 +1,54 @@ +--- +title: Rails::Command::Db::System +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Helpers.html b/src/7.0/classes/Rails/Command/Helpers.html new file mode 100644 index 0000000000..57732f6430 --- /dev/null +++ b/src/7.0/classes/Rails/Command/Helpers.html @@ -0,0 +1,67 @@ +--- +title: Rails::Command::Helpers +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Command/Helpers/Editor.html b/src/7.0/classes/Rails/Command/Helpers/Editor.html new file mode 100644 index 0000000000..49ca7b5b11 --- /dev/null +++ b/src/7.0/classes/Rails/Command/Helpers/Editor.html @@ -0,0 +1,54 @@ +--- +title: Rails::Command::Helpers::Editor +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Conductor.html b/src/7.0/classes/Rails/Conductor.html new file mode 100644 index 0000000000..deffd8b1fc --- /dev/null +++ b/src/7.0/classes/Rails/Conductor.html @@ -0,0 +1,60 @@ +--- +title: Rails::Conductor +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Configuration.html b/src/7.0/classes/Rails/Configuration.html new file mode 100644 index 0000000000..a8a07a116e --- /dev/null +++ b/src/7.0/classes/Rails/Configuration.html @@ -0,0 +1,71 @@ +--- +title: Rails::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Configuration/MiddlewareStackProxy.html b/src/7.0/classes/Rails/Configuration/MiddlewareStackProxy.html new file mode 100644 index 0000000000..085095ea84 --- /dev/null +++ b/src/7.0/classes/Rails/Configuration/MiddlewareStackProxy.html @@ -0,0 +1,550 @@ +--- +title: Rails::Configuration::MiddlewareStackProxy +layout: default +--- +
+ +
+
+ +
+ +

MiddlewareStackProxy is a proxy for the Rails middleware stack that allows you to configure middlewares in your application. It works basically as a command recorder, saving each command to be applied after initialization over the default middleware stack, so you can add, swap, or remove any middleware in Rails.

+ +

You can add your own middlewares by using the config.middleware.use method:

+ +
config.middleware.use Magical::Unicorns
+
+ +

This will put the Magical::Unicorns middleware on the end of the stack. You can use insert_before if you wish to add a middleware before another:

+ +
config.middleware.insert_before Rack::Head, Magical::Unicorns
+
+ +

There’s also insert_after which will insert a middleware after another:

+ +
config.middleware.insert_after Rack::Head, Magical::Unicorns
+
+ +

Middlewares can also be completely swapped out and replaced with others:

+ +
config.middleware.swap ActionDispatch::Flash, Magical::Unicorns
+
+ +

Middlewares can be moved from one place to another:

+ +
config.middleware.move_before ActionDispatch::Flash, Magical::Unicorns
+
+ +

This will move the Magical::Unicorns middleware before the ActionDispatch::Flash. You can also move it after:

+ +
config.middleware.move_after ActionDispatch::Flash, Magical::Unicorns
+
+ +

And finally they can also be removed from the stack completely:

+ +
config.middleware.delete ActionDispatch::Flash
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + delete_operations
+ [R] + operations
+ + + + +

Class Public methods

+ +
+

+ + new(operations = [], delete_operations = []) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 47
+def initialize(operations = [], delete_operations = [])
+  @operations = operations
+  @delete_operations = delete_operations
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + delete(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 70
+def delete(...)
+  @delete_operations << -> middleware { middleware.delete(...) }
+end
+
+
+ +
+ +
+

+ + insert(...) + +

+ + +
+ +
+ + + + + +
+ Alias for: insert_before +
+ + + +
+ +
+

+ + insert_after(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 58
+def insert_after(...)
+  @operations << -> middleware { middleware.insert_after(...) }
+end
+
+
+ +
+ +
+

+ + insert_before(...) + +

+ + +
+ +
+ + + +
+ Also aliased as: insert +
+ + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 52
+def insert_before(...)
+  @operations << -> middleware { middleware.insert_before(...) }
+end
+
+
+ +
+ +
+

+ + move(...) + +

+ + +
+ +
+ + + + + +
+ Alias for: move_before +
+ + + +
+ +
+

+ + move_after(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 80
+def move_after(...)
+  @delete_operations << -> middleware { middleware.move_after(...) }
+end
+
+
+ +
+ +
+

+ + move_before(...) + +

+ + +
+ +
+ + + +
+ Also aliased as: move +
+ + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 74
+def move_before(...)
+  @delete_operations << -> middleware { middleware.move_before(...) }
+end
+
+
+ +
+ +
+

+ + swap(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 62
+def swap(...)
+  @operations << -> middleware { middleware.swap(...) }
+end
+
+
+ +
+ +
+

+ + unshift(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 84
+def unshift(...)
+  @operations << -> middleware { middleware.unshift(...) }
+end
+
+
+ +
+ +
+

+ + use(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/configuration.rb, line 66
+def use(...)
+  @operations << -> middleware { middleware.use(...) }
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Console.html b/src/7.0/classes/Rails/Console.html new file mode 100644 index 0000000000..08c76d661a --- /dev/null +++ b/src/7.0/classes/Rails/Console.html @@ -0,0 +1,412 @@ +--- +title: Rails::Console +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + app
+ [R] + console
+ [R] + options
+ + + + +

Class Public methods

+ +
+

+ + new(app, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 24
+def initialize(app, options = {})
+  @app     = app
+  @options = options
+
+  app.sandbox = sandbox?
+
+  if sandbox? && app.config.disable_sandbox
+    puts "Error: Unable to start console in sandbox mode as sandbox mode is disabled (config.disable_sandbox is true)."
+    exit 1
+  end
+
+  app.load_console
+
+  @console = app.config.console || IRB
+
+  if @console == IRB
+    IRB::WorkSpace.prepend(BacktraceCleaner)
+
+    if Rails.env.production?
+      ENV["IRB_USE_AUTOCOMPLETE"] ||= "false"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + start(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 18
+def self.start(*args)
+  new(*args).start
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + environment() + +

+ + +
+ +
+ + + +
+ Also aliased as: environment? +
+ + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 52
+def environment
+  options[:environment]
+end
+
+
+ +
+ +
+

+ + environment?() + +

+ + +
+ +
+ + + + + +
+ Alias for: environment +
+ + + +
+ +
+

+ + sandbox?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 48
+def sandbox?
+  options[:sandbox]
+end
+
+
+ +
+ +
+

+ + set_environment!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 57
+def set_environment!
+  Rails.env = environment
+end
+
+
+ +
+ +
+

+ + start() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 61
+def start
+  set_environment! if environment?
+
+  if sandbox?
+    puts "Loading #{Rails.env} environment in sandbox (Rails #{Rails.version})"
+    puts "Any modifications you make will be rolled back on exit"
+  else
+    puts "Loading #{Rails.env} environment (Rails #{Rails.version})"
+  end
+
+  if defined?(console::ExtendCommandBundle)
+    console::ExtendCommandBundle.include(Rails::ConsoleMethods)
+  end
+  console.start
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Console/BacktraceCleaner.html b/src/7.0/classes/Rails/Console/BacktraceCleaner.html new file mode 100644 index 0000000000..16411eeb50 --- /dev/null +++ b/src/7.0/classes/Rails/Console/BacktraceCleaner.html @@ -0,0 +1,103 @@ +--- +title: Rails::Console::BacktraceCleaner +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + filter_backtrace(bt) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/console/console_command.rb, line 11
+def filter_backtrace(bt)
+  if result = super
+    Rails.backtrace_cleaner.filter([result]).first
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/ConsoleMethods.html b/src/7.0/classes/Rails/ConsoleMethods.html new file mode 100644 index 0000000000..853e20fabf --- /dev/null +++ b/src/7.0/classes/Rails/ConsoleMethods.html @@ -0,0 +1,276 @@ +--- +title: Rails::ConsoleMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + app(create = false) + +

+ + +
+

reference the global “app” instance, created on demand. To recreate the instance, pass a non-false value as the parameter.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/console/app.rb, line 10
+def app(create = false)
+  @app_integration_instance = nil if create
+  @app_integration_instance ||= new_session do |sess|
+    sess.host! "www.example.com"
+  end
+end
+
+
+ +
+ +
+

+ + controller() + +

+ + +
+

Gets a new instance of a controller object.

+ +

This method assumes an ApplicationController exists, and that it extends ActionController::Base.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/console/helpers.rb, line 15
+def controller
+  @controller ||= ApplicationController.new
+end
+
+
+ +
+ +
+

+ + helper() + +

+ + +
+

Gets the helper methods available to the controller.

+ +

This method assumes an ApplicationController exists, and that it extends ActionController::Base.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/console/helpers.rb, line 8
+def helper
+  ApplicationController.helpers
+end
+
+
+ +
+ +
+

+ + new_session() + +

+ + +
+

create a new session. If a block is given, the new session will be yielded to the block before being returned.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/console/app.rb, line 19
+def new_session
+  app = Rails.application
+  session = ActionDispatch::Integration::Session.new(app)
+  yield session if block_given?
+
+  # This makes app.url_for and app.foo_path available in the console
+  session.extend(app.routes.url_helpers)
+  session.extend(app.routes.mounted_helpers)
+
+  session
+end
+
+
+ +
+ +
+

+ + reload!(print = true) + +

+ + +
+

reloads the environment

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/console/app.rb, line 32
+def reload!(print = true)
+  puts "Reloading..." if print
+  Rails.application.reloader.reload!
+  true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/DBConsole.html b/src/7.0/classes/Rails/DBConsole.html new file mode 100644 index 0000000000..75c97001de --- /dev/null +++ b/src/7.0/classes/Rails/DBConsole.html @@ -0,0 +1,504 @@ +--- +title: Rails::DBConsole +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 13
+def initialize(options = {})
+  @options = options
+end
+
+
+ +
+ +
+

+ + start(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 9
+def self.start(*args)
+  new(*args).start
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + database() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 121
+def database
+  @options[:database]
+end
+
+
+ +
+ +
+

+ + db_config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 97
+def db_config
+  return @db_config if defined?(@db_config)
+
+  # If the user provided a database, use that. Otherwise find
+  # the first config in the database.yml
+  if database
+    @db_config = configurations.configs_for(env_name: environment, name: database, include_hidden: true)
+  else
+    @db_config = configurations.find_db_config(environment)
+  end
+
+  unless @db_config
+    missing_db = database ? "'#{database}' database is not" : "No databases are"
+    raise ActiveRecord::AdapterNotSpecified,
+      "#{missing_db} configured for '#{environment}'. Available configuration: #{configurations.inspect}"
+  end
+
+  @db_config
+end
+
+
+ +
+ +
+

+ + environment() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 117
+def environment
+  Rails.respond_to?(:env) ? Rails.env : Rails::Command.environment
+end
+
+
+ +
+ +
+

+ + start() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 17
+def start
+  ENV["RAILS_ENV"] ||= @options[:environment] || environment
+  config = db_config.configuration_hash
+
+  case db_config.adapter
+  when /^(jdbc)?mysql/
+    args = {
+      host: "--host",
+      port: "--port",
+      socket: "--socket",
+      username: "--user",
+      encoding: "--default-character-set",
+      sslca: "--ssl-ca",
+      sslcert: "--ssl-cert",
+      sslcapath: "--ssl-capath",
+      sslcipher: "--ssl-cipher",
+      sslkey: "--ssl-key"
+    }.filter_map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }
+
+    if config[:password] && @options[:include_password]
+      args << "--password=#{config[:password]}"
+    elsif config[:password] && !config[:password].to_s.empty?
+      args << "-p"
+    end
+
+    args << db_config.database
+
+    find_cmd_and_exec(["mysql", "mysql5"], *args)
+
+  when /^postgres|^postgis/
+    ENV["PGUSER"]         = config[:username] if config[:username]
+    ENV["PGHOST"]         = config[:host] if config[:host]
+    ENV["PGPORT"]         = config[:port].to_s if config[:port]
+    ENV["PGPASSWORD"]     = config[:password].to_s if config[:password] && @options[:include_password]
+    ENV["PGSSLMODE"]      = config[:sslmode].to_s if config[:sslmode]
+    ENV["PGSSLCERT"]      = config[:sslcert].to_s if config[:sslcert]
+    ENV["PGSSLKEY"]       = config[:sslkey].to_s if config[:sslkey]
+    ENV["PGSSLROOTCERT"]  = config[:sslrootcert].to_s if config[:sslrootcert]
+    find_cmd_and_exec("psql", db_config.database)
+
+  when "sqlite3"
+    args = []
+
+    args << "-#{@options[:mode]}" if @options[:mode]
+    args << "-header" if @options[:header]
+    args << File.expand_path(db_config.database, Rails.respond_to?(:root) ? Rails.root : nil)
+
+    find_cmd_and_exec("sqlite3", *args)
+
+  when "oracle", "oracle_enhanced"
+    logon = ""
+
+    if config[:username]
+      logon = config[:username].dup
+      logon << "/#{config[:password]}" if config[:password] && @options[:include_password]
+      logon << "@#{db_config.database}" if db_config.database
+    end
+
+    find_cmd_and_exec("sqlplus", logon)
+
+  when "sqlserver"
+    args = []
+
+    args += ["-d", "#{db_config.database}"] if db_config.database
+    args += ["-U", "#{config[:username]}"] if config[:username]
+    args += ["-P", "#{config[:password]}"] if config[:password]
+
+    if config[:host]
+      host_arg = +"tcp:#{config[:host]}"
+      host_arg << ",#{config[:port]}" if config[:port]
+      args += ["-S", host_arg]
+    end
+
+    find_cmd_and_exec("sqlcmd", *args)
+
+  else
+    abort "Unknown command-line client for #{db_config.database}."
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + configurations() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 126
+def configurations # :doc:
+  require APP_PATH
+  ActiveRecord::Base.configurations = Rails.application.config.database_configuration
+  ActiveRecord::Base.configurations
+end
+
+
+ +
+ +
+

+ + find_cmd_and_exec(commands, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/dbconsole/dbconsole_command.rb, line 132
+def find_cmd_and_exec(commands, *args) # :doc:
+  commands = Array(commands)
+
+  dirs_on_path = ENV["PATH"].to_s.split(File::PATH_SEPARATOR)
+  unless (ext = RbConfig::CONFIG["EXEEXT"]).empty?
+    commands = commands.map { |cmd| "#{cmd}#{ext}" }
+  end
+
+  full_path_command = nil
+  found = commands.detect do |cmd|
+    dirs_on_path.detect do |path|
+      full_path_command = File.join(path, cmd)
+      begin
+        stat = File.stat(full_path_command)
+      rescue SystemCallError
+      else
+        stat.file? && stat.executable?
+      end
+    end
+  end
+
+  if found
+    exec full_path_command, *args
+  else
+    abort("Couldn't find database client: #{commands.join(', ')}. Check your $PATH and try again.")
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Engine.html b/src/7.0/classes/Rails/Engine.html new file mode 100644 index 0000000000..d1cf5f1f0a --- /dev/null +++ b/src/7.0/classes/Rails/Engine.html @@ -0,0 +1,1423 @@ +--- +title: Rails::Engine +layout: default +--- +
+ +
+
+ +
+ +

Rails::Engine allows you to wrap a specific Rails application or subset of functionality and share it with other applications or within a larger packaged application. Every Rails::Application is just an engine, which allows for simple feature and application sharing.

+ +

Any Rails::Engine is also a Rails::Railtie, so the same methods (like rake_tasks and generators) and configuration options that are available in railties can also be used in engines.

+ +

Creating an Engine

+ +

If you want a gem to behave as an engine, you have to specify an Engine for it somewhere inside your plugin’s lib folder (similar to how we specify a Railtie):

+ +
# lib/my_engine.rb
+module MyEngine
+  class Engine < Rails::Engine
+  end
+end
+
+ +

Then ensure that this file is loaded at the top of your config/application.rb (or in your Gemfile), and it will automatically load models, controllers, and helpers inside app, load routes at config/routes.rb, load locales at config/locales/*/, and load tasks at lib/tasks/*/.

+ +

Configuration

+ +

Like railties, engines can access a config object which contains configuration shared by all railties and the application. Additionally, each engine can access autoload_paths, eager_load_paths and autoload_once_paths settings which are scoped to that engine.

+ +
class MyEngine < Rails::Engine
+  # Add a load path for this specific Engine
+  config.autoload_paths << File.expand_path("lib/some/path", __dir__)
+
+  initializer "my_engine.add_middleware" do |app|
+    app.middleware.use MyEngine::Middleware
+  end
+end
+
+ +

Generators

+ +

You can set up generators for engines with config.generators method:

+ +
class MyEngine < Rails::Engine
+  config.generators do |g|
+    g.orm             :active_record
+    g.template_engine :erb
+    g.test_framework  :test_unit
+  end
+end
+
+ +

You can also set generators for an application by using config.app_generators:

+ +
class MyEngine < Rails::Engine
+  # note that you can also pass block to app_generators in the same way you
+  # can pass it to generators method
+  config.app_generators.orm :datamapper
+end
+
+ +

Paths

+ +

Applications and engines have flexible path configuration, meaning that you are not required to place your controllers at app/controllers, but in any place which you find convenient.

+ +

For example, let’s suppose you want to place your controllers in lib/controllers. You can set that as an option:

+ +
class MyEngine < Rails::Engine
+  paths["app/controllers"] = "lib/controllers"
+end
+
+ +

You can also have your controllers loaded from both app/controllers and lib/controllers:

+ +
class MyEngine < Rails::Engine
+  paths["app/controllers"] << "lib/controllers"
+end
+
+ +

The available paths in an engine are:

+ +
class MyEngine < Rails::Engine
+  paths["app"]                 # => ["app"]
+  paths["app/controllers"]     # => ["app/controllers"]
+  paths["app/helpers"]         # => ["app/helpers"]
+  paths["app/models"]          # => ["app/models"]
+  paths["app/views"]           # => ["app/views"]
+  paths["lib"]                 # => ["lib"]
+  paths["lib/tasks"]           # => ["lib/tasks"]
+  paths["config"]              # => ["config"]
+  paths["config/initializers"] # => ["config/initializers"]
+  paths["config/locales"]      # => ["config/locales"]
+  paths["config/routes.rb"]    # => ["config/routes.rb"]
+end
+
+ +

The Application class adds a couple more paths to this set. And as in your Application, all folders under app are automatically added to the load path. If you have an app/services folder for example, it will be added by default.

+ +

Endpoint

+ +

An engine can also be a Rack application. It can be useful if you have a Rack application that you would like to provide with some of the Engine‘s features.

+ +

To do that, use the endpoint method:

+ +
module MyEngine
+  class Engine < Rails::Engine
+    endpoint MyRackApplication
+  end
+end
+
+ +

Now you can mount your engine in application’s routes:

+ +
Rails.application.routes.draw do
+  mount MyEngine::Engine => "/engine"
+end
+
+ +

Middleware stack

+ +

As an engine can now be a Rack endpoint, it can also have a middleware stack. The usage is exactly the same as in Application:

+ +
module MyEngine
+  class Engine < Rails::Engine
+    middleware.use SomeMiddleware
+  end
+end
+
+ +

Routes

+ +

If you don’t specify an endpoint, routes will be used as the default endpoint. You can use them just like you use an application’s routes:

+ +
# ENGINE/config/routes.rb
+MyEngine::Engine.routes.draw do
+  get "/" => "posts#index"
+end
+
+ +

Mount priority

+ +

Note that now there can be more than one router in your application, and it’s better to avoid passing requests through many routers. Consider this situation:

+ +
Rails.application.routes.draw do
+  mount MyEngine::Engine => "/blog"
+  get "/blog/omg" => "main#omg"
+end
+
+ +

MyEngine is mounted at /blog, and /blog/omg points to application’s controller. In such a situation, requests to /blog/omg will go through MyEngine, and if there is no such route in Engine‘s routes, it will be dispatched to main#omg. It’s much better to swap that:

+ +
Rails.application.routes.draw do
+  get "/blog/omg" => "main#omg"
+  mount MyEngine::Engine => "/blog"
+end
+
+ +

Now, Engine will get only requests that were not handled by Application.

+ +

Engine name

+ +

There are some places where an Engine’s name is used:

+
  • +

    routes: when you mount an Engine with mount(MyEngine::Engine => '/my_engine'), it’s used as default :as option

    +
  • +

    rake task for installing migrations my_engine:install:migrations

    +
+ +

Engine name is set by default based on class name. For MyEngine::Engine it will be my_engine_engine. You can change it manually using the engine_name method:

+ +
module MyEngine
+  class Engine < Rails::Engine
+    engine_name "my_engine"
+  end
+end
+
+ +

Isolated Engine

+ +

Normally when you create controllers, helpers, and models inside an engine, they are treated as if they were created inside the application itself. This means that all helpers and named routes from the application will be available to your engine’s controllers as well.

+ +

However, sometimes you want to isolate your engine from the application, especially if your engine has its own router. To do that, you simply need to call isolate_namespace. This method requires you to pass a module where all your controllers, helpers, and models should be nested to:

+ +
module MyEngine
+  class Engine < Rails::Engine
+    isolate_namespace MyEngine
+  end
+end
+
+ +

With such an engine, everything that is inside the MyEngine module will be isolated from the application.

+ +

Consider this controller:

+ +
module MyEngine
+  class FooController < ActionController::Base
+  end
+end
+
+ +

If the MyEngine engine is marked as isolated, FooController only has access to helpers from MyEngine, and url_helpers from MyEngine::Engine.routes.

+ +

The next thing that changes in isolated engines is the behavior of routes. Normally, when you namespace your controllers, you also need to namespace the related routes. With an isolated engine, the engine’s namespace is automatically applied, so you don’t need to specify it explicitly in your routes:

+ +
MyEngine::Engine.routes.draw do
+  resources :articles
+end
+
+ +

If MyEngine is isolated, the routes above will point to MyEngine::ArticlesController. You also don’t need to use longer URL helpers like my_engine_articles_path. Instead, you should simply use articles_path, like you would do with your main application.

+ +

To make this behavior consistent with other parts of the framework, isolated engines also have an effect on ActiveModel::Naming. In a normal Rails app, when you use a namespaced model such as Namespace::Article, ActiveModel::Naming will generate names with the prefix “namespace”. In an isolated engine, the prefix will be omitted in URL helpers and form fields, for convenience.

+ +
polymorphic_url(MyEngine::Article.new)
+# => "articles_path" # not "my_engine_articles_path"
+
+form_for(MyEngine::Article.new) do
+  text_field :title # => <input type="text" name="article[title]" id="article_title" />
+end
+
+ +

Additionally, an isolated engine will set its own name according to its namespace, so MyEngine::Engine.engine_name will return “my_engine”. It will also set MyEngine.table_name_prefix to “my_engine_”, meaning for example that MyEngine::Article will use the my_engine_articles database table by default.

+ +

Using Engine’s routes outside Engine

+ +

Since you can now mount an engine inside application’s routes, you do not have direct access to Engine‘s url_helpers inside Application. When you mount an engine in an application’s routes, a special helper is created to allow you to do that. Consider such a scenario:

+ +
# config/routes.rb
+Rails.application.routes.draw do
+  mount MyEngine::Engine => "/my_engine", as: "my_engine"
+  get "/foo" => "foo#index"
+end
+
+ +

Now, you can use the my_engine helper inside your application:

+ +
class FooController < ApplicationController
+  def index
+    my_engine.root_url # => /my_engine/
+  end
+end
+
+ +

There is also a main_app helper that gives you access to application’s routes inside Engine:

+ +
module MyEngine
+  class BarController
+    def index
+      main_app.foo_path # => /foo
+    end
+  end
+end
+
+ +

Note that the :as option given to mount takes the engine_name as default, so most of the time you can simply omit it.

+ +

Finally, if you want to generate a URL to an engine’s route using polymorphic_url, you also need to pass the engine helper. Let’s say that you want to create a form pointing to one of the engine’s routes. All you need to do is pass the helper as the first element in array with attributes for URL:

+ +
form_for([my_engine, @user])
+
+ +

This code will use my_engine.user_path(@user) to generate the proper route.

+ +

Isolated engine’s helpers

+ +

Sometimes you may want to isolate engine, but use helpers that are defined for it. If you want to share just a few specific helpers you can add them to application’s helpers in ApplicationController:

+ +
class ApplicationController < ActionController::Base
+  helper MyEngine::SharedEngineHelper
+end
+
+ +

If you want to include all of the engine’s helpers, you can use the helper method on an engine’s instance:

+ +
class ApplicationController < ActionController::Base
+  helper MyEngine::Engine.helpers
+end
+
+ +

It will include all of the helpers from engine’s directory. Take into account this does not include helpers defined in controllers with helper_method or other similar solutions, only helpers defined in the helpers directory will be included.

+ +

Migrations & seed data

+ +

Engines can have their own migrations. The default path for migrations is exactly the same as in application: db/migrate

+ +

To use engine’s migrations in application you can use the rake task below, which copies them to application’s dir:

+ +
rake ENGINE_NAME:install:migrations
+
+ +

Note that some of the migrations may be skipped if a migration with the same name already exists in application. In such a situation you must decide whether to leave that migration or rename the migration in the application and rerun copying migrations.

+ +

If your engine has migrations, you may also want to prepare data for the database in the db/seeds.rb file. You can load that data using the load_seed method, e.g.

+ +
MyEngine::Engine.load_seed
+
+ +

Loading priority

+ +

In order to change engine’s priority you can use config.railties_order in the main application. It will affect the priority of loading views, helpers, assets, and all the other files related to engine or application.

+ +
# load Blog::Engine with highest priority, followed by application and other railties
+config.railties_order = [Blog::Engine, :main_app, :all]
+
+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [RW] + called_from
+ [RW] + isolated
+ [RW] + isolated?
+ + + + +

Class Public methods

+ +
+

+ + endpoint(endpoint = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 378
+def endpoint(endpoint = nil)
+  @endpoint ||= nil
+  @endpoint = endpoint if endpoint
+  @endpoint
+end
+
+
+ +
+ +
+

+ + find(path) + +

+ + +
+

Finds engine with given path.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 416
+def find(path)
+  expanded_path = File.expand_path path
+  Rails::Engine.subclasses.each do |klass|
+    engine = klass.instance
+    return engine if File.expand_path(engine.root) == expanded_path
+  end
+  nil
+end
+
+
+ +
+ +
+

+ + find_root(from) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 374
+def find_root(from)
+  find_root_with_flag "lib", from
+end
+
+
+ +
+ +
+

+ + inherited(base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 360
+def inherited(base)
+  unless base.abstract_railtie?
+    Rails::Railtie::Configuration.eager_load_namespaces << base
+
+    base.called_from = begin
+      call_stack = caller_locations.map { |l| l.absolute_path || l.path }
+
+      File.dirname(call_stack.detect { |p| !p.match?(%r[railties[\w.-]*/lib/rails|rack[\w.-]*/lib/rack]) })
+    end
+  end
+
+  super
+end
+
+
+ +
+ +
+

+ + isolate_namespace(mod) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 384
+def isolate_namespace(mod)
+  engine_name(generate_railtie_name(mod.name))
+
+  routes.default_scope = { module: ActiveSupport::Inflector.underscore(mod.name) }
+  self.isolated = true
+
+  unless mod.respond_to?(:railtie_namespace)
+    name, railtie = engine_name, self
+
+    mod.singleton_class.instance_eval do
+      define_method(:railtie_namespace) { railtie }
+
+      unless mod.respond_to?(:table_name_prefix)
+        define_method(:table_name_prefix) { "#{name}_" }
+      end
+
+      unless mod.respond_to?(:use_relative_model_naming?)
+        class_eval "def use_relative_model_naming?; true; end", __FILE__, __LINE__
+      end
+
+      unless mod.respond_to?(:railtie_helpers_paths)
+        define_method(:railtie_helpers_paths) { railtie.helpers_paths }
+      end
+
+      unless mod.respond_to?(:railtie_routes_url_helpers)
+        define_method(:railtie_routes_url_helpers) { |include_path_helpers = true| railtie.routes.url_helpers(include_path_helpers) }
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 432
+def initialize
+  @_all_autoload_paths = nil
+  @_all_load_paths     = nil
+  @app                 = nil
+  @config              = nil
+  @env_config          = nil
+  @helpers             = nil
+  @routes              = nil
+  @app_build_lock      = Mutex.new
+  super
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + app() + +

+ + +
+

Returns the underlying Rack application for this engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 511
+def app
+  @app || @app_build_lock.synchronize {
+    @app ||= begin
+      stack = default_middleware_stack
+      config.middleware = build_middleware.merge_into(stack)
+      config.middleware.build(endpoint)
+    end
+  }
+end
+
+
+ +
+ +
+

+ + call(env) + +

+ + +
+

Define the Rack API for this engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 528
+def call(env)
+  req = build_request env
+  app.call req.env
+end
+
+
+ +
+ +
+

+ + config() + +

+ + +
+

Define the configuration object for the engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 547
+def config
+  @config ||= Engine::Configuration.new(self.class.find_root(self.class.called_from))
+end
+
+
+ +
+ +
+

+ + eager_load!() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 484
+def eager_load!
+  # Already done by Zeitwerk::Loader.eager_load_all. By now, we leave the
+  # method as a no-op for backwards compatibility.
+end
+
+
+ +
+ +
+

+ + endpoint() + +

+ + +
+

Returns the endpoint for this engine. If none is registered, defaults to an ActionDispatch::Routing::RouteSet.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 523
+def endpoint
+  self.class.endpoint || routes
+end
+
+
+ +
+ +
+

+ + env_config() + +

+ + +
+

Defines additional Rack env configuration that is added on each call.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 534
+def env_config
+  @env_config ||= {}
+end
+
+
+ +
+ +
+

+ + helpers() + +

+ + +
+

Returns a module with all the helpers defined for the engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 494
+def helpers
+  @helpers ||= begin
+    helpers = Module.new
+    all = ActionController::Base.all_helpers_from_path(helpers_paths)
+    ActionController::Base.modules_for_helpers(all).each do |mod|
+      helpers.include(mod)
+    end
+    helpers
+  end
+end
+
+
+ +
+ +
+

+ + helpers_paths() + +

+ + +
+

Returns all registered helpers paths.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 506
+def helpers_paths
+  paths["app/helpers"].existent
+end
+
+
+ +
+ +
+

+ + load_console(app = self) + +

+ + +
+

Load console and invoke the registered hooks. Check Rails::Railtie.console for more info.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 446
+def load_console(app = self)
+  require "rails/console/app"
+  require "rails/console/helpers"
+  run_console_blocks(app)
+  self
+end
+
+
+ +
+ +
+

+ + load_generators(app = self) + +

+ + +
+

Load Rails generators and invoke the registered hooks. Check Rails::Railtie.generators for more info.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 470
+def load_generators(app = self)
+  require "rails/generators"
+  run_generators_blocks(app)
+  Rails::Generators.configure!(app.config.generators)
+  self
+end
+
+
+ +
+ +
+

+ + load_runner(app = self) + +

+ + +
+

Load Rails runner and invoke the registered hooks. Check Rails::Railtie.runner for more info.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 455
+def load_runner(app = self)
+  run_runner_blocks(app)
+  self
+end
+
+
+ +
+ +
+

+ + load_seed() + +

+ + +
+

Load data from db/seeds.rb file. It can be used in to load engines’ seeds, e.g.:

+ +

Blog::Engine.load_seed

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 555
+def load_seed
+  seed_file = paths["db/seeds.rb"].existent.first
+  run_callbacks(:load_seed) { load(seed_file) } if seed_file
+end
+
+
+ +
+ +
+

+ + load_server(app = self) + +

+ + +
+

Invoke the server registered hooks. Check Rails::Railtie.server for more info.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 479
+def load_server(app = self)
+  run_server_blocks(app)
+  self
+end
+
+
+ +
+ +
+

+ + load_tasks(app = self) + +

+ + +
+

Load Rake and railties tasks, and invoke the registered hooks. Check Rails::Railtie.rake_tasks for more info.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 462
+def load_tasks(app = self)
+  require "rake"
+  run_tasks_blocks(app)
+  self
+end
+
+
+ +
+ +
+

+ + railties() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 489
+def railties
+  @railties ||= Railties.new
+end
+
+
+ +
+ +
+

+ + routes(&block) + +

+ + +
+

Defines the routes for this engine. If a block is given to routes, it is appended to the engine.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 540
+def routes(&block)
+  @routes ||= ActionDispatch::Routing::RouteSet.new_with_config(config)
+  @routes.append(&block) if block_given?
+  @routes
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + load_config_initializer(initializer) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine.rb, line 665
+def load_config_initializer(initializer) # :doc:
+  ActiveSupport::Notifications.instrument("load_config_initializer.railties", initializer: initializer) do
+    load(initializer)
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Engine/Configuration.html b/src/7.0/classes/Rails/Engine/Configuration.html new file mode 100644 index 0000000000..5e5251a525 --- /dev/null +++ b/src/7.0/classes/Rails/Engine/Configuration.html @@ -0,0 +1,449 @@ +--- +title: Rails::Engine::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ [W] + autoload_once_paths
+ [W] + autoload_paths
+ [W] + eager_load_paths
+ [RW] + javascript_path
+ [RW] + middleware
+ [R] + root
+ + + + +

Class Public methods

+ +
+

+ + new(root = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 12
+def initialize(root = nil)
+  super()
+  @root = root
+  @generators = app_generators.dup
+  @middleware = Rails::Configuration::MiddlewareStackProxy.new
+  @javascript_path = "javascript"
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + autoload_once_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 83
+def autoload_once_paths
+  @autoload_once_paths ||= paths.autoload_once
+end
+
+
+ +
+ +
+

+ + autoload_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 87
+def autoload_paths
+  @autoload_paths ||= paths.autoload_paths
+end
+
+
+ +
+ +
+

+ + eager_load_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 79
+def eager_load_paths
+  @eager_load_paths ||= paths.eager_load
+end
+
+
+ +
+ +
+

+ + generators() + +

+ + +
+

Holds generators configuration:

+ +
config.generators do |g|
+  g.orm             :data_mapper, migration: true
+  g.template_engine :haml
+  g.test_framework  :rspec
+end
+
+ +

If you want to disable color in console, do:

+ +
config.generators.colorize_logging = false
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 32
+def generators
+  @generators ||= Rails::Configuration::Generators.new
+  yield(@generators) if block_given?
+  @generators
+end
+
+
+ +
+ +
+

+ + paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 38
+def paths
+  @paths ||= begin
+    paths = Rails::Paths::Root.new(@root)
+
+    paths.add "app",                 eager_load: true,
+                                     glob: "{*,*/concerns}",
+                                     exclude: ["assets", javascript_path]
+    paths.add "app/assets",          glob: "*"
+    paths.add "app/controllers",     eager_load: true
+    paths.add "app/channels",        eager_load: true
+    paths.add "app/helpers",         eager_load: true
+    paths.add "app/models",          eager_load: true
+    paths.add "app/mailers",         eager_load: true
+    paths.add "app/views"
+
+    paths.add "lib",                 load_path: true
+    paths.add "lib/assets",          glob: "*"
+    paths.add "lib/tasks",           glob: "**/*.rake"
+
+    paths.add "config"
+    paths.add "config/environments", glob: -"#{Rails.env}.rb"
+    paths.add "config/initializers", glob: "**/*.rb"
+    paths.add "config/locales",      glob: "**/*.{rb,yml}"
+    paths.add "config/routes.rb"
+    paths.add "config/routes",       glob: "**/*.rb"
+
+    paths.add "db"
+    paths.add "db/migrate"
+    paths.add "db/seeds.rb"
+
+    paths.add "vendor",              load_path: true
+    paths.add "vendor/assets",       glob: "*"
+
+    paths
+  end
+end
+
+
+ +
+ +
+

+ + root=(value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/configuration.rb, line 75
+def root=(value)
+  @root = paths.path = Pathname.new(value).expand_path
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Engine/Railties.html b/src/7.0/classes/Rails/Engine/Railties.html new file mode 100644 index 0000000000..55ae1a6b69 --- /dev/null +++ b/src/7.0/classes/Rails/Engine/Railties.html @@ -0,0 +1,217 @@ +--- +title: Rails::Engine::Railties +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + - +
  • + +
  • + each +
  • + +
  • + new +
  • + +
+ + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + _all
+ + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/railties.rb, line 9
+def initialize
+  @_all ||= ::Rails::Railtie.subclasses.map(&:instance) +
+    ::Rails::Engine.subclasses.map(&:instance)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + -(others) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/railties.rb, line 18
+def -(others)
+  _all - others
+end
+
+
+ +
+ +
+

+ + each(*args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/railties.rb, line 14
+def each(*args, &block)
+  _all.each(*args, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Engine/Updater.html b/src/7.0/classes/Rails/Engine/Updater.html new file mode 100644 index 0000000000..d211ccabd3 --- /dev/null +++ b/src/7.0/classes/Rails/Engine/Updater.html @@ -0,0 +1,147 @@ +--- +title: Rails::Engine::Updater +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + generator() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/updater.rb, line 10
+def generator
+  @generator ||= Rails::Generators::PluginGenerator.new ["plugin"],
+    { engine: true }, { destination_root: ENGINE_ROOT }
+end
+
+
+ +
+ +
+

+ + run(action) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/engine/updater.rb, line 15
+def run(action)
+  generator.public_send(action)
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators.html b/src/7.0/classes/Rails/Generators.html new file mode 100644 index 0000000000..251e869e3d --- /dev/null +++ b/src/7.0/classes/Rails/Generators.html @@ -0,0 +1,897 @@ +--- +title: Rails::Generators +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
DEFAULT_ALIASES={ +rails: { +actions: "-a", +orm: "-o", +javascripts: "-j", +resource_controller: "-c", +scaffold_controller: "-c", +stylesheets: "-y", +template_engine: "-e", +test_framework: "-t" +}, + +test_unit: { +fixture_replacement: "-r", +} +}
 
DEFAULT_OPTIONS={ +rails: { +api: false, +assets: true, +force_plural: false, +helper: true, +integration_tool: nil, +orm: false, +resource_controller: :controller, +resource_route: true, +scaffold_controller: :scaffold_controller, +system_tests: nil, +test_framework: nil, +template_engine: :erb +} +}
 
RAILS_DEV_PATH=File.expand_path("../../../../../..", __dir__)
 

We need to store the RAILS_DEV_PATH in a constant, otherwise the path can change in Ruby 1.8.7 when we FileUtils.cd.

+ + + + + + +

Class Public methods

+ +
+

+ + api_only!() + +

+ + +
+

Configure generators for API only applications. It basically hides everything that is usually browser related, such as assets and session migration generators, and completely disable helpers and assets so generators such as scaffold won’t create them.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 115
+def api_only!
+  hide_namespaces "assets", "helper", "css", "js"
+
+  options[:rails].merge!(
+    api: true,
+    assets: false,
+    helper: false,
+    template_engine: nil
+  )
+
+  options[:mailer] ||= {}
+  options[:mailer][:template_engine] ||= :erb
+end
+
+
+ +
+ +
+

+ + fallbacks() + +

+ + +
+

Hold configured generators fallbacks. If a plugin developer wants a generator group to fallback to another group in case of missing generators, they can add a fallback.

+ +

For example, shoulda is considered a test_framework and is an extension of test_unit. However, most part of shoulda generators are similar to test_unit ones.

+ +

Shoulda then can tell generators to search for test_unit generators when some of them are not available by adding a fallback:

+ +
Rails::Generators.fallbacks[:shoulda] = :test_unit
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 107
+def fallbacks
+  @fallbacks ||= {}
+end
+
+
+ +
+ +
+

+ + help(command = "generate") + +

+ + +
+

Show help message with available generators.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 168
+def help(command = "generate")
+  puts "Usage: rails #{command} GENERATOR [args] [options]"
+  puts
+  puts "General options:"
+  puts "  -h, [--help]     # Print generator's options and usage"
+  puts "  -p, [--pretend]  # Run but do not make any changes"
+  puts "  -f, [--force]    # Overwrite files that already exist"
+  puts "  -s, [--skip]     # Skip files that already exist"
+  puts "  -q, [--quiet]    # Suppress status output"
+  puts
+  puts "Please choose a generator below."
+  puts
+
+  print_generators
+end
+
+
+ +
+ +
+

+ + hidden_namespaces() + +

+ + +
+

Returns an array of generator namespaces that are hidden. Generator namespaces may be hidden for a variety of reasons. Some are aliased such as “rails:migration” and can be invoked with the shorter “migration”.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 133
+def hidden_namespaces
+  @hidden_namespaces ||= begin
+    orm      = options[:rails][:orm]
+    test     = options[:rails][:test_framework]
+    template = options[:rails][:template_engine]
+
+    [
+      "rails",
+      "resource_route",
+      "#{orm}:migration",
+      "#{orm}:model",
+      "#{test}:controller",
+      "#{test}:helper",
+      "#{test}:integration",
+      "#{test}:system",
+      "#{test}:mailer",
+      "#{test}:model",
+      "#{test}:scaffold",
+      "#{test}:view",
+      "#{test}:job",
+      "#{template}:controller",
+      "#{template}:scaffold",
+      "#{template}:mailer",
+      "action_text:install",
+      "action_mailbox:install"
+    ]
+  end
+end
+
+
+ +
+ +
+

+ + hide_namespace(*namespaces) + +

+ + +
+ +
+ + + + + +
+ Alias for: hide_namespaces +
+ + + +
+ +
+

+ + hide_namespaces(*namespaces) + +

+ + +
+ +
+ + + +
+ Also aliased as: hide_namespace +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 162
+def hide_namespaces(*namespaces)
+  hidden_namespaces.concat(namespaces)
+end
+
+
+ +
+ +
+

+ + invoke(namespace, args = ARGV, config = {}) + +

+ + +
+

Receives a namespace, arguments, and the behavior to invoke the generator. It’s used as the default entry point for generate, destroy, and update commands.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 259
+      def invoke(namespace, args = ARGV, config = {})
+        names = namespace.to_s.split(":")
+        if klass = find_by_namespace(names.pop, names.any? && names.join(":"))
+          args << "--help" if args.empty? && klass.arguments.any?(&:required?)
+          klass.start(args, config)
+          run_after_generate_callback if config[:behavior] == :invoke
+        else
+          options = sorted_groups.flat_map(&:last)
+          error   = Command::Base::CorrectableError.new("Could not find generator '#{namespace}'.", namespace, options)
+
+          if error.respond_to?(:detailed_message)
+            formatted_message = error.detailed_message
+          else
+            formatted_message = error.message
+          end
+
+          puts <<~MSG
+            #{formatted_message}
+            Run `bin/rails generate --help` for more options.
+          MSG
+        end
+      end
+
+
+ +
+ +
+

+ + print_generators() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 189
+def print_generators
+  sorted_groups.each { |b, n| print_list(b, n) }
+end
+
+
+ +
+ +
+

+ + public_namespaces() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 184
+def public_namespaces
+  lookup!
+  subclasses.map(&:namespace)
+end
+
+
+ +
+ +
+

+ + sorted_groups() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 193
+def sorted_groups
+  namespaces = public_namespaces
+  namespaces.sort!
+
+  groups = Hash.new { |h, k| h[k] = [] }
+  namespaces.each do |namespace|
+    base = namespace.split(":").first
+    groups[base] << namespace
+  end
+
+  rails = groups.delete("rails")
+  rails.map! { |n| n.delete_prefix("rails:") }
+  rails.delete("app")
+  rails.delete("plugin")
+  rails.delete("encrypted_secrets")
+  rails.delete("encrypted_file")
+  rails.delete("encryption_key_file")
+  rails.delete("master_key")
+  rails.delete("credentials")
+  rails.delete("db:system:change")
+
+  hidden_namespaces.each { |n| groups.delete(n.to_s) }
+
+  [[ "rails", rails ]] + groups.sort.to_a
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + command_type() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 309
+def command_type # :doc:
+  @command_type ||= "generator"
+end
+
+
+ +
+ +
+

+ + file_lookup_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 317
+def file_lookup_paths # :doc:
+  @file_lookup_paths ||= [ "{#{lookup_paths.join(',')}}", "**", "*_generator.rb" ]
+end
+
+
+ +
+ +
+

+ + lookup_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 313
+def lookup_paths # :doc:
+  @lookup_paths ||= %w( rails/generators generators )
+end
+
+
+ +
+ +
+

+ + print_list(base, namespaces) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators.rb, line 288
+def print_list(base, namespaces) # :doc:
+  namespaces = namespaces.reject { |n| hidden_namespaces.include?(n) }
+  super
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Actions.html b/src/7.0/classes/Rails/Generators/Actions.html new file mode 100644 index 0000000000..c6d834bb87 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Actions.html @@ -0,0 +1,1352 @@ +--- +title: Rails::Generators::Actions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + add_source(source, options = {}, &block) + +

+ + +
+

Add the given source to Gemfile

+ +

If block is given, gem entries in block are wrapped into the source group.

+ +
add_source "http://gems.github.com/"
+
+add_source "http://gems.github.com/" do
+  gem "rspec-rails"
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 151
+def add_source(source, options = {}, &block)
+  log :source, source
+
+  in_root do
+    if block
+      append_file_with_newline "Gemfile", "\nsource #{quote(source)} do", force: true
+      with_indentation(&block)
+      append_file_with_newline "Gemfile", "end", force: true
+    else
+      prepend_file "Gemfile", "source #{quote(source)}\n", verbose: false
+    end
+  end
+end
+
+
+ +
+ +
+

+ + application(data = nil, options = {}) + +

+ + +
+ +
+ + + + + +
+ Alias for: environment +
+ + + +
+ +
+

+ + environment(data = nil, options = {}) + +

+ + +
+

Adds configuration code to a Rails runtime environment.

+ +

By default, adds code inside the Application class in config/application.rb so that it applies to all environments.

+ +
environment %(config.asset_host = "cdn.provider.com")
+
+ +

Results in:

+ +
# config/application.rb
+class Application < Rails::Application
+  config.asset_host = "cdn.provider.com"
+  # ...
+end
+
+ +

If the :env option is specified, the code will be added to the corresponding file in config/environments instead.

+ +
environment %(config.asset_host = "localhost:3000"), env: "development"
+
+ +

Results in:

+ +
# config/environments/development.rb
+Rails.application.configure do
+  config.asset_host = "localhost:3000"
+  # ...
+end
+
+ +

:env can also be an array. In which case, the code is added to each corresponding file in config/environments.

+ +

The code can also be specified as the return value of the block:

+ +
environment do
+  %(config.asset_host = "cdn.provider.com")
+end
+
+environment(nil, env: "development") do
+  %(config.asset_host = "localhost:3000")
+end
+
+
+ + + +
+ Also aliased as: application +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 206
+def environment(data = nil, options = {})
+  sentinel = "class Application < Rails::Application\n"
+  env_file_sentinel = "Rails.application.configure do\n"
+  data ||= yield if block_given?
+
+  in_root do
+    if options[:env].nil?
+      inject_into_file "config/application.rb", optimize_indentation(data, 4), after: sentinel, verbose: false
+    else
+      Array(options[:env]).each do |env|
+        inject_into_file "config/environments/#{env}.rb", optimize_indentation(data, 2), after: env_file_sentinel, verbose: false
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + gem(*args) + +

+ + +
+

Adds a gem declaration to the Gemfile for the specified gem.

+ +
gem "rspec", group: :test
+gem "technoweenie-restful-authentication", lib: "restful-authentication", source: "http://gems.github.com/"
+gem "rails", "3.0", git: "https://github.com/rails/rails"
+gem "RedCloth", ">= 4.1.0", "< 4.2.0"
+gem "rspec", comment: "Put this comment above the gem declaration"
+
+ +

Note that this method only adds the gem to the Gemfile; it does not install the gem.

+ +

Options

+
:version +
+

The version constraints for the gem, specified as a string or an array of strings:

+ +
gem "my_gem", version: "~> 1.1"
+gem "my_gem", version: [">= 1.1", "< 2.0"]
+
+ +

Alternatively, can be specified as one or more arguments following the gem name:

+ +
gem "my_gem", ">= 1.1", "< 2.0"
+
+
:comment +
+

Outputs a comment above the gem declaration in the Gemfile.

+ +
gem "my_gem", comment: "First line.\nSecond line."
+
+ +

Outputs:

+ +
# First line.
+# Second line.
+gem "my_gem"
+
+
:group +
+

The gem group in the Gemfile that the gem belongs to.

+
:git +
+

The URL of the git repository for the gem.

+
+ +

Any additional options passed to this method will be appended to the gem declaration in the Gemfile. For example:

+ +
gem "my_gem", comment: "Edge my_gem", git: "https://example.com/my_gem.git", branch: "master"
+
+ +

Outputs:

+ +
# Edge my_gem
+gem "my_gem", git: "https://example.com/my_gem.git", branch: "master"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 67
+def gem(*args)
+  options = args.extract_options!
+  name, *versions = args
+
+  # Set the message to be shown in logs. Uses the git repo if one is given,
+  # otherwise use name (version).
+  parts, message = [ quote(name) ], name.dup
+
+  # Output a comment above the gem declaration.
+  comment = options.delete(:comment)
+
+  if versions = versions.any? ? versions : options.delete(:version)
+    _versions = Array(versions)
+    _versions.each do |version|
+      parts << quote(version)
+    end
+    message << " (#{_versions.join(", ")})"
+  end
+  message = options[:git] if options[:git]
+
+  log :gemfile, message
+
+  parts << quote(options) unless options.empty?
+
+  in_root do
+    str = []
+    if comment
+      comment.each_line do |comment_line|
+        str << indentation
+        str << "# #{comment_line}"
+      end
+      str << "\n"
+    end
+    str << indentation
+    str << "gem #{parts.join(", ")}"
+    append_file_with_newline "Gemfile", str.join, verbose: false
+  end
+end
+
+
+ +
+ +
+

+ + gem_group(*names, &block) + +

+ + +
+

Wraps gem entries inside a group.

+ +
gem_group :development, :test do
+  gem "rspec-rails"
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 111
+def gem_group(*names, &block)
+  options = names.extract_options!
+  str = names.map(&:inspect)
+  str << quote(options) unless options.empty?
+  str = str.join(", ")
+  log :gemfile, "group #{str}"
+
+  in_root do
+    append_file_with_newline "Gemfile", "\ngroup #{str} do", force: true
+    with_indentation(&block)
+    append_file_with_newline "Gemfile", "end", force: true
+  end
+end
+
+
+ +
+ +
+

+ + generate(what, *args) + +

+ + +
+

Runs another generator.

+ +
generate "scaffold", "Post title:string body:text"
+generate "scaffold", "Post", "title:string", "body:text"
+
+ +

The first argument is the generator name, and the remaining arguments are joined together and passed to the generator.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 332
+def generate(what, *args)
+  log :generate, what
+
+  options = args.extract_options!
+  options[:abort_on_failure] = !options[:inline]
+
+  rails_command "generate #{what} #{args.join(" ")}", options
+end
+
+
+ +
+ +
+

+ + git(commands = {}) + +

+ + +
+

Runs one or more git commands.

+ +
git :init
+# => runs `git init`
+
+git add: "this.file that.rb"
+# => runs `git add this.file that.rb`
+
+git commit: "-m 'First commit'"
+# => runs `git commit -m 'First commit'`
+
+git add: "good.rb", rm: "bad.cxx"
+# => runs `git add good.rb; git rm bad.cxx`
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 237
+def git(commands = {})
+  if commands.is_a?(Symbol)
+    run "git #{commands}"
+  else
+    commands.each do |cmd, options|
+      run "git #{cmd} #{options}"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + github(repo, options = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 125
+def github(repo, options = {}, &block)
+  str = [quote(repo)]
+  str << quote(options) unless options.empty?
+  str = str.join(", ")
+  log :github, "github #{str}"
+
+  in_root do
+    if @indentation.zero?
+      append_file_with_newline "Gemfile", "\ngithub #{str} do", force: true
+    else
+      append_file_with_newline "Gemfile", "#{indentation}github #{str} do", force: true
+    end
+    with_indentation(&block)
+    append_file_with_newline "Gemfile", "#{indentation}end", force: true
+  end
+end
+
+
+ +
+ +
+

+ + initializer(filename, data = nil) + +

+ + +
+

Creates an initializer file in config/initializers/. The code can be specified as an argument or as the return value of the block.

+ +
initializer "api.rb", <<~RUBY
+  API_KEY = "123456"
+RUBY
+
+initializer "api.rb" do
+  %(API_KEY = "123456")
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 319
+def initializer(filename, data = nil)
+  log :initializer, filename
+  data ||= yield if block_given?
+  create_file("config/initializers/#{filename}", optimize_indentation(data), verbose: false)
+end
+
+
+ +
+ +
+

+ + lib(filename, data = nil) + +

+ + +
+

Creates a file in lib/. The contents can be specified as an argument or as the return value of the block.

+ +
lib "foreign.rb", <<~RUBY
+  # Foreign code is fun
+RUBY
+
+lib "foreign.rb" do
+  "# Foreign code is fun"
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 275
+def lib(filename, data = nil)
+  log :lib, filename
+  data ||= yield if block_given?
+  create_file("lib/#{filename}", optimize_indentation(data), verbose: false)
+end
+
+
+ +
+ +
+

+ + rails_command(command, options = {}) + +

+ + +
+

Runs the specified Rails command.

+ +
rails_command "db:migrate"
+rails_command "db:migrate", env: "production"
+rails_command "db:migrate", abort_on_failure: true
+rails_command "stats", capture: true
+rails_command "gems:install", sudo: true
+
+ +

Options

+
:env +
+

The Rails environment in which to run the command. Defaults to ENV["RAILS_ENV"] || "development".

+
:abort_on_failure +
+

Whether to halt the generator if the command exits with a non-success exit status.

+
:capture +
+

Whether to capture and return the output of the command.

+
:sudo +
+

Whether to run the command using sudo.

+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 391
+def rails_command(command, options = {})
+  if options[:inline]
+    log :rails, command
+    command, *args = Shellwords.split(command)
+    in_root do
+      silence_warnings do
+        ::Rails::Command.invoke(command, args, **options)
+      end
+    end
+  else
+    execute_command :rails, command, options
+  end
+end
+
+
+ +
+ +
+

+ + rake(command, options = {}) + +

+ + +
+

Runs the specified Rake task.

+ +
rake "db:migrate"
+rake "db:migrate", env: "production"
+rake "db:migrate", abort_on_failure: true
+rake "stats", capture: true
+rake "gems:install", sudo: true
+
+ +

Options

+
:env +
+

The Rails environment in which to run the task. Defaults to ENV["RAILS_ENV"] || "development".

+
:abort_on_failure +
+

Whether to halt the generator if the task exits with a non-success exit status.

+
:capture +
+

Whether to capture and return the output of the task.

+
:sudo +
+

Whether to run the task using sudo.

+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 364
+def rake(command, options = {})
+  execute_command :rake, command, options
+end
+
+
+ +
+ +
+

+ + rakefile(filename, data = nil) + +

+ + +
+

Creates a Rake tasks file in lib/tasks/. The code can be specified as an argument or as the return value of the block.

+ +
rakefile "bootstrap.rake", <<~RUBY
+  task :bootstrap do
+    puts "Boots! Boots! Boots!"
+  end
+RUBY
+
+rakefile "bootstrap.rake" do
+  project = ask("What is the UNIX name of your project?")
+
+  <<~RUBY
+    namespace :#{project} do
+      task :bootstrap do
+        puts "Boots! Boots! Boots!"
+      end
+    end
+  RUBY
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 302
+def rakefile(filename, data = nil)
+  log :rakefile, filename
+  data ||= yield if block_given?
+  create_file("lib/tasks/#{filename}", optimize_indentation(data), verbose: false)
+end
+
+
+ +
+ +
+

+ + readme(path) + +

+ + +
+

Reads the given file at the source root and prints it in the console.

+ +
readme "README"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 442
+def readme(path)
+  log File.read(find_in_source_paths(path))
+end
+
+
+ +
+ +
+

+ + route(routing_code, namespace: nil) + +

+ + +
+

Make an entry in Rails routing file config/routes.rb

+ +
route "root 'welcome#index'"
+route "root 'admin#index'", namespace: :admin
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 409
+def route(routing_code, namespace: nil)
+  namespace = Array(namespace)
+  namespace_pattern = route_namespace_pattern(namespace)
+  routing_code = namespace.reverse.reduce(routing_code) do |code, name|
+    "namespace :#{name} do\n#{rebase_indentation(code, 2)}end"
+  end
+
+  log :route, routing_code
+
+  in_root do
+    if namespace_match = match_file("config/routes.rb", namespace_pattern)
+      base_indent, *, existing_block_indent = namespace_match.captures.compact.map(&:length)
+      existing_line_pattern = /^[ ]{,#{existing_block_indent}}\S.+\n?/
+      routing_code = rebase_indentation(routing_code, base_indent + 2).gsub(existing_line_pattern, "")
+      namespace_pattern = /#{Regexp.escape namespace_match.to_s}/
+    end
+
+    inject_into_file "config/routes.rb", routing_code, after: namespace_pattern, verbose: false, force: false
+
+    if behavior == :revoke && namespace.any? && namespace_match
+      empty_block_pattern = /(#{namespace_pattern})((?:\s*end\n){1,#{namespace.size}})/
+      gsub_file "config/routes.rb", empty_block_pattern, verbose: false, force: true do |matched|
+        beginning, ending = empty_block_pattern.match(matched).captures
+        ending.sub!(/\A\s*end\n/, "") while !ending.empty? && beginning.sub!(/^[ ]*namespace .+ do\n\s*\z/, "")
+        beginning + ending
+      end
+    end
+  end
+end
+
+
+ +
+ +
+

+ + vendor(filename, data = nil) + +

+ + +
+

Creates a file in vendor/. The contents can be specified as an argument or as the return value of the block.

+ +
vendor "foreign.rb", <<~RUBY
+  # Foreign code is fun
+RUBY
+
+vendor "foreign.rb" do
+  "# Foreign code is fun"
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 258
+def vendor(filename, data = nil)
+  log :vendor, filename
+  data ||= yield if block_given?
+  create_file("vendor/#{filename}", optimize_indentation(data), verbose: false)
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + execute_command(executor, command, options = {}) + +

+ + +
+

Runs the supplied command using either “rake …” or “rails …” based on the executor parameter provided.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 461
+def execute_command(executor, command, options = {}) # :doc:
+  log executor, command
+  sudo = options[:sudo] && !Gem.win_platform? ? "sudo " : ""
+  config = {
+    env: { "RAILS_ENV" => (options[:env] || ENV["RAILS_ENV"] || "development") },
+    verbose: false,
+    capture: options[:capture],
+    abort_on_failure: options[:abort_on_failure],
+  }
+
+  in_root { run("#{sudo}#{extify(executor)} #{command}", config) }
+end
+
+
+ +
+ +
+

+ + extify(name) + +

+ + +
+

Add an extension to the given name based on the platform.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 475
+def extify(name) # :doc:
+  if Gem.win_platform?
+    "#{name}.bat"
+  else
+    name
+  end
+end
+
+
+ +
+ +
+

+ + indentation() + +

+ + +
+

Indent the Gemfile to the depth of @indentation

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 503
+def indentation # :doc:
+  "  " * @indentation
+end
+
+
+ +
+ +
+

+ + log(*args) + +

+ + +
+

Define log for backwards compatibility. If just one argument is sent, invoke say, otherwise invoke say_status. Differently from say and similarly to say_status, this method respects the quiet? option given.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 450
+def log(*args) # :doc:
+  if args.size == 1
+    say args.first.to_s unless options.quiet?
+  else
+    args << (behavior == :invoke ? :green : :red)
+    say_status(*args)
+  end
+end
+
+
+ +
+ +
+

+ + optimize_indentation(value, amount = 0) + +

+ + +
+

Returns optimized string with indentation

+
+ + + +
+ Also aliased as: rebase_indentation +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 496
+def optimize_indentation(value, amount = 0) # :doc:
+  return "#{value}\n" unless value.is_a?(String)
+  "#{value.strip_heredoc.indent(amount).chomp}\n"
+end
+
+
+ +
+ +
+

+ + quote(value) + +

+ + +
+

Always returns value in double quotes.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 484
+def quote(value) # :doc:
+  if value.respond_to? :each_pair
+    return value.map do |k, v|
+      "#{k}: #{quote(v)}"
+    end.join(", ")
+  end
+  return value.inspect unless value.is_a? String
+
+  "\"#{value.tr("'", '"')}\""
+end
+
+
+ +
+ +
+

+ + with_indentation(&block) + +

+ + +
+

Manage Gemfile indentation for a DSL action block

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/actions.rb, line 508
+def with_indentation(&block) # :doc:
+  @indentation += 1
+  instance_eval(&block)
+ensure
+  @indentation -= 1
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/ActiveModel.html b/src/7.0/classes/Rails/Generators/ActiveModel.html new file mode 100644 index 0000000000..3668a8f2ba --- /dev/null +++ b/src/7.0/classes/Rails/Generators/ActiveModel.html @@ -0,0 +1,426 @@ +--- +title: Rails::Generators::ActiveModel +layout: default +--- +
+ +
+
+ +
+ +

ActiveModel is a class to be implemented by each ORM to allow Rails to generate customized controller code.

+ +

The API has the same methods as ActiveRecord, but each method returns a string that matches the ORM API.

+ +

For example:

+ +
ActiveRecord::Generators::ActiveModel.find(Foo, "params[:id]")
+# => "Foo.find(params[:id])"
+
+DataMapper::Generators::ActiveModel.find(Foo, "params[:id]")
+# => "Foo.get(params[:id])"
+
+ +

On initialization, the ActiveModel accepts the instance name that will receive the calls:

+ +
builder = ActiveRecord::Generators::ActiveModel.new "@foo"
+builder.save # => "@foo.save"
+
+ +

The only exception in ActiveModel for ActiveRecord is the use of self.build instead of self.new.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + name
+ + + + +

Class Public methods

+ +
+

+ + all(klass) + +

+ + +
+

GET index

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 36
+def self.all(klass)
+  "#{klass}.all"
+end
+
+
+ +
+ +
+

+ + build(klass, params = nil) + +

+ + +
+

GET new POST create

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 50
+def self.build(klass, params = nil)
+  if params
+    "#{klass}.new(#{params})"
+  else
+    "#{klass}.new"
+  end
+end
+
+
+ +
+ +
+

+ + find(klass, params = nil) + +

+ + +
+

GET show GET edit PATCH/PUT update DELETE destroy

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 44
+def self.find(klass, params = nil)
+  "#{klass}.find(#{params})"
+end
+
+
+ +
+ +
+

+ + new(name) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 31
+def initialize(name)
+  @name = name
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + destroy() + +

+ + +
+

DELETE destroy

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 75
+def destroy
+  "#{name}.destroy"
+end
+
+
+ +
+ +
+

+ + errors() + +

+ + +
+

POST create PATCH/PUT update

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 70
+def errors
+  "#{name}.errors"
+end
+
+
+ +
+ +
+

+ + save() + +

+ + +
+

POST create

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 59
+def save
+  "#{name}.save"
+end
+
+
+ +
+ +
+

+ + update(params = nil) + +

+ + +
+

PATCH/PUT update

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/active_model.rb, line 64
+def update(params = nil)
+  "#{name}.update(#{params})"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/AppBase.html b/src/7.0/classes/Rails/Generators/AppBase.html new file mode 100644 index 0000000000..39e91aef19 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/AppBase.html @@ -0,0 +1,73 @@ +--- +title: Rails::Generators::AppBase +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/AppBase/GemfileEntry.html b/src/7.0/classes/Rails/Generators/AppBase/GemfileEntry.html new file mode 100644 index 0000000000..7443ba85d3 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/AppBase/GemfileEntry.html @@ -0,0 +1,315 @@ +--- +title: Rails::Generators::AppBase::GemfileEntry +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + floats(name, comment = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 268
+def self.floats(name, comment = nil)
+  new(name, nil, comment)
+end
+
+
+ +
+ +
+

+ + github(name, github, branch = nil, comment = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 256
+def self.github(name, github, branch = nil, comment = nil)
+  if branch
+    new(name, nil, comment, github: github, branch: branch)
+  else
+    new(name, nil, comment, github: github)
+  end
+end
+
+
+ +
+ +
+

+ + new(name, version, comment, options = {}, commented_out = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 252
+def initialize(name, version, comment, options = {}, commented_out = false)
+  super
+end
+
+
+ +
+ +
+

+ + path(name, path, comment = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 272
+def self.path(name, path, comment = nil)
+  new(name, nil, comment, path: path)
+end
+
+
+ +
+ +
+

+ + version(name, version, comment = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 264
+def self.version(name, version, comment = nil)
+  new(name, version, comment)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + to_s() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/app_base.rb, line 276
+def to_s
+  [
+    (comment.gsub(/^/, "# ").chomp + "\n" if comment),
+    ("# " if commented_out),
+    "gem \"#{name}\"",
+    *Array(version).map { |constraint| ", \"#{constraint}\"" },
+    *options.map { |key, value| ", #{key}: #{value.inspect}" },
+  ].compact.join
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/AppGenerator.html b/src/7.0/classes/Rails/Generators/AppGenerator.html new file mode 100644 index 0000000000..728d729a7c --- /dev/null +++ b/src/7.0/classes/Rails/Generators/AppGenerator.html @@ -0,0 +1,114 @@ +--- +title: Rails::Generators::AppGenerator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Private methods

+ +
+

+ + after_bundle(&block) + +

+ + +
+

Registers a callback to be executed after bundle binstubs have run.

+ +
after_bundle do
+  git add: '.'
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/app/app_generator.rb, line 553
+def after_bundle(&block) # :doc:
+  @after_bundle_callbacks << block
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Base.html b/src/7.0/classes/Rails/Generators/Base.html new file mode 100644 index 0000000000..afdfe135ea --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Base.html @@ -0,0 +1,1209 @@ +--- +title: Rails::Generators::Base +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + base_root() + +

+ + +
+

Returns the base root for a common set of generators. This is used to dynamically guess the default source root.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 228
+def self.base_root
+  __dir__
+end
+
+
+ +
+ +
+

+ + default_source_root() + +

+ + +
+

Returns the default source root for a given generator. This is used internally by rails to set its generators source root. If you want to customize your source root, you should use source_root.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 219
+def self.default_source_root
+  return unless base_name && generator_name
+  return unless default_generator_root
+  path = File.join(default_generator_root, "templates")
+  path if File.exist?(path)
+end
+
+
+ +
+ +
+

+ + desc(description = nil) + +

+ + +
+

Tries to get the description from a USAGE file one folder above the source root otherwise uses a default description.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 41
+def self.desc(description = nil)
+  return super if description
+
+  @desc ||= if usage_path
+    ERB.new(File.read(usage_path)).result(binding)
+  else
+    "Description:\n    Create #{base_name.humanize.downcase} files for #{generator_name} generator."
+  end
+end
+
+
+ +
+ +
+

+ + hide!() + +

+ + +
+

Convenience method to hide this generator from the available ones when running rails generator command.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 61
+def self.hide!
+  Rails::Generators.hide_namespace(namespace)
+end
+
+
+ +
+ +
+

+ + hook_for(*names, &block) + +

+ + +
+

Invoke a generator based on the value supplied by the user to the given option named “name”. A class option is created when this method is invoked and you can set a hash to customize it.

+ +

Examples

+ +
module Rails::Generators
+  class ControllerGenerator < Base
+    hook_for :test_framework, aliases: "-t"
+  end
+end
+
+ +

The example above will create a test framework option and will invoke a generator based on the user supplied value.

+ +

For example, if the user invoke the controller generator as:

+ +
bin/rails generate controller Account --test-framework=test_unit
+
+ +

The controller generator will then try to invoke the following generators:

+ +
"rails:test_unit", "test_unit:controller", "test_unit"
+
+ +

Notice that “rails:generators:test_unit” could be loaded as well, what Rails looks for is the first and last parts of the namespace. This is what allows any test framework to hook into Rails as long as it provides any of the hooks above.

+ +

Options

+ +

The first and last part used to find the generator to be invoked are guessed based on class invokes hook_for, as noticed in the example above. This can be customized with two options: :in and :as.

+ +

Let’s suppose you are creating a generator that needs to invoke the controller generator from test unit. Your first attempt is:

+ +
class AwesomeGenerator < Rails::Generators::Base
+  hook_for :test_framework
+end
+
+ +

The lookup in this case for test_unit as input is:

+ +
"test_unit:awesome", "test_unit"
+
+ +

Which is not the desired lookup. You can change it by providing the :as option:

+ +
class AwesomeGenerator < Rails::Generators::Base
+  hook_for :test_framework, as: :controller
+end
+
+ +

And now it will look up at:

+ +
"test_unit:controller", "test_unit"
+
+ +

Similarly, if you want it to also look up in the rails namespace, you just need to provide the :in value:

+ +
class AwesomeGenerator < Rails::Generators::Base
+  hook_for :test_framework, in: :rails, as: :controller
+end
+
+ +

And the lookup is exactly the same as previously:

+ +
"rails:test_unit", "test_unit:controller", "test_unit"
+
+ +

Switches

+ +

All hooks come with switches for user interface. If you do not want to use any test framework, you can do:

+ +
bin/rails generate controller Account --skip-test-framework
+
+ +

Or similarly:

+ +
bin/rails generate controller Account --no-test-framework
+
+ +

Boolean hooks

+ +

In some cases, you may want to provide a boolean hook. For example, webrat developers might want to have webrat available on controller generator. This can be achieved as:

+ +
Rails::Generators::ControllerGenerator.hook_for :webrat, type: :boolean
+
+ +

Then, if you want webrat to be invoked, just supply:

+ +
bin/rails generate controller Account --webrat
+
+ +

The hooks lookup is similar as above:

+ +
"rails:generators:webrat", "webrat:generators:controller", "webrat"
+
+ +

Custom invocations

+ +

You can also supply a block to hook_for to customize how the hook is going to be invoked. The block receives two arguments, an instance of the current class and the class to be invoked.

+ +

For example, in the resource generator, the controller should be invoked with a pluralized class name. But by default it is invoked with the same name as the resource generator, which is singular. To change this, we can give a block to customize how the controller can be invoked.

+ +
hook_for :resource_controller do |instance, controller|
+  instance.invoke controller, [ instance.name.pluralize ]
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 174
+def self.hook_for(*names, &block)
+  options = names.extract_options!
+  in_base = options.delete(:in) || base_name
+  as_hook = options.delete(:as) || generator_name
+
+  names.each do |name|
+    unless class_options.key?(name)
+      defaults = if options[:type] == :boolean
+        {}
+      elsif [true, false].include?(default_value_for_option(name, options))
+        { banner: "" }
+      else
+        { desc: "#{name.to_s.humanize} to be invoked", banner: "NAME" }
+      end
+
+      class_option(name, defaults.merge!(options))
+    end
+
+    hooks[name] = [ in_base, as_hook ]
+    invoke_from_option(name, options, &block)
+  end
+end
+
+
+ +
+ +
+

+ + namespace(name = nil) + +

+ + +
+

Convenience method to get the namespace from the class name. It’s the same as Thor default except that the Generator at the end of the class is removed.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 54
+def self.namespace(name = nil)
+  return super if name
+  @namespace ||= super.delete_suffix("_generator").sub(/:generators:/, ":")
+end
+
+
+ +
+ +
+

+ + remove_hook_for(*names) + +

+ + +
+

Remove a previously added hook.

+ +
remove_hook_for :orm
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 200
+def self.remove_hook_for(*names)
+  remove_invocation(*names)
+
+  names.each do |name|
+    hooks.delete(name)
+  end
+end
+
+
+ +
+ +
+

+ + source_root(path = nil) + +

+ + +
+

Returns the source root for this generator using default_source_root as default.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 34
+def self.source_root(path = nil)
+  @_source_root = path if path
+  @_source_root ||= default_source_root
+end
+
+
+ +
+ + +

Class Private methods

+ +
+

+ + add_shebang_option!() + +

+ + +
+

Small macro to add ruby as an option to the generator with proper default value plus an instance helper method called shebang.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 388
+def self.add_shebang_option! # :doc:
+  class_option :ruby, type: :string, aliases: "-r", default: Thor::Util.ruby_command,
+                      desc: "Path to the Ruby binary of your choice", banner: "PATH"
+
+  no_tasks {
+    define_method :shebang do
+      @shebang ||= begin
+        command = if options[:ruby] == Thor::Util.ruby_command
+          "/usr/bin/env #{File.basename(Thor::Util.ruby_command)}"
+        else
+          options[:ruby]
+        end
+        "#!#{command}"
+      end
+    end
+  }
+end
+
+
+ +
+ +
+

+ + banner() + +

+ + +
+

Use Rails default banner.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 321
+def self.banner # :doc:
+  "rails generate #{namespace.delete_prefix("rails:")} #{arguments.map(&:usage).join(' ')} [options]".gsub(/\s+/, " ")
+end
+
+
+ +
+ +
+

+ + base_name() + +

+ + +
+

Sets the base_name taking into account the current class namespace.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 326
+def self.base_name # :doc:
+  @base_name ||= if base = name.to_s.split("::").first
+    base.underscore
+  end
+end
+
+
+ +
+ +
+

+ + default_aliases_for_option(name, options) + +

+ + +
+

Returns default aliases for the option name given doing a lookup in Rails::Generators.aliases.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 349
+def self.default_aliases_for_option(name, options) # :doc:
+  default_for_option(Rails::Generators.aliases, name, options, options[:aliases])
+end
+
+
+ +
+ +
+

+ + default_for_option(config, name, options, default) + +

+ + +
+

Returns default for the option name given doing a lookup in config.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 354
+def self.default_for_option(config, name, options, default) # :doc:
+  if generator_name && (c = config[generator_name.to_sym]) && c.key?(name)
+    c[name]
+  elsif base_name && (c = config[base_name.to_sym]) && c.key?(name)
+    c[name]
+  elsif config[:rails].key?(name)
+    config[:rails][name]
+  else
+    default
+  end
+end
+
+
+ +
+ +
+

+ + default_generator_root() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 414
+def self.default_generator_root # :doc:
+  path = File.expand_path(File.join(base_name, generator_name), base_root)
+  path if File.exist?(path)
+end
+
+
+ +
+ +
+

+ + default_value_for_option(name, options) + +

+ + +
+

Returns the default value for the option name given doing a lookup in Rails::Generators.options.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 343
+def self.default_value_for_option(name, options) # :doc:
+  default_for_option(Rails::Generators.options, name, options, options[:default])
+end
+
+
+ +
+ +
+

+ + generator_name() + +

+ + +
+

Removes the namespaces and get the generator name. For example, Rails::Generators::ModelGenerator will return “model” as generator name.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 334
+def self.generator_name # :doc:
+  @generator_name ||= if generator = name.to_s.split("::").last
+    generator.delete_suffix!("Generator")
+    generator.underscore
+  end
+end
+
+
+ +
+ +
+

+ + usage_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 406
+def self.usage_path # :doc:
+  paths = [
+    source_root && File.expand_path("../USAGE", source_root),
+    default_generator_root && File.join(default_generator_root, "USAGE")
+  ]
+  paths.compact.detect { |path| File.exist? path }
+end
+
+
+ +
+ + + +

Instance Private methods

+ +
+

+ + extract_last_module(nesting) + +

+ + +
+

Takes in an array of nested modules and extracts the last module

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 279
+def extract_last_module(nesting) # :doc:
+  nesting.inject(Object) do |last_module, nest|
+    break unless last_module.const_defined?(nest, false)
+    last_module.const_get(nest)
+  end
+end
+
+
+ +
+ +
+

+ + indent(content, multiplier = 2) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 294
+def indent(content, multiplier = 2) # :doc:
+  spaces = " " * multiplier
+  content.each_line.map { |line| line.blank? ? line : "#{spaces}#{line}" }.join
+end
+
+
+ +
+ +
+

+ + module_namespacing(&block) + +

+ + +
+

Wrap block with namespace of current application if namespace exists and is not skipped

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 288
+def module_namespacing(&block) # :doc:
+  content = capture(&block)
+  content = wrap_with_namespace(content) if namespaced?
+  concat(content)
+end
+
+
+ +
+ +
+

+ + namespace() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 304
+def namespace # :doc:
+  Rails::Generators.namespace
+end
+
+
+ +
+ +
+

+ + namespaced?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 308
+def namespaced? # :doc:
+  !options[:skip_namespace] && namespace
+end
+
+
+ +
+ +
+

+ + namespaced_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 316
+def namespaced_path # :doc:
+  @namespaced_path ||= namespace_dirs.join("/")
+end
+
+
+ +
+ +
+

+ + wrap_with_namespace(content) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/base.rb, line 299
+def wrap_with_namespace(content) # :doc:
+  content = indent(content).chomp
+  "module #{namespace.name}\n#{content}\nend\n"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/BenchmarkGenerator.html b/src/7.0/classes/Rails/Generators/BenchmarkGenerator.html new file mode 100644 index 0000000000..2079d69581 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/BenchmarkGenerator.html @@ -0,0 +1,126 @@ +--- +title: Rails::Generators::BenchmarkGenerator +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
IPS_GEM_NAME="benchmark-ips"
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + generate_layout() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/benchmark/benchmark_generator.rb, line 12
+def generate_layout
+  add_ips_to_gemfile unless ips_installed?
+  template("benchmark.rb.tt", "script/benchmarks/#{file_name}.rb")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Db.html b/src/7.0/classes/Rails/Generators/Db.html new file mode 100644 index 0000000000..103e4372b1 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Db.html @@ -0,0 +1,67 @@ +--- +title: Rails::Generators::Db +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Db/System.html b/src/7.0/classes/Rails/Generators/Db/System.html new file mode 100644 index 0000000000..5606a9294f --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Db/System.html @@ -0,0 +1,54 @@ +--- +title: Rails::Generators::Db::System +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Migration.html b/src/7.0/classes/Rails/Generators/Migration.html new file mode 100644 index 0000000000..5301308a23 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Migration.html @@ -0,0 +1,236 @@ +--- +title: Rails::Generators::Migration +layout: default +--- +
+ +
+
+ +
+ +

Holds common methods for migrations. It assumes that migrations have the [0-9]*_name format and can be used by other frameworks (like Sequel) just by implementing the next migration version method.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + + + + + + + +
+ [R] + migration_class_name
+ [R] + migration_file_name
+ [R] + migration_number
+ + + + + +

Instance Public methods

+ +
+

+ + create_migration(destination, data, config = {}, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/migration.rb, line 35
+def create_migration(destination, data, config = {}, &block)
+  action Rails::Generators::Actions::CreateMigration.new(self, destination, block || data.to_s, config)
+end
+
+
+ +
+ +
+

+ + migration_template(source, destination, config = {}) + +

+ + +
+

Creates a migration template at the given destination. The difference to the default template method is that the migration version is appended to the destination file name.

+ +

The migration version, migration file name, migration class name are available as instance variables in the template to be rendered.

+ +
migration_template "migration.rb", "db/migrate/add_foo_to_bar.rb"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/migration.rb, line 56
+def migration_template(source, destination, config = {})
+  source = File.expand_path(find_in_source_paths(source.to_s))
+
+  set_migration_assigns!(destination)
+  context = instance_eval("binding")
+
+  dir, base = File.split(destination)
+  numbered_destination = File.join(dir, ["%migration_number%", base].join("_"))
+
+  file = create_migration numbered_destination, nil, config do
+    ERB.new(::File.binread(source), trim_mode: "-", eoutvar: "@output_buffer").result(context)
+  end
+  Rails::Generators.add_generated_file(file)
+end
+
+
+ +
+ +
+

+ + set_migration_assigns!(destination) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/migration.rb, line 39
+def set_migration_assigns!(destination)
+  destination = File.expand_path(destination, destination_root)
+
+  migration_dir = File.dirname(destination)
+  @migration_number     = self.class.next_migration_number(migration_dir)
+  @migration_file_name  = File.basename(destination, ".rb")
+  @migration_class_name = @migration_file_name.camelize
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/NamedBase.html b/src/7.0/classes/Rails/Generators/NamedBase.html new file mode 100644 index 0000000000..b95ae1ad15 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/NamedBase.html @@ -0,0 +1,1444 @@ +--- +title: Rails::Generators::NamedBase +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Private methods

+ +
+

+ + check_class_collision(options = {}) + +

+ + +
+

Add a class collisions name to be checked on class initialization. You can supply a hash with a :prefix or :suffix to be tested.

+ +

Examples

+ +
check_class_collision suffix: "Decorator"
+
+ +

If the generator is invoked with class name Admin, it will check for the presence of “AdminDecorator”.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 214
+def self.check_class_collision(options = {}) # :doc:
+  define_method :check_class_collision do
+    name = if respond_to?(:controller_class_name, true) # for ResourceHelpers
+      controller_class_name
+    else
+      class_name
+    end
+
+    class_collisions "#{options[:prefix]}#{name}#{options[:suffix]}"
+  end
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + js_template(source, destination) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 29
+def js_template(source, destination)
+  template(source + ".js", destination + ".js")
+end
+
+
+ +
+ +
+

+ + template(source, *args, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 23
+def template(source, *args, &block)
+  inside_template do
+    Rails::Generators.add_generated_file(super)
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + application_name() + +

+ + +
+

Tries to retrieve the application name or simply return application.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 138
+def application_name # :doc:
+  if defined?(Rails) && Rails.application
+    Rails.application.class.name.split("::").first.underscore
+  else
+    "application"
+  end
+end
+
+
+ +
+ +
+

+ + attributes_names() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 188
+def attributes_names # :doc:
+  @attributes_names ||= attributes.each_with_object([]) do |a, names|
+    names << a.column_name
+    names << "password_confirmation" if a.password_digest?
+    names << "#{a.name}_type" if a.polymorphic?
+  end
+end
+
+
+ +
+ +
+

+ + class_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 70
+def class_name # :doc:
+  (class_path + [file_name]).map!(&:camelize).join("::")
+end
+
+
+ +
+ +
+

+ + class_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 58
+def class_path # :doc:
+  inside_template? || !namespaced? ? regular_class_path : namespaced_class_path
+end
+
+
+ +
+ +
+

+ + edit_helper(...) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 105
+def edit_helper(...) # :doc:
+  "edit_#{show_helper(...)}"
+end
+
+
+ +
+ +
+

+ + file_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 54
+def file_path # :doc:
+  @file_path ||= (class_path + [file_name]).join("/")
+end
+
+
+ +
+ +
+

+ + fixture_file_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 125
+def fixture_file_name # :doc:
+  @fixture_file_name ||= (pluralize_table_names? ? plural_file_name : file_name)
+end
+
+
+ +
+ +
+

+ + human_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 74
+def human_name # :doc:
+  @human_name ||= singular_name.humanize
+end
+
+
+ +
+ +
+

+ + i18n_scope() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 82
+def i18n_scope # :doc:
+  @i18n_scope ||= file_path.tr("/", ".")
+end
+
+
+ +
+ +
+

+ + index_helper(type: nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 97
+def index_helper(type: nil) # :doc:
+  [plural_route_name, ("index" if uncountable?), type].compact.join("_")
+end
+
+
+ +
+ +
+

+ + inside_template() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 43
+def inside_template # :doc:
+  @inside_template = true
+  yield
+ensure
+  @inside_template = false
+end
+
+
+ +
+ +
+

+ + inside_template?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 50
+def inside_template? # :doc:
+  @inside_template
+end
+
+
+ +
+ +
+

+ + model_resource_name(base_name = singular_table_name, prefix: "") + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 150
+def model_resource_name(base_name = singular_table_name, prefix: "") # :doc:
+  resource_name = "#{prefix}#{base_name}"
+  if options[:model_name]
+    "[#{controller_class_path.map { |name| ":" + name }.join(", ")}, #{resource_name}]"
+  else
+    resource_name
+  end
+end
+
+
+ +
+ +
+

+ + mountable_engine?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 200
+def mountable_engine? # :doc:
+  defined?(ENGINE_ROOT) && namespaced?
+end
+
+
+ +
+ +
+

+ + namespaced_class_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 66
+def namespaced_class_path # :doc:
+  @namespaced_class_path ||= namespace_dirs + @class_path
+end
+
+
+ +
+ +
+

+ + new_helper(type: :url) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 109
+def new_helper(type: :url) # :doc:
+  "new_#{singular_route_name}_#{type}"
+end
+
+
+ +
+ +
+

+ + plural_file_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 121
+def plural_file_name # :doc:
+  @plural_file_name ||= file_name.pluralize
+end
+
+
+ +
+ +
+

+ + plural_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 78
+def plural_name # :doc:
+  @plural_name ||= singular_name.pluralize
+end
+
+
+ +
+ +
+

+ + plural_route_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 167
+def plural_route_name # :doc:
+  if options[:model_name]
+    "#{controller_class_path.join('_')}_#{plural_table_name}"
+  else
+    plural_table_name
+  end
+end
+
+
+ +
+ +
+

+ + plural_table_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 117
+def plural_table_name # :doc:
+  @plural_table_name ||= (pluralize_table_names? ? table_name : table_name.pluralize)
+end
+
+
+ +
+ +
+

+ + pluralize_table_names?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 196
+def pluralize_table_names? # :doc:
+  !defined?(ActiveRecord::Base) || ActiveRecord::Base.pluralize_table_names
+end
+
+
+ +
+ +
+

+ + redirect_resource_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 146
+def redirect_resource_name # :doc:
+  model_resource_name(prefix: "@")
+end
+
+
+ +
+ +
+

+ + regular_class_path() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 62
+def regular_class_path # :doc:
+  @class_path
+end
+
+
+ +
+ +
+

+ + route_url() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 129
+def route_url # :doc:
+  @route_url ||= controller_class_path.collect { |dname| "/" + dname }.join + "/" + plural_file_name
+end
+
+
+ +
+ +
+

+ + show_helper(arg = "@#{singular_table_name}", type: :url) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 101
+def show_helper(arg = "@#{singular_table_name}", type: :url) # :doc:
+  "#{singular_route_name}_#{type}(#{arg})"
+end
+
+
+ +
+ +
+

+ + singular_name() + +

+ + +
+

FIXME: We are avoiding to use alias because a bug on thor that make this method public and add it to the task list.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 39
+def singular_name # :doc:
+  file_name
+end
+
+
+ +
+ +
+

+ + singular_route_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 159
+def singular_route_name # :doc:
+  if options[:model_name]
+    "#{controller_class_path.join('_')}_#{singular_table_name}"
+  else
+    singular_table_name
+  end
+end
+
+
+ +
+ +
+

+ + singular_table_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 113
+def singular_table_name # :doc:
+  @singular_table_name ||= (pluralize_table_names? ? table_name.singularize : table_name)
+end
+
+
+ +
+ +
+

+ + table_name() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 86
+def table_name # :doc:
+  @table_name ||= begin
+    base = pluralize_table_names? ? plural_name : singular_name
+    (class_path + [base]).join("_")
+  end
+end
+
+
+ +
+ +
+

+ + uncountable?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 93
+def uncountable? # :doc:
+  singular_name == plural_name
+end
+
+
+ +
+ +
+

+ + url_helper_prefix() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/named_base.rb, line 133
+def url_helper_prefix # :doc:
+  @url_helper_prefix ||= (class_path + [file_name]).join("_")
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/TestCase.html b/src/7.0/classes/Rails/Generators/TestCase.html new file mode 100644 index 0000000000..23c70ed8d4 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/TestCase.html @@ -0,0 +1,117 @@ +--- +title: Rails::Generators::TestCase +layout: default +--- +
+ +
+
+ +
+ +

This class provides a TestCase for testing generators. To set up, you need just to configure the destination and set which generator is being tested:

+ +
class AppGeneratorTest < Rails::Generators::TestCase
+  tests AppGenerator
+  destination File.expand_path("../tmp", __dir__)
+end
+
+ +

If you want to ensure your destination root is clean before running each test, you can set a setup callback:

+ +
class AppGeneratorTest < Rails::Generators::TestCase
+  tests AppGenerator
+  destination File.expand_path("../tmp", __dir__)
+  setup :prepare_destination
+end
+
+ +
+ + + + + + + + + + + + + + +

Included Modules

+ + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Testing.html b/src/7.0/classes/Rails/Generators/Testing.html new file mode 100644 index 0000000000..6f20acefd5 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Testing.html @@ -0,0 +1,75 @@ +--- +title: Rails::Generators::Testing +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Testing/Assertions.html b/src/7.0/classes/Rails/Generators/Testing/Assertions.html new file mode 100644 index 0000000000..460cf462eb --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Testing/Assertions.html @@ -0,0 +1,545 @@ +--- +title: Rails::Generators::Testing::Assertions +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + assert_class_method(method, content, &block) + +

+ + +
+

Asserts the given class method exists in the given content. This method does not detect class methods inside (class << self), only class methods which starts with “self.”. When a block is given, it yields the content of the method.

+ +
assert_migration "db/migrate/create_products.rb" do |migration|
+  assert_class_method :up, migration do |up|
+    assert_match(/create_table/, up)
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 88
+def assert_class_method(method, content, &block)
+  assert_instance_method "self.#{method}", content, &block
+end
+
+
+ +
+ +
+

+ + assert_directory(relative, *contents) + +

+ + +
+ +
+ + + + + +
+ Alias for: assert_file +
+ + + +
+ +
+

+ + assert_field_default_value(attribute_type, value) + +

+ + +
+

Asserts the given attribute type gets a proper default value:

+ +
assert_field_default_value :string, "MyString"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 117
+def assert_field_default_value(attribute_type, value)
+  if value.nil?
+    assert_nil(create_generated_attribute(attribute_type).default)
+  else
+    assert_equal(value, create_generated_attribute(attribute_type).default)
+  end
+end
+
+
+ +
+ +
+

+ + assert_field_type(attribute_type, field_type) + +

+ + +
+

Asserts the given attribute type gets translated to a field type properly:

+ +
assert_field_type :date, :date_select
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 110
+def assert_field_type(attribute_type, field_type)
+  assert_equal(field_type, create_generated_attribute(attribute_type).field_type)
+end
+
+
+ +
+ +
+

+ + assert_file(relative, *contents) + +

+ + +
+

Asserts a given file exists. You need to supply an absolute path or a path relative to the configured destination:

+ +
assert_file "config/environment.rb"
+
+ +

You can also give extra arguments. If the argument is a regexp, it will check if the regular expression matches the given file content. If it’s a string, it compares the file with the given string:

+ +
assert_file "config/environment.rb", /initialize/
+
+ +

Finally, when a block is given, it yields the file content:

+ +
assert_file "app/controllers/products_controller.rb" do |controller|
+  assert_instance_method :index, controller do |index|
+    assert_match(/Product\.all/, index)
+  end
+end
+
+
+ + + +
+ Also aliased as: assert_directory +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 25
+def assert_file(relative, *contents)
+  absolute = File.expand_path(relative, destination_root)
+  assert File.exist?(absolute), "Expected file #{relative.inspect} to exist, but does not"
+
+  read = File.read(absolute) if block_given? || !contents.empty?
+  assert_nothing_raised { yield read } if block_given?
+
+  contents.each do |content|
+    case content
+    when String
+      assert_equal content, read
+    when Regexp
+      assert_match content, read
+    end
+  end
+end
+
+
+ +
+ +
+

+ + assert_instance_method(method, content) + +

+ + +
+

Asserts the given method exists in the given content. When a block is given, it yields the content of the method.

+ +
assert_file "app/controllers/products_controller.rb" do |controller|
+  assert_instance_method :index, controller do |index|
+    assert_match(/Product\.all/, index)
+  end
+end
+
+
+ + + +
+ Also aliased as: assert_method +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 100
+def assert_instance_method(method, content)
+  assert content =~ /(\s+)def #{method}(\(.+\))?(.*?)\n\1end/m, "Expected to have method #{method}"
+  assert_nothing_raised { yield $3.strip } if block_given?
+end
+
+
+ +
+ +
+

+ + assert_method(method, content) + +

+ + +
+ +
+ + + + + +
+ Alias for: assert_instance_method +
+ + + +
+ +
+

+ + assert_migration(relative, *contents, &block) + +

+ + +
+

Asserts a given migration exists. You need to supply an absolute path or a path relative to the configured destination:

+ +
assert_migration "db/migrate/create_products.rb"
+
+ +

This method manipulates the given path and tries to find any migration which matches the migration name. For example, the call above is converted to:

+ +
assert_file "db/migrate/003_create_products.rb"
+
+ +

Consequently, assert_migration accepts the same arguments has assert_file.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 64
+def assert_migration(relative, *contents, &block)
+  file_name = migration_file_name(relative)
+  assert file_name, "Expected migration #{relative} to exist, but was not found"
+  assert_file file_name, *contents, &block
+end
+
+
+ +
+ +
+

+ + assert_no_directory(relative) + +

+ + +
+ +
+ + + + + +
+ Alias for: assert_no_file +
+ + + +
+ +
+

+ + assert_no_file(relative) + +

+ + +
+

Asserts a given file does not exist. You need to supply an absolute path or a path relative to the configured destination:

+ +
assert_no_file "config/random.rb"
+
+
+ + + +
+ Also aliased as: assert_no_directory +
+ + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 47
+def assert_no_file(relative)
+  absolute = File.expand_path(relative, destination_root)
+  assert !File.exist?(absolute), "Expected file #{relative.inspect} to not exist, but does"
+end
+
+
+ +
+ +
+

+ + assert_no_migration(relative) + +

+ + +
+

Asserts a given migration does not exist. You need to supply an absolute path or a path relative to the configured destination:

+ +
assert_no_migration "db/migrate/create_products.rb"
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/assertions.rb, line 74
+def assert_no_migration(relative)
+  file_name = migration_file_name(relative)
+  assert_nil file_name, "Expected migration #{relative} to not exist, but found #{file_name}"
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Testing/Behaviour.html b/src/7.0/classes/Rails/Generators/Testing/Behaviour.html new file mode 100644 index 0000000000..39640c4177 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Testing/Behaviour.html @@ -0,0 +1,257 @@ +--- +title: Rails::Generators::Testing::Behaviour +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create_generated_attribute(attribute_type, name = "test", index = nil) + +

+ + +
+

Create a Rails::Generators::GeneratedAttribute by supplying the attribute type and, optionally, the attribute name:

+ +
create_generated_attribute(:string, "name")
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 85
+def create_generated_attribute(attribute_type, name = "test", index = nil)
+  Rails::Generators::GeneratedAttribute.parse([name, attribute_type, index].compact.join(":"))
+end
+
+
+ +
+ +
+

+ + generator(args = default_arguments, options = {}, config = {}) + +

+ + +
+

Instantiate the generator.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 77
+def generator(args = default_arguments, options = {}, config = {})
+  @generator ||= generator_class.new(args, options, config.reverse_merge(destination_root: destination_root))
+end
+
+
+ +
+ +
+

+ + run_generator(args = default_arguments, config = {}) + +

+ + +
+

Runs the generator configured for this class. The first argument is an array like command line arguments:

+ +
class AppGeneratorTest < Rails::Generators::TestCase
+  tests AppGenerator
+  destination File.expand_path("../tmp", __dir__)
+  setup :prepare_destination
+
+  test "database.yml is not created when skipping Active Record" do
+    run_generator %w(myapp --skip-active-record)
+    assert_no_file "config/database.yml"
+  end
+end
+
+ +

You can provide a configuration hash as second argument. This method returns the output printed by the generator.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 67
+def run_generator(args = default_arguments, config = {})
+  capture(:stdout) do
+    args += ["--skip-bundle"] unless args.include?("--no-skip-bundle") || args.include?("--dev")
+    args += ["--skip-bootsnap"] unless args.include?("--no-skip-bootsnap") || args.include?("--skip-bootsnap")
+
+    generator_class.start(args, config.reverse_merge(destination_root: destination_root))
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + prepare_destination() + +

+ + +
+

Clears all files and directories in destination.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 99
+def prepare_destination # :doc:
+  rm_rf(destination_root)
+  mkdir_p(destination_root)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Testing/Behaviour/ClassMethods.html b/src/7.0/classes/Rails/Generators/Testing/Behaviour/ClassMethods.html new file mode 100644 index 0000000000..0fe005b9b4 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Testing/Behaviour/ClassMethods.html @@ -0,0 +1,188 @@ +--- +title: Rails::Generators::Testing::Behaviour::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + arguments(array) + +

+ + +
+

Sets default arguments on generator invocation. This can be overwritten when invoking it.

+ +
arguments %w(app_name --skip-active-record)
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 39
+def arguments(array)
+  self.default_arguments = array
+end
+
+
+ +
+ +
+

+ + destination(path) + +

+ + +
+

Sets the destination of generator files:

+ +
destination File.expand_path("../tmp", __dir__)
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 46
+def destination(path)
+  self.destination_root = path
+end
+
+
+ +
+ +
+

+ + tests(klass) + +

+ + +
+

Sets which generator should be tested:

+ +
tests AppGenerator
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/testing/behaviour.rb, line 31
+def tests(klass)
+  self.generator_class = klass
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Generators/Testing/SetupAndTeardown.html b/src/7.0/classes/Rails/Generators/Testing/SetupAndTeardown.html new file mode 100644 index 0000000000..40db211a23 --- /dev/null +++ b/src/7.0/classes/Rails/Generators/Testing/SetupAndTeardown.html @@ -0,0 +1,54 @@ +--- +title: Rails::Generators::Testing::SetupAndTeardown +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Info.html b/src/7.0/classes/Rails/Info.html new file mode 100644 index 0000000000..dfbccfc684 --- /dev/null +++ b/src/7.0/classes/Rails/Info.html @@ -0,0 +1,236 @@ +--- +title: Rails::Info +layout: default +--- +
+ +
+
+ +
+ +

This module helps build the runtime properties that are displayed in Rails::InfoController responses. These include the active Rails version, Ruby version, Rack version, and so on.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + inspect() + +

+ + +
+ +
+ + + + + +
+ Alias for: to_s +
+ + + +
+ +
+

+ + property(name, value = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/info.rb, line 25
+def property(name, value = nil)
+  value ||= yield
+  properties << [name, value] if value
+rescue Exception
+end
+
+
+ +
+ +
+

+ + to_html() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/info.rb, line 43
+def to_html
+  (+"<table>").tap do |table|
+    properties.each do |(name, value)|
+      table << %(<tr><td class="name">#{CGI.escapeHTML(name.to_s)}</td>)
+      formatted_value = if value.kind_of?(Array)
+        "<ul>" + value.map { |v| "<li>#{CGI.escapeHTML(v.to_s)}</li>" }.join + "</ul>"
+      else
+        CGI.escapeHTML(value.to_s)
+      end
+      table << %(<td class="value">#{formatted_value}</td></tr>)
+    end
+    table << "</table>"
+  end
+end
+
+
+ +
+ +
+

+ + to_s() + +

+ + +
+ +
+ + + +
+ Also aliased as: inspect +
+ + + + + + +
+ + +
+
# File railties/lib/rails/info.rb, line 31
+def to_s
+  column_width = properties.names.map(&:length).max
+  info = properties.map do |name, value|
+    value = value.join(", ") if value.is_a?(Array)
+    "%-#{column_width}s   %s" % [name, value]
+  end
+  info.unshift "About your application's environment"
+  info * "\n"
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Initializable.html b/src/7.0/classes/Rails/Initializable.html new file mode 100644 index 0000000000..f88e336829 --- /dev/null +++ b/src/7.0/classes/Rails/Initializable.html @@ -0,0 +1,166 @@ +--- +title: Rails::Initializable +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + initializers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 66
+def initializers
+  @initializers ||= self.class.initializers_for(self)
+end
+
+
+ +
+ +
+

+ + run_initializers(group = :default, *args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 58
+def run_initializers(group = :default, *args)
+  return if instance_variable_defined?(:@ran)
+  initializers.tsort_each do |initializer|
+    initializer.run(*args) if initializer.belongs_to?(group)
+  end
+  @ran = true
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Initializable/ClassMethods.html b/src/7.0/classes/Rails/Initializable/ClassMethods.html new file mode 100644 index 0000000000..3fcb14802f --- /dev/null +++ b/src/7.0/classes/Rails/Initializable/ClassMethods.html @@ -0,0 +1,225 @@ +--- +title: Rails::Initializable::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + initializer(name, opts = {}, &blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 88
+def initializer(name, opts = {}, &blk)
+  raise ArgumentError, "A block must be passed when defining an initializer" unless blk
+  opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
+  initializers << Initializer.new(name, nil, opts, &blk)
+end
+
+
+ +
+ +
+

+ + initializers() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 71
+def initializers
+  @initializers ||= Collection.new
+end
+
+
+ +
+ +
+

+ + initializers_chain() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 75
+def initializers_chain
+  initializers = Collection.new
+  ancestors.reverse_each do |klass|
+    next unless klass.respond_to?(:initializers)
+    initializers = initializers + klass.initializers
+  end
+  initializers
+end
+
+
+ +
+ +
+

+ + initializers_for(binding) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 84
+def initializers_for(binding)
+  Collection.new(initializers_chain.map { |i| i.bind(binding) })
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Initializable/Collection.html b/src/7.0/classes/Rails/Initializable/Collection.html new file mode 100644 index 0000000000..44eabaae79 --- /dev/null +++ b/src/7.0/classes/Rails/Initializable/Collection.html @@ -0,0 +1,158 @@ +--- +title: Rails::Initializable::Collection +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+
    + +
  • + + TSort + +
  • + +
+ + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + +(other) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 53
+def +(other)
+  Collection.new(to_a + other.to_a)
+end
+
+
+ +
+ +
+

+ + tsort_each_child(initializer, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 49
+def tsort_each_child(initializer, &block)
+  select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Initializable/Initializer.html b/src/7.0/classes/Rails/Initializable/Initializer.html new file mode 100644 index 0000000000..828961b30b --- /dev/null +++ b/src/7.0/classes/Rails/Initializable/Initializer.html @@ -0,0 +1,368 @@ +--- +title: Rails::Initializable::Initializer +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + + + + + + + +
+ [R] + block
+ [R] + name
+ + + + +

Class Public methods

+ +
+

+ + new(name, context, options, &block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 14
+def initialize(name, context, options, &block)
+  options[:group] ||= :default
+  @name, @context, @options, @block = name, context, options, block
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + after() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 23
+def after
+  @options[:after]
+end
+
+
+ +
+ +
+

+ + before() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 19
+def before
+  @options[:before]
+end
+
+
+ +
+ +
+

+ + belongs_to?(group) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 27
+def belongs_to?(group)
+  @options[:group] == group || @options[:group] == :all
+end
+
+
+ +
+ +
+

+ + bind(context) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 35
+def bind(context)
+  return self if @context
+  Initializer.new(@name, context, @options, &block)
+end
+
+
+ +
+ +
+

+ + context_class() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 40
+def context_class
+  @context.class
+end
+
+
+ +
+ +
+

+ + run(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/initializable.rb, line 31
+def run(*args)
+  @context.instance_exec(*args, &block)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Paths.html b/src/7.0/classes/Rails/Paths.html new file mode 100644 index 0000000000..ea6bfe1177 --- /dev/null +++ b/src/7.0/classes/Rails/Paths.html @@ -0,0 +1,69 @@ +--- +title: Rails::Paths +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Paths/Path.html b/src/7.0/classes/Rails/Paths/Path.html new file mode 100644 index 0000000000..c78e7e6590 --- /dev/null +++ b/src/7.0/classes/Rails/Paths/Path.html @@ -0,0 +1,707 @@ +--- +title: Rails::Paths::Path +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + glob
+ + + + +

Class Public methods

+ +
+

+ + new(root, current, paths, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 116
+def initialize(root, current, paths, options = {})
+  @paths   = paths
+  @current = current
+  @root    = root
+  @glob    = options[:glob]
+  @exclude = options[:exclude]
+
+  options[:autoload_once] ? autoload_once! : skip_autoload_once!
+  options[:eager_load]    ? eager_load!    : skip_eager_load!
+  options[:autoload]      ? autoload!      : skip_autoload!
+  options[:load_path]     ? load_path!     : skip_load_path!
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + <<(path) + +

+ + +
+ +
+ + + +
+ Also aliased as: push +
+ + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 168
+def <<(path)
+  @paths << path
+end
+
+
+ +
+ +
+

+ + children() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 133
+def children
+  keys = @root.keys.find_all { |k|
+    k.start_with?(@current) && k != @current
+  }
+  @root.values_at(*keys.sort)
+end
+
+
+ +
+ +
+

+ + concat(paths) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 173
+def concat(paths)
+  @paths.concat paths
+end
+
+
+ +
+ +
+

+ + each(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 164
+def each(&block)
+  @paths.each(&block)
+end
+
+
+ +
+ +
+

+ + existent() + +

+ + +
+

Returns all expanded paths but only if they exist in the filesystem.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 217
+def existent
+  expanded.select do |f|
+    does_exist = File.exist?(f)
+
+    if !does_exist && File.symlink?(f)
+      raise "File #{f.inspect} is a symlink that does not point to a valid file"
+    end
+    does_exist
+  end
+end
+
+
+ +
+ +
+

+ + existent_directories() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 228
+def existent_directories
+  expanded.select { |d| File.directory?(d) }
+end
+
+
+ +
+ +
+

+ + expanded() + +

+ + +
+

Expands all paths against the root and return all unique values.

+
+ + + +
+ Also aliased as: to_a +
+ + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 198
+def expanded
+  raise "You need to set a path root" unless @root.path
+  result = []
+
+  each do |path|
+    path = File.expand_path(path, @root.path)
+
+    if @glob && File.directory?(path)
+      result.concat files_in(path)
+    else
+      result << path
+    end
+  end
+
+  result.uniq!
+  result
+end
+
+
+ +
+ +
+

+ + first() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 140
+def first
+  expanded.first
+end
+
+
+ +
+ +
+

+ + last() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 144
+def last
+  expanded.last
+end
+
+
+ +
+ +
+

+ + paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 185
+def paths
+  raise "You need to set a path root" unless @root.path
+
+  map do |p|
+    Pathname.new(@root.path).join(p)
+  end
+end
+
+
+ +
+ +
+

+ + push(path) + +

+ + +
+ +
+ + + + + +
+ Alias for: << +
+ + + +
+ +
+

+ + to_a() + +

+ + +
+ +
+ + + + + +
+ Alias for: expanded +
+ + + +
+ +
+

+ + to_ary() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 181
+def to_ary
+  @paths
+end
+
+
+ +
+ +
+

+ + unshift(*paths) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 177
+def unshift(*paths)
+  @paths.unshift(*paths)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Paths/Root.html b/src/7.0/classes/Rails/Paths/Root.html new file mode 100644 index 0000000000..a39aa70bc1 --- /dev/null +++ b/src/7.0/classes/Rails/Paths/Root.html @@ -0,0 +1,601 @@ +--- +title: Rails::Paths::Root +layout: default +--- +
+ +
+
+ +
+ +

This object is an extended hash that behaves as root of the Rails::Paths system. It allows you to collect information about how you want to structure your application paths through a Hash-like API. It requires you to give a physical path on initialization.

+ +
root = Root.new "/rails"
+root.add "app/controllers", eager_load: true
+
+ +

The above command creates a new root object and adds “app/controllers” as a path. This means we can get a Rails::Paths::Path object back like below:

+ +
path = root["app/controllers"]
+path.eager_load?               # => true
+path.is_a?(Rails::Paths::Path) # => true
+
+ +

The Path object is simply an enumerable and allows you to easily add extra paths:

+ +
path.is_a?(Enumerable) # => true
+path.to_ary.inspect    # => ["app/controllers"]
+
+path << "lib/controllers"
+path.to_ary.inspect    # => ["app/controllers", "lib/controllers"]
+
+ +

Notice that when you add a path using add, the path object created already contains the path with the same path value given to add. In some situations, you may not want this behavior, so you can give :with as option.

+ +
root.add "config/routes", with: "config/routes.rb"
+root["config/routes"].inspect # => ["config/routes.rb"]
+
+ +

The add method accepts the following options as arguments: eager_load, autoload, autoload_once, and glob.

+ +

Finally, the Path object also provides a few helpers:

+ +
root = Root.new "/rails"
+root.add "app/controllers"
+
+root["app/controllers"].expanded # => ["/rails/app/controllers"]
+root["app/controllers"].existent # => ["/rails/app/controllers"]
+
+ +

Check the Rails::Paths::Path documentation for more information.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [RW] + path
+ + + + +

Class Public methods

+ +
+

+ + new(path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 51
+def initialize(path)
+  @path = path
+  @root = {}
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + [](path) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 66
+def [](path)
+  @root[path]
+end
+
+
+ +
+ +
+

+ + []=(path, value) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 56
+def []=(path, value)
+  glob = self[path] ? self[path].glob : nil
+  add(path, with: value, glob: glob)
+end
+
+
+ +
+ +
+

+ + add(path, options = {}) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 61
+def add(path, options = {})
+  with = Array(options.fetch(:with, path))
+  @root[path] = Path.new(self, path, with, options)
+end
+
+
+ +
+ +
+

+ + all_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 82
+def all_paths
+  values.tap(&:uniq!)
+end
+
+
+ +
+ +
+

+ + autoload_once() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 86
+def autoload_once
+  filter_by(&:autoload_once?)
+end
+
+
+ +
+ +
+

+ + autoload_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 94
+def autoload_paths
+  filter_by(&:autoload?)
+end
+
+
+ +
+ +
+

+ + eager_load() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 90
+def eager_load
+  filter_by(&:eager_load?)
+end
+
+
+ +
+ +
+

+ + keys() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 74
+def keys
+  @root.keys
+end
+
+
+ +
+ +
+

+ + load_paths() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 98
+def load_paths
+  filter_by(&:load_path?)
+end
+
+
+ +
+ +
+

+ + values() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 70
+def values
+  @root.values
+end
+
+
+ +
+ +
+

+ + values_at(*list) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/paths.rb, line 78
+def values_at(*list)
+  @root.values_at(*list)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/PluginBuilder.html b/src/7.0/classes/Rails/PluginBuilder.html new file mode 100644 index 0000000000..58cf0b99be --- /dev/null +++ b/src/7.0/classes/Rails/PluginBuilder.html @@ -0,0 +1,936 @@ +--- +title: Rails::PluginBuilder +layout: default +--- +
+ +
+
+ +
+ +

The plugin builder allows you to override elements of the plugin generator without being forced to reverse the operations of the default generator.

+ +

This allows you to override entire operations, like the creation of the Gemfile, README, or JavaScript files, without needing to know exactly what those operations do so you can create another template action.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
DUMMY_IGNORE_OPTIONS=%i[dev edge master template]
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + app() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 20
+def app
+  if mountable?
+    if api?
+      directory "app", exclude_pattern: %r{app/(views|helpers)}
+    else
+      directory "app"
+      empty_directory_with_keep_file "app/assets/images/#{namespaced_name}"
+    end
+
+    empty_directory_with_keep_file "app/models/concerns"
+    empty_directory_with_keep_file "app/controllers/concerns"
+    remove_dir "app/mailers" if skip_action_mailer?
+    remove_dir "app/jobs" if options[:skip_active_job]
+  elsif full?
+    empty_directory_with_keep_file "app/models"
+    empty_directory_with_keep_file "app/controllers"
+    empty_directory_with_keep_file "app/models/concerns"
+    empty_directory_with_keep_file "app/controllers/concerns"
+    empty_directory_with_keep_file "app/mailers" unless skip_action_mailer?
+    empty_directory_with_keep_file "app/jobs" unless options[:skip_active_job]
+
+    unless api?
+      empty_directory_with_keep_file "app/assets/images/#{namespaced_name}"
+      empty_directory_with_keep_file "app/helpers"
+      empty_directory_with_keep_file "app/views"
+    end
+  end
+end
+
+
+ +
+ +
+

+ + assets_manifest() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 164
+def assets_manifest
+  template "rails/engine_manifest.js", "app/assets/config/#{underscored_name}_manifest.js"
+end
+
+
+ +
+ +
+

+ + bin(force = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 177
+def bin(force = false)
+  bin_file = engine? ? "bin/rails.tt" : "bin/test.tt"
+  template bin_file, force: force do |content|
+    "#{shebang}\n" + content
+  end
+  chmod "bin", 0755, verbose: false
+end
+
+
+ +
+ +
+

+ + config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 90
+def config
+  template "config/routes.rb" if engine?
+end
+
+
+ +
+ +
+

+ + gemfile() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 53
+def gemfile
+  template "Gemfile"
+end
+
+
+ +
+ +
+

+ + gemfile_entry() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 185
+def gemfile_entry
+  return unless inside_application?
+
+  gemfile_in_app_path = File.join(rails_app_path, "Gemfile")
+  if File.exist? gemfile_in_app_path
+    entry = "\ngem '#{name}', path: '#{relative_path}'"
+    append_file gemfile_in_app_path, entry
+  end
+end
+
+
+ +
+ +
+

+ + gemspec() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 61
+def gemspec
+  template "%name%.gemspec"
+end
+
+
+ +
+ +
+

+ + generate_test_dummy(force = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 115
+def generate_test_dummy(force = false)
+  opts = options.transform_keys(&:to_sym).except(*DUMMY_IGNORE_OPTIONS)
+  opts[:force] = force
+  opts[:skip_bundle] = true
+  opts[:skip_git] = true
+  opts[:skip_hotwire] = true
+  opts[:dummy_app] = true
+
+  invoke Rails::Generators::AppGenerator,
+    [ File.expand_path(dummy_path, destination_root) ], opts
+end
+
+
+ +
+ +
+

+ + gitignore() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 65
+def gitignore
+  template "gitignore", ".gitignore"
+end
+
+
+ +
+ +
+

+ + lib() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 78
+def lib
+  template "lib/%namespaced_name%.rb"
+  template "lib/tasks/%namespaced_name%_tasks.rake"
+  template "lib/%namespaced_name%/version.rb"
+
+  if engine?
+    template "lib/%namespaced_name%/engine.rb"
+  else
+    template "lib/%namespaced_name%/railtie.rb"
+  end
+end
+
+
+ +
+ +
+

+ + license() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 57
+def license
+  template "MIT-LICENSE" unless inside_application?
+end
+
+
+ +
+ +
+

+ + rakefile() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 16
+def rakefile
+  template "Rakefile"
+end
+
+
+ +
+ +
+

+ + readme() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 49
+def readme
+  template "README.md"
+end
+
+
+ +
+ +
+

+ + stylesheets() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 168
+def stylesheets
+  if mountable?
+    copy_file "rails/stylesheets.css",
+              "app/assets/stylesheets/#{namespaced_name}/application.css"
+  elsif full?
+    empty_directory_with_keep_file "app/assets/stylesheets/#{namespaced_name}"
+  end
+end
+
+
+ +
+ +
+

+ + test() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 94
+def test
+  template "test/test_helper.rb"
+  template "test/%namespaced_name%_test.rb"
+
+  if engine?
+    empty_directory_with_keep_file "test/fixtures/files"
+    empty_directory_with_keep_file "test/controllers"
+    empty_directory_with_keep_file "test/mailers"
+    empty_directory_with_keep_file "test/models"
+    empty_directory_with_keep_file "test/integration"
+
+    unless api?
+      empty_directory_with_keep_file "test/helpers"
+    end
+
+    template "test/integration/navigation_test.rb"
+  end
+end
+
+
+ +
+ +
+

+ + test_dummy_clean() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 151
+def test_dummy_clean
+  inside dummy_path do
+    remove_file ".ruby-version"
+    remove_file "db/seeds.rb"
+    remove_file "Gemfile"
+    remove_file "lib/tasks"
+    remove_file "public/robots.txt"
+    remove_file "README.md"
+    remove_file "test"
+    remove_file "vendor"
+  end
+end
+
+
+ +
+ +
+

+ + test_dummy_config() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 127
+    def test_dummy_config
+      template "rails/boot.rb", "#{dummy_path}/config/boot.rb", force: true
+
+      insert_into_file "#{dummy_path}/config/application.rb", <<~RUBY, after: /^Bundler\.require.+\n/
+        require #{namespaced_name.inspect}
+      RUBY
+
+      if mountable?
+        template "rails/routes.rb", "#{dummy_path}/config/routes.rb", force: true
+      end
+      if engine? && !api?
+        insert_into_file "#{dummy_path}/config/application.rb", indent(<<~RUBY, 4), after: /^\s*config\.load_defaults.*\n/
+
+          # For compatibility with applications that use this config
+          config.action_controller.include_all_helpers = false
+        RUBY
+      end
+    end
+
+
+ +
+ +
+

+ + test_dummy_sprocket_assets() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 146
+def test_dummy_sprocket_assets
+  template "rails/stylesheets.css",   "#{dummy_path}/app/assets/stylesheets/application.css", force: true
+  template "rails/dummy_manifest.js", "#{dummy_path}/app/assets/config/manifest.js", force: true
+end
+
+
+ +
+ +
+

+ + version_control() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/generators/rails/plugin/plugin_generator.rb, line 69
+def version_control
+  if !options[:skip_git] && !options[:pretend]
+    run "git init", capture: options[:quiet], abort_on_failure: false
+    if user_default_branch.strip.empty?
+      `git symbolic-ref HEAD refs/heads/main`
+    end
+  end
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rack.html b/src/7.0/classes/Rails/Rack.html new file mode 100644 index 0000000000..7569dff9be --- /dev/null +++ b/src/7.0/classes/Rails/Rack.html @@ -0,0 +1,69 @@ +--- +title: Rails::Rack +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rack/Logger.html b/src/7.0/classes/Rails/Rack/Logger.html new file mode 100644 index 0000000000..6bfb9e441a --- /dev/null +++ b/src/7.0/classes/Rails/Rack/Logger.html @@ -0,0 +1,311 @@ +--- +title: Rails::Rack::Logger +layout: default +--- +
+ +
+
+ +
+ +

Sets log tags, logs the request, calls the app, and flushes the logs.

+ +

Log tags (taggers) can be an Array containing: methods that the request object responds to, objects that respond to to_s or Proc objects that accept an instance of the request object.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(app, taggers = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/rack/logger.rb, line 16
+def initialize(app, taggers = nil)
+  @app          = app
+  @taggers      = taggers || []
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + call(env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/rack/logger.rb, line 21
+def call(env)
+  request = ActionDispatch::Request.new(env)
+
+  if logger.respond_to?(:tagged)
+    logger.tagged(compute_tags(request)) { call_app(request, env) }
+  else
+    call_app(request, env)
+  end
+end
+
+
+ +
+ + +

Instance Private methods

+ +
+

+ + call_app(request, env) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/rack/logger.rb, line 32
+def call_app(request, env) # :doc:
+  instrumenter = ActiveSupport::Notifications.instrumenter
+  instrumenter_state = instrumenter.start "request.action_dispatch", request: request
+  instrumenter_finish = -> () {
+    instrumenter.finish_with_state(instrumenter_state, "request.action_dispatch", request: request)
+  }
+
+  logger.info { started_request_message(request) }
+  status, headers, body = @app.call(env)
+  body = ::Rack::BodyProxy.new(body, &instrumenter_finish)
+  [status, headers, body]
+rescue Exception
+  instrumenter_finish.call
+  raise
+ensure
+  ActiveSupport::LogSubscriber.flush_all!
+end
+
+
+ +
+ +
+

+ + compute_tags(request) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/rack/logger.rb, line 59
+def compute_tags(request) # :doc:
+  @taggers.collect do |tag|
+    case tag
+    when Proc
+      tag.call(request)
+    when Symbol
+      request.send(tag)
+    else
+      tag
+    end
+  end
+end
+
+
+ +
+ +
+

+ + started_request_message(request) + +

+ + +
+

Started GET “/session/new” for 127.0.0.1 at 2012-09-26 14:51:42 -0700

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/rack/logger.rb, line 51
+def started_request_message(request) # :doc:
+  'Started %s "%s" for %s at %s' % [
+    request.raw_request_method,
+    request.filtered_path,
+    request.remote_ip,
+    Time.now.to_default_s ]
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails.html b/src/7.0/classes/Rails/Rails.html new file mode 100644 index 0000000000..87863b394d --- /dev/null +++ b/src/7.0/classes/Rails/Rails.html @@ -0,0 +1,145 @@ +--- +title: Rails::Rails +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor.html b/src/7.0/classes/Rails/Rails/Conductor.html new file mode 100644 index 0000000000..540e77c6e0 --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor.html @@ -0,0 +1,65 @@ +--- +title: Rails::Rails::Conductor +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox.html new file mode 100644 index 0000000000..dad5972e9a --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox.html @@ -0,0 +1,76 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox +layout: default +--- +
+ +
+ + +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails.html new file mode 100644 index 0000000000..c4f611f477 --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails.html @@ -0,0 +1,65 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox::InboundEmails +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails/SourcesController.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails/SourcesController.html new file mode 100644 index 0000000000..db9fd81a0c --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmails/SourcesController.html @@ -0,0 +1,146 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox::InboundEmails::SourcesController +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller.rb, line 8
+def create
+  inbound_email = ActionMailbox::InboundEmail.create_and_extract_message_id! params[:source]
+  redirect_to main_app.rails_conductor_inbound_email_url(inbound_email)
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller.rb, line 5
+def new
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmailsController.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmailsController.html new file mode 100644 index 0000000000..abcdfaa239 --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/InboundEmailsController.html @@ -0,0 +1,224 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox::InboundEmailsController +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb, line 16
+def create
+  inbound_email = create_inbound_email(new_mail)
+  redirect_to main_app.rails_conductor_inbound_email_url(inbound_email)
+end
+
+
+ +
+ +
+

+ + index() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb, line 5
+def index
+  @inbound_emails = ActionMailbox::InboundEmail.order(created_at: :desc)
+end
+
+
+ +
+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb, line 9
+def new
+end
+
+
+ +
+ +
+

+ + show() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller.rb, line 12
+def show
+  @inbound_email = ActionMailbox::InboundEmail.find(params[:id])
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/IncineratesController.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/IncineratesController.html new file mode 100644 index 0000000000..33b4b1f5a6 --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/IncineratesController.html @@ -0,0 +1,115 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox::IncineratesController +layout: default +--- +
+ +
+
+ +
+ +

Incinerating will destroy an email that is due and has already been processed.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/incinerates_controller.rb, line 6
+def create
+  ActionMailbox::InboundEmail.find(params[:inbound_email_id]).incinerate
+
+  redirect_to main_app.rails_conductor_inbound_emails_url
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/ReroutesController.html b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/ReroutesController.html new file mode 100644 index 0000000000..03cf01c92c --- /dev/null +++ b/src/7.0/classes/Rails/Rails/Conductor/ActionMailbox/ReroutesController.html @@ -0,0 +1,116 @@ +--- +title: Rails::Rails::Conductor::ActionMailbox::ReroutesController +layout: default +--- +
+ +
+
+ +
+ +

Rerouting will run routing and processing on an email that has already been, or attempted to be, processed.

+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + create() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File actionmailbox/app/controllers/rails/conductor/action_mailbox/reroutes_controller.rb, line 6
+def create
+  inbound_email = ActionMailbox::InboundEmail.find(params[:inbound_email_id])
+  reroute inbound_email
+
+  redirect_to main_app.rails_conductor_inbound_email_url(inbound_email)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Railtie.html b/src/7.0/classes/Rails/Railtie.html new file mode 100644 index 0000000000..78812ea6fb --- /dev/null +++ b/src/7.0/classes/Rails/Railtie.html @@ -0,0 +1,772 @@ +--- +title: Rails::Railtie +layout: default +--- +
+ +
+
+ +
+ +

Rails::Railtie is the core of the Rails framework and provides several hooks to extend Rails and/or modify the initialization process.

+ +

Every major component of Rails (Action Mailer, Action Controller, Active Record, etc.) implements a railtie. Each of them is responsible for their own initialization. This makes Rails itself absent of any component hooks, allowing other components to be used in place of any of the Rails defaults.

+ +

Developing a Rails extension does not require implementing a railtie, but if you need to interact with the Rails framework during or after boot, then a railtie is needed.

+ +

For example, an extension doing any of the following would need a railtie:

+
  • +

    creating initializers

    +
  • +

    configuring a Rails framework for the application, like setting a generator

    +
  • +

    adding config.* keys to the environment

    +
  • +

    setting up a subscriber with ActiveSupport::Notifications

    +
  • +

    adding Rake tasks

    +
+ +

Creating a Railtie

+ +

To extend Rails using a railtie, create a subclass of Rails::Railtie. This class must be loaded during the Rails boot process, and is conventionally called MyNamespace::Railtie.

+ +

The following example demonstrates an extension which can be used with or without Rails.

+ +
# lib/my_gem/railtie.rb
+module MyGem
+  class Railtie < Rails::Railtie
+  end
+end
+
+# lib/my_gem.rb
+require "my_gem/railtie" if defined?(Rails::Railtie)
+
+ +

Initializers

+ +

To add an initialization step to the Rails boot process from your railtie, just define the initialization code with the initializer macro:

+ +
class MyRailtie < Rails::Railtie
+  initializer "my_railtie.configure_rails_initialization" do
+    # some initialization behavior
+  end
+end
+
+ +

If specified, the block can also receive the application object, in case you need to access some application-specific configuration, like middleware:

+ +
class MyRailtie < Rails::Railtie
+  initializer "my_railtie.configure_rails_initialization" do |app|
+    app.middleware.use MyRailtie::Middleware
+  end
+end
+
+ +

Finally, you can also pass :before and :after as options to initializer, in case you want to couple it with a specific step in the initialization process.

+ +

Configuration

+ +

Railties can access a config object which contains configuration shared by all railties and the application:

+ +
class MyRailtie < Rails::Railtie
+  # Customize the ORM
+  config.app_generators.orm :my_railtie_orm
+
+  # Add a to_prepare block which is executed once in production
+  # and before each request in development.
+  config.to_prepare do
+    MyRailtie.setup!
+  end
+end
+
+ +

Loading Rake Tasks and Generators

+ +

If your railtie has Rake tasks, you can tell Rails to load them through the method rake_tasks:

+ +
class MyRailtie < Rails::Railtie
+  rake_tasks do
+    load "path/to/my_railtie.tasks"
+  end
+end
+
+ +

By default, Rails loads generators from your load path. However, if you want to place your generators at a different location, you can specify in your railtie a block which will load them during normal generators lookup:

+ +
class MyRailtie < Rails::Railtie
+  generators do
+    require "path/to/my_railtie_generator"
+  end
+end
+
+ +

Since filenames on the load path are shared across gems, be sure that files you load through a railtie have unique names.

+ +

Run another program when the Rails server starts

+ +

In development, it’s very usual to have to run another process next to the Rails Server. In example you might want to start the Webpack or React server. Or maybe you need to run your job scheduler process like Sidekiq. This is usually done by opening a new shell and running the program from here.

+ +

Rails allow you to specify a server block which will get called when a Rails server starts. This way, your users don’t need to remember to have to open a new shell and run another program, making this less confusing for everyone. It can be used like this:

+ +
class MyRailtie < Rails::Railtie
+  server do
+    WebpackServer.start
+  end
+end
+
+ +

Application and Engine

+ +

An engine is nothing more than a railtie with some initializers already set. And since Rails::Application is an engine, the same configuration described here can be used in both.

+ +

Be sure to look at the documentation of those specific classes for more information.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + +
ABSTRACT_RAILTIES=%w(Rails::Railtie Rails::Engine Rails::Application)
 
+ + + + +

Attributes

+ + + + + + + + +
+ [R] + load_index
+ + + + +

Class Public methods

+ +
+

+ + abstract_railtie?() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 172
+def abstract_railtie?
+  ABSTRACT_RAILTIES.include?(name)
+end
+
+
+ +
+ +
+

+ + configure(&block) + +

+ + +
+

Allows you to configure the railtie. This is the same method seen in Railtie::Configurable, but this module is no longer required for all subclasses of Railtie so we provide the class method here.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 190
+def configure(&block)
+  instance.configure(&block)
+end
+
+
+ +
+ +
+

+ + console(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 156
+def console(&blk)
+  register_block_for(:load_console, &blk)
+end
+
+
+ +
+ +
+

+ + generators(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 164
+def generators(&blk)
+  register_block_for(:generators, &blk)
+end
+
+
+ +
+ +
+

+ + inherited(subclass) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 198
+def inherited(subclass)
+  subclass.increment_load_index
+  super
+end
+
+
+ +
+ +
+

+ + instance() + +

+ + +
+

Since Rails::Railtie cannot be instantiated, any methods that call instance are intended to be called only on subclasses of a Railtie.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 183
+def instance
+  @instance ||= new
+end
+
+
+ +
+ +
+

+ + railtie_name(name = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 176
+def railtie_name(name = nil)
+  @railtie_name = name.to_s if name
+  @railtie_name ||= generate_railtie_name(self.name)
+end
+
+
+ +
+ +
+

+ + rake_tasks(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 152
+def rake_tasks(&blk)
+  register_block_for(:rake_tasks, &blk)
+end
+
+
+ +
+ +
+

+ + runner(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 160
+def runner(&blk)
+  register_block_for(:runner, &blk)
+end
+
+
+ +
+ +
+

+ + server(&blk) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 168
+def server(&blk)
+  register_block_for(:server, &blk)
+end
+
+
+ +
+ +
+

+ + subclasses() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 148
+def subclasses
+  super.reject(&:abstract_railtie?).sort
+end
+
+
+ +
+ + +

Class Protected methods

+ +
+

+ + increment_load_index() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 206
+def increment_load_index
+  @@load_counter ||= 0
+  @load_index = (@@load_counter += 1)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + config() + +

+ + +
+

This is used to create the config object on Railties, an instance of Railtie::Configuration, that is used by Railties and Application to store related configuration.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie.rb, line 263
+def config
+  @config ||= Railtie::Configuration.new
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Railtie/Configurable.html b/src/7.0/classes/Rails/Railtie/Configurable.html new file mode 100644 index 0000000000..0729b006d5 --- /dev/null +++ b/src/7.0/classes/Rails/Railtie/Configurable.html @@ -0,0 +1,67 @@ +--- +title: Rails::Railtie::Configurable +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Railtie/Configurable/ClassMethods.html b/src/7.0/classes/Rails/Railtie/Configurable/ClassMethods.html new file mode 100644 index 0000000000..3dc6d2ffec --- /dev/null +++ b/src/7.0/classes/Rails/Railtie/Configurable/ClassMethods.html @@ -0,0 +1,218 @@ +--- +title: Rails::Railtie::Configurable::ClassMethods +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + configure(&block) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configurable.rb, line 25
+def configure(&block)
+  class_eval(&block)
+end
+
+
+ +
+ +
+

+ + inherited(base) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configurable.rb, line 13
+def inherited(base)
+  raise "You cannot inherit from a #{superclass.name} child"
+end
+
+
+ +
+ +
+

+ + instance() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configurable.rb, line 17
+def instance
+  @instance ||= new
+end
+
+
+ +
+ +
+

+ + respond_to?(*args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configurable.rb, line 21
+def respond_to?(*args)
+  super || instance.respond_to?(*args)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Railtie/Configuration.html b/src/7.0/classes/Rails/Railtie/Configuration.html new file mode 100644 index 0000000000..eb61c841d6 --- /dev/null +++ b/src/7.0/classes/Rails/Railtie/Configuration.html @@ -0,0 +1,584 @@ +--- +title: Rails::Railtie::Configuration +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 8
+def initialize
+  @@options ||= {}
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + after_initialize(&block) + +

+ + +
+

Last configurable block to run. Called after frameworks initialize.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 70
+def after_initialize(&block)
+  ActiveSupport.on_load(:after_initialize, yield: true, &block)
+end
+
+
+ +
+ +
+

+ + app_generators() + +

+ + +
+

This allows you to modify application’s generators from Railties.

+ +

Values set on app_generators will become defaults for application, unless application overwrites them.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 47
+def app_generators
+  @@app_generators ||= Rails::Configuration::Generators.new
+  yield(@@app_generators) if block_given?
+  @@app_generators
+end
+
+
+ +
+ +
+

+ + app_middleware() + +

+ + +
+

This allows you to modify the application’s middlewares from Engines.

+ +

All operations you run on the app_middleware will be replayed on the application once it is defined and the default_middlewares are created

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 39
+def app_middleware
+  @@app_middleware ||= Rails::Configuration::MiddlewareStackProxy.new
+end
+
+
+ +
+ +
+

+ + before_configuration(&block) + +

+ + +
+

First configurable block to run. Called before any initializers are run.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 54
+def before_configuration(&block)
+  ActiveSupport.on_load(:before_configuration, yield: true, &block)
+end
+
+
+ +
+ +
+

+ + before_eager_load(&block) + +

+ + +
+

Third configurable block to run. Does not run if config.eager_load set to false.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 60
+def before_eager_load(&block)
+  ActiveSupport.on_load(:before_eager_load, yield: true, &block)
+end
+
+
+ +
+ +
+

+ + before_initialize(&block) + +

+ + +
+

Second configurable block to run. Called before frameworks initialize.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 65
+def before_initialize(&block)
+  ActiveSupport.on_load(:before_initialize, yield: true, &block)
+end
+
+
+ +
+ +
+

+ + eager_load_namespaces() + +

+ + +
+

All namespaces that are eager loaded

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 18
+def eager_load_namespaces
+  @@eager_load_namespaces ||= []
+end
+
+
+ +
+ +
+

+ + respond_to?(name, include_private = false) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 85
+def respond_to?(name, include_private = false)
+  super || @@options.key?(name.to_sym)
+end
+
+
+ +
+ +
+

+ + to_prepare(&blk) + +

+ + +
+

Defines generic callbacks to run before after_initialize. Useful for Rails::Railtie subclasses.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 81
+def to_prepare(&blk)
+  to_prepare_blocks << blk if blk
+end
+
+
+ +
+ +
+

+ + to_prepare_blocks() + +

+ + +
+

Array of callbacks defined by to_prepare.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 75
+def to_prepare_blocks
+  @@to_prepare_blocks ||= []
+end
+
+
+ +
+ +
+

+ + watchable_dirs() + +

+ + +
+

Add directories that should be watched for change. The key of the hashes should be directories and the values should be an array of extensions to match in each directory.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 30
+def watchable_dirs
+  @@watchable_dirs ||= {}
+end
+
+
+ +
+ +
+

+ + watchable_files() + +

+ + +
+

Add files that should be watched for change.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/railtie/configuration.rb, line 23
+def watchable_files
+  @@watchable_files ||= []
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Secrets.html b/src/7.0/classes/Rails/Secrets.html new file mode 100644 index 0000000000..e8d0324b6e --- /dev/null +++ b/src/7.0/classes/Rails/Secrets.html @@ -0,0 +1,73 @@ +--- +title: Rails::Secrets +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Secrets/MissingKeyError.html b/src/7.0/classes/Rails/Secrets/MissingKeyError.html new file mode 100644 index 0000000000..3ff02c0994 --- /dev/null +++ b/src/7.0/classes/Rails/Secrets/MissingKeyError.html @@ -0,0 +1,110 @@ +--- +title: Rails::Secrets::MissingKeyError +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+
    + +
  • + new +
  • + +
+ + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/secrets.rb, line 11
+      def initialize
+        super(<<-end_of_message.squish)
+          Missing encryption key to decrypt secrets with.
+          Ask your team for your master key and put it in ENV["RAILS_MASTER_KEY"]
+        end_of_message
+      end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Server.html b/src/7.0/classes/Rails/Server.html new file mode 100644 index 0000000000..eea2b693cb --- /dev/null +++ b/src/7.0/classes/Rails/Server.html @@ -0,0 +1,366 @@ +--- +title: Rails::Server +layout: default +--- +
+ +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + new(options = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 18
+def initialize(options = nil)
+  @default_options = options || {}
+  super(@default_options)
+  set_environment
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + default_options() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 54
+def default_options
+  super.merge(@default_options)
+end
+
+
+ +
+ +
+

+ + middleware() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 50
+def middleware
+  Hash.new([])
+end
+
+
+ +
+ +
+

+ + opt_parser() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 24
+def opt_parser
+  Options.new
+end
+
+
+ +
+ +
+

+ + served_url() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 58
+def served_url
+  "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}" unless use_puma?
+end
+
+
+ +
+ +
+

+ + set_environment() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 28
+def set_environment
+  ENV["RAILS_ENV"] ||= options[:environment]
+end
+
+
+ +
+ +
+

+ + start(after_stop_callback = nil) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 32
+def start(after_stop_callback = nil)
+  trap(:INT) { exit }
+  create_tmp_directories
+  setup_dev_caching
+  log_to_stdout if options[:log_stdout]
+
+  super()
+ensure
+  after_stop_callback.call if after_stop_callback
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/Server/Options.html b/src/7.0/classes/Rails/Server/Options.html new file mode 100644 index 0000000000..6bf9504fb0 --- /dev/null +++ b/src/7.0/classes/Rails/Server/Options.html @@ -0,0 +1,107 @@ +--- +title: Rails::Server::Options +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + parse!(args) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/commands/server/server_command.rb, line 13
+def parse!(args)
+  Rails::Command::ServerCommand.new([], args).server_options
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/SourceAnnotationExtractor.html b/src/7.0/classes/Rails/SourceAnnotationExtractor.html new file mode 100644 index 0000000000..8ac40fe5cb --- /dev/null +++ b/src/7.0/classes/Rails/SourceAnnotationExtractor.html @@ -0,0 +1,390 @@ +--- +title: Rails::SourceAnnotationExtractor +layout: default +--- +
+ +
+
+ +
+ +

Implements the logic behind Rails::Command::NotesCommand. See rails notes --help for usage information.

+ +

Annotation objects are triplets :line, :tag, :text that represent the line where the annotation lives, its tag, and its text. Note the filename is not stored.

+ +

Annotations are looked for in comments and modulus whitespace they have to start with the tag optionally followed by a colon. Everything up to the end of the line (or closing ERB comment tag) is considered to be their text.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + +

Methods

+ + + + + + + + + + + + + + +

Attributes

+ + + + + + + + +
+ [R] + tag
+ + + + +

Class Public methods

+ +
+

+ + enumerate(tag = nil, options = {}) + +

+ + +
+

Prints all annotations with tag tag under the root directories app, config, db, lib, and test (recursively).

+ +

If tag is nil, annotations with either default or registered tags are printed.

+ +

Specific directories can be explicitly set using the :dirs key in options.

+ +
Rails::SourceAnnotationExtractor.enumerate 'TODO|FIXME', dirs: %w(app lib), tag: true
+
+ +

If options has a :tag flag, it will be passed to each annotation’s to_s.

+ +

See SourceAnnotationExtractor#find_in for a list of file extensions that will be taken into account.

+ +

This class method is the single entry point for the rails notes command.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 76
+def self.enumerate(tag = nil, options = {})
+  tag ||= Annotation.tags.join("|")
+  extractor = new(tag)
+  dirs = options.delete(:dirs) || Annotation.directories
+  extractor.display(extractor.find(dirs), options)
+end
+
+
+ +
+ +
+

+ + new(tag) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 85
+def initialize(tag)
+  @tag = tag
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + display(results, options = {}) + +

+ + +
+

Prints the mapping from filenames to annotations in results ordered by filename. The options hash is passed to each annotation’s to_s.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 137
+def display(results, options = {})
+  options[:indent] = results.flat_map { |f, a| a.map(&:line) }.max.to_s.size
+  results.keys.sort.each do |file|
+    puts "#{file}:"
+    results[file].each do |note|
+      puts "  * #{note.to_s(options)}"
+    end
+    puts
+  end
+end
+
+
+ +
+ +
+

+ + extract_annotations_from(file, pattern) + +

+ + +
+

If file is the filename of a file that contains annotations this method returns a hash with a single entry that maps file to an array of its annotations. Otherwise it returns an empty hash.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 125
+def extract_annotations_from(file, pattern)
+  lineno = 0
+  result = File.readlines(file, encoding: Encoding::BINARY).inject([]) do |list, line|
+    lineno += 1
+    next list unless line =~ pattern
+    list << Annotation.new(lineno, $1, $2)
+  end
+  result.empty? ? {} : { file => result }
+end
+
+
+ +
+ +
+

+ + find(dirs) + +

+ + +
+

Returns a hash that maps filenames under dirs (recursively) to arrays with their annotations.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 91
+def find(dirs)
+  dirs.inject({}) { |h, dir| h.update(find_in(dir)) }
+end
+
+
+ +
+ +
+

+ + find_in(dir) + +

+ + +
+

Returns a hash that maps filenames under dir (recursively) to arrays with their annotations. Files with extensions registered in Rails::SourceAnnotationExtractor::Annotation.extensions are taken into account. Only files with annotations are included.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 99
+def find_in(dir)
+  results = {}
+
+  Dir.glob("#{dir}/*") do |item|
+    next if File.basename(item).start_with?(".")
+
+    if File.directory?(item)
+      results.update(find_in(item))
+    else
+      extension = Annotation.extensions.detect do |regexp, _block|
+        regexp.match(item)
+      end
+
+      if extension
+        pattern = extension.last.call(tag)
+        results.update(extract_annotations_from(item, pattern)) if pattern
+      end
+    end
+  end
+
+  results
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/SourceAnnotationExtractor/Annotation.html b/src/7.0/classes/Rails/SourceAnnotationExtractor/Annotation.html new file mode 100644 index 0000000000..0c7f3e390a --- /dev/null +++ b/src/7.0/classes/Rails/SourceAnnotationExtractor/Annotation.html @@ -0,0 +1,360 @@ +--- +title: Rails::SourceAnnotationExtractor::Annotation +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + +

Class Public methods

+ +
+

+ + directories() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 15
+def self.directories
+  @@directories ||= %w(app config db lib test)
+end
+
+
+ +
+ +
+

+ + extensions() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 35
+def self.extensions
+  @@extensions ||= {}
+end
+
+
+ +
+ +
+

+ + register_directories(*dirs) + +

+ + +
+

Registers additional directories to be included

+ +
Rails::SourceAnnotationExtractor::Annotation.register_directories("spec", "another")
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 21
+def self.register_directories(*dirs)
+  directories.push(*dirs)
+end
+
+
+ +
+ +
+

+ + register_extensions(*exts, &block) + +

+ + +
+

Registers new Annotations File Extensions

+ +
Rails::SourceAnnotationExtractor::Annotation.register_extensions("css", "scss", "sass", "less", "js") { |tag| /\/\/\s*(#{tag}):?\s*(.*)$/ }
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 41
+def self.register_extensions(*exts, &block)
+  extensions[/\.(#{exts.join("|")})$/] = block
+end
+
+
+ +
+ +
+

+ + register_tags(*additional_tags) + +

+ + +
+

Registers additional tags

+ +
Rails::SourceAnnotationExtractor::Annotation.register_tags("TESTME", "DEPRECATEME")
+
+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 31
+def self.register_tags(*additional_tags)
+  tags.push(*additional_tags)
+end
+
+
+ +
+ +
+

+ + tags() + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 25
+def self.tags
+  @@tags ||= %w(OPTIMIZE FIXME TODO)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + to_s(options = {}) + +

+ + +
+

Returns a representation of the annotation that looks like this:

+ +
[126] [TODO] This algorithm is simple and clearly correct, make it faster.
+
+ +

If options has a flag :tag the tag is shown as in the example above. Otherwise the string contains just line and text.

+
+ + + + + + + + +
+ + +
+
# File railties/lib/rails/source_annotation_extractor.rb, line 55
+def to_s(options = {})
+  s = +"[#{line.to_s.rjust(options[:indent])}] "
+  s << "[#{tag}] " if options[:tag]
+  s << text
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Rails/VERSION.html b/src/7.0/classes/Rails/VERSION.html new file mode 100644 index 0000000000..232847596e --- /dev/null +++ b/src/7.0/classes/Rails/VERSION.html @@ -0,0 +1,124 @@ +--- +title: Rails::VERSION +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
MAJOR=7
 
MINOR=0
 
PRE=nil
 
STRING=[MAJOR, MINOR, TINY, PRE].compact.join(".")
 
TINY=8
 
+ + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Range.html b/src/7.0/classes/Range.html new file mode 100644 index 0000000000..70dc9b9aa1 --- /dev/null +++ b/src/7.0/classes/Range.html @@ -0,0 +1,115 @@ +--- +title: Range +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + overlaps?(other) + +

+ + +
+

Compare two ranges and see if they overlap each other

+ +
(1..5).overlaps?(4..6) # => true
+(1..5).overlaps?(7..9) # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/range/overlaps.rb, line 7
+def overlaps?(other)
+  other.begin == self.begin || cover?(other.begin) || other.cover?(self.begin)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Regexp.html b/src/7.0/classes/Regexp.html new file mode 100644 index 0000000000..280fd4e5dd --- /dev/null +++ b/src/7.0/classes/Regexp.html @@ -0,0 +1,116 @@ +--- +title: Regexp +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + multiline?() + +

+ + +
+

Returns true if the regexp has the multiline flag set.

+ +
(/./).multiline?  # => false
+(/./m).multiline? # => true
+
+Regexp.new(".").multiline?                    # => false
+Regexp.new(".", Regexp::MULTILINE).multiline? # => true
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/regexp.rb, line 11
+def multiline?
+  options & MULTILINE == MULTILINE
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/SecureRandom.html b/src/7.0/classes/SecureRandom.html new file mode 100644 index 0000000000..062b358999 --- /dev/null +++ b/src/7.0/classes/SecureRandom.html @@ -0,0 +1,198 @@ +--- +title: SecureRandom +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
BASE36_ALPHABET=("0".."9").to_a + ("a".."z").to_a
 
BASE58_ALPHABET=("0".."9").to_a + ("A".."Z").to_a + ("a".."z").to_a - ["0", "O", "I", "l"]
 
+ + + + + + +

Class Public methods

+ +
+

+ + base36(n = 16) + +

+ + +
+

SecureRandom.base36 generates a random base36 string in lowercase.

+ +

The argument n specifies the length of the random string to be generated.

+ +

If n is not specified or is nil, 16 is assumed. It may be larger in the future. This method can be used over base58 if a deterministic case key is necessary.

+ +

The result will contain alphanumeric characters in lowercase.

+ +
p SecureRandom.base36 # => "4kugl2pdqmscqtje"
+p SecureRandom.base36(24) # => "77tmhrhjfvfdwodq8w7ev2m7"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/securerandom.rb, line 38
+def self.base36(n = 16)
+  SecureRandom.random_bytes(n).unpack("C*").map do |byte|
+    idx = byte % 64
+    idx = SecureRandom.random_number(36) if idx >= 36
+    BASE36_ALPHABET[idx]
+  end.join
+end
+
+
+ +
+ +
+

+ + base58(n = 16) + +

+ + +
+

SecureRandom.base58 generates a random base58 string.

+ +

The argument n specifies the length of the random string to be generated.

+ +

If n is not specified or is nil, 16 is assumed. It may be larger in the future.

+ +

The result may contain alphanumeric characters except 0, O, I, and l.

+ +
p SecureRandom.base58 # => "4kUgL2pdQMSCQtjE"
+p SecureRandom.base58(24) # => "77TMHrHJFvFDwodq8w7Ev2m7"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/securerandom.rb, line 19
+def self.base58(n = 16)
+  SecureRandom.random_bytes(n).unpack("C*").map do |byte|
+    idx = byte % 64
+    idx = SecureRandom.random_number(58) if idx >= 58
+    BASE58_ALPHABET[idx]
+  end.join
+end
+
+
+ +
+ + + + + +
+ +
+
diff --git a/src/7.0/classes/Singleton.html b/src/7.0/classes/Singleton.html new file mode 100644 index 0000000000..352c97d5e1 --- /dev/null +++ b/src/7.0/classes/Singleton.html @@ -0,0 +1,104 @@ +--- +title: Singleton +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + duplicable?() + +

+ + +
+

Singleton instances are not duplicable:

+ +
Class.new.include(Singleton).instance.dup # TypeError (can't dup instance of singleton
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 57
+def duplicable?
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/String.html b/src/7.0/classes/String.html new file mode 100644 index 0000000000..2c73aefccf --- /dev/null +++ b/src/7.0/classes/String.html @@ -0,0 +1,2359 @@ +--- +title: String +layout: default +--- +
+ +
+
+ +
+ +

String inflections define new methods on the String class to transform names for different purposes. For instance, you can figure out the name of a table from the name of a class.

+ +
'ScaleScore'.tableize # => "scale_scores"
+
+ +
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
BLANK_RE=/\A[[:space:]]*\z/
 
ENCODED_BLANKS=Concurrent::Map.new do |h, enc| +h[enc] = Regexp.new(BLANK_RE.source.encode(enc), BLANK_RE.options | Regexp::FIXEDENCODING) +end
 
+ + + + + + + +

Instance Public methods

+ +
+

+ + acts_like_string?() + +

+ + +
+

Enables more predictable duck-typing on String-like classes. See Object#acts_like?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/behavior.rb, line 5
+def acts_like_string?
+  true
+end
+
+
+ +
+ +
+

+ + at(position) + +

+ + +
+

If you pass a single integer, returns a substring of one character at that position. The first character of the string is at position 0, the next at position 1, and so on. If a range is supplied, a substring containing characters at offsets given by the range is returned. In both cases, if an offset is negative, it is counted from the end of the string. Returns nil if the initial offset falls outside the string. Returns an empty string if the beginning of the range is greater than the end of the string.

+ +
str = "hello"
+str.at(0)      # => "h"
+str.at(1..3)   # => "ell"
+str.at(-2)     # => "l"
+str.at(-2..-1) # => "lo"
+str.at(5)      # => nil
+str.at(5..-1)  # => ""
+
+ +

If a Regexp is given, the matching portion of the string is returned. If a String is given, that given string is returned if it occurs in the string. In both cases, nil is returned if there is no match.

+ +
str = "hello"
+str.at(/lo/) # => "lo"
+str.at(/ol/) # => nil
+str.at("lo") # => "lo"
+str.at("ol") # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/access.rb, line 29
+def at(position)
+  self[position]
+end
+
+
+ +
+ +
+

+ + blank?() + +

+ + +
+

A string is blank if it’s empty or contains whitespaces only:

+ +
''.blank?       # => true
+'   '.blank?    # => true
+"\t\n\r".blank? # => true
+' blah '.blank? # => false
+
+ +

Unicode whitespace is supported:

+ +
"\u00a0".blank? # => true
+
+ +

@return [true, false]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 121
+def blank?
+  # The regexp that matches blank strings is expensive. For the case of empty
+  # strings we can speed up this method (~3.5x) with an empty? call. The
+  # penalty for the rest of strings is marginal.
+  empty? ||
+    begin
+      BLANK_RE.match?(self)
+    rescue Encoding::CompatibilityError
+      ENCODED_BLANKS[self.encoding].match?(self)
+    end
+end
+
+
+ +
+ +
+

+ + camelcase(first_letter = :upper) + +

+ + +
+ +
+ + + + + +
+ Alias for: camelize +
+ + + +
+ +
+

+ + camelize(first_letter = :upper) + +

+ + +
+

By default, camelize converts strings to UpperCamelCase. If the argument to camelize is set to :lower then camelize produces lowerCamelCase.

+ +

camelize will also convert ‘/’ to ‘::’ which is useful for converting paths to namespaces.

+ +
'active_record'.camelize                # => "ActiveRecord"
+'active_record'.camelize(:lower)        # => "activeRecord"
+'active_record/errors'.camelize         # => "ActiveRecord::Errors"
+'active_record/errors'.camelize(:lower) # => "activeRecord::Errors"
+
+ +

See ActiveSupport::Inflector.camelize.

+
+ + + +
+ Also aliased as: camelcase +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 101
+def camelize(first_letter = :upper)
+  case first_letter
+  when :upper
+    ActiveSupport::Inflector.camelize(self, true)
+  when :lower
+    ActiveSupport::Inflector.camelize(self, false)
+  else
+    raise ArgumentError, "Invalid option, use either :upper or :lower."
+  end
+end
+
+
+ +
+ +
+

+ + classify() + +

+ + +
+

Creates a class name from a plural table name like Rails does for table names to models. Note that this returns a string and not a class. (To convert to an actual class follow classify with constantize.)

+ +
'ham_and_eggs'.classify # => "HamAndEgg"
+'posts'.classify        # => "Post"
+
+ +

See ActiveSupport::Inflector.classify.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 239
+def classify
+  ActiveSupport::Inflector.classify(self)
+end
+
+
+ +
+ +
+

+ + constantize() + +

+ + +
+

constantize tries to find a declared constant with the name specified in the string. It raises a NameError when the name is not in CamelCase or is not initialized.

+ +
'Module'.constantize  # => Module
+'Class'.constantize   # => Class
+'blargle'.constantize # => NameError: wrong constant name blargle
+
+ +

See ActiveSupport::Inflector.constantize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 73
+def constantize
+  ActiveSupport::Inflector.constantize(self)
+end
+
+
+ +
+ +
+

+ + dasherize() + +

+ + +
+

Replaces underscores with dashes in the string.

+ +
'puni_puni'.dasherize # => "puni-puni"
+
+ +

See ActiveSupport::Inflector.dasherize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 148
+def dasherize
+  ActiveSupport::Inflector.dasherize(self)
+end
+
+
+ +
+ +
+

+ + deconstantize() + +

+ + +
+

Removes the rightmost segment from the constant expression in the string.

+ +
'Net::HTTP'.deconstantize   # => "Net"
+'::Net::HTTP'.deconstantize # => "::Net"
+'String'.deconstantize      # => ""
+'::String'.deconstantize    # => ""
+''.deconstantize            # => ""
+
+ +

See ActiveSupport::Inflector.deconstantize.

+ +

See also demodulize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 177
+def deconstantize
+  ActiveSupport::Inflector.deconstantize(self)
+end
+
+
+ +
+ +
+

+ + demodulize() + +

+ + +
+

Removes the module part from the constant expression in the string.

+ +
'ActiveSupport::Inflector::Inflections'.demodulize # => "Inflections"
+'Inflections'.demodulize                           # => "Inflections"
+'::Inflections'.demodulize                         # => "Inflections"
+''.demodulize                                      # => ''
+
+ +

See ActiveSupport::Inflector.demodulize.

+ +

See also deconstantize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 162
+def demodulize
+  ActiveSupport::Inflector.demodulize(self)
+end
+
+
+ +
+ +
+

+ + exclude?(string) + +

+ + +
+

The inverse of String#include?. Returns true if the string does not include the other string.

+ +
"hello".exclude? "lo" # => false
+"hello".exclude? "ol" # => true
+"hello".exclude? ?h   # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/exclude.rb, line 10
+def exclude?(string)
+  !include?(string)
+end
+
+
+ +
+ +
+

+ + first(limit = 1) + +

+ + +
+

Returns the first character. If a limit is supplied, returns a substring from the beginning of the string until it reaches the limit value. If the given limit is greater than or equal to the string length, returns a copy of self.

+ +
str = "hello"
+str.first    # => "h"
+str.first(1) # => "h"
+str.first(2) # => "he"
+str.first(0) # => ""
+str.first(6) # => "hello"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/access.rb, line 78
+def first(limit = 1)
+  self[0, limit] || raise(ArgumentError, "negative limit")
+end
+
+
+ +
+ +
+

+ + foreign_key(separate_class_name_and_id_with_underscore = true) + +

+ + +
+

Creates a foreign key name from a class name. separate_class_name_and_id_with_underscore sets whether the method should put ‘_’ between the name and ‘id’.

+ +
'Message'.foreign_key        # => "message_id"
+'Message'.foreign_key(false) # => "messageid"
+'Admin::Post'.foreign_key    # => "post_id"
+
+ +

See ActiveSupport::Inflector.foreign_key.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 286
+def foreign_key(separate_class_name_and_id_with_underscore = true)
+  ActiveSupport::Inflector.foreign_key(self, separate_class_name_and_id_with_underscore)
+end
+
+
+ +
+ +
+

+ + from(position) + +

+ + +
+

Returns a substring from the given position to the end of the string. If the position is negative, it is counted from the end of the string.

+ +
str = "hello"
+str.from(0)  # => "hello"
+str.from(3)  # => "lo"
+str.from(-2) # => "lo"
+
+ +

You can mix it with to method and do fun things like:

+ +
str = "hello"
+str.from(0).to(-1) # => "hello"
+str.from(1).to(-2) # => "ell"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/access.rb, line 46
+def from(position)
+  self[position, length]
+end
+
+
+ +
+ +
+

+ + html_safe() + +

+ + +
+

Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed. It is your responsibility to ensure that the string contains no malicious content. This method is equivalent to the raw helper in views. It is recommended that you use sanitize instead of this method. It should never be called on user input.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/output_safety.rb, line 368
+def html_safe
+  ActiveSupport::SafeBuffer.new(self)
+end
+
+
+ +
+ +
+

+ + humanize(capitalize: true, keep_id_suffix: false) + +

+ + +
+

Capitalizes the first word, turns underscores into spaces, and (by default)strips a trailing ‘_id’ if present. Like titleize, this is meant for creating pretty output.

+ +

The capitalization of the first word can be turned off by setting the optional parameter capitalize to false. By default, this parameter is true.

+ +

The trailing ‘_id’ can be kept and capitalized by setting the optional parameter keep_id_suffix to true. By default, this parameter is false.

+ +
'employee_salary'.humanize                    # => "Employee salary"
+'author_id'.humanize                          # => "Author"
+'author_id'.humanize(capitalize: false)       # => "author"
+'_id'.humanize                                # => "Id"
+'author_id'.humanize(keep_id_suffix: true)    # => "Author id"
+
+ +

See ActiveSupport::Inflector.humanize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 262
+def humanize(capitalize: true, keep_id_suffix: false)
+  ActiveSupport::Inflector.humanize(self, capitalize: capitalize, keep_id_suffix: keep_id_suffix)
+end
+
+
+ +
+ +
+

+ + in_time_zone(zone = ::Time.zone) + +

+ + +
+

Converts String to a TimeWithZone in the current zone if Time.zone or Time.zone_default is set, otherwise converts String to a Time via String#to_time

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/zones.rb, line 9
+def in_time_zone(zone = ::Time.zone)
+  if zone
+    ::Time.find_zone!(zone).parse(self)
+  else
+    to_time
+  end
+end
+
+
+ +
+ +
+

+ + indent(amount, indent_string = nil, indent_empty_lines = false) + +

+ + +
+

Indents the lines in the receiver:

+ +
<<EOS.indent(2)
+def some_method
+  some_code
+end
+EOS
+# =>
+  def some_method
+    some_code
+  end
+
+ +

The second argument, indent_string, specifies which indent string to use. The default is nil, which tells the method to make a guess by peeking at the first indented line, and fallback to a space if there is none.

+ +
"  foo".indent(2)        # => "    foo"
+"foo\n\t\tbar".indent(2) # => "\t\tfoo\n\t\t\t\tbar"
+"foo".indent(2, "\t")    # => "\t\tfoo"
+
+ +

While indent_string is typically one space or tab, it may be any string.

+ +

The third argument, indent_empty_lines, is a flag that says whether empty lines should be indented. Default is false.

+ +
"foo\n\nbar".indent(2)            # => "  foo\n\n  bar"
+"foo\n\nbar".indent(2, nil, true) # => "  foo\n  \n  bar"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/indent.rb, line 42
+def indent(amount, indent_string = nil, indent_empty_lines = false)
+  dup.tap { |_| _.indent!(amount, indent_string, indent_empty_lines) }
+end
+
+
+ +
+ +
+

+ + indent!(amount, indent_string = nil, indent_empty_lines = false) + +

+ + +
+

Same as indent, except it indents the receiver in-place.

+ +

Returns the indented string, or nil if there was nothing to indent.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/indent.rb, line 7
+def indent!(amount, indent_string = nil, indent_empty_lines = false)
+  indent_string = indent_string || self[/^[ \t]/] || " "
+  re = indent_empty_lines ? /^/ : /^(?!$)/
+  gsub!(re, indent_string * amount)
+end
+
+
+ +
+ +
+

+ + inquiry() + +

+ + +
+

Wraps the current string in the ActiveSupport::StringInquirer class, which gives you a prettier way to test for equality.

+ +
env = 'production'.inquiry
+env.production?  # => true
+env.development? # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inquiry.rb, line 13
+def inquiry
+  ActiveSupport::StringInquirer.new(self)
+end
+
+
+ +
+ +
+

+ + is_utf8?() + +

+ + +
+

Returns true if string has utf_8 encoding.

+ +
utf_8_str = "some string".encode "UTF-8"
+iso_str = "some string".encode "ISO-8859-1"
+
+utf_8_str.is_utf8? # => true
+iso_str.is_utf8?   # => false
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/multibyte.rb, line 48
+def is_utf8?
+  case encoding
+  when Encoding::UTF_8, Encoding::US_ASCII
+    valid_encoding?
+  when Encoding::ASCII_8BIT
+    dup.force_encoding(Encoding::UTF_8).valid_encoding?
+  else
+    false
+  end
+end
+
+
+ +
+ +
+

+ + last(limit = 1) + +

+ + +
+

Returns the last character of the string. If a limit is supplied, returns a substring from the end of the string until it reaches the limit value (counting backwards). If the given limit is greater than or equal to the string length, returns a copy of self.

+ +
str = "hello"
+str.last    # => "o"
+str.last(1) # => "o"
+str.last(2) # => "lo"
+str.last(0) # => ""
+str.last(6) # => "hello"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/access.rb, line 92
+def last(limit = 1)
+  self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
+end
+
+
+ +
+ +
+

+ + mb_chars() + +

+ + +
+

Multibyte proxy

+ +

mb_chars is a multibyte safe proxy for string methods.

+ +

It creates and returns an instance of the ActiveSupport::Multibyte::Chars class which encapsulates the original string. A Unicode safe version of all the String methods are defined on this proxy class. If the proxy class doesn’t respond to a certain method, it’s forwarded to the encapsulated string.

+ +
>> "lj".mb_chars.upcase.to_s
+=> "LJ"
+
+ +

NOTE: Ruby 2.4 and later support native Unicode case mappings:

+ +
>> "lj".upcase
+=> "LJ"
+
+ +

Method chaining

+ +

All the methods on the Chars proxy which normally return a string will return a Chars object. This allows method chaining on the result of any of these methods.

+ +
name.mb_chars.reverse.length # => 12
+
+ +

Interoperability and configuration

+ +

The Chars object tries to be as interchangeable with String objects as possible: sorting and comparing between String and Char work like expected. The bang! methods change the internal string representation in the Chars object. Interoperability problems can be resolved easily with a to_s call.

+ +

For more information about the methods defined on the Chars proxy see ActiveSupport::Multibyte::Chars. For information about how to change the default Multibyte behavior see ActiveSupport::Multibyte.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/multibyte.rb, line 37
+def mb_chars
+  ActiveSupport::Multibyte.proxy_class.new(self)
+end
+
+
+ +
+ +
+

+ + parameterize(separator: "-", preserve_case: false, locale: nil) + +

+ + +
+

Replaces special characters in a string so that it may be used as part of a ‘pretty’ URL.

+ +

If the optional parameter locale is specified, the word will be parameterized as a word of that language. By default, this parameter is set to nil and it will use the configured I18n.locale.

+ +
class Person
+  def to_param
+    "#{id}-#{name.parameterize}"
+  end
+end
+
+@person = Person.find(1)
+# => #<Person id: 1, name: "Donald E. Knuth">
+
+<%= link_to(@person.name, person_path) %>
+# => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
+
+ +

To preserve the case of the characters in a string, use the preserve_case argument.

+ +
class Person
+  def to_param
+    "#{id}-#{name.parameterize(preserve_case: true)}"
+  end
+end
+
+@person = Person.find(1)
+# => #<Person id: 1, name: "Donald E. Knuth">
+
+<%= link_to(@person.name, person_path) %>
+# => <a href="/person/1-Donald-E-Knuth">Donald E. Knuth</a>
+
+ +

See ActiveSupport::Inflector.parameterize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 215
+def parameterize(separator: "-", preserve_case: false, locale: nil)
+  ActiveSupport::Inflector.parameterize(self, separator: separator, preserve_case: preserve_case, locale: locale)
+end
+
+
+ +
+ +
+

+ + pluralize(count = nil, locale = :en) + +

+ + +
+

Returns the plural form of the word in the string.

+ +

If the optional parameter count is specified, the singular form will be returned if count == 1. For any other value of count the plural will be returned.

+ +

If the optional parameter locale is specified, the word will be pluralized as a word of that language. By default, this parameter is set to :en. You must define your own inflection rules for languages other than English.

+ +
'post'.pluralize             # => "posts"
+'octopus'.pluralize          # => "octopi"
+'sheep'.pluralize            # => "sheep"
+'words'.pluralize            # => "words"
+'the blue mailman'.pluralize # => "the blue mailmen"
+'CamelOctopus'.pluralize     # => "CamelOctopi"
+'apple'.pluralize(1)         # => "apple"
+'apple'.pluralize(2)         # => "apples"
+'ley'.pluralize(:es)         # => "leyes"
+'ley'.pluralize(1, :es)      # => "ley"
+
+ +

See ActiveSupport::Inflector.pluralize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 35
+def pluralize(count = nil, locale = :en)
+  locale = count if count.is_a?(Symbol)
+  if count == 1
+    dup
+  else
+    ActiveSupport::Inflector.pluralize(self, locale)
+  end
+end
+
+
+ +
+ +
+

+ + remove(*patterns) + +

+ + +
+

Returns a new string with all occurrences of the patterns removed.

+ +
str = "foo bar test"
+str.remove(" test")                 # => "foo bar"
+str.remove(" test", /bar/)          # => "foo "
+str                                 # => "foo bar test"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 32
+def remove(*patterns)
+  dup.remove!(*patterns)
+end
+
+
+ +
+ +
+

+ + remove!(*patterns) + +

+ + +
+

Alters the string by removing all occurrences of the patterns.

+ +
str = "foo bar test"
+str.remove!(" test", /bar/)         # => "foo "
+str                                 # => "foo "
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 40
+def remove!(*patterns)
+  patterns.each do |pattern|
+    gsub! pattern, ""
+  end
+
+  self
+end
+
+
+ +
+ +
+

+ + safe_constantize() + +

+ + +
+

safe_constantize tries to find a declared constant with the name specified in the string. It returns nil when the name is not in CamelCase or is not initialized.

+ +
'Module'.safe_constantize  # => Module
+'Class'.safe_constantize   # => Class
+'blargle'.safe_constantize # => nil
+
+ +

See ActiveSupport::Inflector.safe_constantize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 86
+def safe_constantize
+  ActiveSupport::Inflector.safe_constantize(self)
+end
+
+
+ +
+ +
+

+ + singularize(locale = :en) + +

+ + +
+

The reverse of pluralize, returns the singular form of a word in a string.

+ +

If the optional parameter locale is specified, the word will be singularized as a word of that language. By default, this parameter is set to :en. You must define your own inflection rules for languages other than English.

+ +
'posts'.singularize            # => "post"
+'octopi'.singularize           # => "octopus"
+'sheep'.singularize            # => "sheep"
+'word'.singularize             # => "word"
+'the blue mailmen'.singularize # => "the blue mailman"
+'CamelOctopi'.singularize      # => "CamelOctopus"
+'leyes'.singularize(:es)       # => "ley"
+
+ +

See ActiveSupport::Inflector.singularize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 60
+def singularize(locale = :en)
+  ActiveSupport::Inflector.singularize(self, locale)
+end
+
+
+ +
+ +
+

+ + squish() + +

+ + +
+

Returns the string, first removing all whitespace on both ends of the string, and then changing remaining consecutive whitespace groups into one space each.

+ +

Note that it handles both ASCII and Unicode whitespace.

+ +
%{ Multi-line
+   string }.squish                   # => "Multi-line string"
+" foo   bar    \n   \t   boo".squish # => "foo bar boo"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 13
+def squish
+  dup.squish!
+end
+
+
+ +
+ +
+

+ + squish!() + +

+ + +
+

Performs a destructive squish. See String#squish.

+ +
str = " foo   bar    \n   \t   boo"
+str.squish!                         # => "foo bar boo"
+str                                 # => "foo bar boo"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 21
+def squish!
+  gsub!(/[[:space:]]+/, " ")
+  strip!
+  self
+end
+
+
+ +
+ +
+

+ + strip_heredoc() + +

+ + +
+

Strips indentation in heredocs.

+ +

For example in

+ +
if options[:usage]
+  puts <<-USAGE.strip_heredoc
+    This command does such and such.
+
+    Supported options are:
+      -h         This message
+      ...
+  USAGE
+end
+
+ +

the user would see the usage message aligned against the left margin.

+ +

Technically, it looks for the least indented non-empty line in the whole string, and removes that amount of leading whitespace.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/strip.rb, line 22
+def strip_heredoc
+  gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, "").tap do |stripped|
+    stripped.freeze if frozen?
+  end
+end
+
+
+ +
+ +
+

+ + tableize() + +

+ + +
+

Creates the name of a table like Rails does for models to table names. This method uses the pluralize method on the last word in the string.

+ +
'RawScaledScorer'.tableize # => "raw_scaled_scorers"
+'ham_and_egg'.tableize     # => "ham_and_eggs"
+'fancyCategory'.tableize   # => "fancy_categories"
+
+ +

See ActiveSupport::Inflector.tableize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 227
+def tableize
+  ActiveSupport::Inflector.tableize(self)
+end
+
+
+ +
+ +
+

+ + titlecase(keep_id_suffix: false) + +

+ + +
+ +
+ + + + + +
+ Alias for: titleize +
+ + + +
+ +
+

+ + titleize(keep_id_suffix: false) + +

+ + +
+

Capitalizes all the words and replaces some characters in the string to create a nicer looking title. titleize is meant for creating pretty output. It is not used in the Rails internals.

+ +

The trailing ‘_id’,‘Id’.. can be kept and capitalized by setting the optional parameter keep_id_suffix to true. By default, this parameter is false.

+ +
'man from the boondocks'.titleize                       # => "Man From The Boondocks"
+'x-men: the last stand'.titleize                        # => "X Men: The Last Stand"
+'string_ending_with_id'.titleize(keep_id_suffix: true)  # => "String Ending With Id"
+
+ +

See ActiveSupport::Inflector.titleize.

+
+ + + +
+ Also aliased as: titlecase +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 126
+def titleize(keep_id_suffix: false)
+  ActiveSupport::Inflector.titleize(self, keep_id_suffix: keep_id_suffix)
+end
+
+
+ +
+ +
+

+ + to(position) + +

+ + +
+

Returns a substring from the beginning of the string to the given position. If the position is negative, it is counted from the end of the string.

+ +
str = "hello"
+str.to(0)  # => "h"
+str.to(3)  # => "hell"
+str.to(-2) # => "hell"
+
+ +

You can mix it with from method and do fun things like:

+ +
str = "hello"
+str.from(0).to(-1) # => "hello"
+str.from(1).to(-2) # => "ell"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/access.rb, line 63
+def to(position)
+  position += size if position < 0
+  self[0, position + 1] || +""
+end
+
+
+ +
+ +
+

+ + to_date() + +

+ + +
+

Converts a string to a Date value.

+ +
"1-1-2012".to_date   # => Sun, 01 Jan 2012
+"01/01/2012".to_date # => Sun, 01 Jan 2012
+"2012-12-13".to_date # => Thu, 13 Dec 2012
+"12/13/2012".to_date # => ArgumentError: invalid date
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/conversions.rb, line 47
+def to_date
+  ::Date.parse(self, false) unless blank?
+end
+
+
+ +
+ +
+

+ + to_datetime() + +

+ + +
+

Converts a string to a DateTime value.

+ +
"1-1-2012".to_datetime            # => Sun, 01 Jan 2012 00:00:00 +0000
+"01/01/2012 23:59:59".to_datetime # => Sun, 01 Jan 2012 23:59:59 +0000
+"2012-12-13 12:50".to_datetime    # => Thu, 13 Dec 2012 12:50:00 +0000
+"12/13/2012".to_datetime          # => ArgumentError: invalid date
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/conversions.rb, line 57
+def to_datetime
+  ::DateTime.parse(self, false) unless blank?
+end
+
+
+ +
+ +
+

+ + to_time(form = :local) + +

+ + +
+

Converts a string to a Time value. The form can be either :utc or :local (default :local).

+ +

The time is parsed using Time.parse method. If form is :local, then the time is in the system timezone. If the date part is missing then the current date is used and if the time part is missing then it is assumed to be 00:00:00.

+ +
"13-12-2012".to_time               # => 2012-12-13 00:00:00 +0100
+"06:12".to_time                    # => 2012-12-13 06:12:00 +0100
+"2012-12-13 06:12".to_time         # => 2012-12-13 06:12:00 +0100
+"2012-12-13T06:12".to_time         # => 2012-12-13 06:12:00 +0100
+"2012-12-13T06:12".to_time(:utc)   # => 2012-12-13 06:12:00 UTC
+"12/13/2012".to_time               # => ArgumentError: argument out of range
+"1604326192".to_time               # => ArgumentError: argument out of range
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/conversions.rb, line 22
+def to_time(form = :local)
+  parts = Date._parse(self, false)
+  used_keys = %i(year mon mday hour min sec sec_fraction offset)
+  return if (parts.keys & used_keys).empty?
+
+  now = Time.now
+  time = Time.new(
+    parts.fetch(:year, now.year),
+    parts.fetch(:mon, now.month),
+    parts.fetch(:mday, now.day),
+    parts.fetch(:hour, 0),
+    parts.fetch(:min, 0),
+    parts.fetch(:sec, 0) + parts.fetch(:sec_fraction, 0),
+    parts.fetch(:offset, form == :utc ? 0 : nil)
+  )
+
+  form == :utc ? time.utc : time.to_time
+end
+
+
+ +
+ +
+

+ + truncate(truncate_at, options = {}) + +

+ + +
+

Truncates a given text after a given length if text is longer than length:

+ +
'Once upon a time in a world far far away'.truncate(27)
+# => "Once upon a time in a wo..."
+
+ +

Pass a string or regexp :separator to truncate text at a natural break:

+ +
'Once upon a time in a world far far away'.truncate(27, separator: ' ')
+# => "Once upon a time in a..."
+
+'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
+# => "Once upon a time in a..."
+
+ +

The last characters will be replaced with the :omission string (defaults to “…”) for a total length not exceeding length:

+ +
'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
+# => "And they f... (continued)"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 66
+def truncate(truncate_at, options = {})
+  return dup unless length > truncate_at
+
+  omission = options[:omission] || "..."
+  length_with_room_for_omission = truncate_at - omission.length
+  stop = \
+    if options[:separator]
+      rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
+    else
+      length_with_room_for_omission
+    end
+
+  +"#{self[0, stop]}#{omission}"
+end
+
+
+ +
+ +
+

+ + truncate_bytes(truncate_at, omission: "…") + +

+ + +
+

Truncates text to at most bytesize bytes in length without breaking string encoding by splitting multibyte characters or breaking grapheme clusters (“perceptual characters”) by truncating at combining characters.

+ +
>> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
+=> 20
+>> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
+=> 80
+>> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
+=> "🔪🔪🔪🔪…"
+
+ +

The truncated text ends with the :omission string, defaulting to “…”, for a total length not exceeding bytesize.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 95
+def truncate_bytes(truncate_at, omission: "…")
+  omission ||= ""
+
+  case
+  when bytesize <= truncate_at
+    dup
+  when omission.bytesize > truncate_at
+    raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
+  when omission.bytesize == truncate_at
+    omission.dup
+  else
+    self.class.new.tap do |cut|
+      cut_at = truncate_at - omission.bytesize
+
+      each_grapheme_cluster do |grapheme|
+        if cut.bytesize + grapheme.bytesize <= cut_at
+          cut << grapheme
+        else
+          break
+        end
+      end
+
+      cut << omission
+    end
+  end
+end
+
+
+ +
+ +
+

+ + truncate_words(words_count, options = {}) + +

+ + +
+

Truncates a given text after a given number of words (words_count):

+ +
'Once upon a time in a world far far away'.truncate_words(4)
+# => "Once upon a time..."
+
+ +

Pass a string or regexp :separator to specify a different separator of words:

+ +
'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
+# => "Once<br>upon<br>a<br>time<br>in..."
+
+ +

The last characters will be replaced with the :omission string (defaults to “…”):

+ +
'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
+# => "And they found that many... (continued)"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/filters.rb, line 136
+def truncate_words(words_count, options = {})
+  sep = options[:separator] || /\s+/
+  sep = Regexp.escape(sep.to_s) unless Regexp === sep
+  if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
+    $1 + (options[:omission] || "...")
+  else
+    dup
+  end
+end
+
+
+ +
+ +
+

+ + underscore() + +

+ + +
+

The reverse of camelize. Makes an underscored, lowercase form from the expression in the string.

+ +

underscore will also change ‘::’ to ‘/’ to convert namespaces to paths.

+ +
'ActiveModel'.underscore         # => "active_model"
+'ActiveModel::Errors'.underscore # => "active_model/errors"
+
+ +

See ActiveSupport::Inflector.underscore.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 139
+def underscore
+  ActiveSupport::Inflector.underscore(self)
+end
+
+
+ +
+ +
+

+ + upcase_first() + +

+ + +
+

Converts just the first character to uppercase.

+ +
'what a Lovely Day'.upcase_first # => "What a Lovely Day"
+'w'.upcase_first                 # => "W"
+''.upcase_first                  # => ""
+
+ +

See ActiveSupport::Inflector.upcase_first.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/string/inflections.rb, line 273
+def upcase_first
+  ActiveSupport::Inflector.upcase_first(self)
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/Symbol.html b/src/7.0/classes/Symbol.html new file mode 100644 index 0000000000..b24247c5f9 --- /dev/null +++ b/src/7.0/classes/Symbol.html @@ -0,0 +1,62 @@ +--- +title: Symbol +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/Time.html b/src/7.0/classes/Time.html new file mode 100644 index 0000000000..fd3f2af364 --- /dev/null +++ b/src/7.0/classes/Time.html @@ -0,0 +1,2707 @@ +--- +title: Time +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + +

Included Modules

+ + + + + + + + + + +

Constants

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
COMMON_YEAR_DAYS_IN_MONTH=[nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
 
DATE_FORMATS={ +db: "%Y-%m-%d %H:%M:%S", +inspect: "%Y-%m-%d %H:%M:%S.%9N %z", +number: "%Y%m%d%H%M%S", +nsec: "%Y%m%d%H%M%S%9N", +usec: "%Y%m%d%H%M%S%6N", +time: "%H:%M", +short: "%d %b %H:%M", +long: "%B %d, %Y %H:%M", +long_ordinal: lambda { |time| +day_format = ActiveSupport::Inflector.ordinalize(time.day) +time.strftime("%B #{day_format}, %Y %H:%M") +}, +rfc822: lambda { |time| +offset_format = time.formatted_offset(false) +time.strftime("%a, %d %b %Y %H:%M:%S #{offset_format}") +}, +iso8601: lambda { |time| time.iso8601 } +}
 
+ + + + +

Attributes

+ + + + + + + + +
+ [RW] + zone_default
+ + + + +

Class Public methods

+ +
+

+ + ===(other) + +

+ + +
+

Overriding case equality method so that it returns true for ActiveSupport::TimeWithZone instances

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 18
+def ===(other)
+  super || (self == Time && other.is_a?(ActiveSupport::TimeWithZone))
+end
+
+
+ +
+ +
+

+ + at(*args, **kwargs) + +

+ + +
+ +
+ + + +
+ Also aliased as: at_without_coercion +
+ + + +
+ Alias for: at_with_coercion +
+ + + +
+ +
+

+ + at_with_coercion(*args, **kwargs) + +

+ + +
+

Layers additional behavior on Time.at so that ActiveSupport::TimeWithZone and DateTime instances can be used when called with a single argument

+
+ + + +
+ Also aliased as: at +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 45
+def at_with_coercion(*args, **kwargs)
+  return at_without_coercion(*args, **kwargs) if args.size != 1 || !kwargs.empty?
+
+  # Time.at can be called with a time or numerical value
+  time_or_number = args.first
+
+  if time_or_number.is_a?(ActiveSupport::TimeWithZone)
+    at_without_coercion(time_or_number.to_r).getlocal
+  elsif time_or_number.is_a?(DateTime)
+    at_without_coercion(time_or_number.to_f).getlocal
+  else
+    at_without_coercion(time_or_number)
+  end
+end
+
+
+ +
+ +
+

+ + at_without_coercion(*args, **kwargs) + +

+ + +
+ +
+ + + + + +
+ Alias for: at +
+ + + +
+ +
+

+ + current() + +

+ + +
+

Returns Time.zone.now when Time.zone or config.time_zone are set, otherwise just returns Time.now.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 39
+def current
+  ::Time.zone ? ::Time.zone.now : ::Time.now
+end
+
+
+ +
+ +
+

+ + days_in_month(month, year = current.year) + +

+ + +
+

Returns the number of days in the given month. If no year is specified, it will use the current year.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 24
+def days_in_month(month, year = current.year)
+  if month == 2 && ::Date.gregorian_leap?(year)
+    29
+  else
+    COMMON_YEAR_DAYS_IN_MONTH[month]
+  end
+end
+
+
+ +
+ +
+

+ + days_in_year(year = current.year) + +

+ + +
+

Returns the number of days in the given year. If no year is specified, it will use the current year.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 34
+def days_in_year(year = current.year)
+  days_in_month(2, year) + 337
+end
+
+
+ +
+ +
+

+ + find_zone(time_zone) + +

+ + +
+

Returns a TimeZone instance matching the time zone provided. Accepts the time zone in any format supported by Time.zone=. Returns nil for invalid time zones.

+ +
Time.find_zone "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
+Time.find_zone "NOT-A-TIMEZONE"   # => nil
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 93
+def find_zone(time_zone)
+  find_zone!(time_zone) rescue nil
+end
+
+
+ +
+ +
+

+ + find_zone!(time_zone) + +

+ + +
+

Returns a TimeZone instance matching the time zone provided. Accepts the time zone in any format supported by Time.zone=. Raises an ArgumentError for invalid time zones.

+ +
Time.find_zone! "America/New_York" # => #<ActiveSupport::TimeZone @name="America/New_York" ...>
+Time.find_zone! "EST"              # => #<ActiveSupport::TimeZone @name="EST" ...>
+Time.find_zone! -5.hours           # => #<ActiveSupport::TimeZone @name="Bogota" ...>
+Time.find_zone! nil                # => nil
+Time.find_zone! false              # => false
+Time.find_zone! "NOT-A-TIMEZONE"   # => ArgumentError: Invalid Timezone: NOT-A-TIMEZONE
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 81
+def find_zone!(time_zone)
+  return time_zone unless time_zone
+
+  ActiveSupport::TimeZone[time_zone] || raise(ArgumentError, "Invalid Timezone: #{time_zone}")
+end
+
+
+ +
+ +
+

+ + rfc3339(str) + +

+ + +
+

Creates a Time instance from an RFC 3339 string.

+ +
Time.rfc3339('1999-12-31T14:00:00-10:00') # => 2000-01-01 00:00:00 -1000
+
+ +

If the time or offset components are missing then an ArgumentError will be raised.

+ +
Time.rfc3339('1999-12-31') # => ArgumentError: invalid date
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 69
+def rfc3339(str)
+  parts = Date._rfc3339(str)
+
+  raise ArgumentError, "invalid date" if parts.empty?
+
+  Time.new(
+    parts.fetch(:year),
+    parts.fetch(:mon),
+    parts.fetch(:mday),
+    parts.fetch(:hour),
+    parts.fetch(:min),
+    parts.fetch(:sec) + parts.fetch(:sec_fraction, 0),
+    parts.fetch(:offset)
+  )
+end
+
+
+ +
+ +
+

+ + use_zone(time_zone) + +

+ + +
+

Allows override of Time.zone locally inside supplied block; resets Time.zone to existing value when done.

+ +
class ApplicationController < ActionController::Base
+  around_action :set_time_zone
+
+  private
+    def set_time_zone
+      Time.use_zone(current_user.timezone) { yield }
+    end
+end
+
+ +

NOTE: This won’t affect any ActiveSupport::TimeWithZone objects that have already been created, e.g. any model timestamp attributes that have been read before the block will remain in the application’s default timezone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 61
+def use_zone(time_zone)
+  new_zone = find_zone!(time_zone)
+  begin
+    old_zone, ::Time.zone = ::Time.zone, new_zone
+    yield
+  ensure
+    ::Time.zone = old_zone
+  end
+end
+
+
+ +
+ +
+

+ + zone() + +

+ + +
+

Returns the TimeZone for the current request, if this has been set (via Time.zone=). If Time.zone has not been set for the current request, returns the TimeZone specified in config.time_zone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 14
+def zone
+  ::ActiveSupport::IsolatedExecutionState[:time_zone] || zone_default
+end
+
+
+ +
+ +
+

+ + zone=(time_zone) + +

+ + +
+

Sets Time.zone to a TimeZone object for the current request/thread.

+ +

This method accepts any of the following:

+
  • +

    A Rails TimeZone object.

    +
  • +

    An identifier for a Rails TimeZone object (e.g., “Eastern Time (US & Canada)”, -5.hours).

    +
  • +

    A TZInfo::Timezone object.

    +
  • +

    An identifier for a TZInfo::Timezone object (e.g., “America/New_York”).

    +
+ +

Here’s an example of how you might set Time.zone on a per request basis and reset it when the request is done. current_user.time_zone just needs to return a string identifying the user’s preferred time zone:

+ +
class ApplicationController < ActionController::Base
+  around_action :set_time_zone
+
+  def set_time_zone
+    if logged_in?
+      Time.use_zone(current_user.time_zone) { yield }
+    else
+      yield
+    end
+  end
+end
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/zones.rb, line 41
+def zone=(time_zone)
+  ::ActiveSupport::IsolatedExecutionState[:time_zone] = find_zone!(time_zone)
+end
+
+
+ +
+ + + +

Instance Public methods

+ +
+

+ + -(other) + +

+ + +
+ +
+ + + + + + + +
+ Alias for: minus_with_coercion +
+ + + +
+ +
+

+ + <=>(other) + +

+ + +
+ +
+ + + +
+ Also aliased as: compare_without_coercion +
+ + + +
+ Alias for: compare_with_coercion +
+ + + +
+ +
+

+ + acts_like_time?() + +

+ + +
+

Duck-types as a Time-like class. See Object#acts_like?.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/acts_like.rb, line 7
+def acts_like_time?
+  true
+end
+
+
+ +
+ +
+

+ + advance(options) + +

+ + +
+

Uses Date to provide precise Time calculations for years, months, and days according to the proleptic Gregorian calendar. The options parameter takes a hash with any of these keys: :years, :months, :weeks, :days, :hours, :minutes, :seconds.

+ +
Time.new(2015, 8, 1, 14, 35, 0).advance(seconds: 1) # => 2015-08-01 14:35:01 -0700
+Time.new(2015, 8, 1, 14, 35, 0).advance(minutes: 1) # => 2015-08-01 14:36:00 -0700
+Time.new(2015, 8, 1, 14, 35, 0).advance(hours: 1)   # => 2015-08-01 15:35:00 -0700
+Time.new(2015, 8, 1, 14, 35, 0).advance(days: 1)    # => 2015-08-02 14:35:00 -0700
+Time.new(2015, 8, 1, 14, 35, 0).advance(weeks: 1)   # => 2015-08-08 14:35:00 -0700
+
+ +

Just like Date#advance, increments are applied in order of time units from largest to smallest. This order can affect the result around the end of a month.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 186
+def advance(options)
+  unless options[:weeks].nil?
+    options[:weeks], partial_weeks = options[:weeks].divmod(1)
+    options[:days] = options.fetch(:days, 0) + 7 * partial_weeks
+  end
+
+  unless options[:days].nil?
+    options[:days], partial_days = options[:days].divmod(1)
+    options[:hours] = options.fetch(:hours, 0) + 24 * partial_days
+  end
+
+  d = to_date.gregorian.advance(options)
+  time_advanced_by_date = change(year: d.year, month: d.month, day: d.day)
+  seconds_to_advance = \
+    options.fetch(:seconds, 0) +
+    options.fetch(:minutes, 0) * 60 +
+    options.fetch(:hours, 0) * 3600
+
+  if seconds_to_advance.zero?
+    time_advanced_by_date
+  else
+    time_advanced_by_date.since(seconds_to_advance)
+  end
+end
+
+
+ +
+ +
+

+ + ago(seconds) + +

+ + +
+

Returns a new Time representing the time a number of seconds ago, this is basically a wrapper around the Numeric extension

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 212
+def ago(seconds)
+  since(-seconds)
+end
+
+
+ +
+ +
+

+ + at_beginning_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_beginning_of_hour() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_hour +
+ + + +
+ +
+

+ + at_beginning_of_minute() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_minute +
+ + + +
+ +
+

+ + at_end_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_day +
+ + + +
+ +
+

+ + at_end_of_hour() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_hour +
+ + + +
+ +
+

+ + at_end_of_minute() + +

+ + +
+ +
+ + + + + +
+ Alias for: end_of_minute +
+ + + +
+ +
+

+ + at_midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_middle_of_day() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + at_midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + at_noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + beginning_of_day() + +

+ + +
+

Returns a new Time representing the start of the day (0:00)

+
+ + + +
+ Also aliased as: midnight, at_midnight, at_beginning_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 225
+def beginning_of_day
+  change(hour: 0)
+end
+
+
+ +
+ +
+

+ + beginning_of_hour() + +

+ + +
+

Returns a new Time representing the start of the hour (x:00)

+
+ + + +
+ Also aliased as: at_beginning_of_hour +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 254
+def beginning_of_hour
+  change(min: 0)
+end
+
+
+ +
+ +
+

+ + beginning_of_minute() + +

+ + +
+

Returns a new Time representing the start of the minute (x:xx:00)

+
+ + + +
+ Also aliased as: at_beginning_of_minute +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 270
+def beginning_of_minute
+  change(sec: 0)
+end
+
+
+ +
+ +
+

+ + ceil(precision = 0) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 121
+def ceil(precision = 0)
+  change(nsec: 0) + subsec.ceil(precision)
+end
+
+
+ +
+ +
+

+ + change(options) + +

+ + +
+

Returns a new Time where one or more of the elements have been changed according to the options parameter. The time options (:hour, :min, :sec, :usec, :nsec) reset cascadingly, so if only the hour is passed, then minute, sec, usec, and nsec is set to 0. If the hour and minute is passed, then sec, usec, and nsec is set to 0. The options parameter takes a hash with any of these keys: :year, :month, :day, :hour, :min, :sec, :usec, :nsec, :offset. Pass either :usec or :nsec, not both.

+ +
Time.new(2012, 8, 29, 22, 35, 0).change(day: 1)              # => Time.new(2012, 8, 1, 22, 35, 0)
+Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, day: 1)  # => Time.new(1981, 8, 1, 22, 35, 0)
+Time.new(2012, 8, 29, 22, 35, 0).change(year: 1981, hour: 0) # => Time.new(1981, 8, 29, 0, 0, 0)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 138
+def change(options)
+  new_year   = options.fetch(:year, year)
+  new_month  = options.fetch(:month, month)
+  new_day    = options.fetch(:day, day)
+  new_hour   = options.fetch(:hour, hour)
+  new_min    = options.fetch(:min, options[:hour] ? 0 : min)
+  new_sec    = options.fetch(:sec, (options[:hour] || options[:min]) ? 0 : sec)
+  new_offset = options.fetch(:offset, nil)
+
+  if new_nsec = options[:nsec]
+    raise ArgumentError, "Can't change both :nsec and :usec at the same time: #{options.inspect}" if options[:usec]
+    new_usec = Rational(new_nsec, 1000)
+  else
+    new_usec = options.fetch(:usec, (options[:hour] || options[:min] || options[:sec]) ? 0 : Rational(nsec, 1000))
+  end
+
+  raise ArgumentError, "argument out of range" if new_usec >= 1000000
+
+  new_sec += Rational(new_usec, 1000000)
+
+  if new_offset
+    ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, new_offset)
+  elsif utc?
+    ::Time.utc(new_year, new_month, new_day, new_hour, new_min, new_sec)
+  elsif zone&.respond_to?(:utc_to_local)
+    ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, zone)
+  elsif zone
+    ::Time.local(new_year, new_month, new_day, new_hour, new_min, new_sec)
+  else
+    ::Time.new(new_year, new_month, new_day, new_hour, new_min, new_sec, utc_offset)
+  end
+end
+
+
+ +
+ +
+

+ + compare_with_coercion(other) + +

+ + +
+

Layers additional behavior on Time#<=> so that DateTime and ActiveSupport::TimeWithZone instances can be chronologically compared with a Time

+
+ + + +
+ Also aliased as: <=> +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 316
+def compare_with_coercion(other)
+  # we're avoiding Time#to_datetime and Time#to_time because they're expensive
+  if other.class == Time
+    compare_without_coercion(other)
+  elsif other.is_a?(Time)
+    compare_without_coercion(other.to_time)
+  else
+    to_datetime <=> other
+  end
+end
+
+
+ +
+ +
+

+ + compare_without_coercion(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: <=> +
+ + + +
+ +
+

+ + end_of_day() + +

+ + +
+

Returns a new Time representing the end of the day, 23:59:59.999999

+
+ + + +
+ Also aliased as: at_end_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 243
+def end_of_day
+  change(
+    hour: 23,
+    min: 59,
+    sec: 59,
+    usec: Rational(999999999, 1000)
+  )
+end
+
+
+ +
+ +
+

+ + end_of_hour() + +

+ + +
+

Returns a new Time representing the end of the hour, x:59:59.999999

+
+ + + +
+ Also aliased as: at_end_of_hour +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 260
+def end_of_hour
+  change(
+    min: 59,
+    sec: 59,
+    usec: Rational(999999999, 1000)
+  )
+end
+
+
+ +
+ +
+

+ + end_of_minute() + +

+ + +
+

Returns a new Time representing the end of the minute, x:xx:59.999999

+
+ + + +
+ Also aliased as: at_end_of_minute +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 276
+def end_of_minute
+  change(
+    sec: 59,
+    usec: Rational(999999999, 1000)
+  )
+end
+
+
+ +
+ +
+

+ + eql?(other) + +

+ + +
+ +
+ + + +
+ Also aliased as: eql_without_coercion +
+ + + +
+ Alias for: eql_with_coercion +
+ + + +
+ +
+

+ + eql_with_coercion(other) + +

+ + +
+

Layers additional behavior on Time#eql? so that ActiveSupport::TimeWithZone instances can be eql? to an equivalent Time

+
+ + + +
+ Also aliased as: eql? +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 331
+def eql_with_coercion(other)
+  # if other is an ActiveSupport::TimeWithZone, coerce a Time instance from it so we can do eql? comparison
+  other = other.comparable_time if other.respond_to?(:comparable_time)
+  eql_without_coercion(other)
+end
+
+
+ +
+ +
+

+ + eql_without_coercion(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: eql? +
+ + + +
+ +
+

+ + floor(precision = 0) + +

+ + +
+ +
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 112
+def floor(precision = 0)
+  change(nsec: 0) + subsec.floor(precision)
+end
+
+
+ +
+ +
+

+ + formatted_offset(colon = true, alternate_utc_string = nil) + +

+ + +
+

Returns a formatted string of the offset from UTC, or an alternative string if the time zone is already UTC.

+ +
Time.local(2000).formatted_offset        # => "-06:00"
+Time.local(2000).formatted_offset(false) # => "-0600"
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/conversions.rb, line 69
+def formatted_offset(colon = true, alternate_utc_string = nil)
+  utc? && alternate_utc_string || ActiveSupport::TimeZone.seconds_to_utc_offset(utc_offset, colon)
+end
+
+
+ +
+ +
+

+ + in(seconds) + +

+ + +
+ +
+ + + + + +
+ Alias for: since +
+ + + +
+ +
+

+ + midday() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + middle_of_day() + +

+ + +
+

Returns a new Time representing the middle of the day (12:00)

+
+ + + +
+ Also aliased as: midday, noon, at_midday, at_noon, at_middle_of_day +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 233
+def middle_of_day
+  change(hour: 12)
+end
+
+
+ +
+ +
+

+ + midnight() + +

+ + +
+ +
+ + + + + +
+ Alias for: beginning_of_day +
+ + + +
+ +
+

+ + minus_with_coercion(other) + +

+ + +
+

Time#- can also be used to determine the number of seconds between two Time instances. We’re layering on additional behavior so that ActiveSupport::TimeWithZone instances are coerced into values that Time#- will recognize

+
+ + + +
+ Also aliased as: - +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 307
+def minus_with_coercion(other)
+  other = other.comparable_time if other.respond_to?(:comparable_time)
+  other.is_a?(DateTime) ? to_f - other.to_f : minus_without_coercion(other)
+end
+
+
+ +
+ +
+

+ + minus_without_coercion(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: - +
+ + + +
+ +
+

+ + minus_without_duration(other) + +

+ + +
+ +
+ + + + + +
+ Alias for: - +
+ + + +
+ +
+

+ + next_day(days = 1) + +

+ + +
+

Returns a new time the specified number of days in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 345
+def next_day(days = 1)
+  advance(days: days)
+end
+
+
+ +
+ +
+

+ + next_month(months = 1) + +

+ + +
+

Returns a new time the specified number of months in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 355
+def next_month(months = 1)
+  advance(months: months)
+end
+
+
+ +
+ +
+

+ + next_year(years = 1) + +

+ + +
+

Returns a new time the specified number of years in the future.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 365
+def next_year(years = 1)
+  advance(years: years)
+end
+
+
+ +
+ +
+

+ + noon() + +

+ + +
+ +
+ + + + + +
+ Alias for: middle_of_day +
+ + + +
+ +
+

+ + prev_day(days = 1) + +

+ + +
+

Returns a new time the specified number of days ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 340
+def prev_day(days = 1)
+  advance(days: -days)
+end
+
+
+ +
+ +
+

+ + prev_month(months = 1) + +

+ + +
+

Returns a new time the specified number of months ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 350
+def prev_month(months = 1)
+  advance(months: -months)
+end
+
+
+ +
+ +
+

+ + prev_year(years = 1) + +

+ + +
+

Returns a new time the specified number of years ago.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 360
+def prev_year(years = 1)
+  advance(years: -years)
+end
+
+
+ +
+ +
+

+ + sec_fraction() + +

+ + +
+

Returns the fraction of a second as a Rational

+ +
Time.new(2012, 8, 29, 0, 0, 0.5).sec_fraction # => (1/2)
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 107
+def sec_fraction
+  subsec
+end
+
+
+ +
+ +
+

+ + seconds_since_midnight() + +

+ + +
+

Returns the number of seconds since 00:00:00.

+ +
Time.new(2012, 8, 29,  0,  0,  0).seconds_since_midnight # => 0.0
+Time.new(2012, 8, 29, 12, 34, 56).seconds_since_midnight # => 45296.0
+Time.new(2012, 8, 29, 23, 59, 59).seconds_since_midnight # => 86399.0
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 91
+def seconds_since_midnight
+  to_i - change(hour: 0).to_i + (usec / 1.0e+6)
+end
+
+
+ +
+ +
+

+ + seconds_until_end_of_day() + +

+ + +
+

Returns the number of seconds until 23:59:59.

+ +
Time.new(2012, 8, 29,  0,  0,  0).seconds_until_end_of_day # => 86399
+Time.new(2012, 8, 29, 12, 34, 56).seconds_until_end_of_day # => 41103
+Time.new(2012, 8, 29, 23, 59, 59).seconds_until_end_of_day # => 0
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 100
+def seconds_until_end_of_day
+  end_of_day.to_i - to_i
+end
+
+
+ +
+ +
+

+ + since(seconds) + +

+ + +
+

Returns a new Time representing the time a number of seconds since the instance time

+
+ + + +
+ Also aliased as: in +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/calculations.rb, line 217
+def since(seconds)
+  self + seconds
+rescue
+  to_datetime.since(seconds)
+end
+
+
+ +
+ +
+

+ + to_formatted_s(format = :default) + +

+ + +
+ +
+ + + + + +
+ Alias for: to_fs +
+ + + +
+ +
+

+ + to_fs(format = :default) + +

+ + +
+

Converts to a formatted string. See DATE_FORMATS for built-in formats.

+ +

This method is aliased to to_formatted_s.

+ +
time = Time.now                    # => 2007-01-18 06:10:17 -06:00
+
+time.to_fs(:time)                  # => "06:10"
+time.to_formatted_s(:time)         # => "06:10"
+
+time.to_fs(:db)           # => "2007-01-18 06:10:17"
+time.to_fs(:number)       # => "20070118061017"
+time.to_fs(:short)        # => "18 Jan 06:10"
+time.to_fs(:long)         # => "January 18, 2007 06:10"
+time.to_fs(:long_ordinal) # => "January 18th, 2007 06:10"
+time.to_fs(:rfc822)       # => "Thu, 18 Jan 2007 06:10:17 -0600"
+time.to_fs(:iso8601)      # => "2007-01-18T06:10:17-06:00"
+
+ +

Adding your own time formats to to_fs

+ +

You can add your own formats to the Time::DATE_FORMATS hash. Use the format name as the hash key and either a strftime string or Proc instance that takes a time argument as the value.

+ +
# config/initializers/time_formats.rb
+Time::DATE_FORMATS[:month_and_year] = '%B %Y'
+Time::DATE_FORMATS[:short_ordinal]  = ->(time) { time.strftime("%B #{time.day.ordinalize}") }
+
+
+ + + +
+ Also aliased as: to_formatted_s +
+ + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/conversions.rb, line 53
+def to_fs(format = :default)
+  if formatter = DATE_FORMATS[format]
+    formatter.respond_to?(:call) ? formatter.call(self).to_s : strftime(formatter)
+  else
+    # Change to `to_s` when deprecation is gone. Also deprecate `to_default_s`.
+    to_default_s
+  end
+end
+
+
+ +
+ +
+

+ + to_time() + +

+ + +
+

Either return self or the time in the local system timezone depending on the setting of ActiveSupport.to_time_preserves_timezone.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/time/compatibility.rb, line 13
+def to_time
+  preserve_timezone ? self : getlocal
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/TrueClass.html b/src/7.0/classes/TrueClass.html new file mode 100644 index 0000000000..e47f18ae1c --- /dev/null +++ b/src/7.0/classes/TrueClass.html @@ -0,0 +1,155 @@ +--- +title: TrueClass +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + blank?() + +

+ + +
+

true is not blank:

+ +
true.blank? # => false
+
+ +

@return [false]

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/blank.rb, line 78
+def blank?
+  false
+end
+
+
+ +
+ +
+

+ + to_param() + +

+ + +
+

Returns self.

+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 27
+def to_param
+  self
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/classes/URI.html b/src/7.0/classes/URI.html new file mode 100644 index 0000000000..c5ee3635cf --- /dev/null +++ b/src/7.0/classes/URI.html @@ -0,0 +1,56 @@ +--- +title: URI +layout: default +--- +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/classes/UnboundMethod.html b/src/7.0/classes/UnboundMethod.html new file mode 100644 index 0000000000..56c84b07fd --- /dev/null +++ b/src/7.0/classes/UnboundMethod.html @@ -0,0 +1,111 @@ +--- +title: UnboundMethod +layout: default +--- +
+ +
+
+ + + + + + + + + + + +

Methods

+ + + + + + + + + + + + + + + + + +

Instance Public methods

+ +
+

+ + duplicable?() + +

+ + +
+

Unbound methods are not duplicable:

+ +
method(:puts).unbind.duplicable? # => false
+method(:puts).unbind.dup         # => TypeError: allocator undefined for UnboundMethod
+
+
+ + + + + + + + +
+ + +
+
# File activesupport/lib/active_support/core_ext/object/duplicable.rb, line 46
+def duplicable?
+  false
+end
+
+
+ +
+ + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/README_md.html b/src/7.0/files/actioncable/README_md.html new file mode 100644 index 0000000000..57a669f5f4 --- /dev/null +++ b/src/7.0/files/actioncable/README_md.html @@ -0,0 +1,82 @@ +--- +title: README.md +layout: default +--- +
+ + +
+
+ +
+ +

Action Cable – Integrated WebSockets for Rails

+ +

Action Cable seamlessly integrates WebSockets with the rest of your Rails application. It allows for real-time features to be written in Ruby in the same style and form as the rest of your Rails application, while still being performant and scalable. It’s a full-stack offering that provides both a client-side JavaScript framework and a server-side Ruby framework. You have access to your full domain model written with Active Record or your ORM of choice.

+ +

You can read more about Action Cable in the Action Cable Overview guide.

+ +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/base_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/base_rb.html new file mode 100644 index 0000000000..ab75f8d731 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/base_rb.html @@ -0,0 +1,89 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
  • active_support/rescuable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/broadcasting_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/broadcasting_rb.html new file mode 100644 index 0000000000..11fca5b7e8 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/broadcasting_rb.html @@ -0,0 +1,82 @@ +--- +title: broadcasting.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/to_param
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/callbacks_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/callbacks_rb.html new file mode 100644 index 0000000000..b945893ccf --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/callbacks_rb.html @@ -0,0 +1,82 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/naming_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/naming_rb.html new file mode 100644 index 0000000000..34615c2f8a --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/naming_rb.html @@ -0,0 +1,74 @@ +--- +title: naming.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/periodic_timers_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/periodic_timers_rb.html new file mode 100644 index 0000000000..5c8ec2dec9 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/periodic_timers_rb.html @@ -0,0 +1,74 @@ +--- +title: periodic_timers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/streams_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/streams_rb.html new file mode 100644 index 0000000000..1efd7dfd0d --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/streams_rb.html @@ -0,0 +1,74 @@ +--- +title: streams.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel/test_case_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel/test_case_rb.html new file mode 100644 index 0000000000..221df5ec67 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel/test_case_rb.html @@ -0,0 +1,103 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/test_case
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • json
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/channel_rb.html b/src/7.0/files/actioncable/lib/action_cable/channel_rb.html new file mode 100644 index 0000000000..0e414bb1c1 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/channel_rb.html @@ -0,0 +1,70 @@ +--- +title: channel.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/authorization_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/authorization_rb.html new file mode 100644 index 0000000000..d001802b31 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/authorization_rb.html @@ -0,0 +1,79 @@ +--- +title: authorization.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/base_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/base_rb.html new file mode 100644 index 0000000000..53fca9c20c --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/base_rb.html @@ -0,0 +1,89 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch
  • + +
  • active_support/rescuable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/client_socket_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/client_socket_rb.html new file mode 100644 index 0000000000..17728a091d --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/client_socket_rb.html @@ -0,0 +1,78 @@ +--- +title: client_socket.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • websocket/driver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/identification_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/identification_rb.html new file mode 100644 index 0000000000..cdc3d3c00d --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/identification_rb.html @@ -0,0 +1,82 @@ +--- +title: identification.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/internal_channel_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/internal_channel_rb.html new file mode 100644 index 0000000000..e204bd3e37 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/internal_channel_rb.html @@ -0,0 +1,72 @@ +--- +title: internal_channel.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/message_buffer_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/message_buffer_rb.html new file mode 100644 index 0000000000..6ff0b51fec --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/message_buffer_rb.html @@ -0,0 +1,70 @@ +--- +title: message_buffer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/stream_event_loop_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/stream_event_loop_rb.html new file mode 100644 index 0000000000..f83c511383 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/stream_event_loop_rb.html @@ -0,0 +1,87 @@ +--- +title: stream_event_loop.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • nio
  • + +
  • thread
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/stream_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/stream_rb.html new file mode 100644 index 0000000000..65bcbff5d6 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/stream_rb.html @@ -0,0 +1,78 @@ +--- +title: stream.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/subscriptions_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/subscriptions_rb.html new file mode 100644 index 0000000000..257a64fea4 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/subscriptions_rb.html @@ -0,0 +1,82 @@ +--- +title: subscriptions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/tagged_logger_proxy_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/tagged_logger_proxy_rb.html new file mode 100644 index 0000000000..6f4f79b8b9 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/tagged_logger_proxy_rb.html @@ -0,0 +1,77 @@ +--- +title: tagged_logger_proxy.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/test_case_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/test_case_rb.html new file mode 100644 index 0000000000..6a32d4ce7e --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/test_case_rb.html @@ -0,0 +1,115 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/test_case
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • action_dispatch
  • + +
  • action_dispatch/http/headers
  • + +
  • action_dispatch/testing/test_request
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection/web_socket_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection/web_socket_rb.html new file mode 100644 index 0000000000..749452226d --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection/web_socket_rb.html @@ -0,0 +1,78 @@ +--- +title: web_socket.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • websocket/driver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/connection_rb.html b/src/7.0/files/actioncable/lib/action_cable/connection_rb.html new file mode 100644 index 0000000000..26ff20ada9 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/connection_rb.html @@ -0,0 +1,70 @@ +--- +title: connection.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/engine_rb.html b/src/7.0/files/actioncable/lib/action_cable/engine_rb.html new file mode 100644 index 0000000000..1a2f98aeee --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/engine_rb.html @@ -0,0 +1,86 @@ +--- +title: engine.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails
  • + +
  • action_cable
  • + +
  • action_cable/helpers/action_cable_helper
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/gem_version_rb.html b/src/7.0/files/actioncable/lib/action_cable/gem_version_rb.html new file mode 100644 index 0000000000..e937ae6674 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/helpers/action_cable_helper_rb.html b/src/7.0/files/actioncable/lib/action_cable/helpers/action_cable_helper_rb.html new file mode 100644 index 0000000000..4c819acc13 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/helpers/action_cable_helper_rb.html @@ -0,0 +1,72 @@ +--- +title: action_cable_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/remote_connections_rb.html b/src/7.0/files/actioncable/lib/action_cable/remote_connections_rb.html new file mode 100644 index 0000000000..48343cd3c2 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/remote_connections_rb.html @@ -0,0 +1,87 @@ +--- +title: remote_connections.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/base_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/base_rb.html new file mode 100644 index 0000000000..d12522bf0c --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/base_rb.html @@ -0,0 +1,87 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/broadcasting_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/broadcasting_rb.html new file mode 100644 index 0000000000..57036f1f58 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/broadcasting_rb.html @@ -0,0 +1,81 @@ +--- +title: broadcasting.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/configuration_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/configuration_rb.html new file mode 100644 index 0000000000..c317687a70 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/configuration_rb.html @@ -0,0 +1,79 @@ +--- +title: configuration.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/connections_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/connections_rb.html new file mode 100644 index 0000000000..0395a465e7 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/connections_rb.html @@ -0,0 +1,70 @@ +--- +title: connections.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/worker/active_record_connection_management_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/worker/active_record_connection_management_rb.html new file mode 100644 index 0000000000..6d5f601a5c --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/worker/active_record_connection_management_rb.html @@ -0,0 +1,81 @@ +--- +title: active_record_connection_management.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server/worker_rb.html b/src/7.0/files/actioncable/lib/action_cable/server/worker_rb.html new file mode 100644 index 0000000000..1aaf5c7fd3 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server/worker_rb.html @@ -0,0 +1,91 @@ +--- +title: worker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
  • active_support/core_ext/module/attribute_accessors_per_thread
  • + +
  • action_cable/server/worker/active_record_connection_management
  • + +
  • concurrent
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/server_rb.html b/src/7.0/files/actioncable/lib/action_cable/server_rb.html new file mode 100644 index 0000000000..ac06a63856 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/server_rb.html @@ -0,0 +1,70 @@ +--- +title: server.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/async_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/async_rb.html new file mode 100644 index 0000000000..c09efd9505 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/async_rb.html @@ -0,0 +1,87 @@ +--- +title: async.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_cable/subscription_adapter/inline
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/base_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/base_rb.html new file mode 100644 index 0000000000..c22200508a --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/base_rb.html @@ -0,0 +1,77 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/channel_prefix_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/channel_prefix_rb.html new file mode 100644 index 0000000000..f358de4728 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/channel_prefix_rb.html @@ -0,0 +1,70 @@ +--- +title: channel_prefix.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/inline_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/inline_rb.html new file mode 100644 index 0000000000..ce27e56798 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/inline_rb.html @@ -0,0 +1,70 @@ +--- +title: inline.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/postgresql_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/postgresql_rb.html new file mode 100644 index 0000000000..c48b0b8838 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/postgresql_rb.html @@ -0,0 +1,95 @@ +--- +title: postgresql.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pg
  • + +
  • thread
  • + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/redis_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/redis_rb.html new file mode 100644 index 0000000000..18cc79962d --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/redis_rb.html @@ -0,0 +1,93 @@ +--- +title: redis.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • redis
  • + +
  • active_support/core_ext/hash/except
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/subscriber_map_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/subscriber_map_rb.html new file mode 100644 index 0000000000..b0ed461970 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/subscriber_map_rb.html @@ -0,0 +1,77 @@ +--- +title: subscriber_map.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/test_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/test_rb.html new file mode 100644 index 0000000000..f5626d0e19 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter/test_rb.html @@ -0,0 +1,77 @@ +--- +title: test.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/subscription_adapter_rb.html b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter_rb.html new file mode 100644 index 0000000000..a955f4e5ef --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/subscription_adapter_rb.html @@ -0,0 +1,70 @@ +--- +title: subscription_adapter.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/test_case_rb.html b/src/7.0/files/actioncable/lib/action_cable/test_case_rb.html new file mode 100644 index 0000000000..751b2b0aa9 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/test_case_rb.html @@ -0,0 +1,83 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/test_case
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/test_helper_rb.html b/src/7.0/files/actioncable/lib/action_cable/test_helper_rb.html new file mode 100644 index 0000000000..c1fb577079 --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/test_helper_rb.html @@ -0,0 +1,74 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actioncable/lib/action_cable/version_rb.html b/src/7.0/files/actioncable/lib/action_cable/version_rb.html new file mode 100644 index 0000000000..35e41fa1fb --- /dev/null +++ b/src/7.0/files/actioncable/lib/action_cable/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/README_md.html b/src/7.0/files/actionmailbox/README_md.html new file mode 100644 index 0000000000..f3c85ad4c6 --- /dev/null +++ b/src/7.0/files/actionmailbox/README_md.html @@ -0,0 +1,73 @@ +--- +title: README.md +layout: default +--- +
+ + +
+
+ +
+ +

Action Mailbox

+ +

Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Mailgun, Mandrill, Postmark, and SendGrid. You can also handle inbound mails directly via the built-in Exim, Postfix, and Qmail ingresses.

+ +

The inbound emails are turned into InboundEmail records using Active Record and feature lifecycle tracking, storage of the original email on cloud storage via Active Storage, and responsible data handling with on-by-default incineration.

+ +

These inbound emails are routed asynchronously using Active Job to one or several dedicated mailboxes, which are capable of interacting directly with the rest of your domain model.

+ +

You can read more about Action Mailbox in the Action Mailbox Basics guide.

+ +

License

+ +

Action Mailbox is released under the MIT License.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/base_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/base_controller_rb.html new file mode 100644 index 0000000000..5829cc0652 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/base_controller_rb.html @@ -0,0 +1,75 @@ +--- +title: base_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..ee5cca3624 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mailgun/inbound_emails_controller_rb.html @@ -0,0 +1,93 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • body-mime
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..ec01821257 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/mandrill/inbound_emails_controller_rb.html @@ -0,0 +1,85 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..412917f4e4 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller_rb.html @@ -0,0 +1,87 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • RawEmail
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/relay/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/relay/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..4d835f369e --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/relay/inbound_emails_controller_rb.html @@ -0,0 +1,79 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/sendgrid/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/sendgrid/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..30e139c0d4 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/action_mailbox/ingresses/sendgrid/inbound_emails_controller_rb.html @@ -0,0 +1,79 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller_rb.html new file mode 100644 index 0000000000..15ba87dbe3 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails/sources_controller_rb.html @@ -0,0 +1,81 @@ +--- +title: sources_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller_rb.html new file mode 100644 index 0000000000..74fc46309c --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/inbound_emails_controller_rb.html @@ -0,0 +1,79 @@ +--- +title: inbound_emails_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/incinerates_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/incinerates_controller_rb.html new file mode 100644 index 0000000000..557a9fee71 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/incinerates_controller_rb.html @@ -0,0 +1,79 @@ +--- +title: incinerates_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/reroutes_controller_rb.html b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/reroutes_controller_rb.html new file mode 100644 index 0000000000..c35789353a --- /dev/null +++ b/src/7.0/files/actionmailbox/app/controllers/rails/conductor/action_mailbox/reroutes_controller_rb.html @@ -0,0 +1,79 @@ +--- +title: reroutes_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/jobs/action_mailbox/incineration_job_rb.html b/src/7.0/files/actionmailbox/app/jobs/action_mailbox/incineration_job_rb.html new file mode 100644 index 0000000000..a140952dfc --- /dev/null +++ b/src/7.0/files/actionmailbox/app/jobs/action_mailbox/incineration_job_rb.html @@ -0,0 +1,77 @@ +--- +title: incineration_job.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/jobs/action_mailbox/routing_job_rb.html b/src/7.0/files/actionmailbox/app/jobs/action_mailbox/routing_job_rb.html new file mode 100644 index 0000000000..c74dd2cf30 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/jobs/action_mailbox/routing_job_rb.html @@ -0,0 +1,75 @@ +--- +title: routing_job.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable/incineration_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable/incineration_rb.html new file mode 100644 index 0000000000..7b0ca902fc --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable/incineration_rb.html @@ -0,0 +1,79 @@ +--- +title: incineration.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable_rb.html new file mode 100644 index 0000000000..3089624956 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/incineratable_rb.html @@ -0,0 +1,83 @@ +--- +title: incineratable.rb +layout: default +--- +
+ + +
+
+ +
+ +

Ensure that the InboundEmail is automatically scheduled for later incineration if the status has been changed to processed. The later incineration will be invoked at the time specified by the ActionMailbox.incinerate_after time using the IncinerationJob.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/message_id_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/message_id_rb.html new file mode 100644 index 0000000000..2d78e5fbfd --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/message_id_rb.html @@ -0,0 +1,91 @@ +--- +title: message_id.rb +layout: default +--- +
+ + +
+
+ +
+ +

The Message-ID as specified by rfc822 is supposed to be a unique identifier for that individual email. That makes it an ideal tracking token for debugging and forensics, just like X-Request-Id does for web request.

+ +

If an inbound email does not, against the rfc822 mandate, specify a Message-ID, one will be generated using the approach from Mail::MessageIdField.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/routable_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/routable_rb.html new file mode 100644 index 0000000000..f9d08f8a44 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email/routable_rb.html @@ -0,0 +1,85 @@ +--- +title: routable.rb +layout: default +--- +
+ + +
+
+ +
+ +

A newly received InboundEmail will not be routed synchronously as part of ingress controller’s receival. Instead, the routing will be done asynchronously, using a RoutingJob, to ensure maximum parallel capacity.

+ +

By default, all newly created InboundEmail records that have the status of pending, which is the default, will be scheduled for automatic, deferred routing.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email_rb.html new file mode 100644 index 0000000000..fcf3b2636c --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/inbound_email_rb.html @@ -0,0 +1,83 @@ +--- +title: inbound_email.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mail
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/app/models/action_mailbox/record_rb.html b/src/7.0/files/actionmailbox/app/models/action_mailbox/record_rb.html new file mode 100644 index 0000000000..c7a5c50136 --- /dev/null +++ b/src/7.0/files/actionmailbox/app/models/action_mailbox/record_rb.html @@ -0,0 +1,68 @@ +--- +title: record.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/base_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/base_rb.html new file mode 100644 index 0000000000..98ebbf9f1f --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/base_rb.html @@ -0,0 +1,87 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/rescuable
  • + +
  • action_mailbox/callbacks
  • + +
  • action_mailbox/routing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/callbacks_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/callbacks_rb.html new file mode 100644 index 0000000000..fba7e908b0 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/callbacks_rb.html @@ -0,0 +1,78 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/engine_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/engine_rb.html new file mode 100644 index 0000000000..6111dea7f9 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/engine_rb.html @@ -0,0 +1,95 @@ +--- +title: engine.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails
  • + +
  • action_controller/railtie
  • + +
  • active_job/railtie
  • + +
  • active_record/railtie
  • + +
  • active_storage/engine
  • + +
  • action_mailbox
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/gem_version_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/gem_version_rb.html new file mode 100644 index 0000000000..ed059873ea --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_equality_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_equality_rb.html new file mode 100644 index 0000000000..d6b8b01075 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_equality_rb.html @@ -0,0 +1,75 @@ +--- +title: address_equality.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_wrapping_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_wrapping_rb.html new file mode 100644 index 0000000000..ec9a092672 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/address_wrapping_rb.html @@ -0,0 +1,75 @@ +--- +title: address_wrapping.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/addresses_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/addresses_rb.html new file mode 100644 index 0000000000..1713e8a069 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/addresses_rb.html @@ -0,0 +1,75 @@ +--- +title: addresses.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/from_source_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/from_source_rb.html new file mode 100644 index 0000000000..5286fe49ec --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/from_source_rb.html @@ -0,0 +1,68 @@ +--- +title: from_source.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/recipients_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/recipients_rb.html new file mode 100644 index 0000000000..cb78118341 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext/recipients_rb.html @@ -0,0 +1,75 @@ +--- +title: recipients.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext_rb.html new file mode 100644 index 0000000000..29bfcee22a --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/mail_ext_rb.html @@ -0,0 +1,63 @@ +--- +title: mail_ext.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mail
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/relayer_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/relayer_rb.html new file mode 100644 index 0000000000..ecbaf4f1d9 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/relayer_rb.html @@ -0,0 +1,91 @@ +--- +title: relayer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_mailbox/version
  • + +
  • net/http
  • + +
  • uri
  • + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/router/route_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/router/route_rb.html new file mode 100644 index 0000000000..392968af3f --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/router/route_rb.html @@ -0,0 +1,77 @@ +--- +title: route.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/router_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/router_rb.html new file mode 100644 index 0000000000..ed3d6d2f13 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/router_rb.html @@ -0,0 +1,85 @@ +--- +title: router.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_mailbox/router/route
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/routing_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/routing_rb.html new file mode 100644 index 0000000000..dee570b6dc --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/routing_rb.html @@ -0,0 +1,70 @@ +--- +title: routing.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/test_case_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/test_case_rb.html new file mode 100644 index 0000000000..9562101e6b --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/test_case_rb.html @@ -0,0 +1,85 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_mailbox/test_helper
  • + +
  • active_support/test_case
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/test_helper_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/test_helper_rb.html new file mode 100644 index 0000000000..cc02f4b712 --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/test_helper_rb.html @@ -0,0 +1,78 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mail
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailbox/lib/action_mailbox/version_rb.html b/src/7.0/files/actionmailbox/lib/action_mailbox/version_rb.html new file mode 100644 index 0000000000..c7264b201a --- /dev/null +++ b/src/7.0/files/actionmailbox/lib/action_mailbox/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/README_rdoc.html b/src/7.0/files/actionmailer/README_rdoc.html new file mode 100644 index 0000000000..cce241dfae --- /dev/null +++ b/src/7.0/files/actionmailer/README_rdoc.html @@ -0,0 +1,192 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Action Mailer – Easy email delivery and testing

+ +

Action Mailer is a framework for designing email service layers. These layers are used to consolidate code for sending out forgotten passwords, welcome wishes on signup, invoices for billing, and any other use case that requires a written notification to either a person or another system.

+ +

Action Mailer is in essence a wrapper around Action Controller and the Mail gem. It provides a way to make emails using templates in the same way that Action Controller renders views using templates.

+ +

Additionally, an Action Mailer class can be used to process incoming email, such as allowing a blog to accept new posts from an email (which could even have been sent from a phone).

+ +

You can read more about Action Mailer in the Action Mailer Basics guide.

+ +

Sending emails

+ +

The framework works by initializing any instance variables you want to be available in the email template, followed by a call to mail to deliver the email.

+ +

This can be as simple as:

+ +
class Notifier < ActionMailer::Base
+  default from: 'system@loudthinking.com'
+
+  def welcome(recipient)
+    @recipient = recipient
+    mail(to: recipient,
+         subject: "[Signed up] Welcome #{recipient}")
+  end
+end
+
+ +

The body of the email is created by using an Action View template (regular ERB) that has the instance variables that are declared in the mailer action.

+ +

So the corresponding body template for the method above could look like this:

+ +
Hello there,
+
+Mr. <%= @recipient %>
+
+Thank you for signing up!
+
+ +

If the recipient was given as “david@loudthinking.com”, the email generated would look like this:

+ +
Date: Mon, 25 Jan 2010 22:48:09 +1100
+From: system@loudthinking.com
+To: david@loudthinking.com
+Message-ID: <4b5d84f9dd6a5_7380800b81ac29578@void.loudthinking.com.mail>
+Subject: [Signed up] Welcome david@loudthinking.com
+Mime-Version: 1.0
+Content-Type: text/plain;
+      charset="US-ASCII";
+Content-Transfer-Encoding: 7bit
+
+Hello there,
+
+Mr. david@loudthinking.com
+
+Thank you for signing up!
+
+ +

In order to send mails, you simply call the method and then call deliver_now on the return value.

+ +

Calling the method returns a Mail Message object:

+ +
message = Notifier.welcome("david@loudthinking.com")   # => Returns a Mail::Message object
+message.deliver_now                                    # => delivers the email
+
+ +

Or you can just chain the methods together like:

+ +
Notifier.welcome("david@loudthinking.com").deliver_now # Creates the email and sends it immediately
+
+ +

Setting defaults

+ +

It is possible to set default values that will be used in every method in your Action Mailer class. To implement this functionality, you just call the public class method default which you get for free from ActionMailer::Base. This method accepts a Hash as the parameter. You can use any of the headers, email messages have, like :from as the key. You can also pass in a string as the key, like “Content-Type”, but Action Mailer does this out of the box for you, so you won’t need to worry about that. Finally, it is also possible to pass in a Proc that will get evaluated when it is needed.

+ +

Note that every value you set with this method will get overwritten if you use the same key in your mailer method.

+ +

Example:

+ +
class AuthenticationMailer < ActionMailer::Base
+  default from: "awesome@application.com", subject: Proc.new { "E-mail was generated at #{Time.now}" }
+  .....
+end
+
+ +

Configuration

+ +

The Base class has the full list of configuration options. Here’s an example:

+ +
ActionMailer::Base.smtp_settings = {
+  address:        'smtp.yourserver.com', # default: localhost
+  port:           '25',                  # default: 25
+  user_name:      'user',
+  password:       'pass',
+  authentication: :plain                 # :plain, :login or :cram_md5
+}
+
+ +

Download and installation

+ +

The latest version of Action Mailer can be installed with RubyGems:

+ +
$ gem install actionmailer
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Action Mailer is released under the MIT license:

+ + +

Support

+ +

API documentation is at

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/base_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/base_rb.html new file mode 100644 index 0000000000..aaa041b00e --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/base_rb.html @@ -0,0 +1,103 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mail
  • + +
  • action_mailer/collector
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/module/anonymous
  • + +
  • action_mailer/log_subscriber
  • + +
  • action_mailer/rescuable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/collector_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/collector_rb.html new file mode 100644 index 0000000000..d995493e14 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/collector_rb.html @@ -0,0 +1,87 @@ +--- +title: collector.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • abstract_controller/collector
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
  • active_support/core_ext/array/extract_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/delivery_methods_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/delivery_methods_rb.html new file mode 100644 index 0000000000..03f895bff7 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/delivery_methods_rb.html @@ -0,0 +1,82 @@ +--- +title: delivery_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • tmpdir
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/gem_version_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/gem_version_rb.html new file mode 100644 index 0000000000..402e5a6c85 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/inline_preview_interceptor_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/inline_preview_interceptor_rb.html new file mode 100644 index 0000000000..cdef5a5a66 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/inline_preview_interceptor_rb.html @@ -0,0 +1,83 @@ +--- +title: inline_preview_interceptor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • base64
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/log_subscriber_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/log_subscriber_rb.html new file mode 100644 index 0000000000..897162255c --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/log_subscriber_rb.html @@ -0,0 +1,83 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/mail_delivery_job_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/mail_delivery_job_rb.html new file mode 100644 index 0000000000..c5fe363a00 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/mail_delivery_job_rb.html @@ -0,0 +1,76 @@ +--- +title: mail_delivery_job.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_job
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/mail_helper_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/mail_helper_rb.html new file mode 100644 index 0000000000..4894000bf8 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/mail_helper_rb.html @@ -0,0 +1,70 @@ +--- +title: mail_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/message_delivery_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/message_delivery_rb.html new file mode 100644 index 0000000000..632bb8cdd3 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/message_delivery_rb.html @@ -0,0 +1,83 @@ +--- +title: message_delivery.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • delegate
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/parameterized_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/parameterized_rb.html new file mode 100644 index 0000000000..fdfe79971c --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/parameterized_rb.html @@ -0,0 +1,72 @@ +--- +title: parameterized.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/preview_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/preview_rb.html new file mode 100644 index 0000000000..8bbbd60734 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/preview_rb.html @@ -0,0 +1,87 @@ +--- +title: preview.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/descendants_tracker
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/railtie_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/railtie_rb.html new file mode 100644 index 0000000000..987659c41f --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/railtie_rb.html @@ -0,0 +1,84 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_job/railtie
  • + +
  • action_mailer
  • + +
  • rails
  • + +
  • abstract_controller/railties/routes_helpers
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/rescuable_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/rescuable_rb.html new file mode 100644 index 0000000000..5ec4b2de04 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/rescuable_rb.html @@ -0,0 +1,70 @@ +--- +title: rescuable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/test_case_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/test_case_rb.html new file mode 100644 index 0000000000..9be6b1602d --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/test_case_rb.html @@ -0,0 +1,95 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/test_case
  • + +
  • rails-dom-testing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/test_helper_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/test_helper_rb.html new file mode 100644 index 0000000000..01e7046b23 --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/test_helper_rb.html @@ -0,0 +1,78 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_job
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionmailer/lib/action_mailer/version_rb.html b/src/7.0/files/actionmailer/lib/action_mailer/version_rb.html new file mode 100644 index 0000000000..54a2b8a25b --- /dev/null +++ b/src/7.0/files/actionmailer/lib/action_mailer/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/README_rdoc.html b/src/7.0/files/actionpack/README_rdoc.html new file mode 100644 index 0000000000..a3459c9ef1 --- /dev/null +++ b/src/7.0/files/actionpack/README_rdoc.html @@ -0,0 +1,110 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Action Pack – From request to response

+ +

Action Pack is a framework for handling and responding to web requests. It provides mechanisms for routing (mapping request URLs to actions), defining controllers that implement actions, and generating responses. In short, Action Pack provides the controller layer in the MVC paradigm.

+ +

It consists of several modules:

+
  • +

    Action Dispatch, which parses information about the web request, handles routing as defined by the user, and does advanced processing related to HTTP such as MIME-type negotiation, decoding parameters in POST, PATCH, or PUT bodies, handling HTTP caching logic, cookies and sessions.

    +
  • +

    Action Controller, which provides a base controller class that can be subclassed to implement filters and actions to handle requests. The result of an action is typically content generated from views.

    +
+ +

With the Ruby on Rails framework, users only directly interface with the Action Controller module. Necessary Action Dispatch functionality is activated by default and Action View rendering is implicitly triggered by Action Controller. However, these modules are designed to function on their own and can be used outside of Rails.

+ +

You can read more about Action Pack in the Action Controller Overview guide.

+ +

Download and installation

+ +

The latest version of Action Pack can be installed with RubyGems:

+ +
$ gem install actionpack
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Action Pack is released under the MIT license:

+ + +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/asset_paths_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/asset_paths_rb.html new file mode 100644 index 0000000000..53ab0c5644 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/asset_paths_rb.html @@ -0,0 +1,68 @@ +--- +title: asset_paths.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/base_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/base_rb.html new file mode 100644 index 0000000000..4ee363fe69 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/base_rb.html @@ -0,0 +1,93 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • abstract_controller/error
  • + +
  • active_support/configurable
  • + +
  • active_support/descendants_tracker
  • + +
  • active_support/core_ext/module/anonymous
  • + +
  • active_support/core_ext/module/attr_internal
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/caching/fragments_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/caching/fragments_rb.html new file mode 100644 index 0000000000..bde1ea6297 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/caching/fragments_rb.html @@ -0,0 +1,76 @@ +--- +title: fragments.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/caching_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/caching_rb.html new file mode 100644 index 0000000000..b911d8a9ae --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/caching_rb.html @@ -0,0 +1,76 @@ +--- +title: caching.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/callbacks_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/callbacks_rb.html new file mode 100644 index 0000000000..b8cdef0c49 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/callbacks_rb.html @@ -0,0 +1,72 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/collector_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/collector_rb.html new file mode 100644 index 0000000000..8b825b47f8 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/collector_rb.html @@ -0,0 +1,80 @@ +--- +title: collector.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/http/mime_type
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/error_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/error_rb.html new file mode 100644 index 0000000000..d84c3b7222 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/error_rb.html @@ -0,0 +1,68 @@ +--- +title: error.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/helpers_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/helpers_rb.html new file mode 100644 index 0000000000..1a6495407a --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/helpers_rb.html @@ -0,0 +1,89 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/dependencies
  • + +
  • active_support/core_ext/name_error
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/logger_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/logger_rb.html new file mode 100644 index 0000000000..be7028c6c2 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/logger_rb.html @@ -0,0 +1,76 @@ +--- +title: logger.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/benchmarkable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/railties/routes_helpers_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/railties/routes_helpers_rb.html new file mode 100644 index 0000000000..a4628f5f44 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/railties/routes_helpers_rb.html @@ -0,0 +1,80 @@ +--- +title: routes_helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/introspection
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/rendering_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/rendering_rb.html new file mode 100644 index 0000000000..a48203e547 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/rendering_rb.html @@ -0,0 +1,91 @@ +--- +title: rendering.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • abstract_controller/error
  • + +
  • action_view
  • + +
  • action_view/view_paths
  • + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/translation_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/translation_rb.html new file mode 100644 index 0000000000..c573eb6222 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/translation_rb.html @@ -0,0 +1,80 @@ +--- +title: translation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/html_safe_translation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/abstract_controller/url_for_rb.html b/src/7.0/files/actionpack/lib/abstract_controller/url_for_rb.html new file mode 100644 index 0000000000..857f4aa281 --- /dev/null +++ b/src/7.0/files/actionpack/lib/abstract_controller/url_for_rb.html @@ -0,0 +1,72 @@ +--- +title: url_for.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/api/api_rendering_rb.html b/src/7.0/files/actionpack/lib/action_controller/api/api_rendering_rb.html new file mode 100644 index 0000000000..d44d2dd244 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/api/api_rendering_rb.html @@ -0,0 +1,70 @@ +--- +title: api_rendering.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/api_rb.html b/src/7.0/files/actionpack/lib/action_controller/api_rb.html new file mode 100644 index 0000000000..52e561fd60 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/api_rb.html @@ -0,0 +1,87 @@ +--- +title: api.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view
  • + +
  • action_controller
  • + +
  • action_controller/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/base_rb.html b/src/7.0/files/actionpack/lib/action_controller/base_rb.html new file mode 100644 index 0000000000..b0c2a80c66 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/base_rb.html @@ -0,0 +1,87 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view
  • + +
  • action_controller/log_subscriber
  • + +
  • action_controller/metal/params_wrapper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/caching_rb.html b/src/7.0/files/actionpack/lib/action_controller/caching_rb.html new file mode 100644 index 0000000000..ec3cf6a200 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/caching_rb.html @@ -0,0 +1,70 @@ +--- +title: caching.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/form_builder_rb.html b/src/7.0/files/actionpack/lib/action_controller/form_builder_rb.html new file mode 100644 index 0000000000..b2d3778e10 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/form_builder_rb.html @@ -0,0 +1,72 @@ +--- +title: form_builder.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/log_subscriber_rb.html b/src/7.0/files/actionpack/lib/action_controller/log_subscriber_rb.html new file mode 100644 index 0000000000..8ba85bd110 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/log_subscriber_rb.html @@ -0,0 +1,77 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/basic_implicit_render_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/basic_implicit_render_rb.html new file mode 100644 index 0000000000..f0916849b8 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/basic_implicit_render_rb.html @@ -0,0 +1,68 @@ +--- +title: basic_implicit_render.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/conditional_get_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/conditional_get_rb.html new file mode 100644 index 0000000000..0f4788debf --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/conditional_get_rb.html @@ -0,0 +1,82 @@ +--- +title: conditional_get.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
  • active_support/core_ext/integer/time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/content_security_policy_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/content_security_policy_rb.html new file mode 100644 index 0000000000..df09c193ed --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/content_security_policy_rb.html @@ -0,0 +1,74 @@ +--- +title: content_security_policy.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/cookies_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/cookies_rb.html new file mode 100644 index 0000000000..d9497f0205 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/cookies_rb.html @@ -0,0 +1,70 @@ +--- +title: cookies.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/data_streaming_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/data_streaming_rb.html new file mode 100644 index 0000000000..5046f0cb03 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/data_streaming_rb.html @@ -0,0 +1,84 @@ +--- +title: data_streaming.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_controller/metal/exceptions
  • + +
  • action_dispatch/http/content_disposition
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/default_headers_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/default_headers_rb.html new file mode 100644 index 0000000000..fdd93c7082 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/default_headers_rb.html @@ -0,0 +1,74 @@ +--- +title: default_headers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_flash_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_flash_rb.html new file mode 100644 index 0000000000..16505f04e7 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_flash_rb.html @@ -0,0 +1,70 @@ +--- +title: etag_with_flash.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_template_digest_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_template_digest_rb.html new file mode 100644 index 0000000000..c25e79f787 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/etag_with_template_digest_rb.html @@ -0,0 +1,72 @@ +--- +title: etag_with_template_digest.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/exceptions_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/exceptions_rb.html new file mode 100644 index 0000000000..5d46d858d6 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/exceptions_rb.html @@ -0,0 +1,75 @@ +--- +title: exceptions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/flash_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/flash_rb.html new file mode 100644 index 0000000000..b7a5bbe35f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/flash_rb.html @@ -0,0 +1,72 @@ +--- +title: flash.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/head_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/head_rb.html new file mode 100644 index 0000000000..0910ed5349 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/head_rb.html @@ -0,0 +1,70 @@ +--- +title: head.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/helpers_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/helpers_rb.html new file mode 100644 index 0000000000..5259088319 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/helpers_rb.html @@ -0,0 +1,74 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/http_authentication_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/http_authentication_rb.html new file mode 100644 index 0000000000..43a9c59828 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/http_authentication_rb.html @@ -0,0 +1,100 @@ +--- +title: http_authentication.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/implicit_render_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/implicit_render_rb.html new file mode 100644 index 0000000000..6f4f38fa87 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/implicit_render_rb.html @@ -0,0 +1,70 @@ +--- +title: implicit_render.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/instrumentation_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/instrumentation_rb.html new file mode 100644 index 0000000000..aee176ee5b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/instrumentation_rb.html @@ -0,0 +1,86 @@ +--- +title: instrumentation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • benchmark
  • + +
  • abstract_controller/logger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/live_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/live_rb.html new file mode 100644 index 0000000000..5e674eb912 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/live_rb.html @@ -0,0 +1,101 @@ +--- +title: live.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/http/response
  • + +
  • delegate
  • + +
  • active_support/json
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/logging_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/logging_rb.html new file mode 100644 index 0000000000..489b39fd49 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/logging_rb.html @@ -0,0 +1,72 @@ +--- +title: logging.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/mime_responds_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/mime_responds_rb.html new file mode 100644 index 0000000000..af8230f143 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/mime_responds_rb.html @@ -0,0 +1,87 @@ +--- +title: mime_responds.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • abstract_controller/collector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/parameter_encoding_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/parameter_encoding_rb.html new file mode 100644 index 0000000000..20b2f39f3f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/parameter_encoding_rb.html @@ -0,0 +1,72 @@ +--- +title: parameter_encoding.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/params_wrapper_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/params_wrapper_rb.html new file mode 100644 index 0000000000..90117d661d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/params_wrapper_rb.html @@ -0,0 +1,95 @@ +--- +title: params_wrapper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/module/anonymous
  • + +
  • action_dispatch/http/mime_type
  • + +
  • mutex_m
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/permissions_policy_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/permissions_policy_rb.html new file mode 100644 index 0000000000..309afdfed2 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/permissions_policy_rb.html @@ -0,0 +1,72 @@ +--- +title: permissions_policy.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/redirecting_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/redirecting_rb.html new file mode 100644 index 0000000000..3d4bc4a063 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/redirecting_rb.html @@ -0,0 +1,79 @@ +--- +title: redirecting.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/renderers_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/renderers_rb.html new file mode 100644 index 0000000000..3866c5c93f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/renderers_rb.html @@ -0,0 +1,89 @@ +--- +title: renderers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/rendering_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/rendering_rb.html new file mode 100644 index 0000000000..d750943071 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/rendering_rb.html @@ -0,0 +1,74 @@ +--- +title: rendering.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/request_forgery_protection_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/request_forgery_protection_rb.html new file mode 100644 index 0000000000..25a9616980 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/request_forgery_protection_rb.html @@ -0,0 +1,101 @@ +--- +title: request_forgery_protection.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/session/abstract/id
  • + +
  • action_controller/metal/exceptions
  • + +
  • active_support/security_utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/rescue_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/rescue_rb.html new file mode 100644 index 0000000000..fb91965eb4 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/rescue_rb.html @@ -0,0 +1,70 @@ +--- +title: rescue.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/streaming_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/streaming_rb.html new file mode 100644 index 0000000000..2d980f1d45 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/streaming_rb.html @@ -0,0 +1,78 @@ +--- +title: streaming.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/chunked
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/strong_parameters_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/strong_parameters_rb.html new file mode 100644 index 0000000000..d004c3751d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/strong_parameters_rb.html @@ -0,0 +1,109 @@ +--- +title: strong_parameters.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • active_support/core_ext/array/wrap
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • action_dispatch/http/upload
  • + +
  • rack/test
  • + +
  • stringio
  • + +
  • set
  • + +
  • yaml
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/testing_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/testing_rb.html new file mode 100644 index 0000000000..fe3a4c52b9 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/testing_rb.html @@ -0,0 +1,70 @@ +--- +title: testing.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal/url_for_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal/url_for_rb.html new file mode 100644 index 0000000000..4da9ce3c2d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal/url_for_rb.html @@ -0,0 +1,70 @@ +--- +title: url_for.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/metal_rb.html b/src/7.0/files/actionpack/lib/action_controller/metal_rb.html new file mode 100644 index 0000000000..6e6d4dbc5c --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/metal_rb.html @@ -0,0 +1,87 @@ +--- +title: metal.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
  • action_dispatch/middleware/stack
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/railtie_rb.html b/src/7.0/files/actionpack/lib/action_controller/railtie_rb.html new file mode 100644 index 0000000000..8246e88f92 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/railtie_rb.html @@ -0,0 +1,90 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails
  • + +
  • action_controller
  • + +
  • action_dispatch/railtie
  • + +
  • abstract_controller/railties/routes_helpers
  • + +
  • action_controller/railties/helpers
  • + +
  • action_view/railtie
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/railties/helpers_rb.html b/src/7.0/files/actionpack/lib/action_controller/railties/helpers_rb.html new file mode 100644 index 0000000000..e624d09ff0 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/railties/helpers_rb.html @@ -0,0 +1,72 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/renderer_rb.html b/src/7.0/files/actionpack/lib/action_controller/renderer_rb.html new file mode 100644 index 0000000000..8bd776b564 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/renderer_rb.html @@ -0,0 +1,77 @@ +--- +title: renderer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/template_assertions_rb.html b/src/7.0/files/actionpack/lib/action_controller/template_assertions_rb.html new file mode 100644 index 0000000000..0c61d76a5e --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/template_assertions_rb.html @@ -0,0 +1,68 @@ +--- +title: template_assertions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_controller/test_case_rb.html b/src/7.0/files/actionpack/lib/action_controller/test_case_rb.html new file mode 100644 index 0000000000..5a7bb2dbd0 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_controller/test_case_rb.html @@ -0,0 +1,113 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/session/abstract/id
  • + +
  • active_support/core_ext/hash/conversions
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/core_ext/module/anonymous
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/testing/constant_lookup
  • + +
  • action_controller/template_assertions
  • + +
  • rails-dom-testing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/cache_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/cache_rb.html new file mode 100644 index 0000000000..4a512c0e8b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/cache_rb.html @@ -0,0 +1,76 @@ +--- +title: cache.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/content_disposition_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/content_disposition_rb.html new file mode 100644 index 0000000000..f1c8ebdffc --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/content_disposition_rb.html @@ -0,0 +1,70 @@ +--- +title: content_disposition.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/content_security_policy_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/content_security_policy_rb.html new file mode 100644 index 0000000000..1715c7037d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/content_security_policy_rb.html @@ -0,0 +1,89 @@ +--- +title: content_security_policy.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/deep_dup
  • + +
  • active_support/core_ext/array/wrap
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/filter_parameters_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/filter_parameters_rb.html new file mode 100644 index 0000000000..2dbfb0afdd --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/filter_parameters_rb.html @@ -0,0 +1,82 @@ +--- +title: filter_parameters.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/parameter_filter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/filter_redirect_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/filter_redirect_rb.html new file mode 100644 index 0000000000..87b183f0ac --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/filter_redirect_rb.html @@ -0,0 +1,72 @@ +--- +title: filter_redirect.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/headers_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/headers_rb.html new file mode 100644 index 0000000000..75049b74df --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/headers_rb.html @@ -0,0 +1,77 @@ +--- +title: headers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/mime_negotiation_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_negotiation_rb.html new file mode 100644 index 0000000000..7139c099b8 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_negotiation_rb.html @@ -0,0 +1,91 @@ +--- +title: mime_negotiation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/mime_type_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_type_rb.html new file mode 100644 index 0000000000..371ad09aa7 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_type_rb.html @@ -0,0 +1,93 @@ +--- +title: mime_type.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • singleton
  • + +
  • action_dispatch/http/mime_types
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/mime_types_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_types_rb.html new file mode 100644 index 0000000000..ea0345bab1 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/mime_types_rb.html @@ -0,0 +1,74 @@ +--- +title: mime_types.rb +layout: default +--- +
+ + +
+
+ +
+ +

Build list of Mime types for HTTP responses www.iana.org/assignments/media-types/

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/parameters_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/parameters_rb.html new file mode 100644 index 0000000000..2f6ae42698 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/parameters_rb.html @@ -0,0 +1,85 @@ +--- +title: parameters.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/permissions_policy_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/permissions_policy_rb.html new file mode 100644 index 0000000000..27386f22fe --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/permissions_policy_rb.html @@ -0,0 +1,87 @@ +--- +title: permissions_policy.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/deep_dup
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/rack_cache_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/rack_cache_rb.html new file mode 100644 index 0000000000..0fee04a95f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/rack_cache_rb.html @@ -0,0 +1,101 @@ +--- +title: rack_cache.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/cache
  • + +
  • rack/cache/context
  • + +
  • active_support/cache
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/request_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/request_rb.html new file mode 100644 index 0000000000..9ebb0fc9b0 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/request_rb.html @@ -0,0 +1,109 @@ +--- +title: request.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • stringio
  • + +
  • active_support/inflector
  • + +
  • action_dispatch/http/headers
  • + +
  • action_controller/metal/exceptions
  • + +
  • rack/request
  • + +
  • action_dispatch/http/cache
  • + +
  • action_dispatch/http/mime_negotiation
  • + +
  • action_dispatch/http/parameters
  • + +
  • action_dispatch/http/filter_parameters
  • + +
  • action_dispatch/http/upload
  • + +
  • action_dispatch/http/url
  • + +
  • active_support/core_ext/array/conversions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/response_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/response_rb.html new file mode 100644 index 0000000000..447aae9f33 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/response_rb.html @@ -0,0 +1,91 @@ +--- +title: response.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • action_dispatch/http/filter_redirect
  • + +
  • action_dispatch/http/cache
  • + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/upload_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/upload_rb.html new file mode 100644 index 0000000000..255d6d8960 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/upload_rb.html @@ -0,0 +1,77 @@ +--- +title: upload.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/http/url_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/http/url_rb.html new file mode 100644 index 0000000000..f2e4488ab8 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/http/url_rb.html @@ -0,0 +1,80 @@ +--- +title: url.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/formatter_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/formatter_rb.html new file mode 100644 index 0000000000..ca9ff58943 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/formatter_rb.html @@ -0,0 +1,91 @@ +--- +title: formatter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_controller/metal/exceptions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/builder_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/builder_rb.html new file mode 100644 index 0000000000..df9e922846 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/builder_rb.html @@ -0,0 +1,78 @@ +--- +title: builder.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/gtg/transition_table
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/simulator_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/simulator_rb.html new file mode 100644 index 0000000000..ce288702f1 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/simulator_rb.html @@ -0,0 +1,78 @@ +--- +title: simulator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • strscan
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/transition_table_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/transition_table_rb.html new file mode 100644 index 0000000000..6ba0001673 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/gtg/transition_table_rb.html @@ -0,0 +1,80 @@ +--- +title: transition_table.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/nfa/dot
  • + +
  • erb
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/nfa/dot_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/nfa/dot_rb.html new file mode 100644 index 0000000000..0224b9b90e --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/nfa/dot_rb.html @@ -0,0 +1,70 @@ +--- +title: dot.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/nodes/node_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/nodes/node_rb.html new file mode 100644 index 0000000000..14869fba81 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/nodes/node_rb.html @@ -0,0 +1,78 @@ +--- +title: node.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/visitors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_extras_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_extras_rb.html new file mode 100644 index 0000000000..c05df78d9f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_extras_rb.html @@ -0,0 +1,87 @@ +--- +title: parser_extras.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/scanner
  • + +
  • action_dispatch/journey/nodes/node
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_rb.html new file mode 100644 index 0000000000..d7473ab4a8 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/parser_rb.html @@ -0,0 +1,91 @@ +--- +title: parser.rb +layout: default +--- +
+ + +
+
+ +
+ +

DO NOT MODIFY!!!! This file is automatically generated by Racc 1.4.16 from Racc grammar file “”.

+ +
+ + + + +

Required Files

+
    + +
  • racc/parser.rb
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/path/pattern_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/path/pattern_rb.html new file mode 100644 index 0000000000..f1efd88aec --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/path/pattern_rb.html @@ -0,0 +1,70 @@ +--- +title: pattern.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/route_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/route_rb.html new file mode 100644 index 0000000000..8f6ec6d129 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/route_rb.html @@ -0,0 +1,83 @@ +--- +title: route.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/router/utils_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/router/utils_rb.html new file mode 100644 index 0000000000..1547c6d300 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/router/utils_rb.html @@ -0,0 +1,70 @@ +--- +title: utils.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/router_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/router_rb.html new file mode 100644 index 0000000000..bf9d78187b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/router_rb.html @@ -0,0 +1,88 @@ +--- +title: router.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/router/utils
  • + +
  • action_dispatch/journey/routes
  • + +
  • action_dispatch/journey/formatter
  • + +
  • action_dispatch/journey/parser
  • + +
  • action_dispatch/journey/route
  • + +
  • action_dispatch/journey/path/pattern
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/routes_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/routes_rb.html new file mode 100644 index 0000000000..da5f1a97e7 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/routes_rb.html @@ -0,0 +1,70 @@ +--- +title: routes.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/scanner_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/scanner_rb.html new file mode 100644 index 0000000000..2502c18f31 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/scanner_rb.html @@ -0,0 +1,78 @@ +--- +title: scanner.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • strscan
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey/visitors_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey/visitors_rb.html new file mode 100644 index 0000000000..44da4ec4ce --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey/visitors_rb.html @@ -0,0 +1,77 @@ +--- +title: visitors.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/journey_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/journey_rb.html new file mode 100644 index 0000000000..ecb793d5c4 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/journey_rb.html @@ -0,0 +1,67 @@ +--- +title: journey.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey/router
  • + +
  • action_dispatch/journey/gtg/builder
  • + +
  • action_dispatch/journey/gtg/simulator
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/actionable_exceptions_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/actionable_exceptions_rb.html new file mode 100644 index 0000000000..604f8b71a2 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/actionable_exceptions_rb.html @@ -0,0 +1,82 @@ +--- +title: actionable_exceptions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • erb
  • + +
  • uri
  • + +
  • active_support/actionable_error
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/callbacks_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/callbacks_rb.html new file mode 100644 index 0000000000..650718af72 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/callbacks_rb.html @@ -0,0 +1,75 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/cookies_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/cookies_rb.html new file mode 100644 index 0000000000..e2f95bf8f0 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/cookies_rb.html @@ -0,0 +1,97 @@ +--- +title: cookies.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/key_generator
  • + +
  • active_support/message_verifier
  • + +
  • active_support/json
  • + +
  • rack/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_exceptions_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_exceptions_rb.html new file mode 100644 index 0000000000..feb7e64002 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_exceptions_rb.html @@ -0,0 +1,93 @@ +--- +title: debug_exceptions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/middleware/exception_wrapper
  • + +
  • action_dispatch/routing/inspector
  • + +
  • action_view
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_locks_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_locks_rb.html new file mode 100644 index 0000000000..e7513105be --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_locks_rb.html @@ -0,0 +1,77 @@ +--- +title: debug_locks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_view_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_view_rb.html new file mode 100644 index 0000000000..0f2b9513fd --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/debug_view_rb.html @@ -0,0 +1,82 @@ +--- +title: debug_view.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pp
  • + +
  • action_view
  • + +
  • action_view/base
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/exception_wrapper_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/exception_wrapper_rb.html new file mode 100644 index 0000000000..a75028c63f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/exception_wrapper_rb.html @@ -0,0 +1,85 @@ +--- +title: exception_wrapper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • rack/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/executor_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/executor_rb.html new file mode 100644 index 0000000000..dac965cb87 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/executor_rb.html @@ -0,0 +1,83 @@ +--- +title: executor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/body_proxy
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/flash_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/flash_rb.html new file mode 100644 index 0000000000..90ec1c6a33 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/flash_rb.html @@ -0,0 +1,89 @@ +--- +title: flash.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/host_authorization_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/host_authorization_rb.html new file mode 100644 index 0000000000..abbbc4a127 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/host_authorization_rb.html @@ -0,0 +1,77 @@ +--- +title: host_authorization.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/public_exceptions_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/public_exceptions_rb.html new file mode 100644 index 0000000000..41535f9393 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/public_exceptions_rb.html @@ -0,0 +1,75 @@ +--- +title: public_exceptions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/reloader_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/reloader_rb.html new file mode 100644 index 0000000000..8574f842a5 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/reloader_rb.html @@ -0,0 +1,75 @@ +--- +title: reloader.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/remote_ip_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/remote_ip_rb.html new file mode 100644 index 0000000000..52f9a10868 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/remote_ip_rb.html @@ -0,0 +1,89 @@ +--- +title: remote_ip.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • ipaddr
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/request_id_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/request_id_rb.html new file mode 100644 index 0000000000..a482dfc905 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/request_id_rb.html @@ -0,0 +1,85 @@ +--- +title: request_id.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
  • active_support/core_ext/string/access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/server_timing_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/server_timing_rb.html new file mode 100644 index 0000000000..b1ace59847 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/server_timing_rb.html @@ -0,0 +1,85 @@ +--- +title: server_timing.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/notifications
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/abstract_store_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/abstract_store_rb.html new file mode 100644 index 0000000000..b428b7764b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/abstract_store_rb.html @@ -0,0 +1,101 @@ +--- +title: abstract_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/utils
  • + +
  • rack/request
  • + +
  • rack/session/abstract/id
  • + +
  • action_dispatch/middleware/cookies
  • + +
  • action_dispatch/request/session
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cache_store_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cache_store_rb.html new file mode 100644 index 0000000000..a8458b51fa --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cache_store_rb.html @@ -0,0 +1,85 @@ +--- +title: cache_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/middleware/session/abstract_store
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cookie_store_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cookie_store_rb.html new file mode 100644 index 0000000000..0d89c16e83 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/cookie_store_rb.html @@ -0,0 +1,91 @@ +--- +title: cookie_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
  • action_dispatch/middleware/session/abstract_store
  • + +
  • rack/session/cookie
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/mem_cache_store_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/mem_cache_store_rb.html new file mode 100644 index 0000000000..41c88c68cb --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/session/mem_cache_store_rb.html @@ -0,0 +1,87 @@ +--- +title: mem_cache_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/middleware/session/abstract_store
  • + +
  • rack/session/dalli
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/show_exceptions_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/show_exceptions_rb.html new file mode 100644 index 0000000000..a1b25a0b99 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/show_exceptions_rb.html @@ -0,0 +1,83 @@ +--- +title: show_exceptions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/middleware/exception_wrapper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/ssl_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/ssl_rb.html new file mode 100644 index 0000000000..ed3a9c90d9 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/ssl_rb.html @@ -0,0 +1,75 @@ +--- +title: ssl.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/stack_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/stack_rb.html new file mode 100644 index 0000000000..f55924795d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/stack_rb.html @@ -0,0 +1,91 @@ +--- +title: stack.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/methods
  • + +
  • active_support/dependencies
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/middleware/static_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/middleware/static_rb.html new file mode 100644 index 0000000000..2693f783e2 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/middleware/static_rb.html @@ -0,0 +1,87 @@ +--- +title: static.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/railtie_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/railtie_rb.html new file mode 100644 index 0000000000..6a27a6239f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/railtie_rb.html @@ -0,0 +1,91 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch
  • + +
  • active_support/messages/rotation_configuration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/request/session_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/request/session_rb.html new file mode 100644 index 0000000000..127135f830 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/request/session_rb.html @@ -0,0 +1,83 @@ +--- +title: session.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/session/abstract/id
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/request/utils_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/request/utils_rb.html new file mode 100644 index 0000000000..34a1d8f7fb --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/request/utils_rb.html @@ -0,0 +1,85 @@ +--- +title: utils.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/endpoint_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/endpoint_rb.html new file mode 100644 index 0000000000..ee801faba7 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/endpoint_rb.html @@ -0,0 +1,72 @@ +--- +title: endpoint.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/inspector_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/inspector_rb.html new file mode 100644 index 0000000000..8c3104b989 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/inspector_rb.html @@ -0,0 +1,95 @@ +--- +title: inspector.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • delegate
  • + +
  • io/console/size
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/mapper_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/mapper_rb.html new file mode 100644 index 0000000000..35e9ce194b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/mapper_rb.html @@ -0,0 +1,115 @@ +--- +title: mapper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/regexp
  • + +
  • action_dispatch/routing/redirection
  • + +
  • action_dispatch/routing/endpoint
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/polymorphic_routes_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/polymorphic_routes_rb.html new file mode 100644 index 0000000000..60c4859467 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/polymorphic_routes_rb.html @@ -0,0 +1,72 @@ +--- +title: polymorphic_routes.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/redirection_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/redirection_rb.html new file mode 100644 index 0000000000..5957d24826 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/redirection_rb.html @@ -0,0 +1,97 @@ +--- +title: redirection.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
  • rack/utils
  • + +
  • action_controller/metal/exceptions
  • + +
  • action_dispatch/routing/endpoint
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/route_set_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/route_set_rb.html new file mode 100644 index 0000000000..40c07cd0fb --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/route_set_rb.html @@ -0,0 +1,121 @@ +--- +title: route_set.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/journey
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/module/remove_method
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • action_controller/metal/exceptions
  • + +
  • action_dispatch/routing/endpoint
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/routes_proxy_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/routes_proxy_rb.html new file mode 100644 index 0000000000..6ce296fa5e --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/routes_proxy_rb.html @@ -0,0 +1,78 @@ +--- +title: routes_proxy.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing/url_for_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing/url_for_rb.html new file mode 100644 index 0000000000..e62a8ad857 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing/url_for_rb.html @@ -0,0 +1,74 @@ +--- +title: url_for.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/routing_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/routing_rb.html new file mode 100644 index 0000000000..cfb9e85b00 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/routing_rb.html @@ -0,0 +1,78 @@ +--- +title: routing.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_test_case_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_test_case_rb.html new file mode 100644 index 0000000000..0dac6b657d --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_test_case_rb.html @@ -0,0 +1,97 @@ +--- +title: system_test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • capybara/dsl
  • + +
  • capybara/minitest
  • + +
  • action_controller
  • + +
  • action_dispatch/system_testing/driver
  • + +
  • action_dispatch/system_testing/browser
  • + +
  • action_dispatch/system_testing/server
  • + +
  • action_dispatch/system_testing/test_helpers/screenshot_helper
  • + +
  • action_dispatch/system_testing/test_helpers/setup_and_teardown
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_testing/browser_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/browser_rb.html new file mode 100644 index 0000000000..cdb99ad1d6 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/browser_rb.html @@ -0,0 +1,70 @@ +--- +title: browser.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_testing/driver_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/driver_rb.html new file mode 100644 index 0000000000..57fdc45cc3 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/driver_rb.html @@ -0,0 +1,80 @@ +--- +title: driver.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • selenium/webdriver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_testing/server_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/server_rb.html new file mode 100644 index 0000000000..5c47443c3f --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/server_rb.html @@ -0,0 +1,70 @@ +--- +title: server.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper_rb.html new file mode 100644 index 0000000000..f4b31355ca --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/screenshot_helper_rb.html @@ -0,0 +1,74 @@ +--- +title: screenshot_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown_rb.html new file mode 100644 index 0000000000..a4a97a77d7 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown_rb.html @@ -0,0 +1,72 @@ +--- +title: setup_and_teardown.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/assertion_response_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertion_response_rb.html new file mode 100644 index 0000000000..120b22b18b --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertion_response_rb.html @@ -0,0 +1,75 @@ +--- +title: assertion_response.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/response_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/response_rb.html new file mode 100644 index 0000000000..8466e8cc93 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/response_rb.html @@ -0,0 +1,74 @@ +--- +title: response.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/routing_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/routing_rb.html new file mode 100644 index 0000000000..e64853a961 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions/routing_rb.html @@ -0,0 +1,94 @@ +--- +title: routing.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • uri
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • active_support/core_ext/string/access
  • + +
  • action_controller/metal/exceptions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions_rb.html new file mode 100644 index 0000000000..e799bf2f68 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/assertions_rb.html @@ -0,0 +1,82 @@ +--- +title: assertions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails-dom-testing
  • + +
  • action_dispatch/testing/assertions/response
  • + +
  • action_dispatch/testing/assertions/routing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/integration_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/integration_rb.html new file mode 100644 index 0000000000..722c62da36 --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/integration_rb.html @@ -0,0 +1,111 @@ +--- +title: integration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • stringio
  • + +
  • uri
  • + +
  • rack/test
  • + +
  • minitest
  • + +
  • action_dispatch/testing/request_encoder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/request_encoder_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/request_encoder_rb.html new file mode 100644 index 0000000000..1feeefc83e --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/request_encoder_rb.html @@ -0,0 +1,79 @@ +--- +title: request_encoder.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/test_process_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_process_rb.html new file mode 100644 index 0000000000..1e1d8ef88e --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_process_rb.html @@ -0,0 +1,89 @@ +--- +title: test_process.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/middleware/cookies
  • + +
  • action_dispatch/middleware/flash
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/test_request_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_request_rb.html new file mode 100644 index 0000000000..d5c388e3aa --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_request_rb.html @@ -0,0 +1,85 @@ +--- +title: test_request.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • rack/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionpack/lib/action_dispatch/testing/test_response_rb.html b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_response_rb.html new file mode 100644 index 0000000000..bcb7e93bba --- /dev/null +++ b/src/7.0/files/actionpack/lib/action_dispatch/testing/test_response_rb.html @@ -0,0 +1,83 @@ +--- +title: test_response.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/testing/request_encoder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/README_md.html b/src/7.0/files/actiontext/README_md.html new file mode 100644 index 0000000000..664f773326 --- /dev/null +++ b/src/7.0/files/actiontext/README_md.html @@ -0,0 +1,73 @@ +--- +title: README.md +layout: default +--- +
+ + +
+
+ +
+ +

Action Text

+ +

Action Text brings rich text content and editing to Rails. It includes the Trix editor that handles everything from formatting to links to quotes to lists to embedded images and galleries. The rich text content generated by the Trix editor is saved in its own RichText model that’s associated with any existing Active Record model in the application. Any embedded images (or other attachments) are automatically stored using Active Storage and associated with the included RichText model.

+ +

You can read more about Action Text in the Action Text Overview guide.

+ +

Development

+ +

The JavaScript for Action Text is distributed both as a npm module under @rails/actiontext and via the asset pipeline as actiontext.js (and we mirror Trix as trix.js). To ensure that the latter remains in sync, you must run yarn build and checkin the artifacts whenever the JavaScript source or the Trix dependency is bumped. CSS changes must be brought over manually to app/assets/stylesheets/trix.css

+ +

License

+ +

Action Text is released under the MIT License.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/app/helpers/action_text/content_helper_rb.html b/src/7.0/files/actiontext/app/helpers/action_text/content_helper_rb.html new file mode 100644 index 0000000000..668f8191c6 --- /dev/null +++ b/src/7.0/files/actiontext/app/helpers/action_text/content_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: content_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails-html-sanitizer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/app/helpers/action_text/tag_helper_rb.html b/src/7.0/files/actiontext/app/helpers/action_text/tag_helper_rb.html new file mode 100644 index 0000000000..851468faee --- /dev/null +++ b/src/7.0/files/actiontext/app/helpers/action_text/tag_helper_rb.html @@ -0,0 +1,97 @@ +--- +title: tag_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
  • action_view/helpers/tags/placeholderable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/app/models/action_text/encrypted_rich_text_rb.html b/src/7.0/files/actiontext/app/models/action_text/encrypted_rich_text_rb.html new file mode 100644 index 0000000000..81cf1dfddb --- /dev/null +++ b/src/7.0/files/actiontext/app/models/action_text/encrypted_rich_text_rb.html @@ -0,0 +1,75 @@ +--- +title: encrypted_rich_text.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/app/models/action_text/record_rb.html b/src/7.0/files/actiontext/app/models/action_text/record_rb.html new file mode 100644 index 0000000000..10610d6a7b --- /dev/null +++ b/src/7.0/files/actiontext/app/models/action_text/record_rb.html @@ -0,0 +1,68 @@ +--- +title: record.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/app/models/action_text/rich_text_rb.html b/src/7.0/files/actiontext/app/models/action_text/rich_text_rb.html new file mode 100644 index 0000000000..dc953cb4cf --- /dev/null +++ b/src/7.0/files/actiontext/app/models/action_text/rich_text_rb.html @@ -0,0 +1,77 @@ +--- +title: rich_text.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachable_rb.html b/src/7.0/files/actiontext/lib/action_text/attachable_rb.html new file mode 100644 index 0000000000..7b241e533f --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachable_rb.html @@ -0,0 +1,72 @@ +--- +title: attachable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachables/content_attachment_rb.html b/src/7.0/files/actiontext/lib/action_text/attachables/content_attachment_rb.html new file mode 100644 index 0000000000..38e41301bc --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachables/content_attachment_rb.html @@ -0,0 +1,77 @@ +--- +title: content_attachment.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachables/missing_attachable_rb.html b/src/7.0/files/actiontext/lib/action_text/attachables/missing_attachable_rb.html new file mode 100644 index 0000000000..3525958709 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachables/missing_attachable_rb.html @@ -0,0 +1,72 @@ +--- +title: missing_attachable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachables/remote_image_rb.html b/src/7.0/files/actiontext/lib/action_text/attachables/remote_image_rb.html new file mode 100644 index 0000000000..b6968e2056 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachables/remote_image_rb.html @@ -0,0 +1,77 @@ +--- +title: remote_image.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachment_gallery_rb.html b/src/7.0/files/actiontext/lib/action_text/attachment_gallery_rb.html new file mode 100644 index 0000000000..96895ccd2e --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachment_gallery_rb.html @@ -0,0 +1,75 @@ +--- +title: attachment_gallery.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachment_rb.html b/src/7.0/files/actiontext/lib/action_text/attachment_rb.html new file mode 100644 index 0000000000..5dec1a1710 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachment_rb.html @@ -0,0 +1,83 @@ +--- +title: attachment.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachments/caching_rb.html b/src/7.0/files/actiontext/lib/action_text/attachments/caching_rb.html new file mode 100644 index 0000000000..cf90c3a5ec --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachments/caching_rb.html @@ -0,0 +1,74 @@ +--- +title: caching.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachments/minification_rb.html b/src/7.0/files/actiontext/lib/action_text/attachments/minification_rb.html new file mode 100644 index 0000000000..00a714eff3 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachments/minification_rb.html @@ -0,0 +1,72 @@ +--- +title: minification.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attachments/trix_conversion_rb.html b/src/7.0/files/actiontext/lib/action_text/attachments/trix_conversion_rb.html new file mode 100644 index 0000000000..9c0ad66c3f --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attachments/trix_conversion_rb.html @@ -0,0 +1,80 @@ +--- +title: trix_conversion.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/attribute_rb.html b/src/7.0/files/actiontext/lib/action_text/attribute_rb.html new file mode 100644 index 0000000000..c18ff55908 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/attribute_rb.html @@ -0,0 +1,70 @@ +--- +title: attribute.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/content_rb.html b/src/7.0/files/actiontext/lib/action_text/content_rb.html new file mode 100644 index 0000000000..2a7851dff6 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/content_rb.html @@ -0,0 +1,75 @@ +--- +title: content.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/encryption_rb.html b/src/7.0/files/actiontext/lib/action_text/encryption_rb.html new file mode 100644 index 0000000000..029965a01f --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/encryption_rb.html @@ -0,0 +1,70 @@ +--- +title: encryption.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/engine_rb.html b/src/7.0/files/actiontext/lib/action_text/engine_rb.html new file mode 100644 index 0000000000..1981c3301e --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/engine_rb.html @@ -0,0 +1,97 @@ +--- +title: engine.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails
  • + +
  • action_controller/railtie
  • + +
  • active_record/railtie
  • + +
  • active_storage/engine
  • + +
  • action_text
  • + +
  • action_text/system_test_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/fixture_set_rb.html b/src/7.0/files/actiontext/lib/action_text/fixture_set_rb.html new file mode 100644 index 0000000000..7f74a49958 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/fixture_set_rb.html @@ -0,0 +1,79 @@ +--- +title: fixture_set.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/fragment_rb.html b/src/7.0/files/actiontext/lib/action_text/fragment_rb.html new file mode 100644 index 0000000000..f2c941b350 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/fragment_rb.html @@ -0,0 +1,75 @@ +--- +title: fragment.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/gem_version_rb.html b/src/7.0/files/actiontext/lib/action_text/gem_version_rb.html new file mode 100644 index 0000000000..0fd224f668 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/html_conversion_rb.html b/src/7.0/files/actiontext/lib/action_text/html_conversion_rb.html new file mode 100644 index 0000000000..e818eef88c --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/html_conversion_rb.html @@ -0,0 +1,70 @@ +--- +title: html_conversion.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/plain_text_conversion_rb.html b/src/7.0/files/actiontext/lib/action_text/plain_text_conversion_rb.html new file mode 100644 index 0000000000..678c581874 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/plain_text_conversion_rb.html @@ -0,0 +1,70 @@ +--- +title: plain_text_conversion.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/rendering_rb.html b/src/7.0/files/actiontext/lib/action_text/rendering_rb.html new file mode 100644 index 0000000000..f7973ac1d4 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/rendering_rb.html @@ -0,0 +1,78 @@ +--- +title: rendering.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/core_ext/module/attribute_accessors_per_thread
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/serialization_rb.html b/src/7.0/files/actiontext/lib/action_text/serialization_rb.html new file mode 100644 index 0000000000..3d7bf7e835 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/serialization_rb.html @@ -0,0 +1,70 @@ +--- +title: serialization.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/system_test_helper_rb.html b/src/7.0/files/actiontext/lib/action_text/system_test_helper_rb.html new file mode 100644 index 0000000000..e03c0fc882 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/system_test_helper_rb.html @@ -0,0 +1,70 @@ +--- +title: system_test_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/trix_attachment_rb.html b/src/7.0/files/actiontext/lib/action_text/trix_attachment_rb.html new file mode 100644 index 0000000000..5af9bd03eb --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/trix_attachment_rb.html @@ -0,0 +1,75 @@ +--- +title: trix_attachment.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actiontext/lib/action_text/version_rb.html b/src/7.0/files/actiontext/lib/action_text/version_rb.html new file mode 100644 index 0000000000..9652645389 --- /dev/null +++ b/src/7.0/files/actiontext/lib/action_text/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/README_rdoc.html b/src/7.0/files/actionview/README_rdoc.html new file mode 100644 index 0000000000..6b27d754f4 --- /dev/null +++ b/src/7.0/files/actionview/README_rdoc.html @@ -0,0 +1,101 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Action View

+ +

Action View is a framework for handling view template lookup and rendering, and provides view helpers that assist when building HTML forms, Atom feeds and more. Template formats that Action View handles are ERB (embedded Ruby, typically used to inline short Ruby snippets inside HTML), and XML Builder.

+ +

You can read more about Action View in the Action View Overview guide.

+ +

Download and installation

+ +

The latest version of Action View can be installed with RubyGems:

+ +
$ gem install actionview
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Action View is released under the MIT license:

+ + +

Support

+ +

API documentation is at

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/base_rb.html b/src/7.0/files/actionview/lib/action_view/base_rb.html new file mode 100644 index 0000000000..76e0af0da2 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/base_rb.html @@ -0,0 +1,99 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attr_internal
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/ordered_options
  • + +
  • action_view/log_subscriber
  • + +
  • action_view/helpers
  • + +
  • action_view/context
  • + +
  • action_view/template
  • + +
  • action_view/lookup_context
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/buffers_rb.html b/src/7.0/files/actionview/lib/action_view/buffers_rb.html new file mode 100644 index 0000000000..886d827c47 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/buffers_rb.html @@ -0,0 +1,76 @@ +--- +title: buffers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/output_safety
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/cache_expiry_rb.html b/src/7.0/files/actionview/lib/action_view/cache_expiry_rb.html new file mode 100644 index 0000000000..a3d75318b0 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/cache_expiry_rb.html @@ -0,0 +1,81 @@ +--- +title: cache_expiry.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/context_rb.html b/src/7.0/files/actionview/lib/action_view/context_rb.html new file mode 100644 index 0000000000..825cf54406 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/context_rb.html @@ -0,0 +1,70 @@ +--- +title: context.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/dependency_tracker/erb_tracker_rb.html b/src/7.0/files/actionview/lib/action_view/dependency_tracker/erb_tracker_rb.html new file mode 100644 index 0000000000..7934fb1d70 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/dependency_tracker/erb_tracker_rb.html @@ -0,0 +1,68 @@ +--- +title: erb_tracker.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/dependency_tracker/ripper_tracker_rb.html b/src/7.0/files/actionview/lib/action_view/dependency_tracker/ripper_tracker_rb.html new file mode 100644 index 0000000000..0a5b6a47d8 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/dependency_tracker/ripper_tracker_rb.html @@ -0,0 +1,68 @@ +--- +title: ripper_tracker.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/dependency_tracker_rb.html b/src/7.0/files/actionview/lib/action_view/dependency_tracker_rb.html new file mode 100644 index 0000000000..52071bb565 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/dependency_tracker_rb.html @@ -0,0 +1,80 @@ +--- +title: dependency_tracker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
  • action_view/path_set
  • + +
  • action_view/render_parser
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/digestor_rb.html b/src/7.0/files/actionview/lib/action_view/digestor_rb.html new file mode 100644 index 0000000000..fc662992cd --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/digestor_rb.html @@ -0,0 +1,95 @@ +--- +title: digestor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/dependency_tracker
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/flows_rb.html b/src/7.0/files/actionview/lib/action_view/flows_rb.html new file mode 100644 index 0000000000..f200a0372d --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/flows_rb.html @@ -0,0 +1,78 @@ +--- +title: flows.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/output_safety
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/gem_version_rb.html b/src/7.0/files/actionview/lib/action_view/gem_version_rb.html new file mode 100644 index 0000000000..982cbaab98 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/active_model_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/active_model_helper_rb.html new file mode 100644 index 0000000000..94f3491add --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/active_model_helper_rb.html @@ -0,0 +1,84 @@ +--- +title: active_model_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/asset_tag_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/asset_tag_helper_rb.html new file mode 100644 index 0000000000..a6482315af --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/asset_tag_helper_rb.html @@ -0,0 +1,88 @@ +--- +title: asset_tag_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/object/inclusion
  • + +
  • action_view/helpers/asset_url_helper
  • + +
  • action_view/helpers/tag_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/asset_url_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/asset_url_helper_rb.html new file mode 100644 index 0000000000..86eb29ad5c --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/asset_url_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: asset_url_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • zlib
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/atom_feed_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/atom_feed_helper_rb.html new file mode 100644 index 0000000000..8218df466b --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/atom_feed_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: atom_feed_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/cache_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/cache_helper_rb.html new file mode 100644 index 0000000000..99965a0118 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/cache_helper_rb.html @@ -0,0 +1,81 @@ +--- +title: cache_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/capture_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/capture_helper_rb.html new file mode 100644 index 0000000000..8dd0a926c3 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/capture_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: capture_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/output_safety
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/controller_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/controller_helper_rb.html new file mode 100644 index 0000000000..4d518f162c --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/controller_helper_rb.html @@ -0,0 +1,78 @@ +--- +title: controller_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attr_internal
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/csp_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/csp_helper_rb.html new file mode 100644 index 0000000000..8e6dab8bc7 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/csp_helper_rb.html @@ -0,0 +1,72 @@ +--- +title: csp_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/csrf_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/csrf_helper_rb.html new file mode 100644 index 0000000000..5894b1bff3 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/csrf_helper_rb.html @@ -0,0 +1,72 @@ +--- +title: csrf_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/date_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/date_helper_rb.html new file mode 100644 index 0000000000..3ea53bbf7f --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/date_helper_rb.html @@ -0,0 +1,101 @@ +--- +title: date_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • action_view/helpers/tag_helper
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/date/conversions
  • + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/object/acts_like
  • + +
  • active_support/core_ext/object/with_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/debug_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/debug_helper_rb.html new file mode 100644 index 0000000000..74c4c78593 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/debug_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: debug_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/helpers/tag_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/form_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/form_helper_rb.html new file mode 100644 index 0000000000..6df0453f3c --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/form_helper_rb.html @@ -0,0 +1,111 @@ +--- +title: form_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • cgi
  • + +
  • action_view/helpers/date_helper
  • + +
  • action_view/helpers/url_helper
  • + +
  • action_view/helpers/form_tag_helper
  • + +
  • action_view/helpers/active_model_helper
  • + +
  • action_view/model_naming
  • + +
  • action_view/record_identifier
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/form_options_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/form_options_helper_rb.html new file mode 100644 index 0000000000..8015fe7c3a --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/form_options_helper_rb.html @@ -0,0 +1,99 @@ +--- +title: form_options_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • cgi
  • + +
  • erb
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/array/wrap
  • + +
  • action_view/helpers/text_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/form_tag_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/form_tag_helper_rb.html new file mode 100644 index 0000000000..2bab62a7ee --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/form_tag_helper_rb.html @@ -0,0 +1,88 @@ +--- +title: form_tag_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • cgi
  • + +
  • action_view/helpers/url_helper
  • + +
  • action_view/helpers/text_helper
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/javascript_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/javascript_helper_rb.html new file mode 100644 index 0000000000..2eef29ea20 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/javascript_helper_rb.html @@ -0,0 +1,72 @@ +--- +title: javascript_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/number_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/number_helper_rb.html new file mode 100644 index 0000000000..6459576127 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/number_helper_rb.html @@ -0,0 +1,93 @@ +--- +title: number_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • active_support/number_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/output_safety_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/output_safety_helper_rb.html new file mode 100644 index 0000000000..ca8fcf6b49 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/output_safety_helper_rb.html @@ -0,0 +1,80 @@ +--- +title: output_safety_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/output_safety
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/rendering_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/rendering_helper_rb.html new file mode 100644 index 0000000000..15ae94f29e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/rendering_helper_rb.html @@ -0,0 +1,72 @@ +--- +title: rendering_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/sanitize_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/sanitize_helper_rb.html new file mode 100644 index 0000000000..eaaabe0b0f --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/sanitize_helper_rb.html @@ -0,0 +1,82 @@ +--- +title: sanitize_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails-html-sanitizer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/tag_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/tag_helper_rb.html new file mode 100644 index 0000000000..211fef8f42 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/tag_helper_rb.html @@ -0,0 +1,90 @@ +--- +title: tag_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • set
  • + +
  • action_view/helpers/capture_helper
  • + +
  • action_view/helpers/output_safety_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/tags_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/tags_rb.html new file mode 100644 index 0000000000..3d43b526c6 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/tags_rb.html @@ -0,0 +1,72 @@ +--- +title: tags.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/text_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/text_helper_rb.html new file mode 100644 index 0000000000..2ee8d56a70 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/text_helper_rb.html @@ -0,0 +1,90 @@ +--- +title: text_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/core_ext/string/access
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • action_view/helpers/sanitize_helper
  • + +
  • action_view/helpers/tag_helper
  • + +
  • action_view/helpers/output_safety_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/translation_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/translation_helper_rb.html new file mode 100644 index 0000000000..b38a9e4fd3 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/translation_helper_rb.html @@ -0,0 +1,84 @@ +--- +title: translation_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/helpers/tag_helper
  • + +
  • active_support/html_safe_translation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers/url_helper_rb.html b/src/7.0/files/actionview/lib/action_view/helpers/url_helper_rb.html new file mode 100644 index 0000000000..5161e9f02e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers/url_helper_rb.html @@ -0,0 +1,90 @@ +--- +title: url_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/access
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • action_view/helpers/tag_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/helpers_rb.html b/src/7.0/files/actionview/lib/action_view/helpers_rb.html new file mode 100644 index 0000000000..ea456e3fc0 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/helpers_rb.html @@ -0,0 +1,124 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/benchmarkable
  • + +
  • action_view/helpers/capture_helper
  • + +
  • action_view/helpers/output_safety_helper
  • + +
  • action_view/helpers/tag_helper
  • + +
  • action_view/helpers/url_helper
  • + +
  • action_view/helpers/sanitize_helper
  • + +
  • action_view/helpers/text_helper
  • + +
  • action_view/helpers/active_model_helper
  • + +
  • action_view/helpers/asset_tag_helper
  • + +
  • action_view/helpers/asset_url_helper
  • + +
  • action_view/helpers/atom_feed_helper
  • + +
  • action_view/helpers/cache_helper
  • + +
  • action_view/helpers/controller_helper
  • + +
  • action_view/helpers/csp_helper
  • + +
  • action_view/helpers/csrf_helper
  • + +
  • action_view/helpers/date_helper
  • + +
  • action_view/helpers/debug_helper
  • + +
  • action_view/helpers/form_tag_helper
  • + +
  • action_view/helpers/form_helper
  • + +
  • action_view/helpers/form_options_helper
  • + +
  • action_view/helpers/javascript_helper
  • + +
  • action_view/helpers/number_helper
  • + +
  • action_view/helpers/rendering_helper
  • + +
  • action_view/helpers/translation_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/layouts_rb.html b/src/7.0/files/actionview/lib/action_view/layouts_rb.html new file mode 100644 index 0000000000..4e614dc794 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/layouts_rb.html @@ -0,0 +1,82 @@ +--- +title: layouts.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/rendering
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/log_subscriber_rb.html b/src/7.0/files/actionview/lib/action_view/log_subscriber_rb.html new file mode 100644 index 0000000000..01c031aa1a --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/log_subscriber_rb.html @@ -0,0 +1,83 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/lookup_context_rb.html b/src/7.0/files/actionview/lib/action_view/lookup_context_rb.html new file mode 100644 index 0000000000..c9e21ffcdd --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/lookup_context_rb.html @@ -0,0 +1,91 @@ +--- +title: lookup_context.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • action_view/template/resolver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/model_naming_rb.html b/src/7.0/files/actionview/lib/action_view/model_naming_rb.html new file mode 100644 index 0000000000..0b76447484 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/model_naming_rb.html @@ -0,0 +1,68 @@ +--- +title: model_naming.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/path_set_rb.html b/src/7.0/files/actionview/lib/action_view/path_set_rb.html new file mode 100644 index 0000000000..27b4768de9 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/path_set_rb.html @@ -0,0 +1,68 @@ +--- +title: path_set.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/railtie_rb.html b/src/7.0/files/actionview/lib/action_view/railtie_rb.html new file mode 100644 index 0000000000..81245b138b --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/railtie_rb.html @@ -0,0 +1,89 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view
  • + +
  • rails
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/record_identifier_rb.html b/src/7.0/files/actionview/lib/action_view/record_identifier_rb.html new file mode 100644 index 0000000000..3503aa182c --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/record_identifier_rb.html @@ -0,0 +1,80 @@ +--- +title: record_identifier.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module
  • + +
  • action_view/model_naming
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/render_parser_rb.html b/src/7.0/files/actionview/lib/action_view/render_parser_rb.html new file mode 100644 index 0000000000..6843cda987 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/render_parser_rb.html @@ -0,0 +1,76 @@ +--- +title: render_parser.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/ripper_ast_parser
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/abstract_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/abstract_renderer_rb.html new file mode 100644 index 0000000000..691d8515a1 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/abstract_renderer_rb.html @@ -0,0 +1,87 @@ +--- +title: abstract_renderer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/collection_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/collection_renderer_rb.html new file mode 100644 index 0000000000..fb8cdfc354 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/collection_renderer_rb.html @@ -0,0 +1,85 @@ +--- +title: collection_renderer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/renderer/partial_renderer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/object_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/object_renderer_rb.html new file mode 100644 index 0000000000..c3d6e9dcbc --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/object_renderer_rb.html @@ -0,0 +1,68 @@ +--- +title: object_renderer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer/collection_caching_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer/collection_caching_rb.html new file mode 100644 index 0000000000..d1cb08ef71 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer/collection_caching_rb.html @@ -0,0 +1,78 @@ +--- +title: collection_caching.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer_rb.html new file mode 100644 index 0000000000..76dc674032 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/partial_renderer_rb.html @@ -0,0 +1,85 @@ +--- +title: partial_renderer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/renderer/partial_renderer/collection_caching
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/renderer_rb.html new file mode 100644 index 0000000000..68949d0c7d --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/renderer_rb.html @@ -0,0 +1,75 @@ +--- +title: renderer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/streaming_template_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/streaming_template_renderer_rb.html new file mode 100644 index 0000000000..0fe7610c31 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/streaming_template_renderer_rb.html @@ -0,0 +1,78 @@ +--- +title: streaming_template_renderer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fiber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/renderer/template_renderer_rb.html b/src/7.0/files/actionview/lib/action_view/renderer/template_renderer_rb.html new file mode 100644 index 0000000000..320e55c4a1 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/renderer/template_renderer_rb.html @@ -0,0 +1,70 @@ +--- +title: template_renderer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/rendering_rb.html b/src/7.0/files/actionview/lib/action_view/rendering_rb.html new file mode 100644 index 0000000000..6fc30d05e0 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/rendering_rb.html @@ -0,0 +1,87 @@ +--- +title: rendering.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/view_paths
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/ripper_ast_parser_rb.html b/src/7.0/files/actionview/lib/action_view/ripper_ast_parser_rb.html new file mode 100644 index 0000000000..82b0af195b --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/ripper_ast_parser_rb.html @@ -0,0 +1,76 @@ +--- +title: ripper_ast_parser.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • ripper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/routing_url_for_rb.html b/src/7.0/files/actionview/lib/action_view/routing_url_for_rb.html new file mode 100644 index 0000000000..fabdde3f0f --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/routing_url_for_rb.html @@ -0,0 +1,86 @@ +--- +title: routing_url_for.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/routing/polymorphic_routes
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/error_rb.html b/src/7.0/files/actionview/lib/action_view/template/error_rb.html new file mode 100644 index 0000000000..3e2641870d --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/error_rb.html @@ -0,0 +1,83 @@ +--- +title: error.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers/builder_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers/builder_rb.html new file mode 100644 index 0000000000..3fc0d6ca35 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers/builder_rb.html @@ -0,0 +1,87 @@ +--- +title: builder.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • builder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers/erb/erubi_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers/erb/erubi_rb.html new file mode 100644 index 0000000000..f30c280e0d --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers/erb/erubi_rb.html @@ -0,0 +1,87 @@ +--- +title: erubi.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • erubi
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers/erb_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers/erb_rb.html new file mode 100644 index 0000000000..454e70a2cd --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers/erb_rb.html @@ -0,0 +1,79 @@ +--- +title: erb.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers/html_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers/html_rb.html new file mode 100644 index 0000000000..a1e813d599 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers/html_rb.html @@ -0,0 +1,79 @@ +--- +title: html.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers/raw_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers/raw_rb.html new file mode 100644 index 0000000000..89de944fb7 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers/raw_rb.html @@ -0,0 +1,79 @@ +--- +title: raw.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/handlers_rb.html b/src/7.0/files/actionview/lib/action_view/template/handlers_rb.html new file mode 100644 index 0000000000..86c958729e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/handlers_rb.html @@ -0,0 +1,77 @@ +--- +title: handlers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/html_rb.html b/src/7.0/files/actionview/lib/action_view/template/html_rb.html new file mode 100644 index 0000000000..ad8dc2cbdc --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/html_rb.html @@ -0,0 +1,75 @@ +--- +title: html.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/inline_rb.html b/src/7.0/files/actionview/lib/action_view/template/inline_rb.html new file mode 100644 index 0000000000..5383ff354e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/inline_rb.html @@ -0,0 +1,75 @@ +--- +title: inline.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/raw_file_rb.html b/src/7.0/files/actionview/lib/action_view/template/raw_file_rb.html new file mode 100644 index 0000000000..943bf8575e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/raw_file_rb.html @@ -0,0 +1,75 @@ +--- +title: raw_file.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/renderable_rb.html b/src/7.0/files/actionview/lib/action_view/template/renderable_rb.html new file mode 100644 index 0000000000..d7d65652b4 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/renderable_rb.html @@ -0,0 +1,75 @@ +--- +title: renderable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/resolver_rb.html b/src/7.0/files/actionview/lib/action_view/template/resolver_rb.html new file mode 100644 index 0000000000..8597c6f0a4 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/resolver_rb.html @@ -0,0 +1,97 @@ +--- +title: resolver.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • active_support/core_ext/class
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • action_view/template
  • + +
  • thread
  • + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/sources/file_rb.html b/src/7.0/files/actionview/lib/action_view/template/sources/file_rb.html new file mode 100644 index 0000000000..e61e4f95cd --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/sources/file_rb.html @@ -0,0 +1,79 @@ +--- +title: file.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/sources_rb.html b/src/7.0/files/actionview/lib/action_view/template/sources_rb.html new file mode 100644 index 0000000000..1bc56e7c79 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/sources_rb.html @@ -0,0 +1,77 @@ +--- +title: sources.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/text_rb.html b/src/7.0/files/actionview/lib/action_view/template/text_rb.html new file mode 100644 index 0000000000..943fad011c --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/text_rb.html @@ -0,0 +1,75 @@ +--- +title: text.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template/types_rb.html b/src/7.0/files/actionview/lib/action_view/template/types_rb.html new file mode 100644 index 0000000000..ff2861c065 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template/types_rb.html @@ -0,0 +1,87 @@ +--- +title: types.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template_details_rb.html b/src/7.0/files/actionview/lib/action_view/template_details_rb.html new file mode 100644 index 0000000000..9fc63c3f5e --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template_details_rb.html @@ -0,0 +1,77 @@ +--- +title: template_details.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template_path_rb.html b/src/7.0/files/actionview/lib/action_view/template_path_rb.html new file mode 100644 index 0000000000..014417c8e1 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template_path_rb.html @@ -0,0 +1,75 @@ +--- +title: template_path.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/template_rb.html b/src/7.0/files/actionview/lib/action_view/template_rb.html new file mode 100644 index 0000000000..2d8c362a6b --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/template_rb.html @@ -0,0 +1,87 @@ +--- +title: template.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • delegate
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/test_case_rb.html b/src/7.0/files/actionview/lib/action_view/test_case_rb.html new file mode 100644 index 0000000000..d92e1c0fa6 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/test_case_rb.html @@ -0,0 +1,107 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/redefine_method
  • + +
  • action_controller
  • + +
  • action_controller/test_case
  • + +
  • action_view
  • + +
  • rails-dom-testing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/testing/resolvers_rb.html b/src/7.0/files/actionview/lib/action_view/testing/resolvers_rb.html new file mode 100644 index 0000000000..5591768862 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/testing/resolvers_rb.html @@ -0,0 +1,89 @@ +--- +title: resolvers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_view/template/resolver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/unbound_template_rb.html b/src/7.0/files/actionview/lib/action_view/unbound_template_rb.html new file mode 100644 index 0000000000..e9d603fc22 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/unbound_template_rb.html @@ -0,0 +1,83 @@ +--- +title: unbound_template.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/version_rb.html b/src/7.0/files/actionview/lib/action_view/version_rb.html new file mode 100644 index 0000000000..a1ffb655e0 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/actionview/lib/action_view/view_paths_rb.html b/src/7.0/files/actionview/lib/action_view/view_paths_rb.html new file mode 100644 index 0000000000..4134b13f97 --- /dev/null +++ b/src/7.0/files/actionview/lib/action_view/view_paths_rb.html @@ -0,0 +1,72 @@ +--- +title: view_paths.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/README_md.html b/src/7.0/files/activejob/README_md.html new file mode 100644 index 0000000000..d86f9371c3 --- /dev/null +++ b/src/7.0/files/activejob/README_md.html @@ -0,0 +1,162 @@ +--- +title: README.md +layout: default +--- +
+ + +
+
+ +
+ +

Active Job – Make work happen later

+ +

Active Job is a framework for declaring jobs and making them run on a variety of queuing backends. These jobs can be everything from regularly scheduled clean-ups, to billing charges, to mailings — anything that can be chopped up into small units of work and run in parallel.

+ +

It also serves as the backend for Action Mailer’s deliver_later functionality that makes it easy to turn any mailing into a job for running later. That’s one of the most common jobs in a modern web application: sending emails outside the request-response cycle, so the user doesn’t have to wait on it.

+ +

The main point is to ensure that all Rails apps will have a job infrastructure in place, even if it’s in the form of an “immediate runner”. We can then have framework features and other gems build on top of that, without having to worry about API differences between Delayed Job and Resque. Picking your queuing backend becomes more of an operational concern, then. And you’ll be able to switch between them without having to rewrite your jobs.

+ +

You can read more about Active Job in the Active Job Basics guide.

+ +

Usage

+ +

To learn how to use your preferred queuing backend see its adapter documentation at ActiveJob::QueueAdapters.

+ +

Declare a job like so:

+ +
class MyJob < ActiveJob::Base
+  queue_as :my_jobs
+
+  def perform(record)
+    record.do_work
+  end
+end
+
+ +

Enqueue a job like so:

+ +
MyJob.perform_later record  # Enqueue a job to be performed as soon as the queuing system is free.
+
+ +
MyJob.set(wait_until: Date.tomorrow.noon).perform_later(record)  # Enqueue a job to be performed tomorrow at noon.
+
+ +
MyJob.set(wait: 1.week).perform_later(record) # Enqueue a job to be performed 1 week from now.
+
+ +

That’s it!

+ +

GlobalID support

+ +

Active Job supports GlobalID serialization for parameters. This makes it possible to pass live Active Record objects to your job instead of class/id pairs, which you then have to manually deserialize. Before, jobs would look like this:

+ +
class TrashableCleanupJob
+  def perform(trashable_class, trashable_id, depth)
+    trashable = trashable_class.constantize.find(trashable_id)
+    trashable.cleanup(depth)
+  end
+end
+
+ +

Now you can simply do:

+ +
class TrashableCleanupJob
+  def perform(trashable, depth)
+    trashable.cleanup(depth)
+  end
+end
+
+ +

This works with any class that mixes in GlobalID::Identification, which by default has been mixed into Active Record classes.

+ +

Supported queuing systems

+ +

Active Job has built-in adapters for multiple queuing backends (Sidekiq, Resque, Delayed Job and others). To get an up-to-date list of the adapters see the API Documentation for ActiveJob::QueueAdapters.

+ +

Please note: We are not accepting pull requests for new adapters. We encourage library authors to provide an ActiveJob adapter as part of their gem, or as a stand-alone gem. For discussion about this see the following PRs: 23311, 21406, and #32285.

+ +

Download and installation

+ +

The latest version of Active Job can be installed with RubyGems:

+ +
$ gem install activejob
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Active Job is released under the MIT license:

+ + +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/arguments_rb.html b/src/7.0/files/activejob/lib/active_job/arguments_rb.html new file mode 100644 index 0000000000..6c07e4514f --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/arguments_rb.html @@ -0,0 +1,93 @@ +--- +title: arguments.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • bigdecimal
  • + +
  • active_support/core_ext/hash
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/base_rb.html b/src/7.0/files/activejob/lib/active_job/base_rb.html new file mode 100644 index 0000000000..a5e39028ce --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/base_rb.html @@ -0,0 +1,107 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_job/core
  • + +
  • active_job/queue_adapter
  • + +
  • active_job/queue_name
  • + +
  • active_job/queue_priority
  • + +
  • active_job/enqueuing
  • + +
  • active_job/execution
  • + +
  • active_job/callbacks
  • + +
  • active_job/exceptions
  • + +
  • active_job/log_subscriber
  • + +
  • active_job/logging
  • + +
  • active_job/instrumentation
  • + +
  • active_job/timezones
  • + +
  • active_job/translation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/callbacks_rb.html b/src/7.0/files/activejob/lib/active_job/callbacks_rb.html new file mode 100644 index 0000000000..6fe58f4c67 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/callbacks_rb.html @@ -0,0 +1,82 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/configured_job_rb.html b/src/7.0/files/activejob/lib/active_job/configured_job_rb.html new file mode 100644 index 0000000000..1383f707ce --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/configured_job_rb.html @@ -0,0 +1,68 @@ +--- +title: configured_job.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/core_rb.html b/src/7.0/files/activejob/lib/active_job/core_rb.html new file mode 100644 index 0000000000..511fcdcde2 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/core_rb.html @@ -0,0 +1,72 @@ +--- +title: core.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/enqueuing_rb.html b/src/7.0/files/activejob/lib/active_job/enqueuing_rb.html new file mode 100644 index 0000000000..ea5abb628e --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/enqueuing_rb.html @@ -0,0 +1,87 @@ +--- +title: enqueuing.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_job/arguments
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/exceptions_rb.html b/src/7.0/files/activejob/lib/active_job/exceptions_rb.html new file mode 100644 index 0000000000..5eaea83620 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/exceptions_rb.html @@ -0,0 +1,82 @@ +--- +title: exceptions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/numeric/time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/execution_rb.html b/src/7.0/files/activejob/lib/active_job/execution_rb.html new file mode 100644 index 0000000000..026baffdd5 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/execution_rb.html @@ -0,0 +1,84 @@ +--- +title: execution.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/rescuable
  • + +
  • active_job/arguments
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/gem_version_rb.html b/src/7.0/files/activejob/lib/active_job/gem_version_rb.html new file mode 100644 index 0000000000..da750e4426 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/instrumentation_rb.html b/src/7.0/files/activejob/lib/active_job/instrumentation_rb.html new file mode 100644 index 0000000000..3697144670 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/instrumentation_rb.html @@ -0,0 +1,70 @@ +--- +title: instrumentation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/log_subscriber_rb.html b/src/7.0/files/activejob/lib/active_job/log_subscriber_rb.html new file mode 100644 index 0000000000..7336542d77 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/log_subscriber_rb.html @@ -0,0 +1,78 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/logging_rb.html b/src/7.0/files/activejob/lib/active_job/logging_rb.html new file mode 100644 index 0000000000..19b45b22c0 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/logging_rb.html @@ -0,0 +1,80 @@ +--- +title: logging.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/tagged_logging
  • + +
  • active_support/logger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapter_rb.html new file mode 100644 index 0000000000..f27cecf81e --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapter_rb.html @@ -0,0 +1,80 @@ +--- +title: queue_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/async_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/async_adapter_rb.html new file mode 100644 index 0000000000..3894474ffd --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/async_adapter_rb.html @@ -0,0 +1,91 @@ +--- +title: async_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
  • concurrent/scheduled_task
  • + +
  • concurrent/executor/thread_pool_executor
  • + +
  • concurrent/utility/processor_counter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/backburner_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/backburner_adapter_rb.html new file mode 100644 index 0000000000..03c4ce2682 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/backburner_adapter_rb.html @@ -0,0 +1,85 @@ +--- +title: backburner_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • backburner
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/delayed_job_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/delayed_job_adapter_rb.html new file mode 100644 index 0000000000..8a5e97cd10 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/delayed_job_adapter_rb.html @@ -0,0 +1,87 @@ +--- +title: delayed_job_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • delayed_job
  • + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/inline_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/inline_adapter_rb.html new file mode 100644 index 0000000000..d750044a91 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/inline_adapter_rb.html @@ -0,0 +1,77 @@ +--- +title: inline_adapter.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/que_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/que_adapter_rb.html new file mode 100644 index 0000000000..cf29edafaf --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/que_adapter_rb.html @@ -0,0 +1,85 @@ +--- +title: que_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • que
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/queue_classic_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/queue_classic_adapter_rb.html new file mode 100644 index 0000000000..b486e57c5f --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/queue_classic_adapter_rb.html @@ -0,0 +1,85 @@ +--- +title: queue_classic_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • queue_classic
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/resque_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/resque_adapter_rb.html new file mode 100644 index 0000000000..9ed6a89212 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/resque_adapter_rb.html @@ -0,0 +1,93 @@ +--- +title: resque_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • resque
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/array/access
  • + +
  • resque-scheduler
  • + +
  • resque_scheduler
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/sidekiq_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/sidekiq_adapter_rb.html new file mode 100644 index 0000000000..5ed5cebe05 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/sidekiq_adapter_rb.html @@ -0,0 +1,85 @@ +--- +title: sidekiq_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • sidekiq
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/sneakers_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/sneakers_adapter_rb.html new file mode 100644 index 0000000000..2a7a001c2c --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/sneakers_adapter_rb.html @@ -0,0 +1,89 @@ +--- +title: sneakers_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • sneakers
  • + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/sucker_punch_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/sucker_punch_adapter_rb.html new file mode 100644 index 0000000000..94cb9737f0 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/sucker_punch_adapter_rb.html @@ -0,0 +1,85 @@ +--- +title: sucker_punch_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • sucker_punch
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters/test_adapter_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters/test_adapter_rb.html new file mode 100644 index 0000000000..9b18b56df3 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters/test_adapter_rb.html @@ -0,0 +1,77 @@ +--- +title: test_adapter.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_adapters_rb.html b/src/7.0/files/activejob/lib/active_job/queue_adapters_rb.html new file mode 100644 index 0000000000..95c4c01258 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_adapters_rb.html @@ -0,0 +1,70 @@ +--- +title: queue_adapters.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_name_rb.html b/src/7.0/files/activejob/lib/active_job/queue_name_rb.html new file mode 100644 index 0000000000..d7d9f89d05 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_name_rb.html @@ -0,0 +1,72 @@ +--- +title: queue_name.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/queue_priority_rb.html b/src/7.0/files/activejob/lib/active_job/queue_priority_rb.html new file mode 100644 index 0000000000..f56832e051 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/queue_priority_rb.html @@ -0,0 +1,72 @@ +--- +title: queue_priority.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/railtie_rb.html b/src/7.0/files/activejob/lib/active_job/railtie_rb.html new file mode 100644 index 0000000000..de69a33f45 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/railtie_rb.html @@ -0,0 +1,82 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • global_id/railtie
  • + +
  • active_job
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/date_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/date_serializer_rb.html new file mode 100644 index 0000000000..a234d33e07 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/date_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: date_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/date_time_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/date_time_serializer_rb.html new file mode 100644 index 0000000000..5037ebcbef --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/date_time_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: date_time_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/duration_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/duration_serializer_rb.html new file mode 100644 index 0000000000..f3b661e94d --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/duration_serializer_rb.html @@ -0,0 +1,72 @@ +--- +title: duration_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/module_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/module_serializer_rb.html new file mode 100644 index 0000000000..5d136a4f8b --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/module_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: module_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/object_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/object_serializer_rb.html new file mode 100644 index 0000000000..3107228f9d --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/object_serializer_rb.html @@ -0,0 +1,79 @@ +--- +title: object_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/range_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/range_serializer_rb.html new file mode 100644 index 0000000000..500e8d10d4 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/range_serializer_rb.html @@ -0,0 +1,77 @@ +--- +title: range_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/symbol_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/symbol_serializer_rb.html new file mode 100644 index 0000000000..d50ecc51e9 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/symbol_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: symbol_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/time_object_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/time_object_serializer_rb.html new file mode 100644 index 0000000000..80f0e94242 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/time_object_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: time_object_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/time_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/time_serializer_rb.html new file mode 100644 index 0000000000..da1b22300f --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/time_serializer_rb.html @@ -0,0 +1,70 @@ +--- +title: time_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers/time_with_zone_serializer_rb.html b/src/7.0/files/activejob/lib/active_job/serializers/time_with_zone_serializer_rb.html new file mode 100644 index 0000000000..0c0f102abb --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers/time_with_zone_serializer_rb.html @@ -0,0 +1,72 @@ +--- +title: time_with_zone_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/serializers_rb.html b/src/7.0/files/activejob/lib/active_job/serializers_rb.html new file mode 100644 index 0000000000..3a441baf46 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/serializers_rb.html @@ -0,0 +1,80 @@ +--- +title: serializers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/test_case_rb.html b/src/7.0/files/activejob/lib/active_job/test_case_rb.html new file mode 100644 index 0000000000..73320d7ca1 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/test_case_rb.html @@ -0,0 +1,83 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/test_case
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/test_helper_rb.html b/src/7.0/files/activejob/lib/active_job/test_helper_rb.html new file mode 100644 index 0000000000..933e569158 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/test_helper_rb.html @@ -0,0 +1,86 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/class/subclasses
  • + +
  • active_support/testing/assertions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/timezones_rb.html b/src/7.0/files/activejob/lib/active_job/timezones_rb.html new file mode 100644 index 0000000000..42900a76be --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/timezones_rb.html @@ -0,0 +1,68 @@ +--- +title: timezones.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/translation_rb.html b/src/7.0/files/activejob/lib/active_job/translation_rb.html new file mode 100644 index 0000000000..e8e6088021 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/translation_rb.html @@ -0,0 +1,68 @@ +--- +title: translation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activejob/lib/active_job/version_rb.html b/src/7.0/files/activejob/lib/active_job/version_rb.html new file mode 100644 index 0000000000..74a29dc797 --- /dev/null +++ b/src/7.0/files/activejob/lib/active_job/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/README_rdoc.html b/src/7.0/files/activemodel/README_rdoc.html new file mode 100644 index 0000000000..010d3d5398 --- /dev/null +++ b/src/7.0/files/activemodel/README_rdoc.html @@ -0,0 +1,324 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Active Model – model interfaces for Rails

+ +

Active Model provides a known set of interfaces for usage in model classes. They allow for Action Pack helpers to interact with non-Active Record models, for example. Active Model also helps with building custom ORMs for use outside of the Rails framework.

+ +

You can read more about Active Model in the Active Model Basics guide.

+ +

Prior to Rails 3.0, if a plugin or gem developer wanted to have an object interact with Action Pack helpers, it was required to either copy chunks of code from Rails, or monkey patch entire helpers to make them handle objects that did not exactly conform to the Active Record interface. This would result in code duplication and fragile applications that broke on upgrades. Active Model solves this by defining an explicit API. You can read more about the API in ActiveModel::Lint::Tests.

+ +

Active Model provides a default module that implements the basic API required to integrate with Action Pack out of the box: ActiveModel::API.

+ +
class Person
+  include ActiveModel::API
+
+  attr_accessor :name, :age
+  validates_presence_of :name
+end
+
+person = Person.new(name: 'bob', age: '18')
+person.name   # => 'bob'
+person.age    # => '18'
+person.valid? # => true
+
+ +

It includes model name introspections, conversions, translations and validations, resulting in a class suitable to be used with Action Pack. See ActiveModel::API for more examples.

+ +

Active Model also provides the following functionality to have ORM-like behavior out of the box:

+
  • +

    Add attribute magic to objects

    + +
    class Person
    +  include ActiveModel::AttributeMethods
    +
    +  attribute_method_prefix 'clear_'
    +  define_attribute_methods :name, :age
    +
    +  attr_accessor :name, :age
    +
    +  def clear_attribute(attr)
    +    send("#{attr}=", nil)
    +  end
    +end
    +
    +person = Person.new
    +person.clear_name
    +person.clear_age
    +
    + +

    Learn more

    +
  • +

    Callbacks for certain operations

    + +
    class Person
    +  extend ActiveModel::Callbacks
    +  define_model_callbacks :create
    +
    +  def create
    +    run_callbacks :create do
    +      # Your create action methods here
    +    end
    +  end
    +end
    +
    + +

    This generates before_create, around_create and after_create class methods that wrap your create method.

    + +

    Learn more

    +
  • +

    Tracking value changes

    + +
    class Person
    +  include ActiveModel::Dirty
    +
    +  define_attribute_methods :name
    +
    +  def name
    +    @name
    +  end
    +
    +  def name=(val)
    +    name_will_change! unless val == @name
    +    @name = val
    +  end
    +
    +  def save
    +    # do persistence work
    +    changes_applied
    +  end
    +end
    +
    +person = Person.new
    +person.name             # => nil
    +person.changed?         # => false
    +person.name = 'bob'
    +person.changed?         # => true
    +person.changed          # => ['name']
    +person.changes          # => { 'name' => [nil, 'bob'] }
    +person.save
    +person.name = 'robert'
    +person.save
    +person.previous_changes # => {'name' => ['bob, 'robert']}
    +
    + +

    Learn more

    +
  • +

    Adding errors interface to objects

    + +

    Exposing error messages allows objects to interact with Action Pack helpers seamlessly.

    + +
    class Person
    +
    +  def initialize
    +    @errors = ActiveModel::Errors.new(self)
    +  end
    +
    +  attr_accessor :name
    +  attr_reader   :errors
    +
    +  def validate!
    +    errors.add(:name, "cannot be nil") if name.nil?
    +  end
    +
    +  def self.human_attribute_name(attr, options = {})
    +    "Name"
    +  end
    +end
    +
    +person = Person.new
    +person.name = nil
    +person.validate!
    +person.errors.full_messages
    +# => ["Name cannot be nil"]
    +
    + +

    Learn more

    +
  • +

    Model name introspection

    + +
    class NamedPerson
    +  extend ActiveModel::Naming
    +end
    +
    +NamedPerson.model_name.name   # => "NamedPerson"
    +NamedPerson.model_name.human  # => "Named person"
    +
    + +

    Learn more

    +
  • +

    Making objects serializable

    + +

    ActiveModel::Serialization provides a standard interface for your object to provide to_json serialization.

    + +
    class SerialPerson
    +  include ActiveModel::Serialization
    +
    +  attr_accessor :name
    +
    +  def attributes
    +    {'name' => name}
    +  end
    +end
    +
    +s = SerialPerson.new
    +s.serializable_hash   # => {"name"=>nil}
    +
    +class SerialPerson
    +  include ActiveModel::Serializers::JSON
    +end
    +
    +s = SerialPerson.new
    +s.to_json             # => "{\"name\":null}"
    +
    + +

    Learn more

    +
  • +

    Internationalization (i18n) support

    + +
    class Person
    +  extend ActiveModel::Translation
    +end
    +
    +Person.human_attribute_name('my_attribute')
    +# => "My attribute"
    +
    + +

    Learn more

    +
  • +

    Validation support

    + +
    class Person
    +  include ActiveModel::Validations
    +
    +  attr_accessor :first_name, :last_name
    +
    +  validates_each :first_name, :last_name do |record, attr, value|
    +    record.errors.add attr, "starts with z." if value.start_with?("z")
    +  end
    +end
    +
    +person = Person.new
    +person.first_name = 'zoolander'
    +person.valid?  # => false
    +
    + +

    Learn more

    +
  • +

    Custom validators

    + +
    class HasNameValidator < ActiveModel::Validator
    +  def validate(record)
    +    record.errors.add(:name, "must exist") if record.name.blank?
    +  end
    +end
    +
    +class ValidatorPerson
    +  include ActiveModel::Validations
    +  validates_with HasNameValidator
    +  attr_accessor :name
    +end
    +
    +p = ValidatorPerson.new
    +p.valid?                  # =>  false
    +p.errors.full_messages    # => ["Name must exist"]
    +p.name = "Bob"
    +p.valid?                  # =>  true
    +
    + +

    Learn more

    +
+ +

Download and installation

+ +

The latest version of Active Model can be installed with RubyGems:

+ +
$ gem install activemodel
+
+ +

Source code can be downloaded as part of the Rails project on GitHub

+ + +

License

+ +

Active Model is released under the MIT license:

+ + +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/api_rb.html b/src/7.0/files/activemodel/lib/active_model/api_rb.html new file mode 100644 index 0000000000..ebe35737c6 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/api_rb.html @@ -0,0 +1,70 @@ +--- +title: api.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute/user_provided_default_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute/user_provided_default_rb.html new file mode 100644 index 0000000000..f7f8522a73 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute/user_provided_default_rb.html @@ -0,0 +1,76 @@ +--- +title: user_provided_default.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_assignment_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_assignment_rb.html new file mode 100644 index 0000000000..47a6193c7f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_assignment_rb.html @@ -0,0 +1,78 @@ +--- +title: attribute_assignment.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_methods_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_methods_rb.html new file mode 100644 index 0000000000..b509bd82d5 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_methods_rb.html @@ -0,0 +1,89 @@ +--- +title: attribute_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_mutation_tracker_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_mutation_tracker_rb.html new file mode 100644 index 0000000000..17ebd9549a --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_mutation_tracker_rb.html @@ -0,0 +1,78 @@ +--- +title: attribute_mutation_tracker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • active_support/core_ext/object/duplicable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_rb.html new file mode 100644 index 0000000000..4a5b536c10 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_rb.html @@ -0,0 +1,76 @@ +--- +title: attribute.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/duplicable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_set/builder_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_set/builder_rb.html new file mode 100644 index 0000000000..0b1c7b7f63 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_set/builder_rb.html @@ -0,0 +1,76 @@ +--- +title: builder.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_set/yaml_encoder_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_set/yaml_encoder_rb.html new file mode 100644 index 0000000000..5f46a1298b --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_set/yaml_encoder_rb.html @@ -0,0 +1,68 @@ +--- +title: yaml_encoder.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attribute_set_rb.html b/src/7.0/files/activemodel/lib/active_model/attribute_set_rb.html new file mode 100644 index 0000000000..d47ca9101d --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attribute_set_rb.html @@ -0,0 +1,82 @@ +--- +title: attribute_set.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/object/deep_dup
  • + +
  • active_model/attribute_set/builder
  • + +
  • active_model/attribute_set/yaml_encoder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/attributes_rb.html b/src/7.0/files/activemodel/lib/active_model/attributes_rb.html new file mode 100644 index 0000000000..20c3533565 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/attributes_rb.html @@ -0,0 +1,84 @@ +--- +title: attributes.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute_set
  • + +
  • active_model/attribute/user_provided_default
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/callbacks_rb.html b/src/7.0/files/activemodel/lib/active_model/callbacks_rb.html new file mode 100644 index 0000000000..54828c5ba3 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/callbacks_rb.html @@ -0,0 +1,82 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/hash/keys
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/conversion_rb.html b/src/7.0/files/activemodel/lib/active_model/conversion_rb.html new file mode 100644 index 0000000000..246e42a832 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/conversion_rb.html @@ -0,0 +1,72 @@ +--- +title: conversion.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/dirty_rb.html b/src/7.0/files/activemodel/lib/active_model/dirty_rb.html new file mode 100644 index 0000000000..aebc32b79c --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/dirty_rb.html @@ -0,0 +1,78 @@ +--- +title: dirty.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute_mutation_tracker
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/error_rb.html b/src/7.0/files/activemodel/lib/active_model/error_rb.html new file mode 100644 index 0000000000..0c6a16d99f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/error_rb.html @@ -0,0 +1,83 @@ +--- +title: error.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/class/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/errors_rb.html b/src/7.0/files/activemodel/lib/active_model/errors_rb.html new file mode 100644 index 0000000000..8800623836 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/errors_rb.html @@ -0,0 +1,101 @@ +--- +title: errors.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/conversions
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/object/deep_dup
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_model/error
  • + +
  • active_model/nested_error
  • + +
  • forwardable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/forbidden_attributes_protection_rb.html b/src/7.0/files/activemodel/lib/active_model/forbidden_attributes_protection_rb.html new file mode 100644 index 0000000000..80b5a92606 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/forbidden_attributes_protection_rb.html @@ -0,0 +1,75 @@ +--- +title: forbidden_attributes_protection.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/gem_version_rb.html b/src/7.0/files/activemodel/lib/active_model/gem_version_rb.html new file mode 100644 index 0000000000..c6743c9c55 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/lint_rb.html b/src/7.0/files/activemodel/lib/active_model/lint_rb.html new file mode 100644 index 0000000000..245dbe547b --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/lint_rb.html @@ -0,0 +1,72 @@ +--- +title: lint.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/model_rb.html b/src/7.0/files/activemodel/lib/active_model/model_rb.html new file mode 100644 index 0000000000..119d9c9194 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/model_rb.html @@ -0,0 +1,70 @@ +--- +title: model.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/naming_rb.html b/src/7.0/files/activemodel/lib/active_model/naming_rb.html new file mode 100644 index 0000000000..cfbbc3898f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/naming_rb.html @@ -0,0 +1,93 @@ +--- +title: naming.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/module/introspection
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/nested_error_rb.html b/src/7.0/files/activemodel/lib/active_model/nested_error_rb.html new file mode 100644 index 0000000000..85a85a0854 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/nested_error_rb.html @@ -0,0 +1,85 @@ +--- +title: nested_error.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/error
  • + +
  • forwardable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/railtie_rb.html b/src/7.0/files/activemodel/lib/active_model/railtie_rb.html new file mode 100644 index 0000000000..5202e703a6 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/railtie_rb.html @@ -0,0 +1,80 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model
  • + +
  • rails
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/secure_password_rb.html b/src/7.0/files/activemodel/lib/active_model/secure_password_rb.html new file mode 100644 index 0000000000..a96d2d9702 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/secure_password_rb.html @@ -0,0 +1,87 @@ +--- +title: secure_password.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • bcrypt
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/serialization_rb.html b/src/7.0/files/activemodel/lib/active_model/serialization_rb.html new file mode 100644 index 0000000000..3b64e1b88f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/serialization_rb.html @@ -0,0 +1,78 @@ +--- +title: serialization.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/serializers/json_rb.html b/src/7.0/files/activemodel/lib/active_model/serializers/json_rb.html new file mode 100644 index 0000000000..3c2d987393 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/serializers/json_rb.html @@ -0,0 +1,82 @@ +--- +title: json.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/json
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/translation_rb.html b/src/7.0/files/activemodel/lib/active_model/translation_rb.html new file mode 100644 index 0000000000..12d5b4d11c --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/translation_rb.html @@ -0,0 +1,70 @@ +--- +title: translation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/big_integer_rb.html b/src/7.0/files/activemodel/lib/active_model/type/big_integer_rb.html new file mode 100644 index 0000000000..da769fbb9e --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/big_integer_rb.html @@ -0,0 +1,78 @@ +--- +title: big_integer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type/integer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/binary_rb.html b/src/7.0/files/activemodel/lib/active_model/type/binary_rb.html new file mode 100644 index 0000000000..ecaa897d47 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/binary_rb.html @@ -0,0 +1,70 @@ +--- +title: binary.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/boolean_rb.html b/src/7.0/files/activemodel/lib/active_model/type/boolean_rb.html new file mode 100644 index 0000000000..c7baba88e1 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/boolean_rb.html @@ -0,0 +1,77 @@ +--- +title: boolean.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/date_rb.html b/src/7.0/files/activemodel/lib/active_model/type/date_rb.html new file mode 100644 index 0000000000..3a6c025960 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/date_rb.html @@ -0,0 +1,70 @@ +--- +title: date.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/date_time_rb.html b/src/7.0/files/activemodel/lib/active_model/type/date_time_rb.html new file mode 100644 index 0000000000..5209399ff3 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/date_time_rb.html @@ -0,0 +1,70 @@ +--- +title: date_time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/decimal_rb.html b/src/7.0/files/activemodel/lib/active_model/type/decimal_rb.html new file mode 100644 index 0000000000..b10a9014c0 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/decimal_rb.html @@ -0,0 +1,78 @@ +--- +title: decimal.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • bigdecimal/util
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/float_rb.html b/src/7.0/files/activemodel/lib/active_model/type/float_rb.html new file mode 100644 index 0000000000..f77e1f7252 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/float_rb.html @@ -0,0 +1,78 @@ +--- +title: float.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time_rb.html new file mode 100644 index 0000000000..5c77a5df09 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers/accepts_multiparameter_time_rb.html @@ -0,0 +1,81 @@ +--- +title: accepts_multiparameter_time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers/mutable_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers/mutable_rb.html new file mode 100644 index 0000000000..6d918cbe47 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers/mutable_rb.html @@ -0,0 +1,74 @@ +--- +title: mutable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers/numeric_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers/numeric_rb.html new file mode 100644 index 0000000000..38747445b4 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers/numeric_rb.html @@ -0,0 +1,74 @@ +--- +title: numeric.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers/time_value_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers/time_value_rb.html new file mode 100644 index 0000000000..8cda5c3cd8 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers/time_value_rb.html @@ -0,0 +1,84 @@ +--- +title: time_value.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/zones
  • + +
  • active_support/core_ext/time/zones
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers/timezone_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers/timezone_rb.html new file mode 100644 index 0000000000..69ba382781 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers/timezone_rb.html @@ -0,0 +1,82 @@ +--- +title: timezone.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/time/zones
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/helpers_rb.html b/src/7.0/files/activemodel/lib/active_model/type/helpers_rb.html new file mode 100644 index 0000000000..86a8f3ac08 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/helpers_rb.html @@ -0,0 +1,71 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type/helpers/accepts_multiparameter_time
  • + +
  • active_model/type/helpers/numeric
  • + +
  • active_model/type/helpers/mutable
  • + +
  • active_model/type/helpers/time_value
  • + +
  • active_model/type/helpers/timezone
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/immutable_string_rb.html b/src/7.0/files/activemodel/lib/active_model/type/immutable_string_rb.html new file mode 100644 index 0000000000..f15c1ab7fc --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/immutable_string_rb.html @@ -0,0 +1,72 @@ +--- +title: immutable_string.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/integer_rb.html b/src/7.0/files/activemodel/lib/active_model/type/integer_rb.html new file mode 100644 index 0000000000..879032e50f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/integer_rb.html @@ -0,0 +1,70 @@ +--- +title: integer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/registry_rb.html b/src/7.0/files/activemodel/lib/active_model/type/registry_rb.html new file mode 100644 index 0000000000..c4a43dc7ad --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/registry_rb.html @@ -0,0 +1,70 @@ +--- +title: registry.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/string_rb.html b/src/7.0/files/activemodel/lib/active_model/type/string_rb.html new file mode 100644 index 0000000000..f813878310 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/string_rb.html @@ -0,0 +1,78 @@ +--- +title: string.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type/immutable_string
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/time_rb.html b/src/7.0/files/activemodel/lib/active_model/type/time_rb.html new file mode 100644 index 0000000000..1f593fb09f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/time_rb.html @@ -0,0 +1,70 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type/value_rb.html b/src/7.0/files/activemodel/lib/active_model/type/value_rb.html new file mode 100644 index 0000000000..9e2423cf30 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type/value_rb.html @@ -0,0 +1,77 @@ +--- +title: value.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/type_rb.html b/src/7.0/files/activemodel/lib/active_model/type_rb.html new file mode 100644 index 0000000000..583f6fc45c --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/type_rb.html @@ -0,0 +1,104 @@ +--- +title: type.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type/helpers
  • + +
  • active_model/type/value
  • + +
  • active_model/type/big_integer
  • + +
  • active_model/type/binary
  • + +
  • active_model/type/boolean
  • + +
  • active_model/type/date
  • + +
  • active_model/type/date_time
  • + +
  • active_model/type/decimal
  • + +
  • active_model/type/float
  • + +
  • active_model/type/immutable_string
  • + +
  • active_model/type/integer
  • + +
  • active_model/type/string
  • + +
  • active_model/type/time
  • + +
  • active_model/type/registry
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/absence_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/absence_rb.html new file mode 100644 index 0000000000..80e40a8862 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/absence_rb.html @@ -0,0 +1,72 @@ +--- +title: absence.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/acceptance_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/acceptance_rb.html new file mode 100644 index 0000000000..07385542fc --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/acceptance_rb.html @@ -0,0 +1,81 @@ +--- +title: acceptance.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/callbacks_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/callbacks_rb.html new file mode 100644 index 0000000000..197cd97c8f --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/callbacks_rb.html @@ -0,0 +1,74 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/clusivity_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/clusivity_rb.html new file mode 100644 index 0000000000..5984872130 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/clusivity_rb.html @@ -0,0 +1,78 @@ +--- +title: clusivity.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/range
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/comparability_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/comparability_rb.html new file mode 100644 index 0000000000..d8bd1e26a9 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/comparability_rb.html @@ -0,0 +1,70 @@ +--- +title: comparability.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/comparison_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/comparison_rb.html new file mode 100644 index 0000000000..763eaaefee --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/comparison_rb.html @@ -0,0 +1,80 @@ +--- +title: comparison.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/validations/comparability
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/confirmation_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/confirmation_rb.html new file mode 100644 index 0000000000..8f48131322 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/confirmation_rb.html @@ -0,0 +1,72 @@ +--- +title: confirmation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/exclusion_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/exclusion_rb.html new file mode 100644 index 0000000000..eb7c1f22f0 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/exclusion_rb.html @@ -0,0 +1,80 @@ +--- +title: exclusion.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/validations/clusivity
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/format_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/format_rb.html new file mode 100644 index 0000000000..d3c090a9a3 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/format_rb.html @@ -0,0 +1,72 @@ +--- +title: format.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/helper_methods_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/helper_methods_rb.html new file mode 100644 index 0000000000..d280deb65b --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/helper_methods_rb.html @@ -0,0 +1,72 @@ +--- +title: helper_methods.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/inclusion_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/inclusion_rb.html new file mode 100644 index 0000000000..e26145bef5 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/inclusion_rb.html @@ -0,0 +1,80 @@ +--- +title: inclusion.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/validations/clusivity
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/length_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/length_rb.html new file mode 100644 index 0000000000..e3debf151c --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/length_rb.html @@ -0,0 +1,72 @@ +--- +title: length.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/numericality_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/numericality_rb.html new file mode 100644 index 0000000000..8732b89615 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/numericality_rb.html @@ -0,0 +1,82 @@ +--- +title: numericality.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/validations/comparability
  • + +
  • bigdecimal/util
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/presence_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/presence_rb.html new file mode 100644 index 0000000000..95b8aacc30 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/presence_rb.html @@ -0,0 +1,72 @@ +--- +title: presence.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/validates_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/validates_rb.html new file mode 100644 index 0000000000..3cfe460a1b --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/validates_rb.html @@ -0,0 +1,80 @@ +--- +title: validates.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/slice
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations/with_rb.html b/src/7.0/files/activemodel/lib/active_model/validations/with_rb.html new file mode 100644 index 0000000000..0b6a3acaca --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations/with_rb.html @@ -0,0 +1,80 @@ +--- +title: with.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validations_rb.html b/src/7.0/files/activemodel/lib/active_model/validations_rb.html new file mode 100644 index 0000000000..52d72169d3 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validations_rb.html @@ -0,0 +1,87 @@ +--- +title: validations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/validator_rb.html b/src/7.0/files/activemodel/lib/active_model/validator_rb.html new file mode 100644 index 0000000000..fcaec5c2eb --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/validator_rb.html @@ -0,0 +1,85 @@ +--- +title: validator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/anonymous
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activemodel/lib/active_model/version_rb.html b/src/7.0/files/activemodel/lib/active_model/version_rb.html new file mode 100644 index 0000000000..84c6c550d5 --- /dev/null +++ b/src/7.0/files/activemodel/lib/active_model/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/README_rdoc.html b/src/7.0/files/activerecord/README_rdoc.html new file mode 100644 index 0000000000..fbd081ccf1 --- /dev/null +++ b/src/7.0/files/activerecord/README_rdoc.html @@ -0,0 +1,273 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Active Record – Object-relational mapping in Rails

+ +

Active Record connects classes to relational database tables to establish an almost zero-configuration persistence layer for applications. The library provides a base class that, when subclassed, sets up a mapping between the new class and an existing table in the database. In the context of an application, these classes are commonly referred to as models. Models can also be connected to other models; this is done by defining associations.

+ +

Active Record relies heavily on naming in that it uses class and association names to establish mappings between respective database tables and foreign key columns. Although these mappings can be defined explicitly, it’s recommended to follow naming conventions, especially when getting started with the library.

+ +

You can read more about Active Record in the Active Record Basics guide.

+ +

A short rundown of some of the major features:

+
  • +

    Automated mapping between classes and tables, attributes and columns.

    + +
    class Product < ActiveRecord::Base
    +end
    +
    + +

    Learn more

    +
+ +

The Product class is automatically mapped to the table named “products”, which might look like this:

+ +
CREATE TABLE products (
+  id bigint NOT NULL auto_increment,
+  name varchar(255),
+  PRIMARY KEY  (id)
+);
+
+ +

This would also define the following accessors: Product#name and Product#name=(new_name).

+
  • +

    Associations between objects defined by simple class methods.

    + +
    class Firm < ActiveRecord::Base
    +  has_many   :clients
    +  has_one    :account
    +  belongs_to :conglomerate
    +end
    +
    + +

    Learn more

    +
  • +

    Aggregations of value objects.

    + +
    class Account < ActiveRecord::Base
    +  composed_of :balance, class_name: 'Money',
    +              mapping: %w(balance amount)
    +  composed_of :address,
    +              mapping: [%w(address_street street), %w(address_city city)]
    +end
    +
    + +

    Learn more

    +
  • +

    Validation rules that can differ for new or existing objects.

    + +
    class Account < ActiveRecord::Base
    +  validates :subdomain, :name, :email_address, :password, presence: true
    +  validates :subdomain, uniqueness: true
    +  validates :terms_of_service, acceptance: true, on: :create
    +  validates :password, :email_address, confirmation: true, on: :create
    +end
    +
    + +

    Learn more

    +
  • +

    Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).

    + +
    class Person < ActiveRecord::Base
    +  before_destroy :invalidate_payment_plan
    +  # the `invalidate_payment_plan` method gets called just before Person#destroy
    +end
    +
    + +

    Learn more

    +
  • +

    Inheritance hierarchies.

    + +
    class Company < ActiveRecord::Base; end
    +class Firm < Company; end
    +class Client < Company; end
    +class PriorityClient < Client; end
    +
    + +

    Learn more

    +
  • +

    Transactions.

    + +
    # Database transaction
    +Account.transaction do
    +  david.withdrawal(100)
    +  mary.deposit(100)
    +end
    +
    + +

    Learn more

    +
  • +

    Reflections on columns, associations, and aggregations.

    + +
    reflection = Firm.reflect_on_association(:clients)
    +reflection.klass # => Client (class)
    +Firm.columns # Returns an array of column descriptors for the firms table
    +
    + +

    Learn more

    +
  • +

    Database abstraction through simple adapters.

    + +
    # connect to SQLite3
    +ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: 'dbfile.sqlite3')
    +
    +# connect to MySQL with authentication
    +ActiveRecord::Base.establish_connection(
    +  adapter:  'mysql2',
    +  host:     'localhost',
    +  username: 'me',
    +  password: 'secret',
    +  database: 'activerecord'
    +)
    +
    + +

    Learn more and read about the built-in support for MySQL, PostgreSQL, and SQLite3.

    +
  • +

    Logging support for Log4r and Logger.

    + +
    ActiveRecord::Base.logger = ActiveSupport::Logger.new(STDOUT)
    +ActiveRecord::Base.logger = Log4r::Logger.new('Application Log')
    +
    +
  • +

    Database agnostic schema management with Migrations.

    + +
    class AddSystemSettings < ActiveRecord::Migration[7.0]
    +  def up
    +    create_table :system_settings do |t|
    +      t.string  :name
    +      t.string  :label
    +      t.text    :value
    +      t.string  :type
    +      t.integer :position
    +    end
    +
    +    SystemSetting.create name: 'notice', label: 'Use notice?', value: 1
    +  end
    +
    +  def down
    +    drop_table :system_settings
    +  end
    +end
    +
    + +

    Learn more

    +
+ +

Philosophy

+ +

Active Record is an implementation of the object-relational mapping (ORM) pattern by the same name described by Martin Fowler:

+ +
"An object that wraps a row in a database table or view,
+encapsulates the database access, and adds domain logic on that data."
+
+ +

Active Record attempts to provide a coherent wrapper as a solution for the inconvenience that is object-relational mapping. The prime directive for this mapping has been to minimize the amount of code needed to build a real-world domain model. This is made possible by relying on a number of conventions that make it easy for Active Record to infer complex relations and structures from a minimal amount of explicit direction.

+ +

Convention over Configuration:

+
  • +

    No XML files!

    +
  • +

    Lots of reflection and run-time extension

    +
  • +

    Magic is not inherently a bad word

    +
+ +

Admit the Database:

+
  • +

    Lets you drop down to SQL for odd cases and performance

    +
  • +

    Doesn’t attempt to duplicate or replace data definitions

    +
+ +

Download and installation

+ +

The latest version of Active Record can be installed with RubyGems:

+ +
$ gem install activerecord
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Active Record is released under the MIT license:

+ + +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/aggregations_rb.html b/src/7.0/files/activerecord/lib/active_record/aggregations_rb.html new file mode 100644 index 0000000000..974c87cbd9 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/aggregations_rb.html @@ -0,0 +1,72 @@ +--- +title: aggregations.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/association_relation_rb.html b/src/7.0/files/activerecord/lib/active_record/association_relation_rb.html new file mode 100644 index 0000000000..3da2bdbefe --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/association_relation_rb.html @@ -0,0 +1,68 @@ +--- +title: association_relation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/alias_tracker_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/alias_tracker_rb.html new file mode 100644 index 0000000000..9123da3b1f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/alias_tracker_rb.html @@ -0,0 +1,80 @@ +--- +title: alias_tracker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/conversions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/association_rb.html new file mode 100644 index 0000000000..ffc5477bc6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/association_rb.html @@ -0,0 +1,70 @@ +--- +title: association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/association_scope_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/association_scope_rb.html new file mode 100644 index 0000000000..de8e0404d5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/association_scope_rb.html @@ -0,0 +1,72 @@ +--- +title: association_scope.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_association_rb.html new file mode 100644 index 0000000000..577f73f055 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_association_rb.html @@ -0,0 +1,70 @@ +--- +title: belongs_to_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_polymorphic_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_polymorphic_association_rb.html new file mode 100644 index 0000000000..3553dcb362 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/belongs_to_polymorphic_association_rb.html @@ -0,0 +1,70 @@ +--- +title: belongs_to_polymorphic_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/association_rb.html new file mode 100644 index 0000000000..a252d3a2a4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/association_rb.html @@ -0,0 +1,86 @@ +--- +title: association.rb +layout: default +--- +
+ + +
+
+ +
+ +

This is the parent Association class which defines the variables used by all associations.

+ +

The hierarchy is defined as follows:

+ +
Association
+  - SingularAssociation
+    - BelongsToAssociation
+    - HasOneAssociation
+  - CollectionAssociation
+    - HasManyAssociation
+
+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/belongs_to_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/belongs_to_rb.html new file mode 100644 index 0000000000..e033241b2c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/belongs_to_rb.html @@ -0,0 +1,70 @@ +--- +title: belongs_to.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/collection_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/collection_association_rb.html new file mode 100644 index 0000000000..2b4834e233 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/collection_association_rb.html @@ -0,0 +1,78 @@ +--- +title: collection_association.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/associations
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many_rb.html new file mode 100644 index 0000000000..571a116bba --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many_rb.html @@ -0,0 +1,70 @@ +--- +title: has_and_belongs_to_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/has_many_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_many_rb.html new file mode 100644 index 0000000000..d004751d32 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_many_rb.html @@ -0,0 +1,70 @@ +--- +title: has_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/has_one_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_one_rb.html new file mode 100644 index 0000000000..d2fa1be998 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/has_one_rb.html @@ -0,0 +1,70 @@ +--- +title: has_one.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/builder/singular_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/builder/singular_association_rb.html new file mode 100644 index 0000000000..bd6e12838c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/builder/singular_association_rb.html @@ -0,0 +1,76 @@ +--- +title: singular_association.rb +layout: default +--- +
+ + +
+
+ +
+ +

This class is inherited by the has_one and belongs_to association classes

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/collection_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/collection_association_rb.html new file mode 100644 index 0000000000..4fd70fb353 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/collection_association_rb.html @@ -0,0 +1,78 @@ +--- +title: collection_association.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/collection_proxy_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/collection_proxy_rb.html new file mode 100644 index 0000000000..8bcdc21f46 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/collection_proxy_rb.html @@ -0,0 +1,77 @@ +--- +title: collection_proxy.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/disable_joins_association_scope_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/disable_joins_association_scope_rb.html new file mode 100644 index 0000000000..5b3c0a18b6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/disable_joins_association_scope_rb.html @@ -0,0 +1,70 @@ +--- +title: disable_joins_association_scope.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/foreign_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/foreign_association_rb.html new file mode 100644 index 0000000000..d80350bd3c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/foreign_association_rb.html @@ -0,0 +1,70 @@ +--- +title: foreign_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/has_many_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/has_many_association_rb.html new file mode 100644 index 0000000000..61a70148d7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/has_many_association_rb.html @@ -0,0 +1,70 @@ +--- +title: has_many_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/has_many_through_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/has_many_through_association_rb.html new file mode 100644 index 0000000000..7ee5505ce7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/has_many_through_association_rb.html @@ -0,0 +1,70 @@ +--- +title: has_many_through_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/has_one_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/has_one_association_rb.html new file mode 100644 index 0000000000..37250d719a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/has_one_association_rb.html @@ -0,0 +1,70 @@ +--- +title: has_one_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/has_one_through_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/has_one_through_association_rb.html new file mode 100644 index 0000000000..01cacbe2dd --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/has_one_through_association_rb.html @@ -0,0 +1,70 @@ +--- +title: has_one_through_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_association_rb.html new file mode 100644 index 0000000000..d0ed7f3d77 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_association_rb.html @@ -0,0 +1,82 @@ +--- +title: join_association.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/associations/join_dependency/join_part
  • + +
  • active_support/core_ext/array/extract
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_base_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_base_rb.html new file mode 100644 index 0000000000..22ac16602d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_base_rb.html @@ -0,0 +1,78 @@ +--- +title: join_base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/associations/join_dependency/join_part
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_part_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_part_rb.html new file mode 100644 index 0000000000..afbf48e6fa --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency/join_part_rb.html @@ -0,0 +1,70 @@ +--- +title: join_part.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/join_dependency_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency_rb.html new file mode 100644 index 0000000000..1b5d3d6466 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/join_dependency_rb.html @@ -0,0 +1,74 @@ +--- +title: join_dependency.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/preloader/association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/preloader/association_rb.html new file mode 100644 index 0000000000..7dfd92cec7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/preloader/association_rb.html @@ -0,0 +1,83 @@ +--- +title: association.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/preloader/batch_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/preloader/batch_rb.html new file mode 100644 index 0000000000..b4b7608076 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/preloader/batch_rb.html @@ -0,0 +1,77 @@ +--- +title: batch.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/preloader/branch_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/preloader/branch_rb.html new file mode 100644 index 0000000000..82578f1a7f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/preloader/branch_rb.html @@ -0,0 +1,77 @@ +--- +title: branch.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/preloader/through_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/preloader/through_association_rb.html new file mode 100644 index 0000000000..2b5b095f07 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/preloader/through_association_rb.html @@ -0,0 +1,77 @@ +--- +title: through_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/preloader_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/preloader_rb.html new file mode 100644 index 0000000000..d66201bb5f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/preloader_rb.html @@ -0,0 +1,85 @@ +--- +title: preloader.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/singular_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/singular_association_rb.html new file mode 100644 index 0000000000..e52bcfd5fe --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/singular_association_rb.html @@ -0,0 +1,70 @@ +--- +title: singular_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations/through_association_rb.html b/src/7.0/files/activerecord/lib/active_record/associations/through_association_rb.html new file mode 100644 index 0000000000..cc3917b7fd --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations/through_association_rb.html @@ -0,0 +1,70 @@ +--- +title: through_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/associations_rb.html b/src/7.0/files/activerecord/lib/active_record/associations_rb.html new file mode 100644 index 0000000000..c63ba5d0c3 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/associations_rb.html @@ -0,0 +1,79 @@ +--- +title: associations.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/asynchronous_queries_tracker_rb.html b/src/7.0/files/activerecord/lib/active_record/asynchronous_queries_tracker_rb.html new file mode 100644 index 0000000000..dbc475657c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/asynchronous_queries_tracker_rb.html @@ -0,0 +1,68 @@ +--- +title: asynchronous_queries_tracker.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_assignment_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_assignment_rb.html new file mode 100644 index 0000000000..d5c6159ef8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_assignment_rb.html @@ -0,0 +1,78 @@ +--- +title: attribute_assignment.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/forbidden_attributes_protection
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/before_type_cast_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/before_type_cast_rb.html new file mode 100644 index 0000000000..e5e4c4d2a6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/before_type_cast_rb.html @@ -0,0 +1,72 @@ +--- +title: before_type_cast.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/dirty_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/dirty_rb.html new file mode 100644 index 0000000000..9c3c2d3109 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/dirty_rb.html @@ -0,0 +1,84 @@ +--- +title: dirty.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/primary_key_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/primary_key_rb.html new file mode 100644 index 0000000000..20751be03e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/primary_key_rb.html @@ -0,0 +1,82 @@ +--- +title: primary_key.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/query_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/query_rb.html new file mode 100644 index 0000000000..b20852bce7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/query_rb.html @@ -0,0 +1,83 @@ +--- +title: query.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/read_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/read_rb.html new file mode 100644 index 0000000000..113e7b9582 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/read_rb.html @@ -0,0 +1,76 @@ +--- +title: read.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/serialization_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/serialization_rb.html new file mode 100644 index 0000000000..d14a9eee1e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/serialization_rb.html @@ -0,0 +1,81 @@ +--- +title: serialization.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/time_zone_conversion_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/time_zone_conversion_rb.html new file mode 100644 index 0000000000..6b93b1fdde --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/time_zone_conversion_rb.html @@ -0,0 +1,80 @@ +--- +title: time_zone_conversion.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods/write_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods/write_rb.html new file mode 100644 index 0000000000..d1bc5d44c1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods/write_rb.html @@ -0,0 +1,76 @@ +--- +title: write.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attribute_methods_rb.html b/src/7.0/files/activerecord/lib/active_record/attribute_methods_rb.html new file mode 100644 index 0000000000..7060f4e04d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attribute_methods_rb.html @@ -0,0 +1,82 @@ +--- +title: attribute_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mutex_m
  • + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/attributes_rb.html b/src/7.0/files/activerecord/lib/active_record/attributes_rb.html new file mode 100644 index 0000000000..63c9eb7c62 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/attributes_rb.html @@ -0,0 +1,82 @@ +--- +title: attributes.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute/user_provided_default
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/autosave_association_rb.html b/src/7.0/files/activerecord/lib/active_record/autosave_association_rb.html new file mode 100644 index 0000000000..3fc703cfce --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/autosave_association_rb.html @@ -0,0 +1,72 @@ +--- +title: autosave_association.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/base_rb.html b/src/7.0/files/activerecord/lib/active_record/base_rb.html new file mode 100644 index 0000000000..67e59d3e93 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/base_rb.html @@ -0,0 +1,103 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/benchmarkable
  • + +
  • active_support/dependencies
  • + +
  • active_support/descendants_tracker
  • + +
  • active_support/time
  • + +
  • active_support/core_ext/class/subclasses
  • + +
  • active_record/log_subscriber
  • + +
  • active_record/explain_subscriber
  • + +
  • active_record/relation/delegation
  • + +
  • active_record/attributes
  • + +
  • active_record/type_caster
  • + +
  • active_record/database_configurations
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/callbacks_rb.html b/src/7.0/files/activerecord/lib/active_record/callbacks_rb.html new file mode 100644 index 0000000000..3ebe79da32 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/callbacks_rb.html @@ -0,0 +1,72 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/coders/json_rb.html b/src/7.0/files/activerecord/lib/active_record/coders/json_rb.html new file mode 100644 index 0000000000..522a37ee5e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/coders/json_rb.html @@ -0,0 +1,70 @@ +--- +title: json.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/coders/yaml_column_rb.html b/src/7.0/files/activerecord/lib/active_record/coders/yaml_column_rb.html new file mode 100644 index 0000000000..543b9ff9a0 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/coders/yaml_column_rb.html @@ -0,0 +1,76 @@ +--- +title: yaml_column.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_handler_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_handler_rb.html new file mode 100644 index 0000000000..e12812cbbf --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_handler_rb.html @@ -0,0 +1,89 @@ +--- +title: connection_handler.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue_rb.html new file mode 100644 index 0000000000..c6b4c96a20 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue_rb.html @@ -0,0 +1,93 @@ +--- +title: queue.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/reaper_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/reaper_rb.html new file mode 100644 index 0000000000..81762b1f6d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/reaper_rb.html @@ -0,0 +1,89 @@ +--- +title: reaper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • weakref
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool_rb.html new file mode 100644 index 0000000000..d1289923c6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/connection_pool_rb.html @@ -0,0 +1,95 @@ +--- +title: connection_pool.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • concurrent/map
  • + +
  • monitor
  • + +
  • active_record/connection_adapters/abstract/connection_pool/queue
  • + +
  • active_record/connection_adapters/abstract/connection_pool/reaper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_limits_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_limits_rb.html new file mode 100644 index 0000000000..7a7227abe2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_limits_rb.html @@ -0,0 +1,72 @@ +--- +title: database_limits.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_statements_rb.html new file mode 100644 index 0000000000..16a29738fb --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/database_statements_rb.html @@ -0,0 +1,74 @@ +--- +title: database_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/query_cache_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/query_cache_rb.html new file mode 100644 index 0000000000..04b819c862 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/query_cache_rb.html @@ -0,0 +1,84 @@ +--- +title: query_cache.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/quoting_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/quoting_rb.html new file mode 100644 index 0000000000..3298c5a2a4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/quoting_rb.html @@ -0,0 +1,86 @@ +--- +title: quoting.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/big_decimal/conversions
  • + +
  • active_support/multibyte/chars
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/savepoints_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/savepoints_rb.html new file mode 100644 index 0000000000..6fd18583e4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/savepoints_rb.html @@ -0,0 +1,72 @@ +--- +title: savepoints.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_creation_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_creation_rb.html new file mode 100644 index 0000000000..0fd9cec253 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_creation_rb.html @@ -0,0 +1,70 @@ +--- +title: schema_creation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions_rb.html new file mode 100644 index 0000000000..9128b2430d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions_rb.html @@ -0,0 +1,81 @@ +--- +title: schema_definitions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper_rb.html new file mode 100644 index 0000000000..1f4661d024 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_dumper_rb.html @@ -0,0 +1,70 @@ +--- +title: schema_dumper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_statements_rb.html new file mode 100644 index 0000000000..79d9905643 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/schema_statements_rb.html @@ -0,0 +1,84 @@ +--- +title: schema_statements.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/access
  • + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/transaction_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/transaction_rb.html new file mode 100644 index 0000000000..1f408e4099 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract/transaction_rb.html @@ -0,0 +1,81 @@ +--- +title: transaction.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_adapter_rb.html new file mode 100644 index 0000000000..d6d8e4f784 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_adapter_rb.html @@ -0,0 +1,109 @@ +--- +title: abstract_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
  • active_record/connection_adapters/sql_type_metadata
  • + +
  • active_record/connection_adapters/abstract/schema_dumper
  • + +
  • active_record/connection_adapters/abstract/schema_creation
  • + +
  • active_support/concurrency/load_interlock_aware_monitor
  • + +
  • arel/collectors/bind
  • + +
  • arel/collectors/composite
  • + +
  • arel/collectors/sql_string
  • + +
  • arel/collectors/substitute_binds
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter_rb.html new file mode 100644 index 0000000000..6c118af5d8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter_rb.html @@ -0,0 +1,107 @@ +--- +title: abstract_mysql_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/connection_adapters/abstract_adapter
  • + +
  • active_record/connection_adapters/statement_pool
  • + +
  • active_record/connection_adapters/mysql/column
  • + +
  • active_record/connection_adapters/mysql/explain_pretty_printer
  • + +
  • active_record/connection_adapters/mysql/quoting
  • + +
  • active_record/connection_adapters/mysql/schema_creation
  • + +
  • active_record/connection_adapters/mysql/schema_definitions
  • + +
  • active_record/connection_adapters/mysql/schema_dumper
  • + +
  • active_record/connection_adapters/mysql/schema_statements
  • + +
  • active_record/connection_adapters/mysql/type_metadata
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/column_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/column_rb.html new file mode 100644 index 0000000000..0ee9a7819e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/column_rb.html @@ -0,0 +1,79 @@ +--- +title: column.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/deduplicable_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/deduplicable_rb.html new file mode 100644 index 0000000000..1641cd890a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/deduplicable_rb.html @@ -0,0 +1,74 @@ +--- +title: deduplicable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/legacy_pool_manager_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/legacy_pool_manager_rb.html new file mode 100644 index 0000000000..8e9ec8c0d2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/legacy_pool_manager_rb.html @@ -0,0 +1,70 @@ +--- +title: legacy_pool_manager.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/column_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/column_rb.html new file mode 100644 index 0000000000..dad720f86f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/column_rb.html @@ -0,0 +1,72 @@ +--- +title: column.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/database_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/database_statements_rb.html new file mode 100644 index 0000000000..0f1c8db2f8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/database_statements_rb.html @@ -0,0 +1,78 @@ +--- +title: database_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer_rb.html new file mode 100644 index 0000000000..b39d728373 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer_rb.html @@ -0,0 +1,72 @@ +--- +title: explain_pretty_printer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/quoting_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/quoting_rb.html new file mode 100644 index 0000000000..0ddc26ca2b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/quoting_rb.html @@ -0,0 +1,82 @@ +--- +title: quoting.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/time_with_zone
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_creation_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_creation_rb.html new file mode 100644 index 0000000000..7686c3db16 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_creation_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_creation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions_rb.html new file mode 100644 index 0000000000..f197348523 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_definitions_rb.html @@ -0,0 +1,83 @@ +--- +title: schema_definitions.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper_rb.html new file mode 100644 index 0000000000..62e24198fa --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_dumper_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_dumper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_statements_rb.html new file mode 100644 index 0000000000..787eaaf3e2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/schema_statements_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/type_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/type_metadata_rb.html new file mode 100644 index 0000000000..7a8f3ac11f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql/type_metadata_rb.html @@ -0,0 +1,72 @@ +--- +title: type_metadata.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql2_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql2_adapter_rb.html new file mode 100644 index 0000000000..01400f1c1e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/mysql2_adapter_rb.html @@ -0,0 +1,91 @@ +--- +title: mysql2_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/connection_adapters/abstract_mysql_adapter
  • + +
  • active_record/connection_adapters/mysql/database_statements
  • + +
  • mysql2
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_config_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_config_rb.html new file mode 100644 index 0000000000..d32a510607 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_config_rb.html @@ -0,0 +1,72 @@ +--- +title: pool_config.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_manager_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_manager_rb.html new file mode 100644 index 0000000000..be312265f1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/pool_manager_rb.html @@ -0,0 +1,70 @@ +--- +title: pool_manager.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/column_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/column_rb.html new file mode 100644 index 0000000000..9572b31143 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/column_rb.html @@ -0,0 +1,80 @@ +--- +title: column.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/blank
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/database_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/database_statements_rb.html new file mode 100644 index 0000000000..d2a366f53a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/database_statements_rb.html @@ -0,0 +1,76 @@ +--- +title: database_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/explain_pretty_printer_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/explain_pretty_printer_rb.html new file mode 100644 index 0000000000..b2a52cf1da --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/explain_pretty_printer_rb.html @@ -0,0 +1,72 @@ +--- +title: explain_pretty_printer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/array_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/array_rb.html new file mode 100644 index 0000000000..e4c8d1af61 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/array_rb.html @@ -0,0 +1,74 @@ +--- +title: array.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_rb.html new file mode 100644 index 0000000000..e2617ca806 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_rb.html @@ -0,0 +1,83 @@ +--- +title: bit.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_varying_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_varying_rb.html new file mode 100644 index 0000000000..8c8971453b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit_varying_rb.html @@ -0,0 +1,74 @@ +--- +title: bit_varying.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea_rb.html new file mode 100644 index 0000000000..15c0fb7cfe --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/bytea_rb.html @@ -0,0 +1,74 @@ +--- +title: bytea.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr_rb.html new file mode 100644 index 0000000000..991f54c495 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/cidr_rb.html @@ -0,0 +1,82 @@ +--- +title: cidr.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • ipaddr
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_rb.html new file mode 100644 index 0000000000..a686101edf --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_rb.html @@ -0,0 +1,74 @@ +--- +title: date.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time_rb.html new file mode 100644 index 0000000000..96de357d03 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/date_time_rb.html @@ -0,0 +1,74 @@ +--- +title: date_time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/decimal_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/decimal_rb.html new file mode 100644 index 0000000000..52d785965e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/decimal_rb.html @@ -0,0 +1,74 @@ +--- +title: decimal.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum_rb.html new file mode 100644 index 0000000000..bd5059634b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum_rb.html @@ -0,0 +1,74 @@ +--- +title: enum.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore_rb.html new file mode 100644 index 0000000000..e1c744a8b4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore_rb.html @@ -0,0 +1,82 @@ +--- +title: hstore.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • strscan
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/inet_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/inet_rb.html new file mode 100644 index 0000000000..82d9dc53fe --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/inet_rb.html @@ -0,0 +1,74 @@ +--- +title: inet.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/interval_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/interval_rb.html new file mode 100644 index 0000000000..9e0f6fbed9 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/interval_rb.html @@ -0,0 +1,84 @@ +--- +title: interval.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/duration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb_rb.html new file mode 100644 index 0000000000..ac4becd6e7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/jsonb_rb.html @@ -0,0 +1,74 @@ +--- +title: jsonb.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point_rb.html new file mode 100644 index 0000000000..85d9e16eeb --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point_rb.html @@ -0,0 +1,74 @@ +--- +title: legacy_point.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/macaddr_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/macaddr_rb.html new file mode 100644 index 0000000000..65203880db --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/macaddr_rb.html @@ -0,0 +1,74 @@ +--- +title: macaddr.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/money_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/money_rb.html new file mode 100644 index 0000000000..db06c1d4bc --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/money_rb.html @@ -0,0 +1,74 @@ +--- +title: money.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/oid_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/oid_rb.html new file mode 100644 index 0000000000..58589edc6e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/oid_rb.html @@ -0,0 +1,74 @@ +--- +title: oid.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/point_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/point_rb.html new file mode 100644 index 0000000000..bb225f8d5c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/point_rb.html @@ -0,0 +1,74 @@ +--- +title: point.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/range_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/range_rb.html new file mode 100644 index 0000000000..f67713ed13 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/range_rb.html @@ -0,0 +1,74 @@ +--- +title: range.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/specialized_string_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/specialized_string_rb.html new file mode 100644 index 0000000000..57f9f304df --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/specialized_string_rb.html @@ -0,0 +1,74 @@ +--- +title: specialized_string.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_rb.html new file mode 100644 index 0000000000..1cb5f057e6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_rb.html @@ -0,0 +1,74 @@ +--- +title: timestamp.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone_rb.html new file mode 100644 index 0000000000..3e15423a0e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone_rb.html @@ -0,0 +1,76 @@ +--- +title: timestamp_with_time_zone.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer_rb.html new file mode 100644 index 0000000000..f785c7dbf0 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer_rb.html @@ -0,0 +1,82 @@ +--- +title: type_map_initializer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid_rb.html new file mode 100644 index 0000000000..ed5f35fa1d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid_rb.html @@ -0,0 +1,74 @@ +--- +title: uuid.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector_rb.html new file mode 100644 index 0000000000..69f660ae14 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/vector_rb.html @@ -0,0 +1,74 @@ +--- +title: vector.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml_rb.html new file mode 100644 index 0000000000..79c72c9603 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid/xml_rb.html @@ -0,0 +1,74 @@ +--- +title: xml.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid_rb.html new file mode 100644 index 0000000000..ace9f11eb7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/oid_rb.html @@ -0,0 +1,132 @@ +--- +title: oid.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/connection_adapters/postgresql/oid/array
  • + +
  • active_record/connection_adapters/postgresql/oid/bit
  • + +
  • active_record/connection_adapters/postgresql/oid/bit_varying
  • + +
  • active_record/connection_adapters/postgresql/oid/bytea
  • + +
  • active_record/connection_adapters/postgresql/oid/cidr
  • + +
  • active_record/connection_adapters/postgresql/oid/date
  • + +
  • active_record/connection_adapters/postgresql/oid/date_time
  • + +
  • active_record/connection_adapters/postgresql/oid/decimal
  • + +
  • active_record/connection_adapters/postgresql/oid/enum
  • + +
  • active_record/connection_adapters/postgresql/oid/hstore
  • + +
  • active_record/connection_adapters/postgresql/oid/inet
  • + +
  • active_record/connection_adapters/postgresql/oid/interval
  • + +
  • active_record/connection_adapters/postgresql/oid/jsonb
  • + +
  • active_record/connection_adapters/postgresql/oid/macaddr
  • + +
  • active_record/connection_adapters/postgresql/oid/money
  • + +
  • active_record/connection_adapters/postgresql/oid/oid
  • + +
  • active_record/connection_adapters/postgresql/oid/point
  • + +
  • active_record/connection_adapters/postgresql/oid/legacy_point
  • + +
  • active_record/connection_adapters/postgresql/oid/range
  • + +
  • active_record/connection_adapters/postgresql/oid/specialized_string
  • + +
  • active_record/connection_adapters/postgresql/oid/timestamp
  • + +
  • active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone
  • + +
  • active_record/connection_adapters/postgresql/oid/uuid
  • + +
  • active_record/connection_adapters/postgresql/oid/vector
  • + +
  • active_record/connection_adapters/postgresql/oid/xml
  • + +
  • active_record/connection_adapters/postgresql/oid/type_map_initializer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/quoting_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/quoting_rb.html new file mode 100644 index 0000000000..73bd8d7c54 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/quoting_rb.html @@ -0,0 +1,85 @@ +--- +title: quoting.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity_rb.html new file mode 100644 index 0000000000..d54e35d6b5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity_rb.html @@ -0,0 +1,72 @@ +--- +title: referential_integrity.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation_rb.html new file mode 100644 index 0000000000..89ae59c96a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_creation_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_creation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions_rb.html new file mode 100644 index 0000000000..78673b860c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions_rb.html @@ -0,0 +1,85 @@ +--- +title: schema_definitions.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper_rb.html new file mode 100644 index 0000000000..cfa6bc173f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_dumper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements_rb.html new file mode 100644 index 0000000000..7229ee1b67 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements_rb.html @@ -0,0 +1,74 @@ +--- +title: schema_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata_rb.html new file mode 100644 index 0000000000..3f138a402f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/type_metadata_rb.html @@ -0,0 +1,79 @@ +--- +title: type_metadata.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/utils_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/utils_rb.html new file mode 100644 index 0000000000..7a65055f3e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql/utils_rb.html @@ -0,0 +1,72 @@ +--- +title: utils.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql_adapter_rb.html new file mode 100644 index 0000000000..0c755ab468 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/postgresql_adapter_rb.html @@ -0,0 +1,121 @@ +--- +title: postgresql_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pg
  • + +
  • active_support/core_ext/object/try
  • + +
  • active_record/connection_adapters/abstract_adapter
  • + +
  • active_record/connection_adapters/statement_pool
  • + +
  • active_record/connection_adapters/postgresql/column
  • + +
  • active_record/connection_adapters/postgresql/database_statements
  • + +
  • active_record/connection_adapters/postgresql/explain_pretty_printer
  • + +
  • active_record/connection_adapters/postgresql/oid
  • + +
  • active_record/connection_adapters/postgresql/quoting
  • + +
  • active_record/connection_adapters/postgresql/referential_integrity
  • + +
  • active_record/connection_adapters/postgresql/schema_creation
  • + +
  • active_record/connection_adapters/postgresql/schema_definitions
  • + +
  • active_record/connection_adapters/postgresql/schema_dumper
  • + +
  • active_record/connection_adapters/postgresql/schema_statements
  • + +
  • active_record/connection_adapters/postgresql/type_metadata
  • + +
  • active_record/connection_adapters/postgresql/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/schema_cache_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/schema_cache_rb.html new file mode 100644 index 0000000000..8ea3447fda --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/schema_cache_rb.html @@ -0,0 +1,85 @@ +--- +title: schema_cache.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/file/atomic
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sql_type_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sql_type_metadata_rb.html new file mode 100644 index 0000000000..fca356ad02 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sql_type_metadata_rb.html @@ -0,0 +1,77 @@ +--- +title: sql_type_metadata.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements_rb.html new file mode 100644 index 0000000000..84826b357c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/database_statements_rb.html @@ -0,0 +1,76 @@ +--- +title: database_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer_rb.html new file mode 100644 index 0000000000..52ef017bc6 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer_rb.html @@ -0,0 +1,72 @@ +--- +title: explain_pretty_printer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/quoting_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/quoting_rb.html new file mode 100644 index 0000000000..125c35b240 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/quoting_rb.html @@ -0,0 +1,72 @@ +--- +title: quoting.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_creation_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_creation_rb.html new file mode 100644 index 0000000000..c18b39eeae --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_creation_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_creation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions_rb.html new file mode 100644 index 0000000000..ee48a87a29 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_definitions_rb.html @@ -0,0 +1,79 @@ +--- +title: schema_definitions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_dumper_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_dumper_rb.html new file mode 100644 index 0000000000..f767950e85 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_dumper_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_dumper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements_rb.html new file mode 100644 index 0000000000..b46739c18e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3/schema_statements_rb.html @@ -0,0 +1,72 @@ +--- +title: schema_statements.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3_adapter_rb.html new file mode 100644 index 0000000000..ba48572b9f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/sqlite3_adapter_rb.html @@ -0,0 +1,109 @@ +--- +title: sqlite3_adapter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/connection_adapters/abstract_adapter
  • + +
  • active_record/connection_adapters/statement_pool
  • + +
  • active_record/connection_adapters/sqlite3/explain_pretty_printer
  • + +
  • active_record/connection_adapters/sqlite3/quoting
  • + +
  • active_record/connection_adapters/sqlite3/database_statements
  • + +
  • active_record/connection_adapters/sqlite3/schema_creation
  • + +
  • active_record/connection_adapters/sqlite3/schema_definitions
  • + +
  • active_record/connection_adapters/sqlite3/schema_dumper
  • + +
  • active_record/connection_adapters/sqlite3/schema_statements
  • + +
  • sqlite3
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters/statement_pool_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters/statement_pool_rb.html new file mode 100644 index 0000000000..295bb57157 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters/statement_pool_rb.html @@ -0,0 +1,70 @@ +--- +title: statement_pool.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_adapters_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_adapters_rb.html new file mode 100644 index 0000000000..3a513c47b7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_adapters_rb.html @@ -0,0 +1,70 @@ +--- +title: connection_adapters.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/connection_handling_rb.html b/src/7.0/files/activerecord/lib/active_record/connection_handling_rb.html new file mode 100644 index 0000000000..823cf9f896 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/connection_handling_rb.html @@ -0,0 +1,74 @@ +--- +title: connection_handling.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/core_rb.html b/src/7.0/files/activerecord/lib/active_record/core_rb.html new file mode 100644 index 0000000000..52dd7740bb --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/core_rb.html @@ -0,0 +1,101 @@ +--- +title: core.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/parameter_filter
  • + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/counter_cache_rb.html b/src/7.0/files/activerecord/lib/active_record/counter_cache_rb.html new file mode 100644 index 0000000000..c0488829e0 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/counter_cache_rb.html @@ -0,0 +1,72 @@ +--- +title: counter_cache.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/database_configurations/connection_url_resolver_rb.html b/src/7.0/files/activerecord/lib/active_record/database_configurations/connection_url_resolver_rb.html new file mode 100644 index 0000000000..07baff7261 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/database_configurations/connection_url_resolver_rb.html @@ -0,0 +1,89 @@ +--- +title: connection_url_resolver.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • uri
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/database_configurations/database_config_rb.html b/src/7.0/files/activerecord/lib/active_record/database_configurations/database_config_rb.html new file mode 100644 index 0000000000..dba7b79aa7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/database_configurations/database_config_rb.html @@ -0,0 +1,77 @@ +--- +title: database_config.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/database_configurations/hash_config_rb.html b/src/7.0/files/activerecord/lib/active_record/database_configurations/hash_config_rb.html new file mode 100644 index 0000000000..3e566f43f1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/database_configurations/hash_config_rb.html @@ -0,0 +1,77 @@ +--- +title: hash_config.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/database_configurations/url_config_rb.html b/src/7.0/files/activerecord/lib/active_record/database_configurations/url_config_rb.html new file mode 100644 index 0000000000..824120fbc5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/database_configurations/url_config_rb.html @@ -0,0 +1,77 @@ +--- +title: url_config.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/database_configurations_rb.html b/src/7.0/files/activerecord/lib/active_record/database_configurations_rb.html new file mode 100644 index 0000000000..d86405b49b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/database_configurations_rb.html @@ -0,0 +1,97 @@ +--- +title: database_configurations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • uri
  • + +
  • active_record/database_configurations/database_config
  • + +
  • active_record/database_configurations/hash_config
  • + +
  • active_record/database_configurations/url_config
  • + +
  • active_record/database_configurations/connection_url_resolver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/delegated_type_rb.html b/src/7.0/files/activerecord/lib/active_record/delegated_type_rb.html new file mode 100644 index 0000000000..47759145bc --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/delegated_type_rb.html @@ -0,0 +1,78 @@ +--- +title: delegated_type.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/inquiry
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/destroy_association_async_job_rb.html b/src/7.0/files/activerecord/lib/active_record/destroy_association_async_job_rb.html new file mode 100644 index 0000000000..f3db2b7741 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/destroy_association_async_job_rb.html @@ -0,0 +1,79 @@ +--- +title: destroy_association_async_job.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/disable_joins_association_relation_rb.html b/src/7.0/files/activerecord/lib/active_record/disable_joins_association_relation_rb.html new file mode 100644 index 0000000000..711627054d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/disable_joins_association_relation_rb.html @@ -0,0 +1,68 @@ +--- +title: disable_joins_association_relation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/dynamic_matchers_rb.html b/src/7.0/files/activerecord/lib/active_record/dynamic_matchers_rb.html new file mode 100644 index 0000000000..004109bd55 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/dynamic_matchers_rb.html @@ -0,0 +1,81 @@ +--- +title: dynamic_matchers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/cipher/aes256_gcm_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/cipher/aes256_gcm_rb.html new file mode 100644 index 0000000000..dca7e41bb8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/cipher/aes256_gcm_rb.html @@ -0,0 +1,91 @@ +--- +title: aes256_gcm.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • openssl
  • + +
  • base64
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/cipher_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/cipher_rb.html new file mode 100644 index 0000000000..74885f6a64 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/cipher_rb.html @@ -0,0 +1,77 @@ +--- +title: cipher.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/config_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/config_rb.html new file mode 100644 index 0000000000..3094cc7f58 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/config_rb.html @@ -0,0 +1,77 @@ +--- +title: config.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/configurable_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/configurable_rb.html new file mode 100644 index 0000000000..931aae6b7c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/configurable_rb.html @@ -0,0 +1,72 @@ +--- +title: configurable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/context_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/context_rb.html new file mode 100644 index 0000000000..b0d188d5d5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/context_rb.html @@ -0,0 +1,77 @@ +--- +title: context.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/contexts_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/contexts_rb.html new file mode 100644 index 0000000000..ae72d629a1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/contexts_rb.html @@ -0,0 +1,72 @@ +--- +title: contexts.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/derived_secret_key_provider_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/derived_secret_key_provider_rb.html new file mode 100644 index 0000000000..c5503006ec --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/derived_secret_key_provider_rb.html @@ -0,0 +1,77 @@ +--- +title: derived_secret_key_provider.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/deterministic_key_provider_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/deterministic_key_provider_rb.html new file mode 100644 index 0000000000..56b03ada72 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/deterministic_key_provider_rb.html @@ -0,0 +1,77 @@ +--- +title: deterministic_key_provider.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/encryptable_record_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/encryptable_record_rb.html new file mode 100644 index 0000000000..6ce5a2cd8e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/encryptable_record_rb.html @@ -0,0 +1,72 @@ +--- +title: encryptable_record.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_attribute_type_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_attribute_type_rb.html new file mode 100644 index 0000000000..427a6c4619 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_attribute_type_rb.html @@ -0,0 +1,77 @@ +--- +title: encrypted_attribute_type.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_fixtures_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_fixtures_rb.html new file mode 100644 index 0000000000..7865526ff4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/encrypted_fixtures_rb.html @@ -0,0 +1,72 @@ +--- +title: encrypted_fixtures.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/encrypting_only_encryptor_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/encrypting_only_encryptor_rb.html new file mode 100644 index 0000000000..2eec777d79 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/encrypting_only_encryptor_rb.html @@ -0,0 +1,77 @@ +--- +title: encrypting_only_encryptor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/encryptor_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/encryptor_rb.html new file mode 100644 index 0000000000..a475e36239 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/encryptor_rb.html @@ -0,0 +1,89 @@ +--- +title: encryptor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • openssl
  • + +
  • zlib
  • + +
  • active_support/core_ext/numeric
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/envelope_encryption_key_provider_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/envelope_encryption_key_provider_rb.html new file mode 100644 index 0000000000..d00a48a9e5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/envelope_encryption_key_provider_rb.html @@ -0,0 +1,77 @@ +--- +title: envelope_encryption_key_provider.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/errors_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/errors_rb.html new file mode 100644 index 0000000000..9aa315cf06 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/errors_rb.html @@ -0,0 +1,91 @@ +--- +title: errors.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_queries_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_queries_rb.html new file mode 100644 index 0000000000..0aa76eaba1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_queries_rb.html @@ -0,0 +1,93 @@ +--- +title: extended_deterministic_queries.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_uniqueness_validator_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_uniqueness_validator_rb.html new file mode 100644 index 0000000000..8faf0531cf --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/extended_deterministic_uniqueness_validator_rb.html @@ -0,0 +1,74 @@ +--- +title: extended_deterministic_uniqueness_validator.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/key_generator_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/key_generator_rb.html new file mode 100644 index 0000000000..68ee9889ac --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/key_generator_rb.html @@ -0,0 +1,87 @@ +--- +title: key_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/key_provider_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/key_provider_rb.html new file mode 100644 index 0000000000..f1432e5be7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/key_provider_rb.html @@ -0,0 +1,77 @@ +--- +title: key_provider.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/key_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/key_rb.html new file mode 100644 index 0000000000..7a159db9c3 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/key_rb.html @@ -0,0 +1,79 @@ +--- +title: key.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/message_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/message_rb.html new file mode 100644 index 0000000000..2307227a35 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/message_rb.html @@ -0,0 +1,79 @@ +--- +title: message.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/message_serializer_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/message_serializer_rb.html new file mode 100644 index 0000000000..c38ea9a31c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/message_serializer_rb.html @@ -0,0 +1,79 @@ +--- +title: message_serializer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/null_encryptor_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/null_encryptor_rb.html new file mode 100644 index 0000000000..d7a21854fc --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/null_encryptor_rb.html @@ -0,0 +1,77 @@ +--- +title: null_encryptor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/properties_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/properties_rb.html new file mode 100644 index 0000000000..673f1694d3 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/properties_rb.html @@ -0,0 +1,79 @@ +--- +title: properties.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/read_only_null_encryptor_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/read_only_null_encryptor_rb.html new file mode 100644 index 0000000000..dfe95a7084 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/read_only_null_encryptor_rb.html @@ -0,0 +1,79 @@ +--- +title: read_only_null_encryptor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption/scheme_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption/scheme_rb.html new file mode 100644 index 0000000000..13ef6e48bf --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption/scheme_rb.html @@ -0,0 +1,79 @@ +--- +title: scheme.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/encryption_rb.html b/src/7.0/files/activerecord/lib/active_record/encryption_rb.html new file mode 100644 index 0000000000..c4f93f9f33 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/encryption_rb.html @@ -0,0 +1,87 @@ +--- +title: encryption.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module
  • + +
  • active_support/core_ext/array
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/enum_rb.html b/src/7.0/files/activerecord/lib/active_record/enum_rb.html new file mode 100644 index 0000000000..15ee15a804 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/enum_rb.html @@ -0,0 +1,82 @@ +--- +title: enum.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/object/deep_dup
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/errors_rb.html b/src/7.0/files/activerecord/lib/active_record/errors_rb.html new file mode 100644 index 0000000000..8f52b29ca1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/errors_rb.html @@ -0,0 +1,175 @@ +--- +title: errors.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/explain_rb.html b/src/7.0/files/activerecord/lib/active_record/explain_rb.html new file mode 100644 index 0000000000..4dd543fa25 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/explain_rb.html @@ -0,0 +1,80 @@ +--- +title: explain.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/explain_registry
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/explain_registry_rb.html b/src/7.0/files/activerecord/lib/active_record/explain_registry_rb.html new file mode 100644 index 0000000000..01b1bd6fce --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/explain_registry_rb.html @@ -0,0 +1,78 @@ +--- +title: explain_registry.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/explain_subscriber_rb.html b/src/7.0/files/activerecord/lib/active_record/explain_subscriber_rb.html new file mode 100644 index 0000000000..d2b5fc0843 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/explain_subscriber_rb.html @@ -0,0 +1,80 @@ +--- +title: explain_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/notifications
  • + +
  • active_record/explain_registry
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixture_set/file_rb.html b/src/7.0/files/activerecord/lib/active_record/fixture_set/file_rb.html new file mode 100644 index 0000000000..3adfc12f49 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixture_set/file_rb.html @@ -0,0 +1,85 @@ +--- +title: file.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/configuration_file
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixture_set/model_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/fixture_set/model_metadata_rb.html new file mode 100644 index 0000000000..c563afa85f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixture_set/model_metadata_rb.html @@ -0,0 +1,75 @@ +--- +title: model_metadata.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixture_set/render_context_rb.html b/src/7.0/files/activerecord/lib/active_record/fixture_set/render_context_rb.html new file mode 100644 index 0000000000..d2a751f168 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixture_set/render_context_rb.html @@ -0,0 +1,81 @@ +--- +title: render_context.rb +layout: default +--- +
+ + +
+
+ +
+ +

NOTE: This class has to be defined in compact style in order for rendering context subclassing to work correctly.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixture_set/table_row_rb.html b/src/7.0/files/activerecord/lib/active_record/fixture_set/table_row_rb.html new file mode 100644 index 0000000000..c44e194ffe --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixture_set/table_row_rb.html @@ -0,0 +1,75 @@ +--- +title: table_row.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixture_set/table_rows_rb.html b/src/7.0/files/activerecord/lib/active_record/fixture_set/table_rows_rb.html new file mode 100644 index 0000000000..d576579192 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixture_set/table_rows_rb.html @@ -0,0 +1,85 @@ +--- +title: table_rows.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/fixture_set/table_row
  • + +
  • active_record/fixture_set/model_metadata
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/fixtures_rb.html b/src/7.0/files/activerecord/lib/active_record/fixtures_rb.html new file mode 100644 index 0000000000..5145637b59 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/fixtures_rb.html @@ -0,0 +1,105 @@ +--- +title: fixtures.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • erb
  • + +
  • yaml
  • + +
  • zlib
  • + +
  • set
  • + +
  • active_support/dependencies
  • + +
  • active_support/core_ext/digest/uuid
  • + +
  • active_record/fixture_set/file
  • + +
  • active_record/fixture_set/render_context
  • + +
  • active_record/fixture_set/table_rows
  • + +
  • active_record/test_fixtures
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/future_result_rb.html b/src/7.0/files/activerecord/lib/active_record/future_result_rb.html new file mode 100644 index 0000000000..1c2f0f2ebd --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/future_result_rb.html @@ -0,0 +1,81 @@ +--- +title: future_result.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/gem_version_rb.html b/src/7.0/files/activerecord/lib/active_record/gem_version_rb.html new file mode 100644 index 0000000000..e60bfdecc9 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/inheritance_rb.html b/src/7.0/files/activerecord/lib/active_record/inheritance_rb.html new file mode 100644 index 0000000000..3dd0e21f81 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/inheritance_rb.html @@ -0,0 +1,82 @@ +--- +title: inheritance.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/insert_all_rb.html b/src/7.0/files/activerecord/lib/active_record/insert_all_rb.html new file mode 100644 index 0000000000..c9b50c93b5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/insert_all_rb.html @@ -0,0 +1,80 @@ +--- +title: insert_all.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/integration_rb.html b/src/7.0/files/activerecord/lib/active_record/integration_rb.html new file mode 100644 index 0000000000..6b05d97ec1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/integration_rb.html @@ -0,0 +1,82 @@ +--- +title: integration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/internal_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/internal_metadata_rb.html new file mode 100644 index 0000000000..07d3d8e92e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/internal_metadata_rb.html @@ -0,0 +1,78 @@ +--- +title: internal_metadata.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/scoping/default
  • + +
  • active_record/scoping/named
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/legacy_yaml_adapter_rb.html b/src/7.0/files/activerecord/lib/active_record/legacy_yaml_adapter_rb.html new file mode 100644 index 0000000000..cc07ba53e0 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/legacy_yaml_adapter_rb.html @@ -0,0 +1,68 @@ +--- +title: legacy_yaml_adapter.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/locking/optimistic_rb.html b/src/7.0/files/activerecord/lib/active_record/locking/optimistic_rb.html new file mode 100644 index 0000000000..7b34344585 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/locking/optimistic_rb.html @@ -0,0 +1,74 @@ +--- +title: optimistic.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/locking/pessimistic_rb.html b/src/7.0/files/activerecord/lib/active_record/locking/pessimistic_rb.html new file mode 100644 index 0000000000..519b01c6ab --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/locking/pessimistic_rb.html @@ -0,0 +1,72 @@ +--- +title: pessimistic.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/log_subscriber_rb.html b/src/7.0/files/activerecord/lib/active_record/log_subscriber_rb.html new file mode 100644 index 0000000000..13c07ddc3f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/log_subscriber_rb.html @@ -0,0 +1,79 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver/session_rb.html b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver/session_rb.html new file mode 100644 index 0000000000..ecdee2243a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver/session_rb.html @@ -0,0 +1,77 @@ +--- +title: session.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver_rb.html b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver_rb.html new file mode 100644 index 0000000000..27bdaf547f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector/resolver_rb.html @@ -0,0 +1,89 @@ +--- +title: resolver.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/middleware/database_selector/resolver/session
  • + +
  • active_support/core_ext/numeric/time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/middleware/database_selector_rb.html b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector_rb.html new file mode 100644 index 0000000000..1e9bf55ba4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/middleware/database_selector_rb.html @@ -0,0 +1,87 @@ +--- +title: database_selector.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/middleware/database_selector/resolver
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/middleware/shard_selector_rb.html b/src/7.0/files/activerecord/lib/active_record/middleware/shard_selector_rb.html new file mode 100644 index 0000000000..06789ed16d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/middleware/shard_selector_rb.html @@ -0,0 +1,79 @@ +--- +title: shard_selector.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/migration/command_recorder_rb.html b/src/7.0/files/activerecord/lib/active_record/migration/command_recorder_rb.html new file mode 100644 index 0000000000..604f933da8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/migration/command_recorder_rb.html @@ -0,0 +1,77 @@ +--- +title: command_recorder.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/migration/compatibility_rb.html b/src/7.0/files/activerecord/lib/active_record/migration/compatibility_rb.html new file mode 100644 index 0000000000..504c1e6264 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/migration/compatibility_rb.html @@ -0,0 +1,105 @@ +--- +title: compatibility.rb +layout: default +--- +
+ + +
+ + +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/migration/join_table_rb.html b/src/7.0/files/activerecord/lib/active_record/migration/join_table_rb.html new file mode 100644 index 0000000000..31171fac3f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/migration/join_table_rb.html @@ -0,0 +1,75 @@ +--- +title: join_table.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/migration_rb.html b/src/7.0/files/activerecord/lib/active_record/migration_rb.html new file mode 100644 index 0000000000..ccc4a4f9cb --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/migration_rb.html @@ -0,0 +1,109 @@ +--- +title: migration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • benchmark
  • + +
  • set
  • + +
  • zlib
  • + +
  • active_support/core_ext/array/access
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/actionable_error
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/model_schema_rb.html b/src/7.0/files/activerecord/lib/active_record/model_schema_rb.html new file mode 100644 index 0000000000..e438c918ba --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/model_schema_rb.html @@ -0,0 +1,84 @@ +--- +title: model_schema.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/nested_attributes_rb.html b/src/7.0/files/activerecord/lib/active_record/nested_attributes_rb.html new file mode 100644 index 0000000000..92ff68dcc5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/nested_attributes_rb.html @@ -0,0 +1,91 @@ +--- +title: nested_attributes.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/no_touching_rb.html b/src/7.0/files/activerecord/lib/active_record/no_touching_rb.html new file mode 100644 index 0000000000..74e6fd609a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/no_touching_rb.html @@ -0,0 +1,74 @@ +--- +title: no_touching.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/null_relation_rb.html b/src/7.0/files/activerecord/lib/active_record/null_relation_rb.html new file mode 100644 index 0000000000..0e71a62e29 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/null_relation_rb.html @@ -0,0 +1,68 @@ +--- +title: null_relation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/persistence_rb.html b/src/7.0/files/activerecord/lib/active_record/persistence_rb.html new file mode 100644 index 0000000000..b62654ea64 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/persistence_rb.html @@ -0,0 +1,82 @@ +--- +title: persistence.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/insert_all
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/query_cache_rb.html b/src/7.0/files/activerecord/lib/active_record/query_cache_rb.html new file mode 100644 index 0000000000..7dca9c5a36 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/query_cache_rb.html @@ -0,0 +1,77 @@ +--- +title: query_cache.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/query_logs_rb.html b/src/7.0/files/activerecord/lib/active_record/query_logs_rb.html new file mode 100644 index 0000000000..be05a00164 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/query_logs_rb.html @@ -0,0 +1,80 @@ +--- +title: query_logs.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors_per_thread
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/querying_rb.html b/src/7.0/files/activerecord/lib/active_record/querying_rb.html new file mode 100644 index 0000000000..1b4c0377b2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/querying_rb.html @@ -0,0 +1,72 @@ +--- +title: querying.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/railtie_rb.html b/src/7.0/files/activerecord/lib/active_record/railtie_rb.html new file mode 100644 index 0000000000..1ceb294031 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/railtie_rb.html @@ -0,0 +1,111 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record
  • + +
  • rails
  • + +
  • active_support/core_ext/object/try
  • + +
  • active_model/railtie
  • + +
  • action_controller/railtie
  • + +
  • active_record/railties/console_sandbox
  • + +
  • active_record/base
  • + +
  • active_record/base
  • + +
  • active_record/relation/record_fetch_warning
  • + +
  • active_record/railties/controller_runtime
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/railties/console_sandbox_rb.html b/src/7.0/files/activerecord/lib/active_record/railties/console_sandbox_rb.html new file mode 100644 index 0000000000..82d9b83cf2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/railties/console_sandbox_rb.html @@ -0,0 +1,70 @@ +--- +title: console_sandbox.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/railties/controller_runtime_rb.html b/src/7.0/files/activerecord/lib/active_record/railties/controller_runtime_rb.html new file mode 100644 index 0000000000..a496b7b229 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/railties/controller_runtime_rb.html @@ -0,0 +1,78 @@ +--- +title: controller_runtime.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attr_internal
  • + +
  • active_record/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/readonly_attributes_rb.html b/src/7.0/files/activerecord/lib/active_record/readonly_attributes_rb.html new file mode 100644 index 0000000000..a956fbe45f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/readonly_attributes_rb.html @@ -0,0 +1,72 @@ +--- +title: readonly_attributes.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/reflection_rb.html b/src/7.0/files/activerecord/lib/active_record/reflection_rb.html new file mode 100644 index 0000000000..78cf6be9a1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/reflection_rb.html @@ -0,0 +1,91 @@ +--- +title: reflection.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/batches/batch_enumerator_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/batches/batch_enumerator_rb.html new file mode 100644 index 0000000000..adba720e97 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/batches/batch_enumerator_rb.html @@ -0,0 +1,77 @@ +--- +title: batch_enumerator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/batches_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/batches_rb.html new file mode 100644 index 0000000000..f36f25abc5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/batches_rb.html @@ -0,0 +1,78 @@ +--- +title: batches.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/relation/batches/batch_enumerator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/calculations_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/calculations_rb.html new file mode 100644 index 0000000000..1acc6d5a0e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/calculations_rb.html @@ -0,0 +1,84 @@ +--- +title: calculations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/delegation_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/delegation_rb.html new file mode 100644 index 0000000000..46a5cfc0c0 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/delegation_rb.html @@ -0,0 +1,80 @@ +--- +title: delegation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mutex_m
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/finder_methods_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/finder_methods_rb.html new file mode 100644 index 0000000000..073b5ee4dc --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/finder_methods_rb.html @@ -0,0 +1,80 @@ +--- +title: finder_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/from_clause_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/from_clause_rb.html new file mode 100644 index 0000000000..0150d3d9fa --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/from_clause_rb.html @@ -0,0 +1,75 @@ +--- +title: from_clause.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/merger_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/merger_rb.html new file mode 100644 index 0000000000..68762719e8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/merger_rb.html @@ -0,0 +1,85 @@ +--- +title: merger.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/array_handler_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/array_handler_rb.html new file mode 100644 index 0000000000..b2a3a9e22d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/array_handler_rb.html @@ -0,0 +1,78 @@ +--- +title: array_handler.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/association_query_value_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/association_query_value_rb.html new file mode 100644 index 0000000000..cb44ae8789 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/association_query_value_rb.html @@ -0,0 +1,68 @@ +--- +title: association_query_value.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler_rb.html new file mode 100644 index 0000000000..d388451f05 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/basic_object_handler_rb.html @@ -0,0 +1,68 @@ +--- +title: basic_object_handler.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value_rb.html new file mode 100644 index 0000000000..4eea4d8b46 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/polymorphic_array_value_rb.html @@ -0,0 +1,68 @@ +--- +title: polymorphic_array_value.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/range_handler_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/range_handler_rb.html new file mode 100644 index 0000000000..a539bd4a5d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/range_handler_rb.html @@ -0,0 +1,68 @@ +--- +title: range_handler.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/relation_handler_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/relation_handler_rb.html new file mode 100644 index 0000000000..c6b42c25c8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder/relation_handler_rb.html @@ -0,0 +1,68 @@ +--- +title: relation_handler.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder_rb.html new file mode 100644 index 0000000000..ac67d0241f --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/predicate_builder_rb.html @@ -0,0 +1,95 @@ +--- +title: predicate_builder.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/relation/predicate_builder/array_handler
  • + +
  • active_record/relation/predicate_builder/basic_object_handler
  • + +
  • active_record/relation/predicate_builder/range_handler
  • + +
  • active_record/relation/predicate_builder/relation_handler
  • + +
  • active_record/relation/predicate_builder/association_query_value
  • + +
  • active_record/relation/predicate_builder/polymorphic_array_value
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/query_attribute_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/query_attribute_rb.html new file mode 100644 index 0000000000..a500e5570d --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/query_attribute_rb.html @@ -0,0 +1,83 @@ +--- +title: query_attribute.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/query_methods_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/query_methods_rb.html new file mode 100644 index 0000000000..9a68012b9a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/query_methods_rb.html @@ -0,0 +1,103 @@ +--- +title: query_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/relation/from_clause
  • + +
  • active_record/relation/query_attribute
  • + +
  • active_record/relation/where_clause
  • + +
  • active_model/forbidden_attributes_protection
  • + +
  • active_support/core_ext/array/wrap
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/record_fetch_warning_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/record_fetch_warning_rb.html new file mode 100644 index 0000000000..8cb20e68e5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/record_fetch_warning_rb.html @@ -0,0 +1,79 @@ +--- +title: record_fetch_warning.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/spawn_methods_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/spawn_methods_rb.html new file mode 100644 index 0000000000..40af98bb8e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/spawn_methods_rb.html @@ -0,0 +1,89 @@ +--- +title: spawn_methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/hash/slice
  • + +
  • active_record/relation/merger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation/where_clause_rb.html b/src/7.0/files/activerecord/lib/active_record/relation/where_clause_rb.html new file mode 100644 index 0000000000..da99e69ef1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation/where_clause_rb.html @@ -0,0 +1,87 @@ +--- +title: where_clause.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/relation_rb.html b/src/7.0/files/activerecord/lib/active_record/relation_rb.html new file mode 100644 index 0000000000..d604e6ab8c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/relation_rb.html @@ -0,0 +1,81 @@ +--- +title: relation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/result_rb.html b/src/7.0/files/activerecord/lib/active_record/result_rb.html new file mode 100644 index 0000000000..c110b0b245 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/result_rb.html @@ -0,0 +1,75 @@ +--- +title: result.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/runtime_registry_rb.html b/src/7.0/files/activerecord/lib/active_record/runtime_registry_rb.html new file mode 100644 index 0000000000..933e1c88af --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/runtime_registry_rb.html @@ -0,0 +1,70 @@ +--- +title: runtime_registry.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/sanitization_rb.html b/src/7.0/files/activerecord/lib/active_record/sanitization_rb.html new file mode 100644 index 0000000000..dda3ab5f30 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/sanitization_rb.html @@ -0,0 +1,72 @@ +--- +title: sanitization.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/schema_dumper_rb.html b/src/7.0/files/activerecord/lib/active_record/schema_dumper_rb.html new file mode 100644 index 0000000000..a2304e36dc --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/schema_dumper_rb.html @@ -0,0 +1,76 @@ +--- +title: schema_dumper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/schema_migration_rb.html b/src/7.0/files/activerecord/lib/active_record/schema_migration_rb.html new file mode 100644 index 0000000000..3d4d867824 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/schema_migration_rb.html @@ -0,0 +1,78 @@ +--- +title: schema_migration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/scoping/default
  • + +
  • active_record/scoping/named
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/schema_rb.html b/src/7.0/files/activerecord/lib/active_record/schema_rb.html new file mode 100644 index 0000000000..e944bdddf4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/schema_rb.html @@ -0,0 +1,81 @@ +--- +title: schema.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/scoping/default_rb.html b/src/7.0/files/activerecord/lib/active_record/scoping/default_rb.html new file mode 100644 index 0000000000..ac37ed4138 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/scoping/default_rb.html @@ -0,0 +1,74 @@ +--- +title: default.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/scoping/named_rb.html b/src/7.0/files/activerecord/lib/active_record/scoping/named_rb.html new file mode 100644 index 0000000000..6f7f91e7cd --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/scoping/named_rb.html @@ -0,0 +1,74 @@ +--- +title: named.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/scoping_rb.html b/src/7.0/files/activerecord/lib/active_record/scoping_rb.html new file mode 100644 index 0000000000..3e88d7c117 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/scoping_rb.html @@ -0,0 +1,80 @@ +--- +title: scoping.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/secure_token_rb.html b/src/7.0/files/activerecord/lib/active_record/secure_token_rb.html new file mode 100644 index 0000000000..d897387372 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/secure_token_rb.html @@ -0,0 +1,87 @@ +--- +title: secure_token.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/securerandom
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/serialization_rb.html b/src/7.0/files/activerecord/lib/active_record/serialization_rb.html new file mode 100644 index 0000000000..9935e70cca --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/serialization_rb.html @@ -0,0 +1,70 @@ +--- +title: serialization.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/signed_id_rb.html b/src/7.0/files/activerecord/lib/active_record/signed_id_rb.html new file mode 100644 index 0000000000..dbe9b2dc99 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/signed_id_rb.html @@ -0,0 +1,74 @@ +--- +title: signed_id.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/statement_cache_rb.html b/src/7.0/files/activerecord/lib/active_record/statement_cache_rb.html new file mode 100644 index 0000000000..2904b448f5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/statement_cache_rb.html @@ -0,0 +1,79 @@ +--- +title: statement_cache.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/store_rb.html b/src/7.0/files/activerecord/lib/active_record/store_rb.html new file mode 100644 index 0000000000..1d22ebe1b9 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/store_rb.html @@ -0,0 +1,82 @@ +--- +title: store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/suppressor_rb.html b/src/7.0/files/activerecord/lib/active_record/suppressor_rb.html new file mode 100644 index 0000000000..da6c69fb82 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/suppressor_rb.html @@ -0,0 +1,74 @@ +--- +title: suppressor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/table_metadata_rb.html b/src/7.0/files/activerecord/lib/active_record/table_metadata_rb.html new file mode 100644 index 0000000000..899dc45a39 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/table_metadata_rb.html @@ -0,0 +1,70 @@ +--- +title: table_metadata.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/tasks/database_tasks_rb.html b/src/7.0/files/activerecord/lib/active_record/tasks/database_tasks_rb.html new file mode 100644 index 0000000000..dfdea28431 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/tasks/database_tasks_rb.html @@ -0,0 +1,91 @@ +--- +title: database_tasks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/database_configurations
  • + +
  • active_record/schema_dumper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/tasks/mysql_database_tasks_rb.html b/src/7.0/files/activerecord/lib/active_record/tasks/mysql_database_tasks_rb.html new file mode 100644 index 0000000000..1b84a6aece --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/tasks/mysql_database_tasks_rb.html @@ -0,0 +1,70 @@ +--- +title: mysql_database_tasks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/tasks/postgresql_database_tasks_rb.html b/src/7.0/files/activerecord/lib/active_record/tasks/postgresql_database_tasks_rb.html new file mode 100644 index 0000000000..a77c7d5e6c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/tasks/postgresql_database_tasks_rb.html @@ -0,0 +1,78 @@ +--- +title: postgresql_database_tasks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • tempfile
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/tasks/sqlite_database_tasks_rb.html b/src/7.0/files/activerecord/lib/active_record/tasks/sqlite_database_tasks_rb.html new file mode 100644 index 0000000000..da04c4f4f5 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/tasks/sqlite_database_tasks_rb.html @@ -0,0 +1,78 @@ +--- +title: sqlite_database_tasks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/test_databases_rb.html b/src/7.0/files/activerecord/lib/active_record/test_databases_rb.html new file mode 100644 index 0000000000..78f1dcd70a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/test_databases_rb.html @@ -0,0 +1,82 @@ +--- +title: test_databases.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/testing/parallelization
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/test_fixtures_rb.html b/src/7.0/files/activerecord/lib/active_record/test_fixtures_rb.html new file mode 100644 index 0000000000..681e02a9aa --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/test_fixtures_rb.html @@ -0,0 +1,82 @@ +--- +title: test_fixtures.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/timestamp_rb.html b/src/7.0/files/activerecord/lib/active_record/timestamp_rb.html new file mode 100644 index 0000000000..6125137601 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/timestamp_rb.html @@ -0,0 +1,70 @@ +--- +title: timestamp.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/touch_later_rb.html b/src/7.0/files/activerecord/lib/active_record/touch_later_rb.html new file mode 100644 index 0000000000..a5e1be833b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/touch_later_rb.html @@ -0,0 +1,70 @@ +--- +title: touch_later.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/transactions_rb.html b/src/7.0/files/activerecord/lib/active_record/transactions_rb.html new file mode 100644 index 0000000000..68475f468e --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/transactions_rb.html @@ -0,0 +1,72 @@ +--- +title: transactions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/translation_rb.html b/src/7.0/files/activerecord/lib/active_record/translation_rb.html new file mode 100644 index 0000000000..e28f0ccc2a --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/translation_rb.html @@ -0,0 +1,70 @@ +--- +title: translation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/adapter_specific_registry_rb.html b/src/7.0/files/activerecord/lib/active_record/type/adapter_specific_registry_rb.html new file mode 100644 index 0000000000..52f984dca9 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/adapter_specific_registry_rb.html @@ -0,0 +1,78 @@ +--- +title: adapter_specific_registry.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type/registry
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/date_rb.html b/src/7.0/files/activerecord/lib/active_record/type/date_rb.html new file mode 100644 index 0000000000..e49db083c8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/date_rb.html @@ -0,0 +1,77 @@ +--- +title: date.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/date_time_rb.html b/src/7.0/files/activerecord/lib/active_record/type/date_time_rb.html new file mode 100644 index 0000000000..26f63be31c --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/date_time_rb.html @@ -0,0 +1,77 @@ +--- +title: date_time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/decimal_without_scale_rb.html b/src/7.0/files/activerecord/lib/active_record/type/decimal_without_scale_rb.html new file mode 100644 index 0000000000..a4b2f79387 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/decimal_without_scale_rb.html @@ -0,0 +1,70 @@ +--- +title: decimal_without_scale.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/hash_lookup_type_map_rb.html b/src/7.0/files/activerecord/lib/active_record/type/hash_lookup_type_map_rb.html new file mode 100644 index 0000000000..bfbe2b76c2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/hash_lookup_type_map_rb.html @@ -0,0 +1,70 @@ +--- +title: hash_lookup_type_map.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/internal/timezone_rb.html b/src/7.0/files/activerecord/lib/active_record/type/internal/timezone_rb.html new file mode 100644 index 0000000000..a128b6ad31 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/internal/timezone_rb.html @@ -0,0 +1,74 @@ +--- +title: timezone.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/json_rb.html b/src/7.0/files/activerecord/lib/active_record/type/json_rb.html new file mode 100644 index 0000000000..92630f7417 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/json_rb.html @@ -0,0 +1,81 @@ +--- +title: json.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/serialized_rb.html b/src/7.0/files/activerecord/lib/active_record/type/serialized_rb.html new file mode 100644 index 0000000000..e4ebb78d33 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/serialized_rb.html @@ -0,0 +1,76 @@ +--- +title: serialized.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/text_rb.html b/src/7.0/files/activerecord/lib/active_record/type/text_rb.html new file mode 100644 index 0000000000..8cadc06327 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/text_rb.html @@ -0,0 +1,70 @@ +--- +title: text.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/time_rb.html b/src/7.0/files/activerecord/lib/active_record/type/time_rb.html new file mode 100644 index 0000000000..4779256db4 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/time_rb.html @@ -0,0 +1,77 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/type_map_rb.html b/src/7.0/files/activerecord/lib/active_record/type/type_map_rb.html new file mode 100644 index 0000000000..d4247080d7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/type_map_rb.html @@ -0,0 +1,78 @@ +--- +title: type_map.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type/unsigned_integer_rb.html b/src/7.0/files/activerecord/lib/active_record/type/unsigned_integer_rb.html new file mode 100644 index 0000000000..cdea84ea92 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type/unsigned_integer_rb.html @@ -0,0 +1,70 @@ +--- +title: unsigned_integer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type_caster/connection_rb.html b/src/7.0/files/activerecord/lib/active_record/type_caster/connection_rb.html new file mode 100644 index 0000000000..dd995a79a1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type_caster/connection_rb.html @@ -0,0 +1,68 @@ +--- +title: connection.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type_caster/map_rb.html b/src/7.0/files/activerecord/lib/active_record/type_caster/map_rb.html new file mode 100644 index 0000000000..f638c93094 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type_caster/map_rb.html @@ -0,0 +1,68 @@ +--- +title: map.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type_caster_rb.html b/src/7.0/files/activerecord/lib/active_record/type_caster_rb.html new file mode 100644 index 0000000000..1cbc1d51e1 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type_caster_rb.html @@ -0,0 +1,78 @@ +--- +title: type_caster.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/type_caster/map
  • + +
  • active_record/type_caster/connection
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/type_rb.html b/src/7.0/files/activerecord/lib/active_record/type_rb.html new file mode 100644 index 0000000000..7b095ea79b --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/type_rb.html @@ -0,0 +1,102 @@ +--- +title: type.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_model/type
  • + +
  • active_record/type/internal/timezone
  • + +
  • active_record/type/date
  • + +
  • active_record/type/date_time
  • + +
  • active_record/type/decimal_without_scale
  • + +
  • active_record/type/json
  • + +
  • active_record/type/time
  • + +
  • active_record/type/text
  • + +
  • active_record/type/unsigned_integer
  • + +
  • active_record/type/serialized
  • + +
  • active_record/type/adapter_specific_registry
  • + +
  • active_record/type/type_map
  • + +
  • active_record/type/hash_lookup_type_map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/absence_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/absence_rb.html new file mode 100644 index 0000000000..0c7ae4e003 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/absence_rb.html @@ -0,0 +1,72 @@ +--- +title: absence.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/associated_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/associated_rb.html new file mode 100644 index 0000000000..5eafa69ed2 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/associated_rb.html @@ -0,0 +1,72 @@ +--- +title: associated.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/length_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/length_rb.html new file mode 100644 index 0000000000..3413b49cad --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/length_rb.html @@ -0,0 +1,72 @@ +--- +title: length.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/numericality_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/numericality_rb.html new file mode 100644 index 0000000000..b7cbda53b7 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/numericality_rb.html @@ -0,0 +1,72 @@ +--- +title: numericality.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/presence_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/presence_rb.html new file mode 100644 index 0000000000..1cccd6ed76 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/presence_rb.html @@ -0,0 +1,72 @@ +--- +title: presence.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations/uniqueness_rb.html b/src/7.0/files/activerecord/lib/active_record/validations/uniqueness_rb.html new file mode 100644 index 0000000000..33f598db49 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations/uniqueness_rb.html @@ -0,0 +1,72 @@ +--- +title: uniqueness.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/validations_rb.html b/src/7.0/files/activerecord/lib/active_record/validations_rb.html new file mode 100644 index 0000000000..d4829b6ac8 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/validations_rb.html @@ -0,0 +1,95 @@ +--- +title: validations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_record/validations/associated
  • + +
  • active_record/validations/uniqueness
  • + +
  • active_record/validations/presence
  • + +
  • active_record/validations/absence
  • + +
  • active_record/validations/length
  • + +
  • active_record/validations/numericality
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/active_record/version_rb.html b/src/7.0/files/activerecord/lib/active_record/version_rb.html new file mode 100644 index 0000000000..356a03ac59 --- /dev/null +++ b/src/7.0/files/activerecord/lib/active_record/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activerecord/lib/arel_rb.html b/src/7.0/files/activerecord/lib/arel_rb.html new file mode 100644 index 0000000000..4a71c78694 --- /dev/null +++ b/src/7.0/files/activerecord/lib/arel_rb.html @@ -0,0 +1,116 @@ +--- +title: arel.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • arel/errors
  • + +
  • arel/crud
  • + +
  • arel/factory_methods
  • + +
  • arel/expressions
  • + +
  • arel/predications
  • + +
  • arel/filter_predications
  • + +
  • arel/window_predications
  • + +
  • arel/math
  • + +
  • arel/alias_predication
  • + +
  • arel/order_predications
  • + +
  • arel/table
  • + +
  • arel/attributes/attribute
  • + +
  • arel/visitors
  • + +
  • arel/collectors/sql_string
  • + +
  • arel/tree_manager
  • + +
  • arel/insert_manager
  • + +
  • arel/select_manager
  • + +
  • arel/update_manager
  • + +
  • arel/delete_manager
  • + +
  • arel/nodes
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/README_md.html b/src/7.0/files/activestorage/README_md.html new file mode 100644 index 0000000000..dcdcac1aed --- /dev/null +++ b/src/7.0/files/activestorage/README_md.html @@ -0,0 +1,323 @@ +--- +title: README.md +layout: default +--- +
+ + +
+
+ +
+ +

Active Storage

+ +

Active Storage makes it simple to upload and reference files in cloud services like Amazon S3, Google Cloud Storage, or Microsoft Azure Storage, and attach those files to Active Records. Supports having one main service and mirrors in other services for redundancy. It also provides a disk service for testing or local deployments, but the focus is on cloud storage.

+ +

Files can be uploaded from the server to the cloud or directly from the client to the cloud.

+ +

Image files can furthermore be transformed using on-demand variants for quality, aspect ratio, size, or any other MiniMagick or Vips supported transformation.

+ +

You can read more about Active Storage in the Active Storage Overview guide.

+ +

Compared to other storage solutions

+ +

A key difference to how Active Storage works compared to other attachment solutions in Rails is through the use of built-in Blob and Attachment models (backed by Active Record). This means existing application models do not need to be modified with additional columns to associate with files. Active Storage uses polymorphic associations via the Attachment join model, which then connects to the actual Blob.

+ +

Blob models store attachment metadata (filename, content-type, etc.), and their identifier key in the storage service. Blob models do not store the actual binary data. They are intended to be immutable in spirit. One file, one blob. You can associate the same blob with multiple application models as well. And if you want to do transformations of a given Blob, the idea is that you’ll simply create a new one, rather than attempt to mutate the existing one (though of course you can delete the previous version later if you don’t need it).

+ +

Installation

+ +

Run bin/rails active_storage:install to copy over active_storage migrations.

+ +

NOTE: If the task cannot be found, verify that require "active_storage/engine" is present in config/application.rb.

+ +

Examples

+ +

One attachment:

+ +
class User < ApplicationRecord
+  # Associates an attachment and a blob. When the user is destroyed they are
+  # purged by default (models destroyed, and resource files deleted).
+  has_one_attached :avatar
+end
+
+# Attach an avatar to the user.
+user.avatar.attach(io: File.open("/path/to/face.jpg"), filename: "face.jpg", content_type: "image/jpeg")
+
+# Does the user have an avatar?
+user.avatar.attached? # => true
+
+# Synchronously destroy the avatar and actual resource files.
+user.avatar.purge
+
+# Destroy the associated models and actual resource files async, via Active Job.
+user.avatar.purge_later
+
+# Does the user have an avatar?
+user.avatar.attached? # => false
+
+# Generate a permanent URL for the blob that points to the application.
+# Upon access, a redirect to the actual service endpoint is returned.
+# This indirection decouples the public URL from the actual one, and
+# allows for example mirroring attachments in different services for
+# high-availability. The redirection has an HTTP expiration of 5 min.
+url_for(user.avatar)
+
+class AvatarsController < ApplicationController
+  def update
+    # params[:avatar] contains an ActionDispatch::Http::UploadedFile object
+    Current.user.avatar.attach(params.require(:avatar))
+    redirect_to Current.user
+  end
+end
+
+ +

Many attachments:

+ +
class Message < ApplicationRecord
+  has_many_attached :images
+end
+
+ +
<%= form_with model: @message, local: true do |form| %>
+  <%= form.text_field :title, placeholder: "Title" %><br>
+  <%= form.text_area :content %><br><br>
+
+  <%= form.file_field :images, multiple: true %><br>
+  <%= form.submit %>
+<% end %>
+
+ +
class MessagesController < ApplicationController
+  def index
+    # Use the built-in with_attached_images scope to avoid N+1
+    @messages = Message.all.with_attached_images
+  end
+
+  def create
+    message = Message.create! params.require(:message).permit(:title, :content, images: [])
+    redirect_to message
+  end
+
+  def show
+    @message = Message.find(params[:id])
+  end
+end
+
+ +

Variation of image attachment:

+ +
<%# Hitting the variant URL will lazy transform the original blob and then redirect to its new service location %>
+<%= image_tag user.avatar.variant(resize_to_limit: [100, 100]) %>
+
+ +

File serving strategies

+ +

Active Storage supports two ways to serve files: redirecting and proxying.

+ +

Redirecting

+ +

Active Storage generates stable application URLs for files which, when accessed, redirect to signed, short-lived service URLs. This relieves application servers of the burden of serving file data. It is the default file serving strategy.

+ +

When the application is configured to proxy files by default, use the rails_storage_redirect_path and _url route helpers to redirect instead:

+ +
<%= image_tag rails_storage_redirect_path(@user.avatar) %>
+
+ +

Proxying

+ +

Optionally, files can be proxied instead. This means that your application servers will download file data from the storage service in response to requests. This can be useful for serving files from a CDN.

+ +

You can configure Active Storage to use proxying by default:

+ +
# config/initializers/active_storage.rb
+Rails.application.config.active_storage.resolve_model_to_route = :rails_storage_proxy
+
+ +

Or if you want to explicitly proxy specific attachments there are URL helpers you can use in the form of rails_storage_proxy_path and rails_storage_proxy_url.

+ +
<%= image_tag rails_storage_proxy_path(@user.avatar) %>
+
+ +

Direct uploads

+ +

Active Storage, with its included JavaScript library, supports uploading directly from the client to the cloud.

+ +

Direct upload installation

+
  1. +

    Include the Active Storage JavaScript in your application's JavaScript bundle or reference it directly.

    + +

    Requiring directly without bundling through the asset pipeline in the application html with autostart:

    + +
    <%= javascript_include_tag "activestorage" %>
    +
    + +

    Requiring via importmap-rails without bundling through the asset pipeline in the application html without autostart as ESM:

    + +
    # config/importmap.rb
    +pin "@rails/activestorage", to: "activestorage.esm.js"
    +
    + +
    <script type="module-shim">
    +  import * as ActiveStorage from "@rails/activestorage"
    +  ActiveStorage.start()
    +</script>
    +
    + +

    Using the asset pipeline:

    + +
    //= require activestorage
    +
    + +

    Using the npm package:

    + +
    import * as ActiveStorage from "@rails/activestorage"
    +ActiveStorage.start()
    +
    +
  2. +

    Annotate file inputs with the direct upload URL.

    + +
    <%= form.file_field :attachments, multiple: true, direct_upload: true %>
    +
    +
  3. +

    That's it! Uploads begin upon form submission.

    +
+ +

Direct upload JavaScript events

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Event nameEvent targetEvent data (‘event.detail`)Description
‘direct-uploads:start`‘<form>`NoneA form containing files for direct upload fields was submitted.
‘direct-upload:initialize`‘<input>`‘{id, file}`Dispatched for every file after form submission.
‘direct-upload:start`‘<input>`‘{id, file}`A direct upload is starting.
‘direct-upload:before-blob-request`‘<input>`‘{id, file, xhr}`Before making a request to your application for direct upload metadata.
‘direct-upload:before-storage-request`‘<input>`‘{id, file, xhr}`Before making a request to store a file.
‘direct-upload:progress`‘<input>`‘{id, file, progress}`As requests to store files progress.
‘direct-upload:error`‘<input>`‘{id, file, error}`An error occurred. An ‘alert` will display unless this event is canceled.
‘direct-upload:end`‘<input>`‘{id, file}`A direct upload has ended.
‘direct-uploads:end`‘<form>`NoneAll direct uploads have ended.
+ +

License

+ +

Active Storage is released under the MIT License.

+ +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/base_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/base_controller_rb.html new file mode 100644 index 0000000000..821ac50682 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/base_controller_rb.html @@ -0,0 +1,81 @@ +--- +title: base_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

The base class for all Active Storage controllers.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/blobs/proxy_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/blobs/proxy_controller_rb.html new file mode 100644 index 0000000000..53e315f9b5 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/blobs/proxy_controller_rb.html @@ -0,0 +1,85 @@ +--- +title: proxy_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Proxy files through application. This avoids having a redirect and makes files easier to cache.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/blobs/redirect_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/blobs/redirect_controller_rb.html new file mode 100644 index 0000000000..9ba50c7001 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/blobs/redirect_controller_rb.html @@ -0,0 +1,85 @@ +--- +title: redirect_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Take a signed permanent reference for a blob and turn it into an expiring service URL for download.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/direct_uploads_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/direct_uploads_controller_rb.html new file mode 100644 index 0000000000..6068501f2b --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/direct_uploads_controller_rb.html @@ -0,0 +1,81 @@ +--- +title: direct_uploads_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Creates a new blob on the server side in anticipation of a direct-to-service upload from the client side. When the client-side upload is completed, the signed_blob_id can be submitted as part of the form to reference the blob that was created up front.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/disk_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/disk_controller_rb.html new file mode 100644 index 0000000000..49941f00b3 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/disk_controller_rb.html @@ -0,0 +1,81 @@ +--- +title: disk_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Serves files stored with the disk service in the same way that the cloud services do. This means using expiring, signed URLs that are meant for immediate access, not permanent linking. Always go through the BlobsController, or your own authenticated controller, rather than directly to the service URL.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/representations/base_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/representations/base_controller_rb.html new file mode 100644 index 0000000000..c76b0e970f --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/representations/base_controller_rb.html @@ -0,0 +1,70 @@ +--- +title: base_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/representations/proxy_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/representations/proxy_controller_rb.html new file mode 100644 index 0000000000..bebc87ef6d --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/representations/proxy_controller_rb.html @@ -0,0 +1,85 @@ +--- +title: proxy_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Proxy files through application. This avoids having a redirect and makes files easier to cache.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/active_storage/representations/redirect_controller_rb.html b/src/7.0/files/activestorage/app/controllers/active_storage/representations/redirect_controller_rb.html new file mode 100644 index 0000000000..0a7de6cc39 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/active_storage/representations/redirect_controller_rb.html @@ -0,0 +1,85 @@ +--- +title: redirect_controller.rb +layout: default +--- +
+ + +
+
+ +
+ +

Take a signed permanent reference for a blob representation and turn it into an expiring service URL for download.

+ +

WARNING: All Active Storage controllers are publicly accessible by default. The generated URLs are hard to guess, but permanent by design. If your files require a higher level of protection consider implementing Authenticated Controllers.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/concerns/active_storage/file_server_rb.html b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/file_server_rb.html new file mode 100644 index 0000000000..cd9f21f6e9 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/file_server_rb.html @@ -0,0 +1,68 @@ +--- +title: file_server.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_blob_rb.html b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_blob_rb.html new file mode 100644 index 0000000000..4d38f4b7fd --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_blob_rb.html @@ -0,0 +1,68 @@ +--- +title: set_blob.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_current_rb.html b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_current_rb.html new file mode 100644 index 0000000000..298571a7ec --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/set_current_rb.html @@ -0,0 +1,76 @@ +--- +title: set_current.rb +layout: default +--- +
+ + +
+
+ +
+ +

Sets the ActiveStorage::Current.url_options attribute, which the disk service uses to generate URLs. Include this concern in custom controllers that call ActiveStorage::Blob#url, ActiveStorage::Variant#url, or ActiveStorage::Preview#url so the disk service can generate URLs using the same host, protocol, and port as the current request.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/controllers/concerns/active_storage/streaming_rb.html b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/streaming_rb.html new file mode 100644 index 0000000000..7f808824e7 --- /dev/null +++ b/src/7.0/files/activestorage/app/controllers/concerns/active_storage/streaming_rb.html @@ -0,0 +1,78 @@ +--- +title: streaming.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/jobs/active_storage/analyze_job_rb.html b/src/7.0/files/activestorage/app/jobs/active_storage/analyze_job_rb.html new file mode 100644 index 0000000000..bdc7238f08 --- /dev/null +++ b/src/7.0/files/activestorage/app/jobs/active_storage/analyze_job_rb.html @@ -0,0 +1,83 @@ +--- +title: analyze_job.rb +layout: default +--- +
+ + +
+
+ +
+ +

Provides asynchronous analysis of ActiveStorage::Blob records via ActiveStorage::Blob#analyze_later.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/jobs/active_storage/base_job_rb.html b/src/7.0/files/activestorage/app/jobs/active_storage/base_job_rb.html new file mode 100644 index 0000000000..fc53c436a1 --- /dev/null +++ b/src/7.0/files/activestorage/app/jobs/active_storage/base_job_rb.html @@ -0,0 +1,75 @@ +--- +title: base_job.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/jobs/active_storage/mirror_job_rb.html b/src/7.0/files/activestorage/app/jobs/active_storage/mirror_job_rb.html new file mode 100644 index 0000000000..b424e460d7 --- /dev/null +++ b/src/7.0/files/activestorage/app/jobs/active_storage/mirror_job_rb.html @@ -0,0 +1,83 @@ +--- +title: mirror_job.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/jobs/active_storage/purge_job_rb.html b/src/7.0/files/activestorage/app/jobs/active_storage/purge_job_rb.html new file mode 100644 index 0000000000..c47009b754 --- /dev/null +++ b/src/7.0/files/activestorage/app/jobs/active_storage/purge_job_rb.html @@ -0,0 +1,83 @@ +--- +title: purge_job.rb +layout: default +--- +
+ + +
+
+ +
+ +

Provides asynchronous purging of ActiveStorage::Blob records via ActiveStorage::Blob#purge_later.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/attachment_rb.html b/src/7.0/files/activestorage/app/models/active_storage/attachment_rb.html new file mode 100644 index 0000000000..0c5acf114f --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/attachment_rb.html @@ -0,0 +1,83 @@ +--- +title: attachment.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/blob/analyzable_rb.html b/src/7.0/files/activestorage/app/models/active_storage/blob/analyzable_rb.html new file mode 100644 index 0000000000..b5776bade0 --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/blob/analyzable_rb.html @@ -0,0 +1,85 @@ +--- +title: analyzable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_storage/analyzer/null_analyzer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/blob/identifiable_rb.html b/src/7.0/files/activestorage/app/models/active_storage/blob/identifiable_rb.html new file mode 100644 index 0000000000..6e6cb471fa --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/blob/identifiable_rb.html @@ -0,0 +1,77 @@ +--- +title: identifiable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/blob/representable_rb.html b/src/7.0/files/activestorage/app/models/active_storage/blob/representable_rb.html new file mode 100644 index 0000000000..4626220e1a --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/blob/representable_rb.html @@ -0,0 +1,85 @@ +--- +title: representable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mini_mime
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/blob_rb.html b/src/7.0/files/activestorage/app/models/active_storage/blob_rb.html new file mode 100644 index 0000000000..43d613c8d6 --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/blob_rb.html @@ -0,0 +1,96 @@ +--- +title: blob.rb +layout: default +--- +
+ + +
+
+ +
+ +

A blob is a record that contains the metadata about a file and a key for where that file resides on the service. Blobs can be created in two ways:

+
  1. +

    Ahead of the file being uploaded server-side to the service, via create_and_upload!. A rewindable io with the file contents must be available at the server for this operation.

    +
  2. +

    Ahead of the file being directly uploaded client-side to the service, via create_before_direct_upload!.

    +
+ +

The first option doesn’t require any client-side JavaScript integration, and can be used by any other back-end service that deals with files. The second option is faster, since you’re not using your own server as a staging point for uploads, and can work with deployments like Heroku that do not provide large amounts of disk space.

+ +

Blobs are intended to be immutable in as-so-far as their reference to a specific file goes. You’re allowed to update a blob’s metadata on a subsequent pass, but you should not update the key or change the uploaded file. If you need to create a derivative or otherwise change the blob, simply create a new blob and purge the old one.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/current_rb.html b/src/7.0/files/activestorage/app/models/active_storage/current_rb.html new file mode 100644 index 0000000000..6dda849072 --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/current_rb.html @@ -0,0 +1,70 @@ +--- +title: current.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/filename_rb.html b/src/7.0/files/activestorage/app/models/active_storage/filename_rb.html new file mode 100644 index 0000000000..c9c34c712a --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/filename_rb.html @@ -0,0 +1,81 @@ +--- +title: filename.rb +layout: default +--- +
+ + +
+
+ +
+ +

Encapsulates a string representing a filename to provide convenient access to parts of it and sanitization. A Filename instance is returned by ActiveStorage::Blob#filename, and is comparable so it can be used for sorting.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/preview_rb.html b/src/7.0/files/activestorage/app/models/active_storage/preview_rb.html new file mode 100644 index 0000000000..3b81fef006 --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/preview_rb.html @@ -0,0 +1,103 @@ +--- +title: preview.rb +layout: default +--- +
+ + +
+
+ +
+ +

Some non-image blobs can be previewed: that is, they can be presented as images. A video blob can be previewed by extracting its first frame, and a PDF blob can be previewed by extracting its first page.

+ +

A previewer extracts a preview image from a blob. Active Storage provides previewers for videos and PDFs. ActiveStorage::Previewer::VideoPreviewer is used for videos whereas ActiveStorage::Previewer::PopplerPDFPreviewer and ActiveStorage::Previewer::MuPDFPreviewer are used for PDFs. Build custom previewers by subclassing ActiveStorage::Previewer and implementing the requisite methods. Consult the ActiveStorage::Previewer documentation for more details on what’s required of previewers.

+ +

To choose the previewer for a blob, Active Storage calls accept? on each registered previewer in order. It uses the first previewer for which accept? returns true when given the blob. In a Rails application, add or remove previewers by manipulating Rails.application.config.active_storage.previewers in an initializer:

+ +
Rails.application.config.active_storage.previewers
+# => [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer ]
+
+# Add a custom previewer for Microsoft Office documents:
+Rails.application.config.active_storage.previewers << DOCXPreviewer
+# => [ ActiveStorage::Previewer::PopplerPDFPreviewer, ActiveStorage::Previewer::MuPDFPreviewer, ActiveStorage::Previewer::VideoPreviewer, DOCXPreviewer ]
+
+ +

Outside of a Rails application, modify ActiveStorage.previewers instead.

+ +

The built-in previewers rely on third-party system libraries. Specifically, the built-in video previewer requires FFmpeg. Two PDF previewers are provided: one requires Poppler, and the other requires muPDF (version 1.8 or newer). To preview PDFs, install either Poppler or muPDF.

+ +

These libraries are not provided by Rails. You must install them yourself to use the built-in previewers. Before you install and use third-party software, make sure you understand the licensing implications of doing so.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/record_rb.html b/src/7.0/files/activestorage/app/models/active_storage/record_rb.html new file mode 100644 index 0000000000..fc4d7146dd --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/record_rb.html @@ -0,0 +1,68 @@ +--- +title: record.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/variant_rb.html b/src/7.0/files/activestorage/app/models/active_storage/variant_rb.html new file mode 100644 index 0000000000..bea0425728 --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/variant_rb.html @@ -0,0 +1,122 @@ +--- +title: variant.rb +layout: default +--- +
+ + +
+
+ +
+ +

Image blobs can have variants that are the result of a set of transformations applied to the original. These variants are used to create thumbnails, fixed-size avatars, or any other derivative image from the original.

+ +

Variants rely on ImageProcessing gem for the actual transformations of the file, so you must add gem "image_processing" to your Gemfile if you wish to use variants. By default, images will be processed with ImageMagick using the MiniMagick gem, but you can also switch to the libvips processor operated by the ruby-vips gem).

+ +
Rails.application.config.active_storage.variant_processor
+# => :mini_magick
+
+Rails.application.config.active_storage.variant_processor = :vips
+# => :vips
+
+ +

Note that to create a variant it’s necessary to download the entire blob file from the service. Because of this process, you also want to be considerate about when the variant is actually processed. You shouldn’t be processing variants inline in a template, for example. Delay the processing to an on-demand controller, like the one provided in ActiveStorage::RepresentationsController.

+ +

To refer to such a delayed on-demand variant, simply link to the variant through the resolved route provided by Active Storage like so:

+ +
<%= image_tag Current.user.avatar.variant(resize_to_limit: [100, 100]) %>
+
+ +

This will create a URL for that specific blob with that specific variant, which the ActiveStorage::RepresentationsController can then produce on-demand.

+ +

When you do want to actually produce the variant needed, call processed. This will check that the variant has already been processed and uploaded to the service, and, if so, just return that. Otherwise it will perform the transformations, upload the variant to the service, and return itself again. Example:

+ +
avatar.variant(resize_to_limit: [100, 100]).processed.url
+
+ +

This will create and process a variant of the avatar blob that’s constrained to a height and width of 100. Then it’ll upload said variant to the service according to a derivative key of the blob and the transformations.

+ +

You can combine any number of ImageMagick/libvips operations into a variant, as well as any macros provided by the ImageProcessing gem (such as resize_to_limit):

+ +
avatar.variant(resize_to_limit: [800, 800], colourspace: "b-w", rotate: "-90")
+
+ +

Visit the following links for a list of available ImageProcessing commands and ImageMagick/libvips operations:

+ + +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/variant_record_rb.html b/src/7.0/files/activestorage/app/models/active_storage/variant_record_rb.html new file mode 100644 index 0000000000..a3b05dad8c --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/variant_record_rb.html @@ -0,0 +1,75 @@ +--- +title: variant_record.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/variant_with_record_rb.html b/src/7.0/files/activestorage/app/models/active_storage/variant_with_record_rb.html new file mode 100644 index 0000000000..644502251f --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/variant_with_record_rb.html @@ -0,0 +1,83 @@ +--- +title: variant_with_record.rb +layout: default +--- +
+ + +
+
+ +
+ +

Like an ActiveStorage::Variant, but keeps detail about the variant in the database as an ActiveStorage::VariantRecord. This is only used if ActiveStorage.track_variants is enabled.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/app/models/active_storage/variation_rb.html b/src/7.0/files/activestorage/app/models/active_storage/variation_rb.html new file mode 100644 index 0000000000..ad48157f2b --- /dev/null +++ b/src/7.0/files/activestorage/app/models/active_storage/variation_rb.html @@ -0,0 +1,87 @@ +--- +title: variation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mini_mime
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/audio_analyzer_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/audio_analyzer_rb.html new file mode 100644 index 0000000000..1f9fa4908a --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/audio_analyzer_rb.html @@ -0,0 +1,77 @@ +--- +title: audio_analyzer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/image_magick_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/image_magick_rb.html new file mode 100644 index 0000000000..c22ad901ef --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/image_magick_rb.html @@ -0,0 +1,87 @@ +--- +title: image_magick.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mini_magick
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/vips_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/vips_rb.html new file mode 100644 index 0000000000..2a2a5ea02e --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer/vips_rb.html @@ -0,0 +1,87 @@ +--- +title: vips.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • ruby-vips
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer_rb.html new file mode 100644 index 0000000000..89814e0936 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/image_analyzer_rb.html @@ -0,0 +1,77 @@ +--- +title: image_analyzer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/null_analyzer_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/null_analyzer_rb.html new file mode 100644 index 0000000000..a7ed52d82a --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/null_analyzer_rb.html @@ -0,0 +1,75 @@ +--- +title: null_analyzer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer/video_analyzer_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer/video_analyzer_rb.html new file mode 100644 index 0000000000..4271d6658b --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer/video_analyzer_rb.html @@ -0,0 +1,77 @@ +--- +title: video_analyzer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/analyzer_rb.html b/src/7.0/files/activestorage/lib/active_storage/analyzer_rb.html new file mode 100644 index 0000000000..c81f9eb085 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/analyzer_rb.html @@ -0,0 +1,77 @@ +--- +title: analyzer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_many_rb.html new file mode 100644 index 0000000000..dba5a4c5c1 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_many_rb.html @@ -0,0 +1,75 @@ +--- +title: create_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_of_many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_of_many_rb.html new file mode 100644 index 0000000000..2683d95422 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_of_many_rb.html @@ -0,0 +1,75 @@ +--- +title: create_one_of_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_rb.html new file mode 100644 index 0000000000..ddba803067 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/create_one_rb.html @@ -0,0 +1,89 @@ +--- +title: create_one.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch
  • + +
  • action_dispatch/http/upload
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_many_rb.html new file mode 100644 index 0000000000..df4ae604d0 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_many_rb.html @@ -0,0 +1,75 @@ +--- +title: delete_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_one_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_one_rb.html new file mode 100644 index 0000000000..bc3b0f4dd9 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/delete_one_rb.html @@ -0,0 +1,75 @@ +--- +title: delete_one.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_many_rb.html new file mode 100644 index 0000000000..2fd13d3e00 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_many_rb.html @@ -0,0 +1,75 @@ +--- +title: detach_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_one_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_one_rb.html new file mode 100644 index 0000000000..6e3c43538c --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/detach_one_rb.html @@ -0,0 +1,75 @@ +--- +title: detach_one.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_many_rb.html new file mode 100644 index 0000000000..4caa7626cd --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_many_rb.html @@ -0,0 +1,75 @@ +--- +title: purge_many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_one_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_one_rb.html new file mode 100644 index 0000000000..5f3ec4f21a --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes/purge_one_rb.html @@ -0,0 +1,75 @@ +--- +title: purge_one.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/changes_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/changes_rb.html new file mode 100644 index 0000000000..f11f48ed00 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/changes_rb.html @@ -0,0 +1,75 @@ +--- +title: changes.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/many_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/many_rb.html new file mode 100644 index 0000000000..c016c25c31 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/many_rb.html @@ -0,0 +1,77 @@ +--- +title: many.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/model_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/model_rb.html new file mode 100644 index 0000000000..ec681e98f2 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/model_rb.html @@ -0,0 +1,89 @@ +--- +title: model.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached/one_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached/one_rb.html new file mode 100644 index 0000000000..3124399b1e --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached/one_rb.html @@ -0,0 +1,77 @@ +--- +title: one.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/attached_rb.html b/src/7.0/files/activestorage/lib/active_storage/attached_rb.html new file mode 100644 index 0000000000..13fc1654e0 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/attached_rb.html @@ -0,0 +1,91 @@ +--- +title: attached.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
  • active_storage/attached/model
  • + +
  • active_storage/attached/one
  • + +
  • active_storage/attached/many
  • + +
  • active_storage/attached/changes
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/downloader_rb.html b/src/7.0/files/activestorage/lib/active_storage/downloader_rb.html new file mode 100644 index 0000000000..c867b3be95 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/downloader_rb.html @@ -0,0 +1,70 @@ +--- +title: downloader.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/engine_rb.html b/src/7.0/files/activestorage/lib/active_storage/engine_rb.html new file mode 100644 index 0000000000..1bd2e70045 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/engine_rb.html @@ -0,0 +1,123 @@ +--- +title: engine.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails
  • + +
  • action_controller/railtie
  • + +
  • active_job/railtie
  • + +
  • active_record/railtie
  • + +
  • active_storage
  • + +
  • active_storage/previewer/poppler_pdf_previewer
  • + +
  • active_storage/previewer/mupdf_previewer
  • + +
  • active_storage/previewer/video_previewer
  • + +
  • active_storage/analyzer/image_analyzer
  • + +
  • active_storage/analyzer/image_analyzer/image_magick
  • + +
  • active_storage/analyzer/image_analyzer/vips
  • + +
  • active_storage/analyzer/video_analyzer
  • + +
  • active_storage/analyzer/audio_analyzer
  • + +
  • active_storage/service/registry
  • + +
  • active_storage/reflection
  • + +
  • active_storage/attached
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/errors_rb.html b/src/7.0/files/activestorage/lib/active_storage/errors_rb.html new file mode 100644 index 0000000000..59ae4dc829 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/errors_rb.html @@ -0,0 +1,87 @@ +--- +title: errors.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/fixture_set_rb.html b/src/7.0/files/activestorage/lib/active_storage/fixture_set_rb.html new file mode 100644 index 0000000000..18b8599fed --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/fixture_set_rb.html @@ -0,0 +1,85 @@ +--- +title: fixture_set.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/testing/file_fixtures
  • + +
  • active_record/secure_token
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/gem_version_rb.html b/src/7.0/files/activestorage/lib/active_storage/gem_version_rb.html new file mode 100644 index 0000000000..e37124fadf --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/log_subscriber_rb.html b/src/7.0/files/activestorage/lib/active_storage/log_subscriber_rb.html new file mode 100644 index 0000000000..235775025e --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/log_subscriber_rb.html @@ -0,0 +1,83 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/log_subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/previewer/mupdf_previewer_rb.html b/src/7.0/files/activestorage/lib/active_storage/previewer/mupdf_previewer_rb.html new file mode 100644 index 0000000000..8459453ed2 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/previewer/mupdf_previewer_rb.html @@ -0,0 +1,77 @@ +--- +title: mupdf_previewer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/previewer/poppler_pdf_previewer_rb.html b/src/7.0/files/activestorage/lib/active_storage/previewer/poppler_pdf_previewer_rb.html new file mode 100644 index 0000000000..422f6a55ca --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/previewer/poppler_pdf_previewer_rb.html @@ -0,0 +1,77 @@ +--- +title: poppler_pdf_previewer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/previewer/video_previewer_rb.html b/src/7.0/files/activestorage/lib/active_storage/previewer/video_previewer_rb.html new file mode 100644 index 0000000000..3963605052 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/previewer/video_previewer_rb.html @@ -0,0 +1,85 @@ +--- +title: video_previewer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • shellwords
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/previewer_rb.html b/src/7.0/files/activestorage/lib/active_storage/previewer_rb.html new file mode 100644 index 0000000000..b6ffb267c7 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/previewer_rb.html @@ -0,0 +1,77 @@ +--- +title: previewer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/reflection_rb.html b/src/7.0/files/activestorage/lib/active_storage/reflection_rb.html new file mode 100644 index 0000000000..c3877ff1b6 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/reflection_rb.html @@ -0,0 +1,74 @@ +--- +title: reflection.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/azure_storage_service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/azure_storage_service_rb.html new file mode 100644 index 0000000000..0f9ae3225d --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/azure_storage_service_rb.html @@ -0,0 +1,89 @@ +--- +title: azure_storage_service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/numeric/bytes
  • + +
  • azure/storage/blob
  • + +
  • azure/storage/common/core/auth/shared_access_signature
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/configurator_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/configurator_rb.html new file mode 100644 index 0000000000..3f2a2ebf78 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/configurator_rb.html @@ -0,0 +1,75 @@ +--- +title: configurator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/disk_service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/disk_service_rb.html new file mode 100644 index 0000000000..956a6945f8 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/disk_service_rb.html @@ -0,0 +1,93 @@ +--- +title: disk_service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • pathname
  • + +
  • openssl
  • + +
  • active_support/core_ext/numeric/bytes
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/gcs_service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/gcs_service_rb.html new file mode 100644 index 0000000000..751250a553 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/gcs_service_rb.html @@ -0,0 +1,91 @@ +--- +title: gcs_service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • google/apis/iamcredentials_v1
  • + +
  • google/cloud/storage
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/mirror_service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/mirror_service_rb.html new file mode 100644 index 0000000000..821a80653a --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/mirror_service_rb.html @@ -0,0 +1,85 @@ +--- +title: mirror_service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/registry_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/registry_rb.html new file mode 100644 index 0000000000..7c9938356c --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/registry_rb.html @@ -0,0 +1,75 @@ +--- +title: registry.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service/s3_service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service/s3_service_rb.html new file mode 100644 index 0000000000..6a49b7397d --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service/s3_service_rb.html @@ -0,0 +1,87 @@ +--- +title: s3_service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • aws-sdk-s3
  • + +
  • active_support/core_ext/numeric/bytes
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/service_rb.html b/src/7.0/files/activestorage/lib/active_storage/service_rb.html new file mode 100644 index 0000000000..60ae510d9e --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/service_rb.html @@ -0,0 +1,95 @@ +--- +title: service.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_storage/log_subscriber
  • + +
  • active_storage/downloader
  • + +
  • action_dispatch
  • + +
  • action_dispatch/http/content_disposition
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/transformers/image_processing_transformer_rb.html b/src/7.0/files/activestorage/lib/active_storage/transformers/image_processing_transformer_rb.html new file mode 100644 index 0000000000..b327759d58 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/transformers/image_processing_transformer_rb.html @@ -0,0 +1,89 @@ +--- +title: image_processing_transformer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • image_processing
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/transformers/transformer_rb.html b/src/7.0/files/activestorage/lib/active_storage/transformers/transformer_rb.html new file mode 100644 index 0000000000..c6ed0899dc --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/transformers/transformer_rb.html @@ -0,0 +1,77 @@ +--- +title: transformer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activestorage/lib/active_storage/version_rb.html b/src/7.0/files/activestorage/lib/active_storage/version_rb.html new file mode 100644 index 0000000000..eac579efd3 --- /dev/null +++ b/src/7.0/files/activestorage/lib/active_storage/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/README_rdoc.html b/src/7.0/files/activesupport/README_rdoc.html new file mode 100644 index 0000000000..590cbad7ac --- /dev/null +++ b/src/7.0/files/activesupport/README_rdoc.html @@ -0,0 +1,101 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Active Support – Utility classes and Ruby extensions from Rails

+ +

Active Support is a collection of utility classes and standard library extensions that were found useful for the Rails framework. These additions reside in this package so they can be loaded as needed in Ruby projects outside of Rails.

+ +

You can read more about the extensions in the Active Support Core Extensions guide.

+ +

Download and installation

+ +

The latest version of Active Support can be installed with RubyGems:

+ +
$ gem install activesupport
+
+ +

Source code can be downloaded as part of the Rails project on GitHub:

+ + +

License

+ +

Active Support is released under the MIT license:

+ + +

Support

+ +

API documentation is at:

+ + +

Bug reports for the Ruby on Rails project can be filed here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/actionable_error_rb.html b/src/7.0/files/activesupport/lib/active_support/actionable_error_rb.html new file mode 100644 index 0000000000..25b82f45a7 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/actionable_error_rb.html @@ -0,0 +1,79 @@ +--- +title: actionable_error.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/all_rb.html b/src/7.0/files/activesupport/lib/active_support/all_rb.html new file mode 100644 index 0000000000..096e067d32 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/all_rb.html @@ -0,0 +1,67 @@ +--- +title: all.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/time
  • + +
  • active_support/core_ext
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/array_inquirer_rb.html b/src/7.0/files/activesupport/lib/active_support/array_inquirer_rb.html new file mode 100644 index 0000000000..18ae0f7ea4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/array_inquirer_rb.html @@ -0,0 +1,75 @@ +--- +title: array_inquirer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/backtrace_cleaner_rb.html b/src/7.0/files/activesupport/lib/active_support/backtrace_cleaner_rb.html new file mode 100644 index 0000000000..5b91cac220 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/backtrace_cleaner_rb.html @@ -0,0 +1,75 @@ +--- +title: backtrace_cleaner.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/benchmarkable_rb.html b/src/7.0/files/activesupport/lib/active_support/benchmarkable_rb.html new file mode 100644 index 0000000000..ce79f2a2a6 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/benchmarkable_rb.html @@ -0,0 +1,80 @@ +--- +title: benchmarkable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/benchmark
  • + +
  • active_support/core_ext/hash/keys
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/builder_rb.html b/src/7.0/files/activesupport/lib/active_support/builder_rb.html new file mode 100644 index 0000000000..dacb282f3b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/builder_rb.html @@ -0,0 +1,63 @@ +--- +title: builder.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • builder
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/file_store_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/file_store_rb.html new file mode 100644 index 0000000000..9bae40e5d4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/file_store_rb.html @@ -0,0 +1,89 @@ +--- +title: file_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/file/atomic
  • + +
  • active_support/core_ext/string/conversions
  • + +
  • uri/common
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/mem_cache_store_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/mem_cache_store_rb.html new file mode 100644 index 0000000000..f05c36a932 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/mem_cache_store_rb.html @@ -0,0 +1,107 @@ +--- +title: mem_cache_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • dalli
  • + +
  • delegate
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/array/extract_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/memory_store_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/memory_store_rb.html new file mode 100644 index 0000000000..a5d885d22b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/memory_store_rb.html @@ -0,0 +1,87 @@ +--- +title: memory_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/null_store_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/null_store_rb.html new file mode 100644 index 0000000000..607d246afa --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/null_store_rb.html @@ -0,0 +1,79 @@ +--- +title: null_store.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/redis_cache_store_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/redis_cache_store_rb.html new file mode 100644 index 0000000000..79ea22e98e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/redis_cache_store_rb.html @@ -0,0 +1,97 @@ +--- +title: redis_cache_store.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • redis
  • + +
  • redis/distributed
  • + +
  • redis/connection/hiredis
  • + +
  • hiredis-client
  • + +
  • active_support/digest
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_middleware_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_middleware_rb.html new file mode 100644 index 0000000000..095cbf26ef --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_middleware_rb.html @@ -0,0 +1,84 @@ +--- +title: local_cache_middleware.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rack/body_proxy
  • + +
  • rack/utils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_rb.html b/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_rb.html new file mode 100644 index 0000000000..b370a7b35e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache/strategy/local_cache_rb.html @@ -0,0 +1,89 @@ +--- +title: local_cache.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/cache_rb.html b/src/7.0/files/activesupport/lib/active_support/cache_rb.html new file mode 100644 index 0000000000..ea1fc65b59 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/cache_rb.html @@ -0,0 +1,115 @@ +--- +title: cache.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • zlib
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/array/wrap
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/numeric/bytes
  • + +
  • active_support/core_ext/numeric/time
  • + +
  • active_support/core_ext/object/to_param
  • + +
  • active_support/core_ext/object/try
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • connection_pool
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/callbacks_rb.html b/src/7.0/files/activesupport/lib/active_support/callbacks_rb.html new file mode 100644 index 0000000000..86e0e087ee --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/callbacks_rb.html @@ -0,0 +1,121 @@ +--- +title: callbacks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/descendants_tracker
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/core_ext/object/blank
  • + +
  • thread
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/code_generator_rb.html b/src/7.0/files/activesupport/lib/active_support/code_generator_rb.html new file mode 100644 index 0000000000..3cca70d981 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/code_generator_rb.html @@ -0,0 +1,77 @@ +--- +title: code_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/concern_rb.html b/src/7.0/files/activesupport/lib/active_support/concern_rb.html new file mode 100644 index 0000000000..3198578c8e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/concern_rb.html @@ -0,0 +1,70 @@ +--- +title: concern.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor_rb.html b/src/7.0/files/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor_rb.html new file mode 100644 index 0000000000..832553e46b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/concurrency/load_interlock_aware_monitor_rb.html @@ -0,0 +1,85 @@ +--- +title: load_interlock_aware_monitor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/concurrency/share_lock_rb.html b/src/7.0/files/activesupport/lib/active_support/concurrency/share_lock_rb.html new file mode 100644 index 0000000000..282d8ca65c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/concurrency/share_lock_rb.html @@ -0,0 +1,87 @@ +--- +title: share_lock.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • monitor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/configurable_rb.html b/src/7.0/files/activesupport/lib/active_support/configurable_rb.html new file mode 100644 index 0000000000..8841f82f5d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/configurable_rb.html @@ -0,0 +1,89 @@ +--- +title: configurable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/ordered_options
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/configuration_file_rb.html b/src/7.0/files/activesupport/lib/active_support/configuration_file_rb.html new file mode 100644 index 0000000000..3348744e6f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/configuration_file_rb.html @@ -0,0 +1,87 @@ +--- +title: configuration_file.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
  • erb
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/access_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/access_rb.html new file mode 100644 index 0000000000..0fe77e845c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/access_rb.html @@ -0,0 +1,68 @@ +--- +title: access.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/conversions_rb.html new file mode 100644 index 0000000000..9c29b9d0dc --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/conversions_rb.html @@ -0,0 +1,91 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/object/to_param
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/builder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/deprecated_conversions_rb.html new file mode 100644 index 0000000000..00db5c7670 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/deprecated_conversions_rb.html @@ -0,0 +1,75 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_options_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_options_rb.html new file mode 100644 index 0000000000..9dc79fb6b8 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_options_rb.html @@ -0,0 +1,70 @@ +--- +title: extract_options.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_rb.html new file mode 100644 index 0000000000..3dfbd01602 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/extract_rb.html @@ -0,0 +1,68 @@ +--- +title: extract.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/grouping_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/grouping_rb.html new file mode 100644 index 0000000000..39ff92ea63 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/grouping_rb.html @@ -0,0 +1,68 @@ +--- +title: grouping.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/inquiry_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/inquiry_rb.html new file mode 100644 index 0000000000..cb91abce63 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/inquiry_rb.html @@ -0,0 +1,83 @@ +--- +title: inquiry.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/array_inquirer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array/wrap_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array/wrap_rb.html new file mode 100644 index 0000000000..bb5d7f987d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array/wrap_rb.html @@ -0,0 +1,68 @@ +--- +title: wrap.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/array_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/array_rb.html new file mode 100644 index 0000000000..10f58772c0 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/array_rb.html @@ -0,0 +1,77 @@ +--- +title: array.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/wrap
  • + +
  • active_support/core_ext/array/access
  • + +
  • active_support/core_ext/array/conversions
  • + +
  • active_support/core_ext/array/deprecated_conversions
  • + +
  • active_support/core_ext/array/extract
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/array/grouping
  • + +
  • active_support/core_ext/array/inquiry
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/benchmark_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/benchmark_rb.html new file mode 100644 index 0000000000..a6d0c792ea --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/benchmark_rb.html @@ -0,0 +1,76 @@ +--- +title: benchmark.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • benchmark
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal/conversions_rb.html new file mode 100644 index 0000000000..14b1509790 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal/conversions_rb.html @@ -0,0 +1,78 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • bigdecimal
  • + +
  • bigdecimal/util
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal_rb.html new file mode 100644 index 0000000000..932ac2ecab --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/big_decimal_rb.html @@ -0,0 +1,63 @@ +--- +title: big_decimal.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/big_decimal/conversions
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_accessors_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_accessors_rb.html new file mode 100644 index 0000000000..c520ee5660 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_accessors_rb.html @@ -0,0 +1,69 @@ +--- +title: attribute_accessors.rb +layout: default +--- +
+ + +
+
+ +
+ +

cattr_* became mattr_* aliases in 7dfbd91b0780fbd6a1dd9bfbc176e10894871d2d, but we keep this around for libraries that directly require it knowing they want cattr_*. No need to deprecate.

+ +
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_rb.html new file mode 100644 index 0000000000..f89a0ee3e1 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/class/attribute_rb.html @@ -0,0 +1,76 @@ +--- +title: attribute.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/class/subclasses_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/class/subclasses_rb.html new file mode 100644 index 0000000000..ad671a14e8 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/class/subclasses_rb.html @@ -0,0 +1,83 @@ +--- +title: subclasses.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/ruby_features
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/class_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/class_rb.html new file mode 100644 index 0000000000..58f9698e2d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/class_rb.html @@ -0,0 +1,65 @@ +--- +title: class.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/core_ext/class/subclasses
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/acts_like_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/acts_like_rb.html new file mode 100644 index 0000000000..876ffe734f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/acts_like_rb.html @@ -0,0 +1,76 @@ +--- +title: acts_like.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/acts_like
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/blank_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/blank_rb.html new file mode 100644 index 0000000000..98c172875a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/blank_rb.html @@ -0,0 +1,76 @@ +--- +title: blank.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/calculations_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/calculations_rb.html new file mode 100644 index 0000000000..52ef95fd30 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/calculations_rb.html @@ -0,0 +1,93 @@ +--- +title: calculations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/duration
  • + +
  • active_support/core_ext/object/acts_like
  • + +
  • active_support/core_ext/date/zones
  • + +
  • active_support/core_ext/time/zones
  • + +
  • active_support/core_ext/date_and_time/calculations
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/conversions_rb.html new file mode 100644 index 0000000000..2be1e0ec7d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/conversions_rb.html @@ -0,0 +1,82 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/inflector/methods
  • + +
  • active_support/core_ext/date/zones
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/deprecated_conversions_rb.html new file mode 100644 index 0000000000..86c925e663 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/deprecated_conversions_rb.html @@ -0,0 +1,83 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date/zones_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date/zones_rb.html new file mode 100644 index 0000000000..b4429c4b82 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date/zones_rb.html @@ -0,0 +1,78 @@ +--- +title: zones.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/core_ext/date_and_time/zones
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/calculations_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/calculations_rb.html new file mode 100644 index 0000000000..0eb09bed6b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/calculations_rb.html @@ -0,0 +1,80 @@ +--- +title: calculations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/try
  • + +
  • active_support/core_ext/date_time/conversions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/compatibility_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/compatibility_rb.html new file mode 100644 index 0000000000..6e9390367a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/compatibility_rb.html @@ -0,0 +1,78 @@ +--- +title: compatibility.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/zones_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/zones_rb.html new file mode 100644 index 0000000000..0bd3a06f99 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_and_time/zones_rb.html @@ -0,0 +1,72 @@ +--- +title: zones.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_rb.html new file mode 100644 index 0000000000..de54b78be5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_rb.html @@ -0,0 +1,73 @@ +--- +title: date.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/date/acts_like
  • + +
  • active_support/core_ext/date/blank
  • + +
  • active_support/core_ext/date/calculations
  • + +
  • active_support/core_ext/date/conversions
  • + +
  • active_support/core_ext/date/deprecated_conversions
  • + +
  • active_support/core_ext/date/zones
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/acts_like_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/acts_like_rb.html new file mode 100644 index 0000000000..9bf9fb2111 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/acts_like_rb.html @@ -0,0 +1,78 @@ +--- +title: acts_like.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/core_ext/object/acts_like
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/blank_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/blank_rb.html new file mode 100644 index 0000000000..c944cdbf0b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/blank_rb.html @@ -0,0 +1,76 @@ +--- +title: blank.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/calculations_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/calculations_rb.html new file mode 100644 index 0000000000..03aefcdc61 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/calculations_rb.html @@ -0,0 +1,76 @@ +--- +title: calculations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/compatibility_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/compatibility_rb.html new file mode 100644 index 0000000000..7e6cdf0d58 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/compatibility_rb.html @@ -0,0 +1,78 @@ +--- +title: compatibility.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/date_and_time/compatibility
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/conversions_rb.html new file mode 100644 index 0000000000..c6253e0e2f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/conversions_rb.html @@ -0,0 +1,91 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/inflector/methods
  • + +
  • active_support/core_ext/time/conversions
  • + +
  • active_support/core_ext/date_time/calculations
  • + +
  • active_support/values/time_zone
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions_rb.html new file mode 100644 index 0000000000..a3f8cc52ec --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time/deprecated_conversions_rb.html @@ -0,0 +1,83 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/date_time_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time_rb.html new file mode 100644 index 0000000000..5e6fdce4bc --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/date_time_rb.html @@ -0,0 +1,73 @@ +--- +title: date_time.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/date_time/acts_like
  • + +
  • active_support/core_ext/date_time/blank
  • + +
  • active_support/core_ext/date_time/calculations
  • + +
  • active_support/core_ext/date_time/compatibility
  • + +
  • active_support/core_ext/date_time/conversions
  • + +
  • active_support/core_ext/date_time/deprecated_conversions
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/digest/uuid_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/digest/uuid_rb.html new file mode 100644 index 0000000000..ddc25a9266 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/digest/uuid_rb.html @@ -0,0 +1,82 @@ +--- +title: uuid.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/digest_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/digest_rb.html new file mode 100644 index 0000000000..953804e3eb --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/digest_rb.html @@ -0,0 +1,63 @@ +--- +title: digest.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/digest/uuid
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/enumerable_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/enumerable_rb.html new file mode 100644 index 0000000000..8f644c46c6 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/enumerable_rb.html @@ -0,0 +1,87 @@ +--- +title: enumerable.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/file/atomic_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/file/atomic_rb.html new file mode 100644 index 0000000000..feeec018b2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/file/atomic_rb.html @@ -0,0 +1,78 @@ +--- +title: atomic.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • tempfile
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/file_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/file_rb.html new file mode 100644 index 0000000000..49f376f395 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/file_rb.html @@ -0,0 +1,63 @@ +--- +title: file.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/file/atomic
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/conversions_rb.html new file mode 100644 index 0000000000..70bbed8928 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/conversions_rb.html @@ -0,0 +1,101 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/core_ext/object/to_param
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/core_ext/object/try
  • + +
  • active_support/core_ext/array/wrap
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/builder
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_merge_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_merge_rb.html new file mode 100644 index 0000000000..37d98665d5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_merge_rb.html @@ -0,0 +1,68 @@ +--- +title: deep_merge.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_transform_values_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_transform_values_rb.html new file mode 100644 index 0000000000..fe3aa7b439 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/deep_transform_values_rb.html @@ -0,0 +1,68 @@ +--- +title: deep_transform_values.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/except_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/except_rb.html new file mode 100644 index 0000000000..055bd38e26 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/except_rb.html @@ -0,0 +1,68 @@ +--- +title: except.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/indifferent_access_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/indifferent_access_rb.html new file mode 100644 index 0000000000..f82e93d808 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/indifferent_access_rb.html @@ -0,0 +1,83 @@ +--- +title: indifferent_access.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/hash_with_indifferent_access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/keys_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/keys_rb.html new file mode 100644 index 0000000000..ad2c272d3c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/keys_rb.html @@ -0,0 +1,68 @@ +--- +title: keys.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/reverse_merge_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/reverse_merge_rb.html new file mode 100644 index 0000000000..b98e5756d8 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/reverse_merge_rb.html @@ -0,0 +1,68 @@ +--- +title: reverse_merge.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash/slice_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/slice_rb.html new file mode 100644 index 0000000000..60baee8337 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash/slice_rb.html @@ -0,0 +1,68 @@ +--- +title: slice.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/hash_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/hash_rb.html new file mode 100644 index 0000000000..3b3af71122 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/hash_rb.html @@ -0,0 +1,77 @@ +--- +title: hash.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/conversions
  • + +
  • active_support/core_ext/hash/deep_merge
  • + +
  • active_support/core_ext/hash/deep_transform_values
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/hash/indifferent_access
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
  • active_support/core_ext/hash/slice
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/integer/inflections_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/inflections_rb.html new file mode 100644 index 0000000000..dbaa5c50b5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/inflections_rb.html @@ -0,0 +1,83 @@ +--- +title: inflections.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/integer/multiple_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/multiple_rb.html new file mode 100644 index 0000000000..962a634729 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/multiple_rb.html @@ -0,0 +1,68 @@ +--- +title: multiple.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/integer/time_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/time_rb.html new file mode 100644 index 0000000000..383d423714 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/integer/time_rb.html @@ -0,0 +1,85 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/duration
  • + +
  • active_support/core_ext/numeric/time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/integer_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/integer_rb.html new file mode 100644 index 0000000000..d51c8f4b34 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/integer_rb.html @@ -0,0 +1,67 @@ +--- +title: integer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/integer/multiple
  • + +
  • active_support/core_ext/integer/inflections
  • + +
  • active_support/core_ext/integer/time
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/concern_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/concern_rb.html new file mode 100644 index 0000000000..27132035d8 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/concern_rb.html @@ -0,0 +1,76 @@ +--- +title: concern.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/concerning
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/reporting_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/reporting_rb.html new file mode 100644 index 0000000000..af93426b2a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/reporting_rb.html @@ -0,0 +1,68 @@ +--- +title: reporting.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/singleton_class_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/singleton_class_rb.html new file mode 100644 index 0000000000..a0d508b9f9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel/singleton_class_rb.html @@ -0,0 +1,68 @@ +--- +title: singleton_class.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/kernel_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel_rb.html new file mode 100644 index 0000000000..222586c56c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/kernel_rb.html @@ -0,0 +1,67 @@ +--- +title: kernel.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/kernel/concern
  • + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/core_ext/kernel/singleton_class
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/load_error_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/load_error_rb.html new file mode 100644 index 0000000000..bcfee4c5f3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/load_error_rb.html @@ -0,0 +1,68 @@ +--- +title: load_error.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/aliasing_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/aliasing_rb.html new file mode 100644 index 0000000000..09e11bd352 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/aliasing_rb.html @@ -0,0 +1,68 @@ +--- +title: aliasing.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/anonymous_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/anonymous_rb.html new file mode 100644 index 0000000000..f887746f19 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/anonymous_rb.html @@ -0,0 +1,68 @@ +--- +title: anonymous.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/attr_internal_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attr_internal_rb.html new file mode 100644 index 0000000000..7c57123b05 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attr_internal_rb.html @@ -0,0 +1,68 @@ +--- +title: attr_internal.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread_rb.html new file mode 100644 index 0000000000..64d291c673 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_per_thread_rb.html @@ -0,0 +1,87 @@ +--- +title: attribute_accessors_per_thread.rb +layout: default +--- +
+ + +
+
+ +
+ +

Attribute Accessors per Thread

+ +

Extends the module object with class/module and instance accessors for class/module attributes, just like the native attr* accessors for instance attributes, but does so on a per-thread basis.

+ +

So the values are scoped within the Thread.current space under the class name of the module.

+ +

Note that it can also be scoped per-fiber if Rails.application.config.active_support.isolation_level is set to :fiber.

+ +
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_rb.html new file mode 100644 index 0000000000..cc41719a6a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/attribute_accessors_rb.html @@ -0,0 +1,76 @@ +--- +title: attribute_accessors.rb +layout: default +--- +
+ + +
+
+ +
+ +

Attribute Accessors

+ +

Extends the module object with class/module and instance accessors for class/module attributes, just like the native attr* accessors for instance attributes.

+ +
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/concerning_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/concerning_rb.html new file mode 100644 index 0000000000..f097c57fa2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/concerning_rb.html @@ -0,0 +1,83 @@ +--- +title: concerning.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/delegation_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/delegation_rb.html new file mode 100644 index 0000000000..28e99a9534 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/delegation_rb.html @@ -0,0 +1,78 @@ +--- +title: delegation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/deprecation_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/deprecation_rb.html new file mode 100644 index 0000000000..2a8b4f4dc5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/deprecation_rb.html @@ -0,0 +1,75 @@ +--- +title: deprecation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/introspection_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/introspection_rb.html new file mode 100644 index 0000000000..9f223522bc --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/introspection_rb.html @@ -0,0 +1,85 @@ +--- +title: introspection.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/inflector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/redefine_method_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/redefine_method_rb.html new file mode 100644 index 0000000000..35f62771f4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/redefine_method_rb.html @@ -0,0 +1,68 @@ +--- +title: redefine_method.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module/remove_method_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module/remove_method_rb.html new file mode 100644 index 0000000000..b100190ce7 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module/remove_method_rb.html @@ -0,0 +1,76 @@ +--- +title: remove_method.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/module_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/module_rb.html new file mode 100644 index 0000000000..257b36acb3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/module_rb.html @@ -0,0 +1,83 @@ +--- +title: module.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/aliasing
  • + +
  • active_support/core_ext/module/introspection
  • + +
  • active_support/core_ext/module/anonymous
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/module/attribute_accessors_per_thread
  • + +
  • active_support/core_ext/module/attr_internal
  • + +
  • active_support/core_ext/module/concerning
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/module/deprecation
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/module/remove_method
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/name_error_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/name_error_rb.html new file mode 100644 index 0000000000..59928d684d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/name_error_rb.html @@ -0,0 +1,68 @@ +--- +title: name_error.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/bytes_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/bytes_rb.html new file mode 100644 index 0000000000..0c5cd6b09c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/bytes_rb.html @@ -0,0 +1,68 @@ +--- +title: bytes.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/conversions_rb.html new file mode 100644 index 0000000000..416058ceb5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/conversions_rb.html @@ -0,0 +1,80 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/big_decimal/conversions
  • + +
  • active_support/number_helper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions_rb.html new file mode 100644 index 0000000000..31b2068f77 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/deprecated_conversions_rb.html @@ -0,0 +1,68 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/time_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/time_rb.html new file mode 100644 index 0000000000..f0442895c0 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric/time_rb.html @@ -0,0 +1,91 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/duration
  • + +
  • active_support/core_ext/time/calculations
  • + +
  • active_support/core_ext/time/acts_like
  • + +
  • active_support/core_ext/date/calculations
  • + +
  • active_support/core_ext/date/acts_like
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/numeric_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric_rb.html new file mode 100644 index 0000000000..0ec1e5d8be --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/numeric_rb.html @@ -0,0 +1,69 @@ +--- +title: numeric.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/numeric/bytes
  • + +
  • active_support/core_ext/numeric/time
  • + +
  • active_support/core_ext/numeric/conversions
  • + +
  • active_support/core_ext/numeric/deprecated_conversions
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/acts_like_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/acts_like_rb.html new file mode 100644 index 0000000000..6503c87510 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/acts_like_rb.html @@ -0,0 +1,68 @@ +--- +title: acts_like.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/blank_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/blank_rb.html new file mode 100644 index 0000000000..dea4554ed3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/blank_rb.html @@ -0,0 +1,92 @@ +--- +title: blank.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/conversions_rb.html new file mode 100644 index 0000000000..876290df3e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/conversions_rb.html @@ -0,0 +1,69 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/to_param
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/core_ext/array/conversions
  • + +
  • active_support/core_ext/hash/conversions
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/deep_dup_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/deep_dup_rb.html new file mode 100644 index 0000000000..b82532fbb2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/deep_dup_rb.html @@ -0,0 +1,80 @@ +--- +title: deep_dup.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/duplicable
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/duplicable_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/duplicable_rb.html new file mode 100644 index 0000000000..30342ad73f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/duplicable_rb.html @@ -0,0 +1,87 @@ +--- +title: duplicable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • singleton
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/inclusion_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/inclusion_rb.html new file mode 100644 index 0000000000..e459949b92 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/inclusion_rb.html @@ -0,0 +1,68 @@ +--- +title: inclusion.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/instance_variables_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/instance_variables_rb.html new file mode 100644 index 0000000000..153d9a835f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/instance_variables_rb.html @@ -0,0 +1,68 @@ +--- +title: instance_variables.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/json_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/json_rb.html new file mode 100644 index 0000000000..f55c4e58e6 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/json_rb.html @@ -0,0 +1,157 @@ +--- +title: json.rb +layout: default +--- +
+ + +
+
+ +
+ +

Hack to load json gem first so we can override its to_json.

+ +
+ + + + +

Required Files

+
    + +
  • json
  • + +
  • bigdecimal
  • + +
  • ipaddr
  • + +
  • uri/generic
  • + +
  • pathname
  • + +
  • active_support/core_ext/big_decimal/conversions
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/hash/slice
  • + +
  • active_support/core_ext/object/instance_variables
  • + +
  • time
  • + +
  • active_support/core_ext/time/conversions
  • + +
  • active_support/core_ext/date_time/conversions
  • + +
  • active_support/core_ext/date/conversions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_param_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_param_rb.html new file mode 100644 index 0000000000..ce99282b1d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_param_rb.html @@ -0,0 +1,63 @@ +--- +title: to_param.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/to_query
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_query_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_query_rb.html new file mode 100644 index 0000000000..2b0b34a273 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/to_query_rb.html @@ -0,0 +1,86 @@ +--- +title: to_query.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • cgi
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/try_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/try_rb.html new file mode 100644 index 0000000000..8c5e9c95a2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/try_rb.html @@ -0,0 +1,87 @@ +--- +title: try.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • delegate
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object/with_options_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object/with_options_rb.html new file mode 100644 index 0000000000..a45095296d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object/with_options_rb.html @@ -0,0 +1,83 @@ +--- +title: with_options.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/option_merger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/object_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/object_rb.html new file mode 100644 index 0000000000..2dd09e0e58 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/object_rb.html @@ -0,0 +1,85 @@ +--- +title: object.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/acts_like
  • + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/core_ext/object/duplicable
  • + +
  • active_support/core_ext/object/deep_dup
  • + +
  • active_support/core_ext/object/try
  • + +
  • active_support/core_ext/object/inclusion
  • + +
  • active_support/core_ext/object/conversions
  • + +
  • active_support/core_ext/object/instance_variables
  • + +
  • active_support/core_ext/object/json
  • + +
  • active_support/core_ext/object/to_param
  • + +
  • active_support/core_ext/object/to_query
  • + +
  • active_support/core_ext/object/with_options
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/pathname/existence_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/pathname/existence_rb.html new file mode 100644 index 0000000000..b2cd27dc97 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/pathname/existence_rb.html @@ -0,0 +1,68 @@ +--- +title: existence.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/pathname_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/pathname_rb.html new file mode 100644 index 0000000000..12e6365d29 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/pathname_rb.html @@ -0,0 +1,63 @@ +--- +title: pathname.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/pathname/existence
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/compare_range_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/compare_range_rb.html new file mode 100644 index 0000000000..614270bac7 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/compare_range_rb.html @@ -0,0 +1,70 @@ +--- +title: compare_range.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/conversions_rb.html new file mode 100644 index 0000000000..030ffa1dbe --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/conversions_rb.html @@ -0,0 +1,70 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/deprecated_conversions_rb.html new file mode 100644 index 0000000000..8c4de5eb1d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/deprecated_conversions_rb.html @@ -0,0 +1,70 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/each_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/each_rb.html new file mode 100644 index 0000000000..4962fc688f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/each_rb.html @@ -0,0 +1,76 @@ +--- +title: each.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/time_with_zone
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/include_time_with_zone_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/include_time_with_zone_rb.html new file mode 100644 index 0000000000..2220c553ee --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/include_time_with_zone_rb.html @@ -0,0 +1,68 @@ +--- +title: include_time_with_zone.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range/overlaps_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range/overlaps_rb.html new file mode 100644 index 0000000000..4737dd39cc --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range/overlaps_rb.html @@ -0,0 +1,68 @@ +--- +title: overlaps.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/range_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/range_rb.html new file mode 100644 index 0000000000..361d811ebd --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/range_rb.html @@ -0,0 +1,71 @@ +--- +title: range.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/range/conversions
  • + +
  • active_support/core_ext/range/deprecated_conversions
  • + +
  • active_support/core_ext/range/compare_range
  • + +
  • active_support/core_ext/range/overlaps
  • + +
  • active_support/core_ext/range/each
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/regexp_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/regexp_rb.html new file mode 100644 index 0000000000..40fe389f79 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/regexp_rb.html @@ -0,0 +1,68 @@ +--- +title: regexp.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/securerandom_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/securerandom_rb.html new file mode 100644 index 0000000000..192f0c2b98 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/securerandom_rb.html @@ -0,0 +1,76 @@ +--- +title: securerandom.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/access_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/access_rb.html new file mode 100644 index 0000000000..b5939b2e8c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/access_rb.html @@ -0,0 +1,68 @@ +--- +title: access.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/behavior_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/behavior_rb.html new file mode 100644 index 0000000000..3a527cd0b5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/behavior_rb.html @@ -0,0 +1,68 @@ +--- +title: behavior.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/conversions_rb.html new file mode 100644 index 0000000000..4c11326a26 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/conversions_rb.html @@ -0,0 +1,78 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • active_support/core_ext/time/calculations
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/exclude_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/exclude_rb.html new file mode 100644 index 0000000000..412238334d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/exclude_rb.html @@ -0,0 +1,68 @@ +--- +title: exclude.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/filters_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/filters_rb.html new file mode 100644 index 0000000000..9dbd173456 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/filters_rb.html @@ -0,0 +1,68 @@ +--- +title: filters.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/indent_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/indent_rb.html new file mode 100644 index 0000000000..eec99c6852 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/indent_rb.html @@ -0,0 +1,68 @@ +--- +title: indent.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/inflections_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/inflections_rb.html new file mode 100644 index 0000000000..334f77fc73 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/inflections_rb.html @@ -0,0 +1,85 @@ +--- +title: inflections.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/methods
  • + +
  • active_support/inflector/transliterate
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/inquiry_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/inquiry_rb.html new file mode 100644 index 0000000000..2baac1b18c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/inquiry_rb.html @@ -0,0 +1,85 @@ +--- +title: inquiry.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/string_inquirer
  • + +
  • active_support/environment_inquirer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/multibyte_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/multibyte_rb.html new file mode 100644 index 0000000000..be40ca1d1b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/multibyte_rb.html @@ -0,0 +1,83 @@ +--- +title: multibyte.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/multibyte
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/output_safety_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/output_safety_rb.html new file mode 100644 index 0000000000..0b8413fd46 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/output_safety_rb.html @@ -0,0 +1,99 @@ +--- +title: output_safety.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • erb
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/multibyte/unicode
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/starts_ends_with_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/starts_ends_with_rb.html new file mode 100644 index 0000000000..730edcbff1 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/starts_ends_with_rb.html @@ -0,0 +1,68 @@ +--- +title: starts_ends_with.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/strip_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/strip_rb.html new file mode 100644 index 0000000000..324111a2d9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/strip_rb.html @@ -0,0 +1,68 @@ +--- +title: strip.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string/zones_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string/zones_rb.html new file mode 100644 index 0000000000..216c73772c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string/zones_rb.html @@ -0,0 +1,78 @@ +--- +title: zones.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/conversions
  • + +
  • active_support/core_ext/time/zones
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/string_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/string_rb.html new file mode 100644 index 0000000000..84cf597267 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/string_rb.html @@ -0,0 +1,87 @@ +--- +title: string.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/conversions
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/core_ext/string/multibyte
  • + +
  • active_support/core_ext/string/starts_ends_with
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/string/access
  • + +
  • active_support/core_ext/string/behavior
  • + +
  • active_support/core_ext/string/output_safety
  • + +
  • active_support/core_ext/string/exclude
  • + +
  • active_support/core_ext/string/strip
  • + +
  • active_support/core_ext/string/inquiry
  • + +
  • active_support/core_ext/string/indent
  • + +
  • active_support/core_ext/string/zones
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/symbol/starts_ends_with_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/symbol/starts_ends_with_rb.html new file mode 100644 index 0000000000..ceef90ea8a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/symbol/starts_ends_with_rb.html @@ -0,0 +1,68 @@ +--- +title: starts_ends_with.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/symbol_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/symbol_rb.html new file mode 100644 index 0000000000..c4599ee338 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/symbol_rb.html @@ -0,0 +1,63 @@ +--- +title: symbol.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/symbol/starts_ends_with
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/acts_like_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/acts_like_rb.html new file mode 100644 index 0000000000..185a6c4738 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/acts_like_rb.html @@ -0,0 +1,76 @@ +--- +title: acts_like.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/acts_like
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/calculations_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/calculations_rb.html new file mode 100644 index 0000000000..735145b113 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/calculations_rb.html @@ -0,0 +1,95 @@ +--- +title: calculations.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/duration
  • + +
  • active_support/core_ext/time/conversions
  • + +
  • active_support/time_with_zone
  • + +
  • active_support/core_ext/time/zones
  • + +
  • active_support/core_ext/date_and_time/calculations
  • + +
  • active_support/core_ext/date/calculations
  • + +
  • active_support/core_ext/module/remove_method
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/compatibility_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/compatibility_rb.html new file mode 100644 index 0000000000..24fa4bc3cf --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/compatibility_rb.html @@ -0,0 +1,78 @@ +--- +title: compatibility.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/date_and_time/compatibility
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/conversions_rb.html new file mode 100644 index 0000000000..f9802f08b1 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/conversions_rb.html @@ -0,0 +1,87 @@ +--- +title: conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • time
  • + +
  • active_support/inflector/methods
  • + +
  • active_support/values/time_zone
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/deprecated_conversions_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/deprecated_conversions_rb.html new file mode 100644 index 0000000000..2afaec2de3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/deprecated_conversions_rb.html @@ -0,0 +1,85 @@ +--- +title: deprecated_conversions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time/zones_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time/zones_rb.html new file mode 100644 index 0000000000..76e2bc2e24 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time/zones_rb.html @@ -0,0 +1,87 @@ +--- +title: zones.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/time_with_zone
  • + +
  • active_support/core_ext/time/acts_like
  • + +
  • active_support/core_ext/date_and_time/zones
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/time_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/time_rb.html new file mode 100644 index 0000000000..80a8fa69ec --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/time_rb.html @@ -0,0 +1,73 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/time/acts_like
  • + +
  • active_support/core_ext/time/calculations
  • + +
  • active_support/core_ext/time/compatibility
  • + +
  • active_support/core_ext/time/conversions
  • + +
  • active_support/core_ext/time/deprecated_conversions
  • + +
  • active_support/core_ext/time/zones
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext/uri_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext/uri_rb.html new file mode 100644 index 0000000000..f0e7fd508d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext/uri_rb.html @@ -0,0 +1,68 @@ +--- +title: uri.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/core_ext_rb.html b/src/7.0/files/activesupport/lib/active_support/core_ext_rb.html new file mode 100644 index 0000000000..8f5db1e5f2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/core_ext_rb.html @@ -0,0 +1,55 @@ +--- +title: core_ext.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/current_attributes/test_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/current_attributes/test_helper_rb.html new file mode 100644 index 0000000000..4c5679a836 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/current_attributes/test_helper_rb.html @@ -0,0 +1,75 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/current_attributes_rb.html b/src/7.0/files/activesupport/lib/active_support/current_attributes_rb.html new file mode 100644 index 0000000000..5e43265387 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/current_attributes_rb.html @@ -0,0 +1,87 @@ +--- +title: current_attributes.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/dependencies/autoload_rb.html b/src/7.0/files/activesupport/lib/active_support/dependencies/autoload_rb.html new file mode 100644 index 0000000000..b30cb8ac50 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/dependencies/autoload_rb.html @@ -0,0 +1,78 @@ +--- +title: autoload.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/methods
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/dependencies/interlock_rb.html b/src/7.0/files/activesupport/lib/active_support/dependencies/interlock_rb.html new file mode 100644 index 0000000000..e78a136c87 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/dependencies/interlock_rb.html @@ -0,0 +1,87 @@ +--- +title: interlock.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concurrency/share_lock
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/dependencies/require_dependency_rb.html b/src/7.0/files/activesupport/lib/active_support/dependencies/require_dependency_rb.html new file mode 100644 index 0000000000..16d75074a7 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/dependencies/require_dependency_rb.html @@ -0,0 +1,72 @@ +--- +title: require_dependency.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/dependencies_rb.html b/src/7.0/files/activesupport/lib/active_support/dependencies_rb.html new file mode 100644 index 0000000000..2035352c09 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/dependencies_rb.html @@ -0,0 +1,80 @@ +--- +title: dependencies.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • set
  • + +
  • active_support/dependencies/interlock
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/behaviors_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/behaviors_rb.html new file mode 100644 index 0000000000..8dd81efa3d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/behaviors_rb.html @@ -0,0 +1,87 @@ +--- +title: behaviors.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/notifications
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/constant_accessor_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/constant_accessor_rb.html new file mode 100644 index 0000000000..82ceb7f444 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/constant_accessor_rb.html @@ -0,0 +1,85 @@ +--- +title: constant_accessor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/methods
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/disallowed_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/disallowed_rb.html new file mode 100644 index 0000000000..d3ae658ade --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/disallowed_rb.html @@ -0,0 +1,77 @@ +--- +title: disallowed.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/instance_delegator_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/instance_delegator_rb.html new file mode 100644 index 0000000000..dc257b5e8a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/instance_delegator_rb.html @@ -0,0 +1,83 @@ +--- +title: instance_delegator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/method_wrappers_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/method_wrappers_rb.html new file mode 100644 index 0000000000..dee5083826 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/method_wrappers_rb.html @@ -0,0 +1,87 @@ +--- +title: method_wrappers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/module/redefine_method
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/proxy_wrappers_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/proxy_wrappers_rb.html new file mode 100644 index 0000000000..d09f48cf15 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/proxy_wrappers_rb.html @@ -0,0 +1,89 @@ +--- +title: proxy_wrappers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/methods
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation/reporting_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation/reporting_rb.html new file mode 100644 index 0000000000..21ec854105 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation/reporting_rb.html @@ -0,0 +1,85 @@ +--- +title: reporting.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rbconfig
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/deprecation_rb.html b/src/7.0/files/activesupport/lib/active_support/deprecation_rb.html new file mode 100644 index 0000000000..7383319b6e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/deprecation_rb.html @@ -0,0 +1,101 @@ +--- +title: deprecation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • singleton
  • + +
  • active_support/deprecation/instance_delegator
  • + +
  • active_support/deprecation/behaviors
  • + +
  • active_support/deprecation/reporting
  • + +
  • active_support/deprecation/disallowed
  • + +
  • active_support/deprecation/constant_accessor
  • + +
  • active_support/deprecation/method_wrappers
  • + +
  • active_support/deprecation/proxy_wrappers
  • + +
  • active_support/core_ext/module/deprecation
  • + +
  • concurrent/atomic/thread_local_var
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/descendants_tracker_rb.html b/src/7.0/files/activesupport/lib/active_support/descendants_tracker_rb.html new file mode 100644 index 0000000000..da5bde0055 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/descendants_tracker_rb.html @@ -0,0 +1,80 @@ +--- +title: descendants_tracker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • weakref
  • + +
  • active_support/ruby_features
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/digest_rb.html b/src/7.0/files/activesupport/lib/active_support/digest_rb.html new file mode 100644 index 0000000000..44bd5b4139 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/digest_rb.html @@ -0,0 +1,78 @@ +--- +title: digest.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/duration/iso8601_parser_rb.html b/src/7.0/files/activesupport/lib/active_support/duration/iso8601_parser_rb.html new file mode 100644 index 0000000000..60eec510a3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/duration/iso8601_parser_rb.html @@ -0,0 +1,87 @@ +--- +title: iso8601_parser.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • strscan
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/duration/iso8601_serializer_rb.html b/src/7.0/files/activesupport/lib/active_support/duration/iso8601_serializer_rb.html new file mode 100644 index 0000000000..26a0f9c545 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/duration/iso8601_serializer_rb.html @@ -0,0 +1,83 @@ +--- +title: iso8601_serializer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/blank
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/duration_rb.html b/src/7.0/files/activesupport/lib/active_support/duration_rb.html new file mode 100644 index 0000000000..a2854681c7 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/duration_rb.html @@ -0,0 +1,89 @@ +--- +title: duration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/array/conversions
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/object/acts_like
  • + +
  • active_support/core_ext/string/filters
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/encrypted_configuration_rb.html b/src/7.0/files/activesupport/lib/active_support/encrypted_configuration_rb.html new file mode 100644 index 0000000000..9fbf85d000 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/encrypted_configuration_rb.html @@ -0,0 +1,91 @@ +--- +title: encrypted_configuration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
  • active_support/encrypted_file
  • + +
  • active_support/ordered_options
  • + +
  • active_support/core_ext/object/inclusion
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/encrypted_file_rb.html b/src/7.0/files/activesupport/lib/active_support/encrypted_file_rb.html new file mode 100644 index 0000000000..ae665154ee --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/encrypted_file_rb.html @@ -0,0 +1,93 @@ +--- +title: encrypted_file.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • tempfile
  • + +
  • active_support/message_encryptor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/environment_inquirer_rb.html b/src/7.0/files/activesupport/lib/active_support/environment_inquirer_rb.html new file mode 100644 index 0000000000..71a7879ef4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/environment_inquirer_rb.html @@ -0,0 +1,76 @@ +--- +title: environment_inquirer.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/string_inquirer
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/error_reporter_rb.html b/src/7.0/files/activesupport/lib/active_support/error_reporter_rb.html new file mode 100644 index 0000000000..dc0413c873 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/error_reporter_rb.html @@ -0,0 +1,75 @@ +--- +title: error_reporter.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/evented_file_update_checker_rb.html b/src/7.0/files/activesupport/lib/active_support/evented_file_update_checker_rb.html new file mode 100644 index 0000000000..5ee73fd5af --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/evented_file_update_checker_rb.html @@ -0,0 +1,93 @@ +--- +title: evented_file_update_checker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • listen
  • + +
  • set
  • + +
  • pathname
  • + +
  • concurrent/atomic/atomic_boolean
  • + +
  • active_support/fork_tracker
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/execution_context/test_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/execution_context/test_helper_rb.html new file mode 100644 index 0000000000..c950661738 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/execution_context/test_helper_rb.html @@ -0,0 +1,68 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/execution_context_rb.html b/src/7.0/files/activesupport/lib/active_support/execution_context_rb.html new file mode 100644 index 0000000000..1fa11679e6 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/execution_context_rb.html @@ -0,0 +1,68 @@ +--- +title: execution_context.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/execution_wrapper_rb.html b/src/7.0/files/activesupport/lib/active_support/execution_wrapper_rb.html new file mode 100644 index 0000000000..10df43f8f1 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/execution_wrapper_rb.html @@ -0,0 +1,87 @@ +--- +title: execution_wrapper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/error_reporter
  • + +
  • active_support/callbacks
  • + +
  • concurrent/hash
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/executor/test_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/executor/test_helper_rb.html new file mode 100644 index 0000000000..03d4fb4f38 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/executor/test_helper_rb.html @@ -0,0 +1,75 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/executor_rb.html b/src/7.0/files/activesupport/lib/active_support/executor_rb.html new file mode 100644 index 0000000000..335ce2e0c1 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/executor_rb.html @@ -0,0 +1,83 @@ +--- +title: executor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/execution_wrapper
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/file_update_checker_rb.html b/src/7.0/files/activesupport/lib/active_support/file_update_checker_rb.html new file mode 100644 index 0000000000..45eebfd1aa --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/file_update_checker_rb.html @@ -0,0 +1,83 @@ +--- +title: file_update_checker.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/time/calculations
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/fork_tracker_rb.html b/src/7.0/files/activesupport/lib/active_support/fork_tracker_rb.html new file mode 100644 index 0000000000..e723afdc92 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/fork_tracker_rb.html @@ -0,0 +1,76 @@ +--- +title: fork_tracker.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/gem_version_rb.html b/src/7.0/files/activesupport/lib/active_support/gem_version_rb.html new file mode 100644 index 0000000000..a483ac26e0 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/gzip_rb.html b/src/7.0/files/activesupport/lib/active_support/gzip_rb.html new file mode 100644 index 0000000000..0671e716eb --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/gzip_rb.html @@ -0,0 +1,87 @@ +--- +title: gzip.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • zlib
  • + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/hash_with_indifferent_access_rb.html b/src/7.0/files/activesupport/lib/active_support/hash_with_indifferent_access_rb.html new file mode 100644 index 0000000000..e7a55f80a4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/hash_with_indifferent_access_rb.html @@ -0,0 +1,89 @@ +--- +title: hash_with_indifferent_access.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/hash/slice
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/html_safe_translation_rb.html b/src/7.0/files/activesupport/lib/active_support/html_safe_translation_rb.html new file mode 100644 index 0000000000..4aeff9b286 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/html_safe_translation_rb.html @@ -0,0 +1,75 @@ +--- +title: html_safe_translation.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/i18n_railtie_rb.html b/src/7.0/files/activesupport/lib/active_support/i18n_railtie_rb.html new file mode 100644 index 0000000000..2341148507 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/i18n_railtie_rb.html @@ -0,0 +1,65 @@ +--- +title: i18n_railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/core_ext/array/wrap
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/i18n_rb.html b/src/7.0/files/activesupport/lib/active_support/i18n_rb.html new file mode 100644 index 0000000000..98b7c75019 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/i18n_rb.html @@ -0,0 +1,73 @@ +--- +title: i18n.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/deep_merge
  • + +
  • active_support/core_ext/hash/except
  • + +
  • active_support/core_ext/hash/slice
  • + +
  • i18n
  • + +
  • i18n/backend/fallbacks
  • + +
  • active_support/lazy_load_hooks
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/inflections_rb.html b/src/7.0/files/activesupport/lib/active_support/inflections_rb.html new file mode 100644 index 0000000000..6801f16d5c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/inflections_rb.html @@ -0,0 +1,76 @@ +--- +title: inflections.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/inflector/inflections_rb.html b/src/7.0/files/activesupport/lib/active_support/inflector/inflections_rb.html new file mode 100644 index 0000000000..80b8119638 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/inflector/inflections_rb.html @@ -0,0 +1,89 @@ +--- +title: inflections.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
  • active_support/i18n
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/inflector/methods_rb.html b/src/7.0/files/activesupport/lib/active_support/inflector/methods_rb.html new file mode 100644 index 0000000000..e9ca6f5397 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/inflector/methods_rb.html @@ -0,0 +1,80 @@ +--- +title: methods.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflections
  • + +
  • active_support/core_ext/object/blank
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/inflector/transliterate_rb.html b/src/7.0/files/activesupport/lib/active_support/inflector/transliterate_rb.html new file mode 100644 index 0000000000..f380531b9e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/inflector/transliterate_rb.html @@ -0,0 +1,80 @@ +--- +title: transliterate.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/multibyte
  • + +
  • active_support/i18n
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/inflector_rb.html b/src/7.0/files/activesupport/lib/active_support/inflector_rb.html new file mode 100644 index 0000000000..8456208d62 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/inflector_rb.html @@ -0,0 +1,77 @@ +--- +title: inflector.rb +layout: default +--- +
+ + +
+
+ +
+ +

in case active_support/inflector is required without the rest of active_support

+ +
+ + + + +

Required Files

+
    + +
  • active_support/inflector/inflections
  • + +
  • active_support/inflector/transliterate
  • + +
  • active_support/inflector/methods
  • + +
  • active_support/inflections
  • + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/isolated_execution_state_rb.html b/src/7.0/files/activesupport/lib/active_support/isolated_execution_state_rb.html new file mode 100644 index 0000000000..cd2c94a054 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/isolated_execution_state_rb.html @@ -0,0 +1,76 @@ +--- +title: isolated_execution_state.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fiber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/json/decoding_rb.html b/src/7.0/files/activesupport/lib/active_support/json/decoding_rb.html new file mode 100644 index 0000000000..4da853f91c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/json/decoding_rb.html @@ -0,0 +1,82 @@ +--- +title: decoding.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • json
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/json/encoding_rb.html b/src/7.0/files/activesupport/lib/active_support/json/encoding_rb.html new file mode 100644 index 0000000000..3d2e0ec781 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/json/encoding_rb.html @@ -0,0 +1,80 @@ +--- +title: encoding.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/json
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/json_rb.html b/src/7.0/files/activesupport/lib/active_support/json_rb.html new file mode 100644 index 0000000000..faafb8952c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/json_rb.html @@ -0,0 +1,65 @@ +--- +title: json.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/json/decoding
  • + +
  • active_support/json/encoding
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/key_generator_rb.html b/src/7.0/files/activesupport/lib/active_support/key_generator_rb.html new file mode 100644 index 0000000000..3786d1dd91 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/key_generator_rb.html @@ -0,0 +1,89 @@ +--- +title: key_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • concurrent/map
  • + +
  • openssl
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/lazy_load_hooks_rb.html b/src/7.0/files/activesupport/lib/active_support/lazy_load_hooks_rb.html new file mode 100644 index 0000000000..c9decbb816 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/lazy_load_hooks_rb.html @@ -0,0 +1,70 @@ +--- +title: lazy_load_hooks.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/locale/en_rb.html b/src/7.0/files/activesupport/lib/active_support/locale/en_rb.html new file mode 100644 index 0000000000..5d6c03c74d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/locale/en_rb.html @@ -0,0 +1,55 @@ +--- +title: en.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/log_subscriber/test_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/log_subscriber/test_helper_rb.html new file mode 100644 index 0000000000..e6a463f097 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/log_subscriber/test_helper_rb.html @@ -0,0 +1,91 @@ +--- +title: test_helper.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/log_subscriber
  • + +
  • active_support/logger
  • + +
  • active_support/notifications
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/log_subscriber_rb.html b/src/7.0/files/activesupport/lib/active_support/log_subscriber_rb.html new file mode 100644 index 0000000000..51309db677 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/log_subscriber_rb.html @@ -0,0 +1,87 @@ +--- +title: log_subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/subscriber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/logger_rb.html b/src/7.0/files/activesupport/lib/active_support/logger_rb.html new file mode 100644 index 0000000000..037679169a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/logger_rb.html @@ -0,0 +1,89 @@ +--- +title: logger.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/logger_silence
  • + +
  • active_support/logger_thread_safe_level
  • + +
  • logger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/logger_silence_rb.html b/src/7.0/files/activesupport/lib/active_support/logger_silence_rb.html new file mode 100644 index 0000000000..3b7ec6a622 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/logger_silence_rb.html @@ -0,0 +1,82 @@ +--- +title: logger_silence.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/logger_thread_safe_level
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/logger_thread_safe_level_rb.html b/src/7.0/files/activesupport/lib/active_support/logger_thread_safe_level_rb.html new file mode 100644 index 0000000000..5d3982912c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/logger_thread_safe_level_rb.html @@ -0,0 +1,89 @@ +--- +title: logger_thread_safe_level.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • concurrent
  • + +
  • fiber
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/message_encryptor_rb.html b/src/7.0/files/activesupport/lib/active_support/message_encryptor_rb.html new file mode 100644 index 0000000000..827b07b74b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/message_encryptor_rb.html @@ -0,0 +1,93 @@ +--- +title: message_encryptor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • openssl
  • + +
  • base64
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/message_verifier
  • + +
  • active_support/messages/metadata
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/message_verifier_rb.html b/src/7.0/files/activesupport/lib/active_support/message_verifier_rb.html new file mode 100644 index 0000000000..965b641fb3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/message_verifier_rb.html @@ -0,0 +1,95 @@ +--- +title: message_verifier.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • openssl
  • + +
  • base64
  • + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/security_utils
  • + +
  • active_support/messages/metadata
  • + +
  • active_support/messages/rotator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/messages/metadata_rb.html b/src/7.0/files/activesupport/lib/active_support/messages/metadata_rb.html new file mode 100644 index 0000000000..6c9c1c83a9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/messages/metadata_rb.html @@ -0,0 +1,78 @@ +--- +title: metadata.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/messages/rotation_configuration_rb.html b/src/7.0/files/activesupport/lib/active_support/messages/rotation_configuration_rb.html new file mode 100644 index 0000000000..fe1e8b2e8a --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/messages/rotation_configuration_rb.html @@ -0,0 +1,70 @@ +--- +title: rotation_configuration.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/messages/rotator_rb.html b/src/7.0/files/activesupport/lib/active_support/messages/rotator_rb.html new file mode 100644 index 0000000000..0f3c7de897 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/messages/rotator_rb.html @@ -0,0 +1,76 @@ +--- +title: rotator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/multibyte/chars_rb.html b/src/7.0/files/activesupport/lib/active_support/multibyte/chars_rb.html new file mode 100644 index 0000000000..f33dff823d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/multibyte/chars_rb.html @@ -0,0 +1,91 @@ +--- +title: chars.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/json
  • + +
  • active_support/core_ext/string/access
  • + +
  • active_support/core_ext/string/behavior
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/multibyte/unicode_rb.html b/src/7.0/files/activesupport/lib/active_support/multibyte/unicode_rb.html new file mode 100644 index 0000000000..cdf02217d9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/multibyte/unicode_rb.html @@ -0,0 +1,72 @@ +--- +title: unicode.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/multibyte_rb.html b/src/7.0/files/activesupport/lib/active_support/multibyte_rb.html new file mode 100644 index 0000000000..55d5e6cf33 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/multibyte_rb.html @@ -0,0 +1,70 @@ +--- +title: multibyte.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/notifications/fanout_rb.html b/src/7.0/files/activesupport/lib/active_support/notifications/fanout_rb.html new file mode 100644 index 0000000000..a60969208c --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/notifications/fanout_rb.html @@ -0,0 +1,103 @@ +--- +title: fanout.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • mutex_m
  • + +
  • concurrent/map
  • + +
  • set
  • + +
  • active_support/core_ext/object/try
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/notifications/instrumenter_rb.html b/src/7.0/files/activesupport/lib/active_support/notifications/instrumenter_rb.html new file mode 100644 index 0000000000..2dd2f4f3c3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/notifications/instrumenter_rb.html @@ -0,0 +1,89 @@ +--- +title: instrumenter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • securerandom
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/notifications_rb.html b/src/7.0/files/activesupport/lib/active_support/notifications_rb.html new file mode 100644 index 0000000000..5634f27ebd --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/notifications_rb.html @@ -0,0 +1,80 @@ +--- +title: notifications.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/notifications/instrumenter
  • + +
  • active_support/notifications/fanout
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_converter_rb.html new file mode 100644 index 0000000000..18d3c8b970 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_converter_rb.html @@ -0,0 +1,86 @@ +--- +title: number_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/big_decimal/conversions
  • + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/i18n
  • + +
  • active_support/core_ext/class/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_currency_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_currency_converter_rb.html new file mode 100644 index 0000000000..f7b4dc1db9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_currency_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_currency_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_delimited_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_delimited_converter_rb.html new file mode 100644 index 0000000000..e9cfcc717b --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_delimited_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_delimited_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_converter_rb.html new file mode 100644 index 0000000000..0c76022feb --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_human_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_size_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_size_converter_rb.html new file mode 100644 index 0000000000..cdc80b875e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_human_size_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_human_size_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_percentage_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_percentage_converter_rb.html new file mode 100644 index 0000000000..aca1d13abe --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_percentage_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_percentage_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_phone_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_phone_converter_rb.html new file mode 100644 index 0000000000..0680cae9a9 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_phone_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_phone_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_rounded_converter_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_rounded_converter_rb.html new file mode 100644 index 0000000000..e9a97cb1fb --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/number_to_rounded_converter_rb.html @@ -0,0 +1,78 @@ +--- +title: number_to_rounded_converter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/number_helper/number_converter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper/rounding_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper/rounding_helper_rb.html new file mode 100644 index 0000000000..3735cfc2cf --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper/rounding_helper_rb.html @@ -0,0 +1,70 @@ +--- +title: rounding_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/number_helper_rb.html b/src/7.0/files/activesupport/lib/active_support/number_helper_rb.html new file mode 100644 index 0000000000..e48b2b11a0 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/number_helper_rb.html @@ -0,0 +1,70 @@ +--- +title: number_helper.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/option_merger_rb.html b/src/7.0/files/activesupport/lib/active_support/option_merger_rb.html new file mode 100644 index 0000000000..af09ac2657 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/option_merger_rb.html @@ -0,0 +1,76 @@ +--- +title: option_merger.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/deep_merge
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/ordered_hash_rb.html b/src/7.0/files/activesupport/lib/active_support/ordered_hash_rb.html new file mode 100644 index 0000000000..69ed755455 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/ordered_hash_rb.html @@ -0,0 +1,76 @@ +--- +title: ordered_hash.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/ordered_options_rb.html b/src/7.0/files/activesupport/lib/active_support/ordered_options_rb.html new file mode 100644 index 0000000000..b433484a16 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/ordered_options_rb.html @@ -0,0 +1,85 @@ +--- +title: ordered_options.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/blank
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/parameter_filter_rb.html b/src/7.0/files/activesupport/lib/active_support/parameter_filter_rb.html new file mode 100644 index 0000000000..be050c1963 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/parameter_filter_rb.html @@ -0,0 +1,83 @@ +--- +title: parameter_filter.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/duplicable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/per_thread_registry_rb.html b/src/7.0/files/activesupport/lib/active_support/per_thread_registry_rb.html new file mode 100644 index 0000000000..93186817e5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/per_thread_registry_rb.html @@ -0,0 +1,78 @@ +--- +title: per_thread_registry.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/proxy_object_rb.html b/src/7.0/files/activesupport/lib/active_support/proxy_object_rb.html new file mode 100644 index 0000000000..eef9efccff --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/proxy_object_rb.html @@ -0,0 +1,75 @@ +--- +title: proxy_object.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/rails_rb.html b/src/7.0/files/activesupport/lib/active_support/rails_rb.html new file mode 100644 index 0000000000..7c2048b735 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/rails_rb.html @@ -0,0 +1,81 @@ +--- +title: rails.rb +layout: default +--- +
+ + +
+
+ +
+ +

This is a private interface.

+ +

Rails components cherry pick from Active Support as needed, but there are a few features that are used for sure in some way or another and it is not worth putting individual requires absolutely everywhere. Think blank? for example.

+ +

This file is loaded by every Rails component except Active Support itself, but it does not belong to the Rails public interface. It is internal to Rails and can change anytime.

+ +
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/concern
  • + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/deprecation
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/railtie_rb.html b/src/7.0/files/activesupport/lib/active_support/railtie_rb.html new file mode 100644 index 0000000000..10391c49b4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/railtie_rb.html @@ -0,0 +1,92 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/i18n_railtie
  • + +
  • active_support/time_with_zone
  • + +
  • active_support/executor/test_helper
  • + +
  • active_support/current_attributes/test_helper
  • + +
  • active_support/execution_context/test_helper
  • + +
  • active_support/core_ext/time/zones
  • + +
  • active_support/core_ext/date/calculations
  • + +
  • active_support/core_ext/digest
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/reloader_rb.html b/src/7.0/files/activesupport/lib/active_support/reloader_rb.html new file mode 100644 index 0000000000..5350fc7ca5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/reloader_rb.html @@ -0,0 +1,85 @@ +--- +title: reloader.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/execution_wrapper
  • + +
  • active_support/executor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/rescuable_rb.html b/src/7.0/files/activesupport/lib/active_support/rescuable_rb.html new file mode 100644 index 0000000000..13e2514140 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/rescuable_rb.html @@ -0,0 +1,84 @@ +--- +title: rescuable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/ruby_features_rb.html b/src/7.0/files/activesupport/lib/active_support/ruby_features_rb.html new file mode 100644 index 0000000000..23d03c4214 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/ruby_features_rb.html @@ -0,0 +1,68 @@ +--- +title: ruby_features.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/secure_compare_rotator_rb.html b/src/7.0/files/activesupport/lib/active_support/secure_compare_rotator_rb.html new file mode 100644 index 0000000000..120323eaed --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/secure_compare_rotator_rb.html @@ -0,0 +1,87 @@ +--- +title: secure_compare_rotator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/security_utils
  • + +
  • active_support/messages/rotator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/security_utils_rb.html b/src/7.0/files/activesupport/lib/active_support/security_utils_rb.html new file mode 100644 index 0000000000..938ca8da5f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/security_utils_rb.html @@ -0,0 +1,70 @@ +--- +title: security_utils.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/string_inquirer_rb.html b/src/7.0/files/activesupport/lib/active_support/string_inquirer_rb.html new file mode 100644 index 0000000000..9b98f3f4c2 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/string_inquirer_rb.html @@ -0,0 +1,75 @@ +--- +title: string_inquirer.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/subscriber_rb.html b/src/7.0/files/activesupport/lib/active_support/subscriber_rb.html new file mode 100644 index 0000000000..8bc970b2ca --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/subscriber_rb.html @@ -0,0 +1,85 @@ +--- +title: subscriber.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/notifications
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/tagged_logging_rb.html b/src/7.0/files/activesupport/lib/active_support/tagged_logging_rb.html new file mode 100644 index 0000000000..892853fb07 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/tagged_logging_rb.html @@ -0,0 +1,91 @@ +--- +title: tagged_logging.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/object/blank
  • + +
  • logger
  • + +
  • active_support/logger
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/test_case_rb.html b/src/7.0/files/activesupport/lib/active_support/test_case_rb.html new file mode 100644 index 0000000000..813da9b778 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/test_case_rb.html @@ -0,0 +1,107 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • minitest
  • + +
  • active_support/testing/tagged_logging
  • + +
  • active_support/testing/setup_and_teardown
  • + +
  • active_support/testing/assertions
  • + +
  • active_support/testing/deprecation
  • + +
  • active_support/testing/declarative
  • + +
  • active_support/testing/isolation
  • + +
  • active_support/testing/constant_lookup
  • + +
  • active_support/testing/time_helpers
  • + +
  • active_support/testing/file_fixtures
  • + +
  • active_support/testing/parallelization
  • + +
  • active_support/testing/parallelize_executor
  • + +
  • concurrent/utility/processor_counter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/assertions_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/assertions_rb.html new file mode 100644 index 0000000000..cd56eab84e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/assertions_rb.html @@ -0,0 +1,82 @@ +--- +title: assertions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/autorun_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/autorun_rb.html new file mode 100644 index 0000000000..103c257a13 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/autorun_rb.html @@ -0,0 +1,63 @@ +--- +title: autorun.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • minitest
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/constant_lookup_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/constant_lookup_rb.html new file mode 100644 index 0000000000..ba16472273 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/constant_lookup_rb.html @@ -0,0 +1,82 @@ +--- +title: constant_lookup.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • active_support/inflector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/declarative_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/declarative_rb.html new file mode 100644 index 0000000000..af4123fc36 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/declarative_rb.html @@ -0,0 +1,72 @@ +--- +title: declarative.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/deprecation_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/deprecation_rb.html new file mode 100644 index 0000000000..fefceaec61 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/deprecation_rb.html @@ -0,0 +1,80 @@ +--- +title: deprecation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/deprecation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/file_fixtures_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/file_fixtures_rb.html new file mode 100644 index 0000000000..18337caa2d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/file_fixtures_rb.html @@ -0,0 +1,80 @@ +--- +title: file_fixtures.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/isolation_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/isolation_rb.html new file mode 100644 index 0000000000..a42b906fd5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/isolation_rb.html @@ -0,0 +1,88 @@ +--- +title: isolation.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thread
  • + +
  • tempfile
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/method_call_assertions_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/method_call_assertions_rb.html new file mode 100644 index 0000000000..973dc62f01 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/method_call_assertions_rb.html @@ -0,0 +1,80 @@ +--- +title: method_call_assertions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • minitest/mock
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/parallelization/server_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/parallelization/server_rb.html new file mode 100644 index 0000000000..f441be7b17 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/parallelization/server_rb.html @@ -0,0 +1,91 @@ +--- +title: server.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • drb
  • + +
  • drb/unix
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/parallelization/worker_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/parallelization/worker_rb.html new file mode 100644 index 0000000000..cebe15ed66 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/parallelization/worker_rb.html @@ -0,0 +1,81 @@ +--- +title: worker.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/parallelization_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/parallelization_rb.html new file mode 100644 index 0000000000..518e7bfa38 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/parallelization_rb.html @@ -0,0 +1,93 @@ +--- +title: parallelization.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • drb
  • + +
  • drb/unix
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/testing/parallelization/server
  • + +
  • active_support/testing/parallelization/worker
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/parallelize_executor_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/parallelize_executor_rb.html new file mode 100644 index 0000000000..3426abb3c5 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/parallelize_executor_rb.html @@ -0,0 +1,72 @@ +--- +title: parallelize_executor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/setup_and_teardown_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/setup_and_teardown_rb.html new file mode 100644 index 0000000000..a87569c194 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/setup_and_teardown_rb.html @@ -0,0 +1,84 @@ +--- +title: setup_and_teardown.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/callbacks
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/stream_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/stream_rb.html new file mode 100644 index 0000000000..eb10998f5d --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/stream_rb.html @@ -0,0 +1,77 @@ +--- +title: stream.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+
    + +
  • IO
  • + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/tagged_logging_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/tagged_logging_rb.html new file mode 100644 index 0000000000..7601dfa243 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/tagged_logging_rb.html @@ -0,0 +1,70 @@ +--- +title: tagged_logging.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/testing/time_helpers_rb.html b/src/7.0/files/activesupport/lib/active_support/testing/time_helpers_rb.html new file mode 100644 index 0000000000..8b570530be --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/testing/time_helpers_rb.html @@ -0,0 +1,84 @@ +--- +title: time_helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/redefine_method
  • + +
  • active_support/core_ext/time/calculations
  • + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/time_rb.html b/src/7.0/files/activesupport/lib/active_support/time_rb.html new file mode 100644 index 0000000000..9d061994c4 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/time_rb.html @@ -0,0 +1,92 @@ +--- +title: time.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • date
  • + +
  • time
  • + +
  • active_support/core_ext/time
  • + +
  • active_support/core_ext/date
  • + +
  • active_support/core_ext/date_time
  • + +
  • active_support/core_ext/integer/time
  • + +
  • active_support/core_ext/numeric/time
  • + +
  • active_support/core_ext/string/conversions
  • + +
  • active_support/core_ext/string/zones
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/time_with_zone_rb.html b/src/7.0/files/activesupport/lib/active_support/time_with_zone_rb.html new file mode 100644 index 0000000000..0cfb1cc95e --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/time_with_zone_rb.html @@ -0,0 +1,95 @@ +--- +title: time_with_zone.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
  • active_support/duration
  • + +
  • active_support/values/time_zone
  • + +
  • active_support/core_ext/object/acts_like
  • + +
  • active_support/core_ext/date_and_time/compatibility
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/values/time_zone_rb.html b/src/7.0/files/activesupport/lib/active_support/values/time_zone_rb.html new file mode 100644 index 0000000000..b2ad10baf8 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/values/time_zone_rb.html @@ -0,0 +1,85 @@ +--- +title: time_zone.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • tzinfo
  • + +
  • concurrent/map
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/version_rb.html b/src/7.0/files/activesupport/lib/active_support/version_rb.html new file mode 100644 index 0000000000..001aff4a83 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/version_rb.html @@ -0,0 +1,68 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/jdom_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/jdom_rb.html new file mode 100644 index 0000000000..0ff1511921 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/jdom_rb.html @@ -0,0 +1,78 @@ +--- +title: jdom.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • jruby
  • + +
  • active_support/core_ext/object/blank
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/libxml_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/libxml_rb.html new file mode 100644 index 0000000000..0cd389684f --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/libxml_rb.html @@ -0,0 +1,80 @@ +--- +title: libxml.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • libxml
  • + +
  • active_support/core_ext/object/blank
  • + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/libxmlsax_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/libxmlsax_rb.html new file mode 100644 index 0000000000..5172081c48 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/libxmlsax_rb.html @@ -0,0 +1,89 @@ +--- +title: libxmlsax.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • libxml
  • + +
  • active_support/core_ext/object/blank
  • + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogiri_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogiri_rb.html new file mode 100644 index 0000000000..405ba87131 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogiri_rb.html @@ -0,0 +1,80 @@ +--- +title: nokogiri.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • nokogiri
  • + +
  • active_support/core_ext/object/blank
  • + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogirisax_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogirisax_rb.html new file mode 100644 index 0000000000..bdb50d15c3 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/nokogirisax_rb.html @@ -0,0 +1,89 @@ +--- +title: nokogirisax.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • nokogiri
  • + +
  • active_support/core_ext/object/blank
  • + +
  • stringio
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini/rexml_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini/rexml_rb.html new file mode 100644 index 0000000000..251b0712f6 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini/rexml_rb.html @@ -0,0 +1,82 @@ +--- +title: rexml.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/core_ext/object/blank
  • + +
  • stringio
  • + +
  • rexml/document
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/activesupport/lib/active_support/xml_mini_rb.html b/src/7.0/files/activesupport/lib/active_support/xml_mini_rb.html new file mode 100644 index 0000000000..d1e8951022 --- /dev/null +++ b/src/7.0/files/activesupport/lib/active_support/xml_mini_rb.html @@ -0,0 +1,90 @@ +--- +title: xml_mini.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • time
  • + +
  • base64
  • + +
  • bigdecimal
  • + +
  • bigdecimal/util
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/date_time/calculations
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/RDOC_MAIN_rdoc.html b/src/7.0/files/railties/RDOC_MAIN_rdoc.html new file mode 100644 index 0000000000..e98318ecf7 --- /dev/null +++ b/src/7.0/files/railties/RDOC_MAIN_rdoc.html @@ -0,0 +1,131 @@ +--- +title: RDOC_MAIN.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Welcome to Rails

+ +

What’s Rails

+ +

Rails is a web-application framework that includes everything needed to create database-backed web applications according to the Model-View-Controller (MVC) pattern.

+ +

Understanding the MVC pattern is key to understanding Rails. MVC divides your application into three layers: Model, View, and Controller, each with a specific responsibility.

+ +

Model layer

+ +

The Model layer represents the domain model (such as Account, Product, Person, Post, etc.) and encapsulates the business logic specific to your application. In Rails, database-backed model classes are derived from ActiveRecord::Base. Active Record allows you to present the data from database rows as objects and embellish these data objects with business logic methods. Although most Rails models are backed by a database, models can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as provided by the Active Model module.

+ +

Controller layer

+ +

The Controller layer is responsible for handling incoming HTTP requests and providing a suitable response. Usually, this means returning HTML, but Rails controllers can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers load and manipulate models and render view templates in order to generate the appropriate HTTP response. In Rails, incoming requests are routed by Action Dispatch to an appropriate controller, and controller classes are derived from ActionController::Base. Action Dispatch and Action Controller are bundled together in Action Pack.

+ +

View layer

+ +

The View layer is composed of “templates” that are responsible for providing appropriate representations of your application’s resources. Templates can come in a variety of formats, but most view templates are HTML with embedded Ruby code (ERB files). Views are typically rendered to generate a controller response, or to generate the body of an email. In Rails, View generation is handled by Action View.

+ +

Frameworks and libraries

+ +

Active Record, Active Model, Action Pack, and Action View can each be used independently outside Rails. In addition to that, Rails also comes with Action Mailer, a library to generate and send emails; Action Mailbox, a library to receive emails within a Rails application; Active Job, a framework for declaring jobs and making them run on a variety of queueing backends; Action Cable, a framework to integrate WebSockets with a Rails application; Active Storage, a library to attach cloud and local files to Rails applications; Action Text, a library to handle rich text content; and Active Support, a collection of utility classes and standard library extensions that are useful for Rails, and may also be used independently outside Rails.

+ +

Getting Started

+
  1. +

    Install Rails at the command prompt if you haven’t yet:

    + +
    $ gem install rails
    +
    +
  2. +

    At the command prompt, create a new Rails application:

    + +
    $ rails new myapp
    +
    + +

    where “myapp” is the application name.

    +
  3. +

    Change directory to myapp and start the web server:

    + +
    $ cd myapp
    +$ bin/rails server
    +
    + +

    Run with --help or -h for options.

    +
  4. +

    Go to http://localhost:3000, and you’ll see: “Yay! You’re on Rails!”

    +
  5. +

    Follow the guidelines to start developing your application. You may find the following resources handy:

    + +
+ +

Contributing

+ +

We encourage you to contribute to Ruby on Rails! Please check out the Contributing to Ruby on Rails guide for guidelines about how to proceed. Join us!

+ +

Trying to report a possible security vulnerability in Rails? Please check out our security policy for guidelines about how to proceed.

+ +

Everyone interacting in Rails and its sub-projects’ codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails code of conduct.

+ +

License

+ +

Ruby on Rails is released under the MIT License.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/README_rdoc.html b/src/7.0/files/railties/README_rdoc.html new file mode 100644 index 0000000000..78276cdd89 --- /dev/null +++ b/src/7.0/files/railties/README_rdoc.html @@ -0,0 +1,106 @@ +--- +title: README.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Railties – Gluing the Engine to the Rails

+ +

Railties is responsible for gluing all frameworks together. Overall, it:

+
  • +

    handles the bootstrapping process for a Rails application;

    +
  • +

    manages the rails command line interface;

    +
  • +

    and provides the Rails generators core.

    +
+ +

Download

+ +

The latest version of Railties can be installed with RubyGems:

+
  • +

    gem install railties

    +
+ +

Source code can be downloaded as part of the Rails project on GitHub

+ + +

License

+ +

Railties is released under the MIT license:

+ + +

Support

+ +

API documentation is at

+ + +

Bug reports can be filed for the Ruby on Rails project here:

+ + +

Feature requests should be discussed on the rails-core mailing list here:

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/minitest/rails_plugin_rb.html b/src/7.0/files/railties/lib/minitest/rails_plugin_rb.html new file mode 100644 index 0000000000..942514224f --- /dev/null +++ b/src/7.0/files/railties/lib/minitest/rails_plugin_rb.html @@ -0,0 +1,91 @@ +--- +title: rails_plugin.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • rails/test_unit/reporter
  • + +
  • rails/test_unit/runner
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/all_rb.html b/src/7.0/files/railties/lib/rails/all_rb.html new file mode 100644 index 0000000000..b51881c1fe --- /dev/null +++ b/src/7.0/files/railties/lib/rails/all_rb.html @@ -0,0 +1,69 @@ +--- +title: all.rb +layout: default +--- +
+ + +
+
+ +
+ +

rubocop:disable Style/RedundantBegin

+ +
+ + + + +

Required Files

+
    + +
  • rails
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/api/task_rb.html b/src/7.0/files/railties/lib/rails/api/task_rb.html new file mode 100644 index 0000000000..29fbb0d832 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/api/task_rb.html @@ -0,0 +1,93 @@ +--- +title: task.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rdoc/task
  • + +
  • rails/api/generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/app_loader_rb.html b/src/7.0/files/railties/lib/rails/app_loader_rb.html new file mode 100644 index 0000000000..0b207d1eb2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/app_loader_rb.html @@ -0,0 +1,80 @@ +--- +title: app_loader.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • rails/version
  • + +
  • rails/commands
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/app_updater_rb.html b/src/7.0/files/railties/lib/rails/app_updater_rb.html new file mode 100644 index 0000000000..9cc4541a09 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/app_updater_rb.html @@ -0,0 +1,94 @@ +--- +title: app_updater.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/rails/app/app_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/bootstrap_rb.html b/src/7.0/files/railties/lib/rails/application/bootstrap_rb.html new file mode 100644 index 0000000000..5bfc877fb2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/bootstrap_rb.html @@ -0,0 +1,101 @@ +--- +title: bootstrap.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • active_support/notifications
  • + +
  • active_support/dependencies
  • + +
  • active_support/descendants_tracker
  • + +
  • rails/secrets
  • + +
  • active_support/all
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/configuration_rb.html b/src/7.0/files/railties/lib/rails/application/configuration_rb.html new file mode 100644 index 0000000000..476aa98dba --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/configuration_rb.html @@ -0,0 +1,111 @@ +--- +title: configuration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • ipaddr
  • + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/file_update_checker
  • + +
  • active_support/configuration_file
  • + +
  • rails/engine/configuration
  • + +
  • rails/source_annotation_extractor
  • + +
  • rails/application/dummy_erb_compiler
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/default_middleware_stack_rb.html b/src/7.0/files/railties/lib/rails/application/default_middleware_stack_rb.html new file mode 100644 index 0000000000..6680b26805 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/default_middleware_stack_rb.html @@ -0,0 +1,99 @@ +--- +title: default_middleware_stack.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • action_dispatch/http/rack_cache
  • + +
  • rack/cache
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/dummy_erb_compiler_rb.html b/src/7.0/files/railties/lib/rails/application/dummy_erb_compiler_rb.html new file mode 100644 index 0000000000..0ab1941ca8 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/dummy_erb_compiler_rb.html @@ -0,0 +1,61 @@ +--- +title: dummy_erb_compiler.rb +layout: default +--- +
+ + +
+
+ +
+ +

These classes are used to strip out the ERB configuration values so we can evaluate the database.yml without evaluating the ERB values.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/finisher_rb.html b/src/7.0/files/railties/lib/rails/application/finisher_rb.html new file mode 100644 index 0000000000..9de1578d67 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/finisher_rb.html @@ -0,0 +1,93 @@ +--- +title: finisher.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/inflections
  • + +
  • active_support/core_ext/array/conversions
  • + +
  • active_support/descendants_tracker
  • + +
  • active_support/dependencies
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application/routes_reloader_rb.html b/src/7.0/files/railties/lib/rails/application/routes_reloader_rb.html new file mode 100644 index 0000000000..a851b3630f --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application/routes_reloader_rb.html @@ -0,0 +1,87 @@ +--- +title: routes_reloader.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application_controller_rb.html b/src/7.0/files/railties/lib/rails/application_controller_rb.html new file mode 100644 index 0000000000..e2e4b8c1b7 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application_controller_rb.html @@ -0,0 +1,68 @@ +--- +title: application_controller.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/application_rb.html b/src/7.0/files/railties/lib/rails/application_rb.html new file mode 100644 index 0000000000..fcf97ebff4 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/application_rb.html @@ -0,0 +1,111 @@ +--- +title: application.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
  • active_support/core_ext/hash/keys
  • + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/key_generator
  • + +
  • active_support/message_verifier
  • + +
  • active_support/encrypted_configuration
  • + +
  • active_support/hash_with_indifferent_access
  • + +
  • active_support/configuration_file
  • + +
  • rails/engine
  • + +
  • rails/secrets
  • + +
  • rails/autoloaders
  • + +
  • erb
  • + +
  • psych/y
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/autoloaders/inflector_rb.html b/src/7.0/files/railties/lib/rails/autoloaders/inflector_rb.html new file mode 100644 index 0000000000..d358db0183 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/autoloaders/inflector_rb.html @@ -0,0 +1,76 @@ +--- +title: inflector.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/inflector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/autoloaders_rb.html b/src/7.0/files/railties/lib/rails/autoloaders_rb.html new file mode 100644 index 0000000000..f3889686e7 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/autoloaders_rb.html @@ -0,0 +1,76 @@ +--- +title: autoloaders.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • zeitwerk
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/backtrace_cleaner_rb.html b/src/7.0/files/railties/lib/rails/backtrace_cleaner_rb.html new file mode 100644 index 0000000000..55fc692e77 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/backtrace_cleaner_rb.html @@ -0,0 +1,85 @@ +--- +title: backtrace_cleaner.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/backtrace_cleaner
  • + +
  • active_support/core_ext/string/access
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/cli_rb.html b/src/7.0/files/railties/lib/rails/cli_rb.html new file mode 100644 index 0000000000..b85b097ecf --- /dev/null +++ b/src/7.0/files/railties/lib/rails/cli_rb.html @@ -0,0 +1,80 @@ +--- +title: cli.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/app_loader
  • + +
  • rails/ruby_version_check
  • + +
  • rails/command
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/code_statistics_calculator_rb.html b/src/7.0/files/railties/lib/rails/code_statistics_calculator_rb.html new file mode 100644 index 0000000000..e597fd9999 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/code_statistics_calculator_rb.html @@ -0,0 +1,55 @@ +--- +title: code_statistics_calculator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/code_statistics_rb.html b/src/7.0/files/railties/lib/rails/code_statistics_rb.html new file mode 100644 index 0000000000..fe1676926d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/code_statistics_rb.html @@ -0,0 +1,65 @@ +--- +title: code_statistics.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/code_statistics_calculator
  • + +
  • active_support/core_ext/enumerable
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command/actions_rb.html b/src/7.0/files/railties/lib/rails/command/actions_rb.html new file mode 100644 index 0000000000..822150f210 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command/actions_rb.html @@ -0,0 +1,74 @@ +--- +title: actions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command/base_rb.html b/src/7.0/files/railties/lib/rails/command/base_rb.html new file mode 100644 index 0000000000..494cd8054a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command/base_rb.html @@ -0,0 +1,95 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thor
  • + +
  • erb
  • + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/core_ext/string/inflections
  • + +
  • rails/command/actions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command/behavior_rb.html b/src/7.0/files/railties/lib/rails/command/behavior_rb.html new file mode 100644 index 0000000000..7c951ef86a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command/behavior_rb.html @@ -0,0 +1,78 @@ +--- +title: behavior.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command/environment_argument_rb.html b/src/7.0/files/railties/lib/rails/command/environment_argument_rb.html new file mode 100644 index 0000000000..9a9c558483 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command/environment_argument_rb.html @@ -0,0 +1,80 @@ +--- +title: environment_argument.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/core_ext/class/attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command/helpers/editor_rb.html b/src/7.0/files/railties/lib/rails/command/helpers/editor_rb.html new file mode 100644 index 0000000000..07b1eb9be8 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command/helpers/editor_rb.html @@ -0,0 +1,82 @@ +--- +title: editor.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/encrypted_file
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/command_rb.html b/src/7.0/files/railties/lib/rails/command_rb.html new file mode 100644 index 0000000000..b87337de5c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/command_rb.html @@ -0,0 +1,84 @@ +--- +title: command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/object/blank
  • + +
  • thor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/application/application_command_rb.html b/src/7.0/files/railties/lib/rails/commands/application/application_command_rb.html new file mode 100644 index 0000000000..6ef2656483 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/application/application_command_rb.html @@ -0,0 +1,91 @@ +--- +title: application_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/rails/app/app_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/console/console_command_rb.html b/src/7.0/files/railties/lib/rails/commands/console/console_command_rb.html new file mode 100644 index 0000000000..838b7e479d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/console/console_command_rb.html @@ -0,0 +1,93 @@ +--- +title: console_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • irb
  • + +
  • irb/completion
  • + +
  • rails/command/environment_argument
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command/diffing_rb.html b/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command/diffing_rb.html new file mode 100644 index 0000000000..428b3c027a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command/diffing_rb.html @@ -0,0 +1,77 @@ +--- +title: diffing.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command_rb.html b/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command_rb.html new file mode 100644 index 0000000000..103b521aea --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/credentials/credentials_command_rb.html @@ -0,0 +1,102 @@ +--- +title: credentials_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • shellwords
  • + +
  • active_support
  • + +
  • rails/command/helpers/editor
  • + +
  • rails/command/environment_argument
  • + +
  • rails/generators
  • + +
  • rails/generators/rails/encryption_key_file/encryption_key_file_generator
  • + +
  • rails/generators
  • + +
  • rails/generators/rails/encrypted_file/encrypted_file_generator
  • + +
  • rails/generators
  • + +
  • rails/generators/rails/credentials/credentials_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/db/system/change/change_command_rb.html b/src/7.0/files/railties/lib/rails/commands/db/system/change/change_command_rb.html new file mode 100644 index 0000000000..b322205900 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/db/system/change/change_command_rb.html @@ -0,0 +1,88 @@ +--- +title: change_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/rails/db/system/change/change_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/dbconsole/dbconsole_command_rb.html b/src/7.0/files/railties/lib/rails/commands/dbconsole/dbconsole_command_rb.html new file mode 100644 index 0000000000..330f82a9d4 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/dbconsole/dbconsole_command_rb.html @@ -0,0 +1,95 @@ +--- +title: dbconsole_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/string/filters
  • + +
  • active_support/deprecation
  • + +
  • rails/command/environment_argument
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/destroy/destroy_command_rb.html b/src/7.0/files/railties/lib/rails/commands/destroy/destroy_command_rb.html new file mode 100644 index 0000000000..76e5bac318 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/destroy/destroy_command_rb.html @@ -0,0 +1,80 @@ +--- +title: destroy_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/dev/dev_command_rb.html b/src/7.0/files/railties/lib/rails/commands/dev/dev_command_rb.html new file mode 100644 index 0000000000..d888a6f5c1 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/dev/dev_command_rb.html @@ -0,0 +1,80 @@ +--- +title: dev_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/dev_caching
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/encrypted/encrypted_command_rb.html b/src/7.0/files/railties/lib/rails/commands/encrypted/encrypted_command_rb.html new file mode 100644 index 0000000000..d6e1cf2609 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/encrypted/encrypted_command_rb.html @@ -0,0 +1,94 @@ +--- +title: encrypted_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • active_support
  • + +
  • rails/command/helpers/editor
  • + +
  • rails/generators
  • + +
  • rails/generators/rails/encryption_key_file/encryption_key_file_generator
  • + +
  • rails/generators
  • + +
  • rails/generators/rails/encrypted_file/encrypted_file_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/generate/generate_command_rb.html b/src/7.0/files/railties/lib/rails/commands/generate/generate_command_rb.html new file mode 100644 index 0000000000..d4aaf467a2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/generate/generate_command_rb.html @@ -0,0 +1,80 @@ +--- +title: generate_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/help/help_command_rb.html b/src/7.0/files/railties/lib/rails/commands/help/help_command_rb.html new file mode 100644 index 0000000000..4000b0dd0b --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/help/help_command_rb.html @@ -0,0 +1,72 @@ +--- +title: help_command.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/initializers/initializers_command_rb.html b/src/7.0/files/railties/lib/rails/commands/initializers/initializers_command_rb.html new file mode 100644 index 0000000000..c426fb6241 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/initializers/initializers_command_rb.html @@ -0,0 +1,78 @@ +--- +title: initializers_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/command/environment_argument
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/new/new_command_rb.html b/src/7.0/files/railties/lib/rails/commands/new/new_command_rb.html new file mode 100644 index 0000000000..8d2805e77b --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/new/new_command_rb.html @@ -0,0 +1,72 @@ +--- +title: new_command.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/notes/notes_command_rb.html b/src/7.0/files/railties/lib/rails/commands/notes/notes_command_rb.html new file mode 100644 index 0000000000..b3bb2b3792 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/notes/notes_command_rb.html @@ -0,0 +1,80 @@ +--- +title: notes_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/source_annotation_extractor
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/plugin/plugin_command_rb.html b/src/7.0/files/railties/lib/rails/commands/plugin/plugin_command_rb.html new file mode 100644 index 0000000000..ec4b57b13d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/plugin/plugin_command_rb.html @@ -0,0 +1,84 @@ +--- +title: plugin_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/rails/plugin/plugin_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/rake/rake_command_rb.html b/src/7.0/files/railties/lib/rails/commands/rake/rake_command_rb.html new file mode 100644 index 0000000000..b2a955793c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/rake/rake_command_rb.html @@ -0,0 +1,78 @@ +--- +title: rake_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rake
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/routes/routes_command_rb.html b/src/7.0/files/railties/lib/rails/commands/routes/routes_command_rb.html new file mode 100644 index 0000000000..4f10804c49 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/routes/routes_command_rb.html @@ -0,0 +1,86 @@ +--- +title: routes_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/command
  • + +
  • action_dispatch/routing/inspector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/runner/runner_command_rb.html b/src/7.0/files/railties/lib/rails/commands/runner/runner_command_rb.html new file mode 100644 index 0000000000..943cb6eecc --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/runner/runner_command_rb.html @@ -0,0 +1,78 @@ +--- +title: runner_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/command/environment_argument
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/secrets/secrets_command_rb.html b/src/7.0/files/railties/lib/rails/commands/secrets/secrets_command_rb.html new file mode 100644 index 0000000000..7116b56727 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/secrets/secrets_command_rb.html @@ -0,0 +1,82 @@ +--- +title: secrets_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support
  • + +
  • rails/secrets
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/server/server_command_rb.html b/src/7.0/files/railties/lib/rails/commands/server/server_command_rb.html new file mode 100644 index 0000000000..44fc937f3d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/server/server_command_rb.html @@ -0,0 +1,101 @@ +--- +title: server_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • action_dispatch
  • + +
  • rails
  • + +
  • active_support/core_ext/string/filters
  • + +
  • rails/dev_caching
  • + +
  • rails/command/environment_argument
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/test/test_command_rb.html b/src/7.0/files/railties/lib/rails/commands/test/test_command_rb.html new file mode 100644 index 0000000000..034a2c1cfb --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/test/test_command_rb.html @@ -0,0 +1,84 @@ +--- +title: test_command.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/command
  • + +
  • rails/test_unit/runner
  • + +
  • rails/test_unit/reporter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands/version/version_command_rb.html b/src/7.0/files/railties/lib/rails/commands/version/version_command_rb.html new file mode 100644 index 0000000000..e9a7982fd3 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands/version/version_command_rb.html @@ -0,0 +1,72 @@ +--- +title: version_command.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/commands_rb.html b/src/7.0/files/railties/lib/rails/commands_rb.html new file mode 100644 index 0000000000..5caa5bcf2c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/commands_rb.html @@ -0,0 +1,76 @@ +--- +title: commands.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/command
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/configuration_rb.html b/src/7.0/files/railties/lib/rails/configuration_rb.html new file mode 100644 index 0000000000..a81537d582 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/configuration_rb.html @@ -0,0 +1,91 @@ +--- +title: configuration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/ordered_options
  • + +
  • active_support/core_ext/object
  • + +
  • rails/paths
  • + +
  • rails/rack
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/console/app_rb.html b/src/7.0/files/railties/lib/rails/console/app_rb.html new file mode 100644 index 0000000000..f99690e8ae --- /dev/null +++ b/src/7.0/files/railties/lib/rails/console/app_rb.html @@ -0,0 +1,84 @@ +--- +title: app.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/all
  • + +
  • action_controller
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/console/helpers_rb.html b/src/7.0/files/railties/lib/rails/console/helpers_rb.html new file mode 100644 index 0000000000..e5e2a566ca --- /dev/null +++ b/src/7.0/files/railties/lib/rails/console/helpers_rb.html @@ -0,0 +1,70 @@ +--- +title: helpers.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/dev_caching_rb.html b/src/7.0/files/railties/lib/rails/dev_caching_rb.html new file mode 100644 index 0000000000..e3aaacc05b --- /dev/null +++ b/src/7.0/files/railties/lib/rails/dev_caching_rb.html @@ -0,0 +1,76 @@ +--- +title: dev_caching.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/engine/commands_rb.html b/src/7.0/files/railties/lib/rails/engine/commands_rb.html new file mode 100644 index 0000000000..1b26b7dc40 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/engine/commands_rb.html @@ -0,0 +1,63 @@ +--- +title: commands.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/commands
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/engine/configuration_rb.html b/src/7.0/files/railties/lib/rails/engine/configuration_rb.html new file mode 100644 index 0000000000..67df4bb47d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/engine/configuration_rb.html @@ -0,0 +1,89 @@ +--- +title: configuration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/railtie/configuration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/engine/railties_rb.html b/src/7.0/files/railties/lib/rails/engine/railties_rb.html new file mode 100644 index 0000000000..ecef1e6ee1 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/engine/railties_rb.html @@ -0,0 +1,79 @@ +--- +title: railties.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/engine/updater_rb.html b/src/7.0/files/railties/lib/rails/engine/updater_rb.html new file mode 100644 index 0000000000..05d989f82c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/engine/updater_rb.html @@ -0,0 +1,91 @@ +--- +title: updater.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/rails/plugin/plugin_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/engine_rb.html b/src/7.0/files/railties/lib/rails/engine_rb.html new file mode 100644 index 0000000000..8d4969d418 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/engine_rb.html @@ -0,0 +1,113 @@ +--- +title: engine.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/railtie
  • + +
  • rails/engine/railties
  • + +
  • active_support/callbacks
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/object/try
  • + +
  • pathname
  • + +
  • thread
  • + +
  • rails/console/app
  • + +
  • rails/console/helpers
  • + +
  • rake
  • + +
  • rails/generators
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/gem_version_rb.html b/src/7.0/files/railties/lib/rails/gem_version_rb.html new file mode 100644 index 0000000000..7f9af44c8c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/gem_version_rb.html @@ -0,0 +1,70 @@ +--- +title: gem_version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/actions/create_migration_rb.html b/src/7.0/files/railties/lib/rails/generators/actions/create_migration_rb.html new file mode 100644 index 0000000000..035801abd3 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/actions/create_migration_rb.html @@ -0,0 +1,82 @@ +--- +title: create_migration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • thor/actions
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/actions_rb.html b/src/7.0/files/railties/lib/rails/generators/actions_rb.html new file mode 100644 index 0000000000..949dcc0234 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/actions_rb.html @@ -0,0 +1,86 @@ +--- +title: actions.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • shellwords
  • + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/core_ext/string/strip
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/active_model_rb.html b/src/7.0/files/railties/lib/rails/generators/active_model_rb.html new file mode 100644 index 0000000000..0ff4c935ba --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/active_model_rb.html @@ -0,0 +1,77 @@ +--- +title: active_model.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/app_base_rb.html b/src/7.0/files/railties/lib/rails/generators/app_base_rb.html new file mode 100644 index 0000000000..f9106fe687 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/app_base_rb.html @@ -0,0 +1,107 @@ +--- +title: app_base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • fileutils
  • + +
  • digest/md5
  • + +
  • rails/version
  • + +
  • open-uri
  • + +
  • uri
  • + +
  • rails/generators
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • bundler
  • + +
  • shellwords
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/app_name_rb.html b/src/7.0/files/railties/lib/rails/generators/app_name_rb.html new file mode 100644 index 0000000000..32d8cde863 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/app_name_rb.html @@ -0,0 +1,72 @@ +--- +title: app_name.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/base_rb.html b/src/7.0/files/railties/lib/rails/generators/base_rb.html new file mode 100644 index 0000000000..b722938c48 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/base_rb.html @@ -0,0 +1,87 @@ +--- +title: base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thor/group
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/database_rb.html b/src/7.0/files/railties/lib/rails/generators/database_rb.html new file mode 100644 index 0000000000..385fe0535b --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/database_rb.html @@ -0,0 +1,70 @@ +--- +title: database.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/erb/controller/controller_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/erb/controller/controller_generator_rb.html new file mode 100644 index 0000000000..0f824fd923 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/erb/controller/controller_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: controller_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/erb
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/erb/mailer/mailer_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/erb/mailer/mailer_generator_rb.html new file mode 100644 index 0000000000..80586a7d4f --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/erb/mailer/mailer_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: mailer_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/erb
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/erb/scaffold/scaffold_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/erb/scaffold/scaffold_generator_rb.html new file mode 100644 index 0000000000..7b1c1fa0dc --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/erb/scaffold/scaffold_generator_rb.html @@ -0,0 +1,65 @@ +--- +title: scaffold_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/erb
  • + +
  • rails/generators/resource_helpers
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/erb_rb.html b/src/7.0/files/railties/lib/rails/generators/erb_rb.html new file mode 100644 index 0000000000..7da5a87a66 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/erb_rb.html @@ -0,0 +1,63 @@ +--- +title: erb.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/named_base
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/generated_attribute_rb.html b/src/7.0/files/railties/lib/rails/generators/generated_attribute_rb.html new file mode 100644 index 0000000000..9b627f83d0 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/generated_attribute_rb.html @@ -0,0 +1,80 @@ +--- +title: generated_attribute.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/time
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/migration_rb.html b/src/7.0/files/railties/lib/rails/generators/migration_rb.html new file mode 100644 index 0000000000..598ef69c48 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/migration_rb.html @@ -0,0 +1,86 @@ +--- +title: migration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
  • rails/generators/actions/create_migration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/model_helpers_rb.html b/src/7.0/files/railties/lib/rails/generators/model_helpers_rb.html new file mode 100644 index 0000000000..0e6d3bbd3a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/model_helpers_rb.html @@ -0,0 +1,78 @@ +--- +title: model_helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/active_model
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/named_base_rb.html b/src/7.0/files/railties/lib/rails/generators/named_base_rb.html new file mode 100644 index 0000000000..7402e7f598 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/named_base_rb.html @@ -0,0 +1,91 @@ +--- +title: named_base.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/base
  • + +
  • rails/generators/generated_attribute
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/app/app_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/app/app_generator_rb.html new file mode 100644 index 0000000000..49f2d5b73c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/app/app_generator_rb.html @@ -0,0 +1,97 @@ +--- +title: app_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/app_base
  • + +
  • rails/generators/rails/master_key/master_key_generator
  • + +
  • rails/generators/rails/credentials/credentials_generator
  • + +
  • rails/version
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/application_record/application_record_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/application_record/application_record_generator_rb.html new file mode 100644 index 0000000000..d0cfa4a004 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/application_record/application_record_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: application_record_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/benchmark/benchmark_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/benchmark/benchmark_generator_rb.html new file mode 100644 index 0000000000..3e68a8f15a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/benchmark/benchmark_generator_rb.html @@ -0,0 +1,85 @@ +--- +title: benchmark_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/named_base
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/controller/controller_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/controller/controller_generator_rb.html new file mode 100644 index 0000000000..7b0ef3858f --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/controller/controller_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: controller_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/credentials/credentials_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/credentials/credentials_generator_rb.html new file mode 100644 index 0000000000..a5b487d41d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/credentials/credentials_generator_rb.html @@ -0,0 +1,84 @@ +--- +title: credentials_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/base
  • + +
  • rails/generators/rails/master_key/master_key_generator
  • + +
  • active_support/encrypted_configuration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/db/system/change/change_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/db/system/change/change_generator_rb.html new file mode 100644 index 0000000000..1c486a450e --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/db/system/change/change_generator_rb.html @@ -0,0 +1,82 @@ +--- +title: change_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/base
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator_rb.html new file mode 100644 index 0000000000..089bbc05ed --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/encrypted_file/encrypted_file_generator_rb.html @@ -0,0 +1,82 @@ +--- +title: encrypted_file_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/base
  • + +
  • active_support/encrypted_file
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator_rb.html new file mode 100644 index 0000000000..14045632d5 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/encryption_key_file/encryption_key_file_generator_rb.html @@ -0,0 +1,84 @@ +--- +title: encryption_key_file_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • rails/generators/base
  • + +
  • active_support/encrypted_file
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/generator/generator_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/generator/generator_generator_rb.html new file mode 100644 index 0000000000..da4de68e8c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/generator/generator_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: generator_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/helper/helper_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/helper/helper_generator_rb.html new file mode 100644 index 0000000000..419a4b90fa --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/helper/helper_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: helper_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/integration_test/integration_test_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/integration_test/integration_test_generator_rb.html new file mode 100644 index 0000000000..d27b5ceebd --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/integration_test/integration_test_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: integration_test_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/master_key/master_key_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/master_key/master_key_generator_rb.html new file mode 100644 index 0000000000..c0263cb816 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/master_key/master_key_generator_rb.html @@ -0,0 +1,86 @@ +--- +title: master_key_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
  • rails/generators/base
  • + +
  • rails/generators/rails/encryption_key_file/encryption_key_file_generator
  • + +
  • active_support/encrypted_file
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/migration/migration_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/migration/migration_generator_rb.html new file mode 100644 index 0000000000..b453e060c7 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/migration/migration_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: migration_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/model/model_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/model/model_generator_rb.html new file mode 100644 index 0000000000..e9d281de38 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/model/model_generator_rb.html @@ -0,0 +1,78 @@ +--- +title: model_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/model_helpers
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/plugin/plugin_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/plugin/plugin_generator_rb.html new file mode 100644 index 0000000000..dd3c419ae9 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/plugin/plugin_generator_rb.html @@ -0,0 +1,91 @@ +--- +title: plugin_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/hash/except
  • + +
  • rails/generators/rails/app/app_generator
  • + +
  • date
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/resource/resource_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/resource/resource_generator_rb.html new file mode 100644 index 0000000000..e1e2bd6eb5 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/resource/resource_generator_rb.html @@ -0,0 +1,80 @@ +--- +title: resource_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/resource_helpers
  • + +
  • rails/generators/rails/model/model_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/resource_route/resource_route_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/resource_route/resource_route_generator_rb.html new file mode 100644 index 0000000000..e6a568bb27 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/resource_route/resource_route_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: resource_route_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/scaffold/scaffold_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/scaffold/scaffold_generator_rb.html new file mode 100644 index 0000000000..7330cb87ec --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/scaffold/scaffold_generator_rb.html @@ -0,0 +1,78 @@ +--- +title: scaffold_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/rails/resource/resource_generator
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator_rb.html new file mode 100644 index 0000000000..1844024a5c --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator_rb.html @@ -0,0 +1,78 @@ +--- +title: scaffold_controller_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/resource_helpers
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/system_test/system_test_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/system_test/system_test_generator_rb.html new file mode 100644 index 0000000000..8d81f8cd46 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/system_test/system_test_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: system_test_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/rails/task/task_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/rails/task/task_generator_rb.html new file mode 100644 index 0000000000..42701ff71e --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/rails/task/task_generator_rb.html @@ -0,0 +1,70 @@ +--- +title: task_generator.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/resource_helpers_rb.html b/src/7.0/files/railties/lib/rails/generators/resource_helpers_rb.html new file mode 100644 index 0000000000..029bb83ead --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/resource_helpers_rb.html @@ -0,0 +1,82 @@ +--- +title: resource_helpers.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/active_model
  • + +
  • rails/generators/model_helpers
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_case_rb.html b/src/7.0/files/railties/lib/rails/generators/test_case_rb.html new file mode 100644 index 0000000000..78be97cafc --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_case_rb.html @@ -0,0 +1,93 @@ +--- +title: test_case.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators
  • + +
  • rails/generators/testing/behaviour
  • + +
  • rails/generators/testing/setup_and_teardown
  • + +
  • rails/generators/testing/assertions
  • + +
  • fileutils
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/controller/controller_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/controller/controller_generator_rb.html new file mode 100644 index 0000000000..52c0ebbd97 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/controller/controller_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: controller_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/generator/generator_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/generator/generator_generator_rb.html new file mode 100644 index 0000000000..0c54419947 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/generator/generator_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: generator_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/helper/helper_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/helper/helper_generator_rb.html new file mode 100644 index 0000000000..e3e80c1af2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/helper/helper_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: helper_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/integration/integration_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/integration/integration_generator_rb.html new file mode 100644 index 0000000000..9cf1343a9e --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/integration/integration_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: integration_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/job/job_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/job/job_generator_rb.html new file mode 100644 index 0000000000..2d99e9dcf5 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/job/job_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: job_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/mailer/mailer_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/mailer/mailer_generator_rb.html new file mode 100644 index 0000000000..7258fcc586 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/mailer/mailer_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: mailer_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/model/model_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/model/model_generator_rb.html new file mode 100644 index 0000000000..dc2e31ab3f --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/model/model_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: model_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/plugin/plugin_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/plugin/plugin_generator_rb.html new file mode 100644 index 0000000000..37741e3d45 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/plugin/plugin_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: plugin_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator_rb.html new file mode 100644 index 0000000000..c4823c1a2d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/scaffold/scaffold_generator_rb.html @@ -0,0 +1,65 @@ +--- +title: scaffold_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
  • rails/generators/resource_helpers
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit/system/system_generator_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit/system/system_generator_rb.html new file mode 100644 index 0000000000..acac46dabc --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit/system/system_generator_rb.html @@ -0,0 +1,63 @@ +--- +title: system_generator.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/test_unit
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/test_unit_rb.html b/src/7.0/files/railties/lib/rails/generators/test_unit_rb.html new file mode 100644 index 0000000000..2a1361e84e --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/test_unit_rb.html @@ -0,0 +1,63 @@ +--- +title: test_unit.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/generators/named_base
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/testing/assertions_rb.html b/src/7.0/files/railties/lib/rails/generators/testing/assertions_rb.html new file mode 100644 index 0000000000..8d0757b3a6 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/testing/assertions_rb.html @@ -0,0 +1,74 @@ +--- +title: assertions.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/testing/behaviour_rb.html b/src/7.0/files/railties/lib/rails/generators/testing/behaviour_rb.html new file mode 100644 index 0000000000..73deb29e62 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/testing/behaviour_rb.html @@ -0,0 +1,98 @@ +--- +title: behaviour.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/class/attribute
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/hash/reverse_merge
  • + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/testing/stream
  • + +
  • active_support/concern
  • + +
  • rails/generators
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators/testing/setup_and_teardown_rb.html b/src/7.0/files/railties/lib/rails/generators/testing/setup_and_teardown_rb.html new file mode 100644 index 0000000000..7273af3205 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators/testing/setup_and_teardown_rb.html @@ -0,0 +1,74 @@ +--- +title: setup_and_teardown.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/generators_rb.html b/src/7.0/files/railties/lib/rails/generators_rb.html new file mode 100644 index 0000000000..6ef3591681 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/generators_rb.html @@ -0,0 +1,101 @@ +--- +title: generators.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • thor/group
  • + +
  • rails/command
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/enumerable
  • + +
  • active_support/core_ext/hash/deep_merge
  • + +
  • active_support/core_ext/module/attribute_accessors
  • + +
  • active_support/core_ext/string/indent
  • + +
  • active_support/core_ext/string/inflections
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/info_controller_rb.html b/src/7.0/files/railties/lib/rails/info_controller_rb.html new file mode 100644 index 0000000000..dd8dfa7baa --- /dev/null +++ b/src/7.0/files/railties/lib/rails/info_controller_rb.html @@ -0,0 +1,84 @@ +--- +title: info_controller.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/application_controller
  • + +
  • action_dispatch/routing/inspector
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/info_rb.html b/src/7.0/files/railties/lib/rails/info_rb.html new file mode 100644 index 0000000000..af81ddd7c4 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/info_rb.html @@ -0,0 +1,80 @@ +--- +title: info.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • cgi
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/initializable_rb.html b/src/7.0/files/railties/lib/rails/initializable_rb.html new file mode 100644 index 0000000000..57bf8bd6d5 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/initializable_rb.html @@ -0,0 +1,89 @@ +--- +title: initializable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • tsort
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/mailers_controller_rb.html b/src/7.0/files/railties/lib/rails/mailers_controller_rb.html new file mode 100644 index 0000000000..93701f7aa2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/mailers_controller_rb.html @@ -0,0 +1,84 @@ +--- +title: mailers_controller.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/application_controller
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/paths_rb.html b/src/7.0/files/railties/lib/rails/paths_rb.html new file mode 100644 index 0000000000..24b9454b04 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/paths_rb.html @@ -0,0 +1,87 @@ +--- +title: paths.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • pathname
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/plugin/test_rb.html b/src/7.0/files/railties/lib/rails/plugin/test_rb.html new file mode 100644 index 0000000000..d9096cd20b --- /dev/null +++ b/src/7.0/files/railties/lib/rails/plugin/test_rb.html @@ -0,0 +1,78 @@ +--- +title: test.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/test_unit/runner
  • + +
  • rails/test_unit/reporter
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/rack/logger_rb.html b/src/7.0/files/railties/lib/rails/rack/logger_rb.html new file mode 100644 index 0000000000..719d45f474 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/rack/logger_rb.html @@ -0,0 +1,95 @@ +--- +title: logger.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/core_ext/time/conversions
  • + +
  • active_support/core_ext/object/blank
  • + +
  • active_support/log_subscriber
  • + +
  • rack/body_proxy
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/rack_rb.html b/src/7.0/files/railties/lib/rails/rack_rb.html new file mode 100644 index 0000000000..7f76c16535 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/rack_rb.html @@ -0,0 +1,70 @@ +--- +title: rack.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/railtie/configurable_rb.html b/src/7.0/files/railties/lib/rails/railtie/configurable_rb.html new file mode 100644 index 0000000000..decf7d9f23 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/railtie/configurable_rb.html @@ -0,0 +1,87 @@ +--- +title: configurable.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • active_support/concern
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/railtie/configuration_rb.html b/src/7.0/files/railties/lib/rails/railtie/configuration_rb.html new file mode 100644 index 0000000000..e749adce43 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/railtie/configuration_rb.html @@ -0,0 +1,89 @@ +--- +title: configuration.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/configuration
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/railtie_rb.html b/src/7.0/files/railties/lib/rails/railtie_rb.html new file mode 100644 index 0000000000..be767a5fc2 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/railtie_rb.html @@ -0,0 +1,93 @@ +--- +title: railtie.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/initializable
  • + +
  • active_support/descendants_tracker
  • + +
  • active_support/inflector
  • + +
  • active_support/core_ext/module/introspection
  • + +
  • active_support/core_ext/module/delegation
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/ruby_version_check_rb.html b/src/7.0/files/railties/lib/rails/ruby_version_check_rb.html new file mode 100644 index 0000000000..137621c3b0 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/ruby_version_check_rb.html @@ -0,0 +1,55 @@ +--- +title: ruby_version_check.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/secrets_rb.html b/src/7.0/files/railties/lib/rails/secrets_rb.html new file mode 100644 index 0000000000..1e85ed5a7a --- /dev/null +++ b/src/7.0/files/railties/lib/rails/secrets_rb.html @@ -0,0 +1,93 @@ +--- +title: secrets.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • yaml
  • + +
  • tempfile
  • + +
  • active_support/message_encryptor
  • + +
  • erb
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/source_annotation_extractor_rb.html b/src/7.0/files/railties/lib/rails/source_annotation_extractor_rb.html new file mode 100644 index 0000000000..cf13e5eb8d --- /dev/null +++ b/src/7.0/files/railties/lib/rails/source_annotation_extractor_rb.html @@ -0,0 +1,77 @@ +--- +title: source_annotation_extractor.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + +

Class

+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/tasks_rb.html b/src/7.0/files/railties/lib/rails/tasks_rb.html new file mode 100644 index 0000000000..2e8d0b841e --- /dev/null +++ b/src/7.0/files/railties/lib/rails/tasks_rb.html @@ -0,0 +1,63 @@ +--- +title: tasks.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rake
  • + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/test_help_rb.html b/src/7.0/files/railties/lib/rails/test_help_rb.html new file mode 100644 index 0000000000..04f07e9dc5 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/test_help_rb.html @@ -0,0 +1,94 @@ +--- +title: test_help.rb +layout: default +--- +
+ + +
+
+ +
+ +

Make double-sure the RAILS_ENV is not set to production, so fixtures aren’t loaded into that environment

+ +
+ + + + +

Required Files

+
    + +
  • active_support/test_case
  • + +
  • action_controller
  • + +
  • action_controller/test_case
  • + +
  • action_dispatch/testing/integration
  • + +
  • rails/generators/test_case
  • + +
  • active_support/testing/autorun
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/version_rb.html b/src/7.0/files/railties/lib/rails/version_rb.html new file mode 100644 index 0000000000..a4eb3da637 --- /dev/null +++ b/src/7.0/files/railties/lib/rails/version_rb.html @@ -0,0 +1,70 @@ +--- +title: version.rb +layout: default +--- +
+ + +
+
+ + + + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails/welcome_controller_rb.html b/src/7.0/files/railties/lib/rails/welcome_controller_rb.html new file mode 100644 index 0000000000..bf52e8c8da --- /dev/null +++ b/src/7.0/files/railties/lib/rails/welcome_controller_rb.html @@ -0,0 +1,76 @@ +--- +title: welcome_controller.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/application_controller
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/files/railties/lib/rails_rb.html b/src/7.0/files/railties/lib/rails_rb.html new file mode 100644 index 0000000000..4c84afe159 --- /dev/null +++ b/src/7.0/files/railties/lib/rails_rb.html @@ -0,0 +1,102 @@ +--- +title: rails.rb +layout: default +--- +
+ + +
+
+ + + + +

Required Files

+
    + +
  • rails/ruby_version_check
  • + +
  • pathname
  • + +
  • active_support
  • + +
  • active_support/core_ext/kernel/reporting
  • + +
  • active_support/core_ext/module/delegation
  • + +
  • active_support/core_ext/array/extract_options
  • + +
  • active_support/core_ext/object/blank
  • + +
  • rails/application
  • + +
  • rails/version
  • + +
  • active_support/railtie
  • + +
  • action_dispatch/railtie
  • + +
  • rails/backtrace_cleaner
  • + +
+ + + + + + + +

Namespace

+ + +

Module

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/index.html b/src/7.0/index.html new file mode 100644 index 0000000000..e98318ecf7 --- /dev/null +++ b/src/7.0/index.html @@ -0,0 +1,131 @@ +--- +title: RDOC_MAIN.rdoc +layout: default +--- +
+ + +
+
+ +
+ +

Welcome to Rails

+ +

What’s Rails

+ +

Rails is a web-application framework that includes everything needed to create database-backed web applications according to the Model-View-Controller (MVC) pattern.

+ +

Understanding the MVC pattern is key to understanding Rails. MVC divides your application into three layers: Model, View, and Controller, each with a specific responsibility.

+ +

Model layer

+ +

The Model layer represents the domain model (such as Account, Product, Person, Post, etc.) and encapsulates the business logic specific to your application. In Rails, database-backed model classes are derived from ActiveRecord::Base. Active Record allows you to present the data from database rows as objects and embellish these data objects with business logic methods. Although most Rails models are backed by a database, models can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as provided by the Active Model module.

+ +

Controller layer

+ +

The Controller layer is responsible for handling incoming HTTP requests and providing a suitable response. Usually, this means returning HTML, but Rails controllers can also generate XML, JSON, PDFs, mobile-specific views, and more. Controllers load and manipulate models and render view templates in order to generate the appropriate HTTP response. In Rails, incoming requests are routed by Action Dispatch to an appropriate controller, and controller classes are derived from ActionController::Base. Action Dispatch and Action Controller are bundled together in Action Pack.

+ +

View layer

+ +

The View layer is composed of “templates” that are responsible for providing appropriate representations of your application’s resources. Templates can come in a variety of formats, but most view templates are HTML with embedded Ruby code (ERB files). Views are typically rendered to generate a controller response, or to generate the body of an email. In Rails, View generation is handled by Action View.

+ +

Frameworks and libraries

+ +

Active Record, Active Model, Action Pack, and Action View can each be used independently outside Rails. In addition to that, Rails also comes with Action Mailer, a library to generate and send emails; Action Mailbox, a library to receive emails within a Rails application; Active Job, a framework for declaring jobs and making them run on a variety of queueing backends; Action Cable, a framework to integrate WebSockets with a Rails application; Active Storage, a library to attach cloud and local files to Rails applications; Action Text, a library to handle rich text content; and Active Support, a collection of utility classes and standard library extensions that are useful for Rails, and may also be used independently outside Rails.

+ +

Getting Started

+
  1. +

    Install Rails at the command prompt if you haven’t yet:

    + +
    $ gem install rails
    +
    +
  2. +

    At the command prompt, create a new Rails application:

    + +
    $ rails new myapp
    +
    + +

    where “myapp” is the application name.

    +
  3. +

    Change directory to myapp and start the web server:

    + +
    $ cd myapp
    +$ bin/rails server
    +
    + +

    Run with --help or -h for options.

    +
  4. +

    Go to http://localhost:3000, and you’ll see: “Yay! You’re on Rails!”

    +
  5. +

    Follow the guidelines to start developing your application. You may find the following resources handy:

    + +
+ +

Contributing

+ +

We encourage you to contribute to Ruby on Rails! Please check out the Contributing to Ruby on Rails guide for guidelines about how to proceed. Join us!

+ +

Trying to report a possible security vulnerability in Rails? Please check out our security policy for guidelines about how to proceed.

+ +

Everyone interacting in Rails and its sub-projects’ codebases, issue trackers, chat rooms, and mailing lists is expected to follow the Rails code of conduct.

+ +

License

+ +

Ruby on Rails is released under the MIT License.

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
diff --git a/src/7.0/navigation.html b/src/7.0/navigation.html index 9bf6ac45f5..59a731a5c4 100644 --- a/src/7.0/navigation.html +++ b/src/7.0/navigation.html @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/_layouts/default.html b/src/_layouts/default.html index 8585a64ada..f42d18af7c 100644 --- a/src/_layouts/default.html +++ b/src/_layouts/default.html @@ -38,10 +38,14 @@ v{{ page.version }} diff --git a/src/classes/AbstractController.html b/src/classes/AbstractController.html index cfb0b7a519..4654544996 100644 --- a/src/classes/AbstractController.html +++ b/src/classes/AbstractController.html @@ -5,7 +5,7 @@